diff options
Diffstat (limited to 'clang/lib/Sema/SemaLookup.cpp')
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 194 |
1 files changed, 123 insertions, 71 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 29038ab9fe1c..5e8c4de61e5d 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -638,8 +638,8 @@ void LookupResult::resolveKind() { void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { CXXBasePaths::const_paths_iterator I, E; for (I = P.begin(), E = P.end(); I != E; ++I) - for (DeclContext::lookup_iterator DI = I->Decls.begin(), - DE = I->Decls.end(); DI != DE; ++DI) + for (DeclContext::lookup_iterator DI = I->Decls, DE = DI.end(); DI != DE; + ++DI) addDecl(*DI); } @@ -677,9 +677,43 @@ LLVM_DUMP_METHOD void LookupResult::dump() { D->dump(); } +/// Diagnose a missing builtin type. +static QualType diagOpenCLBuiltinTypeError(Sema &S, llvm::StringRef TypeClass, + llvm::StringRef Name) { + S.Diag(SourceLocation(), diag::err_opencl_type_not_found) + << TypeClass << Name; + return S.Context.VoidTy; +} + +/// Lookup an OpenCL enum type. +static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name) { + LookupResult Result(S, &S.Context.Idents.get(Name), SourceLocation(), + Sema::LookupTagName); + S.LookupName(Result, S.TUScope); + if (Result.empty()) + return diagOpenCLBuiltinTypeError(S, "enum", Name); + EnumDecl *Decl = Result.getAsSingle<EnumDecl>(); + if (!Decl) + return diagOpenCLBuiltinTypeError(S, "enum", Name); + return S.Context.getEnumType(Decl); +} + +/// Lookup an OpenCL typedef type. +static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name) { + LookupResult Result(S, &S.Context.Idents.get(Name), SourceLocation(), + Sema::LookupOrdinaryName); + S.LookupName(Result, S.TUScope); + if (Result.empty()) + return diagOpenCLBuiltinTypeError(S, "typedef", Name); + TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>(); + if (!Decl) + return diagOpenCLBuiltinTypeError(S, "typedef", Name); + return S.Context.getTypedefType(Decl); +} + /// Get the QualType instances of the return type and arguments for an OpenCL /// builtin function signature. -/// \param Context (in) The Context instance. +/// \param S (in) The Sema instance. /// \param OpenCLBuiltin (in) The signature currently handled. /// \param GenTypeMaxCnt (out) Maximum number of types contained in a generic /// type used as return type or as argument. @@ -689,20 +723,20 @@ LLVM_DUMP_METHOD void LookupResult::dump() { /// argument, ArgTypes contains QualTypes for the Cartesian product /// of (vector sizes) x (types) . static void GetQualTypesForOpenCLBuiltin( - ASTContext &Context, const OpenCLBuiltinStruct &OpenCLBuiltin, - unsigned &GenTypeMaxCnt, SmallVector<QualType, 1> &RetTypes, + Sema &S, const OpenCLBuiltinStruct &OpenCLBuiltin, unsigned &GenTypeMaxCnt, + SmallVector<QualType, 1> &RetTypes, SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) { // Get the QualType instances of the return types. unsigned Sig = SignatureTable[OpenCLBuiltin.SigTableIndex]; - OCL2Qual(Context, TypeTable[Sig], RetTypes); + OCL2Qual(S, TypeTable[Sig], RetTypes); GenTypeMaxCnt = RetTypes.size(); // Get the QualType instances of the arguments. // First type is the return type, skip it. for (unsigned Index = 1; Index < OpenCLBuiltin.NumTypes; Index++) { SmallVector<QualType, 1> Ty; - OCL2Qual(Context, - TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]], Ty); + OCL2Qual(S, TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]], + Ty); GenTypeMaxCnt = (Ty.size() > GenTypeMaxCnt) ? Ty.size() : GenTypeMaxCnt; ArgTypes.push_back(std::move(Ty)); } @@ -721,14 +755,24 @@ static void GetOpenCLBuiltinFctOverloads( ASTContext &Context, unsigned GenTypeMaxCnt, std::vector<QualType> &FunctionList, SmallVector<QualType, 1> &RetTypes, SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) { - FunctionProtoType::ExtProtoInfo PI; + FunctionProtoType::ExtProtoInfo PI( + Context.getDefaultCallingConvention(false, false, true)); PI.Variadic = false; + // Do not attempt to create any FunctionTypes if there are no return types, + // which happens when a type belongs to a disabled extension. + if (RetTypes.size() == 0) + return; + // Create FunctionTypes for each (gen)type. for (unsigned IGenType = 0; IGenType < GenTypeMaxCnt; IGenType++) { SmallVector<QualType, 5> ArgList; for (unsigned A = 0; A < ArgTypes.size(); A++) { + // Bail out if there is an argument that has no available types. + if (ArgTypes[A].size() == 0) + return; + // Builtins such as "max" have an "sgentype" argument that represents // the corresponding scalar type of a gentype. The number of gentypes // must be a multiple of the number of sgentypes. @@ -743,18 +787,6 @@ static void GetOpenCLBuiltinFctOverloads( } } -/// Add extensions to the function declaration. -/// \param S (in/out) The Sema instance. -/// \param BIDecl (in) Description of the builtin. -/// \param FDecl (in/out) FunctionDecl instance. -static void AddOpenCLExtensions(Sema &S, const OpenCLBuiltinStruct &BIDecl, - FunctionDecl *FDecl) { - // Fetch extension associated with a function prototype. - StringRef E = FunctionExtensionTable[BIDecl.Extension]; - if (E != "") - S.setOpenCLExtensionForDecl(FDecl, E); -} - /// When trying to resolve a function name, if isOpenCLBuiltin() returns a /// non-null <Index, Len> pair, then the name is referencing an OpenCL /// builtin function. Add all candidate signatures to the LookUpResult. @@ -775,27 +807,42 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, // as argument. Only meaningful for generic types, otherwise equals 1. unsigned GenTypeMaxCnt; + ASTContext &Context = S.Context; + for (unsigned SignatureIndex = 0; SignatureIndex < Len; SignatureIndex++) { const OpenCLBuiltinStruct &OpenCLBuiltin = BuiltinTable[FctIndex + SignatureIndex]; - ASTContext &Context = S.Context; - // Ignore this BIF if its version does not match the language options. - unsigned OpenCLVersion = Context.getLangOpts().OpenCLVersion; - if (Context.getLangOpts().OpenCLCPlusPlus) - OpenCLVersion = 200; - if (OpenCLVersion < OpenCLBuiltin.MinVersion) - continue; - if ((OpenCLBuiltin.MaxVersion != 0) && - (OpenCLVersion >= OpenCLBuiltin.MaxVersion)) + // Ignore this builtin function if it is not available in the currently + // selected language version. + if (!isOpenCLVersionContainedInMask(Context.getLangOpts(), + OpenCLBuiltin.Versions)) continue; + // Ignore this builtin function if it carries an extension macro that is + // not defined. This indicates that the extension is not supported by the + // target, so the builtin function should not be available. + StringRef Extensions = FunctionExtensionTable[OpenCLBuiltin.Extension]; + if (!Extensions.empty()) { + SmallVector<StringRef, 2> ExtVec; + Extensions.split(ExtVec, " "); + bool AllExtensionsDefined = true; + for (StringRef Ext : ExtVec) { + if (!S.getPreprocessor().isMacroDefined(Ext)) { + AllExtensionsDefined = false; + break; + } + } + if (!AllExtensionsDefined) + continue; + } + SmallVector<QualType, 1> RetTypes; SmallVector<SmallVector<QualType, 1>, 5> ArgTypes; // Obtain QualType lists for the function signature. - GetQualTypesForOpenCLBuiltin(Context, OpenCLBuiltin, GenTypeMaxCnt, - RetTypes, ArgTypes); + GetQualTypesForOpenCLBuiltin(S, OpenCLBuiltin, GenTypeMaxCnt, RetTypes, + ArgTypes); if (GenTypeMaxCnt > 1) { HasGenType = true; } @@ -809,28 +856,24 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, DeclContext *Parent = Context.getTranslationUnitDecl(); FunctionDecl *NewOpenCLBuiltin; - for (unsigned Index = 0; Index < GenTypeMaxCnt; Index++) { + for (const auto &FTy : FunctionList) { NewOpenCLBuiltin = FunctionDecl::Create( - Context, Parent, Loc, Loc, II, FunctionList[Index], - /*TInfo=*/nullptr, SC_Extern, false, - FunctionList[Index]->isFunctionProtoType()); + Context, Parent, Loc, Loc, II, FTy, /*TInfo=*/nullptr, SC_Extern, + false, FTy->isFunctionProtoType()); NewOpenCLBuiltin->setImplicit(); // Create Decl objects for each parameter, adding them to the // FunctionDecl. - if (const FunctionProtoType *FP = - dyn_cast<FunctionProtoType>(FunctionList[Index])) { - SmallVector<ParmVarDecl *, 16> ParmList; - for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) { - ParmVarDecl *Parm = ParmVarDecl::Create( - Context, NewOpenCLBuiltin, SourceLocation(), SourceLocation(), - nullptr, FP->getParamType(IParm), - /*TInfo=*/nullptr, SC_None, nullptr); - Parm->setScopeInfo(0, IParm); - ParmList.push_back(Parm); - } - NewOpenCLBuiltin->setParams(ParmList); + const auto *FP = cast<FunctionProtoType>(FTy); + SmallVector<ParmVarDecl *, 4> ParmList; + for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) { + ParmVarDecl *Parm = ParmVarDecl::Create( + Context, NewOpenCLBuiltin, SourceLocation(), SourceLocation(), + nullptr, FP->getParamType(IParm), nullptr, SC_None, nullptr); + Parm->setScopeInfo(0, IParm); + ParmList.push_back(Parm); } + NewOpenCLBuiltin->setParams(ParmList); // Add function attributes. if (OpenCLBuiltin.IsPure) @@ -843,8 +886,6 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, if (!S.getLangOpts().OpenCLCPlusPlus) NewOpenCLBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context)); - AddOpenCLExtensions(S, OpenCLBuiltin, NewOpenCLBuiltin); - LR.addDecl(NewOpenCLBuiltin); } } @@ -2191,9 +2232,9 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl(); // Drop leading non-matching lookup results from the declaration list so // we don't need to consider them again below. - for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) + for (Path.Decls = BaseRecord->lookup(Name).begin(); + Path.Decls != Path.Decls.end(); ++Path.Decls) { + if ((*Path.Decls)->isInIdentifierNamespace(IDNS)) return true; } return false; @@ -2217,9 +2258,9 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, AccessSpecifier SubobjectAccess = AS_none; // Check whether the given lookup result contains only static members. - auto HasOnlyStaticMembers = [&](DeclContextLookupResult Result) { - for (NamedDecl *ND : Result) - if (ND->isInIdentifierNamespace(IDNS) && ND->isCXXInstanceMember()) + auto HasOnlyStaticMembers = [&](DeclContext::lookup_iterator Result) { + for (DeclContext::lookup_iterator I = Result, E = I.end(); I != E; ++I) + if ((*I)->isInIdentifierNamespace(IDNS) && (*I)->isCXXInstanceMember()) return false; return true; }; @@ -2228,8 +2269,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // Determine whether two sets of members contain the same members, as // required by C++ [class.member.lookup]p6. - auto HasSameDeclarations = [&](DeclContextLookupResult A, - DeclContextLookupResult B) { + auto HasSameDeclarations = [&](DeclContext::lookup_iterator A, + DeclContext::lookup_iterator B) { using Iterator = DeclContextLookupResult::iterator; using Result = const void *; @@ -2266,7 +2307,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // We'll often find the declarations are in the same order. Handle this // case (and the special case of only one declaration) efficiently. - Iterator AIt = A.begin(), BIt = B.begin(), AEnd = A.end(), BEnd = B.end(); + Iterator AIt = A, BIt = B, AEnd, BEnd; while (true) { Result AResult = Next(AIt, AEnd); Result BResult = Next(BIt, BEnd); @@ -2349,10 +2390,11 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // Lookup in a base class succeeded; return these results. - for (auto *D : Paths.front().Decls) { + for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end(); + I != E; ++I) { AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, - D->getAccess()); - if (NamedDecl *ND = R.getAcceptableDecl(D)) + (*I)->getAccess()); + if (NamedDecl *ND = R.getAcceptableDecl(*I)) R.addDecl(ND, AS); } R.resolveKind(); @@ -2495,7 +2537,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) << LookupRange; - DeclContext::lookup_iterator Found = Paths->front().Decls.begin(); + DeclContext::lookup_iterator Found = Paths->front().Decls; while (isa<CXXMethodDecl>(*Found) && cast<CXXMethodDecl>(*Found)->isStatic()) ++Found; @@ -2513,7 +2555,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { for (CXXBasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end(); Path != PathEnd; ++Path) { - const NamedDecl *D = Path->Decls.front(); + const NamedDecl *D = *Path->Decls; if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace())) continue; if (DeclsPrinted.insert(D).second) { @@ -3117,7 +3159,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, ArgType.addVolatile(); // This isn't /really/ specified by the standard, but it's implied - // we should be working from an RValue in the case of move to ensure + // we should be working from a PRValue in the case of move to ensure // that we prefer to bind to rvalue references, and an LValue in the // case of copy to ensure we don't bind to rvalue references. // Possibly an XValue is actually correct in the case of move, but @@ -3126,7 +3168,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, if (SM == CXXCopyConstructor || SM == CXXCopyAssignment) VK = VK_LValue; else - VK = VK_RValue; + VK = VK_PRValue; } OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK); @@ -3143,8 +3185,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, if (VolatileThis) ThisTy.addVolatile(); Expr::Classification Classification = - OpaqueValueExpr(LookupLoc, ThisTy, - RValueThis ? VK_RValue : VK_LValue).Classify(Context); + OpaqueValueExpr(LookupLoc, ThisTy, RValueThis ? VK_PRValue : VK_LValue) + .Classify(Context); // Now we perform lookup on the name we computed earlier and do overload // resolution. Lookup is only performed directly into the class since there @@ -3690,7 +3732,7 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { // A shadow declaration that's created by a resolved using declaration // is not hidden by the same using declaration. if (isa<UsingShadowDecl>(ND) && isa<UsingDecl>(D) && - cast<UsingShadowDecl>(ND)->getUsingDecl() == D) + cast<UsingShadowDecl>(ND)->getIntroducer() == D) continue; // We've found a declaration that hides this one. @@ -3793,6 +3835,7 @@ private: if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) Result.getSema().ForceDeclarationOfImplicitMembers(Class); + llvm::SmallVector<NamedDecl *, 4> DeclsToVisit; // We sometimes skip loading namespace-level results (they tend to be huge). bool Load = LoadExternal || !(isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx)); @@ -3802,12 +3845,21 @@ private: : Ctx->noload_lookups(/*PreserveInternalState=*/false)) { for (auto *D : R) { if (auto *ND = Result.getAcceptableDecl(D)) { - Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); - Visited.add(ND); + // Rather than visit immediatelly, we put ND into a vector and visit + // all decls, in order, outside of this loop. The reason is that + // Consumer.FoundDecl() may invalidate the iterators used in the two + // loops above. + DeclsToVisit.push_back(ND); } } } + for (auto *ND : DeclsToVisit) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); + } + DeclsToVisit.clear(); + // Traverse using directives for qualified name lookup. if (QualifiedNameLookup) { ShadowContextRAII Shadow(Visited); |