aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaLookup.cpp')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp194
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);