summaryrefslogtreecommitdiff
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.cpp225
1 files changed, 57 insertions, 168 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 0ed51de0cc131..5757eaf3fac08 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -215,6 +215,7 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
case Sema::LookupOrdinaryName:
case Sema::LookupRedeclarationWithLinkage:
case Sema::LookupLocalFriendName:
+ case Sema::LookupDestructorName:
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus) {
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
@@ -378,11 +379,14 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
// type), per a generous reading of C++ [dcl.typedef]p3 and p4. The typedef
// might carry additional semantic information, such as an alignment override.
// However, per C++ [dcl.typedef]p5, when looking up a tag name, prefer a tag
- // declaration over a typedef.
+ // declaration over a typedef. Also prefer a tag over a typedef for
+ // destructor name lookup because in some contexts we only accept a
+ // class-name in a destructor declaration.
if (DUnderlying->getCanonicalDecl() != EUnderlying->getCanonicalDecl()) {
assert(isa<TypeDecl>(DUnderlying) && isa<TypeDecl>(EUnderlying));
bool HaveTag = isa<TagDecl>(EUnderlying);
- bool WantTag = Kind == Sema::LookupTagName;
+ bool WantTag =
+ Kind == Sema::LookupTagName || Kind == Sema::LookupDestructorName;
return HaveTag != WantTag;
}
@@ -1149,73 +1153,14 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) {
return false;
}
-// Find the next outer declaration context from this scope. This
-// routine actually returns the semantic outer context, which may
-// differ from the lexical context (encoded directly in the Scope
-// stack) when we are parsing a member of a class template. In this
-// case, the second element of the pair will be true, to indicate that
-// name lookup should continue searching in this semantic context when
-// it leaves the current template parameter scope.
-static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
- DeclContext *DC = S->getEntity();
- DeclContext *Lexical = nullptr;
- for (Scope *OuterS = S->getParent(); OuterS;
- OuterS = OuterS->getParent()) {
- if (OuterS->getEntity()) {
- Lexical = OuterS->getEntity();
- break;
- }
- }
-
- // C++ [temp.local]p8:
- // In the definition of a member of a class template that appears
- // outside of the namespace containing the class template
- // definition, the name of a template-parameter hides the name of
- // a member of this namespace.
- //
- // Example:
- //
- // namespace N {
- // class C { };
- //
- // template<class T> class B {
- // void f(T);
- // };
- // }
- //
- // template<class C> void N::B<C>::f(C) {
- // C b; // C is the template parameter, not N::C
- // }
- //
- // In this example, the lexical context we return is the
- // TranslationUnit, while the semantic context is the namespace N.
- if (!Lexical || !DC || !S->getParent() ||
- !S->getParent()->isTemplateParamScope())
- return std::make_pair(Lexical, false);
-
- // Find the outermost template parameter scope.
- // For the example, this is the scope for the template parameters of
- // template<class C>.
- Scope *OutermostTemplateScope = S->getParent();
- while (OutermostTemplateScope->getParent() &&
- OutermostTemplateScope->getParent()->isTemplateParamScope())
- OutermostTemplateScope = OutermostTemplateScope->getParent();
-
- // Find the namespace context in which the original scope occurs. In
- // the example, this is namespace N.
- DeclContext *Semantic = DC;
- while (!Semantic->isFileContext())
- Semantic = Semantic->getParent();
-
- // Find the declaration context just outside of the template
- // parameter scope. This is the context in which the template is
- // being lexically declaration (a namespace context). In the
- // example, this is the global scope.
- if (Lexical->isFileContext() && !Lexical->Equals(Semantic) &&
- Lexical->Encloses(Semantic))
- return std::make_pair(Semantic, true);
-
- return std::make_pair(Lexical, false);
+/// Find the outer declaration context from this scope. This indicates the
+/// context that we should search up to (exclusive) before considering the
+/// parent of the specified scope.
+static DeclContext *findOuterContext(Scope *S) {
+ for (Scope *OuterS = S->getParent(); OuterS; OuterS = OuterS->getParent())
+ if (DeclContext *DC = OuterS->getLookupEntity())
+ return DC;
+ return nullptr;
}
namespace {
@@ -1282,13 +1227,11 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
UnqualUsingDirectiveSet UDirs(*this);
bool VisitedUsingDirectives = false;
bool LeftStartingScope = false;
- DeclContext *OutsideOfTemplateParamDC = nullptr;
// When performing a scope lookup, we want to find local extern decls.
FindLocalExternScope FindLocals(R);
for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
- DeclContext *Ctx = S->getEntity();
bool SearchNamespaceScope = true;
// Check whether the IdResolver has anything in this scope.
for (; I != IEnd && S->isDeclScope(*I); ++I) {
@@ -1320,7 +1263,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
if (!SearchNamespaceScope) {
R.resolveKind();
if (S->isClassScope())
- if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx))
+ if (CXXRecordDecl *Record =
+ dyn_cast_or_null<CXXRecordDecl>(S->getEntity()))
R.setNamingClass(Record);
return true;
}
@@ -1334,24 +1278,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return false;
}
- if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
- S->getParent() && !S->getParent()->isTemplateParamScope()) {
- // We've just searched the last template parameter scope and
- // found nothing, so look into the contexts between the
- // lexical and semantic declaration contexts returned by
- // findOuterContext(). This implements the name lookup behavior
- // of C++ [temp.local]p8.
- Ctx = OutsideOfTemplateParamDC;
- OutsideOfTemplateParamDC = nullptr;
- }
-
- if (Ctx) {
- DeclContext *OuterCtx;
- bool SearchAfterTemplateScope;
- std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
- if (SearchAfterTemplateScope)
- OutsideOfTemplateParamDC = OuterCtx;
-
+ if (DeclContext *Ctx = S->getLookupEntity()) {
+ DeclContext *OuterCtx = findOuterContext(S);
for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
// We do not directly look into transparent contexts, since
// those entities will be found in the nearest enclosing
@@ -1476,25 +1404,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return true;
}
- DeclContext *Ctx = S->getEntity();
- if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
- S->getParent() && !S->getParent()->isTemplateParamScope()) {
- // We've just searched the last template parameter scope and
- // found nothing, so look into the contexts between the
- // lexical and semantic declaration contexts returned by
- // findOuterContext(). This implements the name lookup behavior
- // of C++ [temp.local]p8.
- Ctx = OutsideOfTemplateParamDC;
- OutsideOfTemplateParamDC = nullptr;
- }
-
+ DeclContext *Ctx = S->getLookupEntity();
if (Ctx) {
- DeclContext *OuterCtx;
- bool SearchAfterTemplateScope;
- std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
- if (SearchAfterTemplateScope)
- OutsideOfTemplateParamDC = OuterCtx;
-
+ DeclContext *OuterCtx = findOuterContext(S);
for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
// We do not directly look into transparent contexts, since
// those entities will be found in the nearest enclosing
@@ -1575,7 +1487,9 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() {
unsigned N = CodeSynthesisContexts.size();
for (unsigned I = CodeSynthesisContextLookupModules.size();
I != N; ++I) {
- Module *M = getDefiningModule(*this, CodeSynthesisContexts[I].Entity);
+ Module *M = CodeSynthesisContexts[I].Entity ?
+ getDefiningModule(*this, CodeSynthesisContexts[I].Entity) :
+ nullptr;
if (M && !LookupModulesCache.insert(M).second)
M = nullptr;
CodeSynthesisContextLookupModules.push_back(M);
@@ -1704,7 +1618,8 @@ bool Sema::hasVisibleMemberSpecialization(
/// path (by instantiating a template, you allow it to see the declarations that
/// your module can see, including those later on in your module).
bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
- assert(D->isHidden() && "should not call this: not in slow case");
+ assert(!D->isUnconditionallyVisible() &&
+ "should not call this: not in slow case");
Module *DeclModule = SemaRef.getOwningModule(D);
assert(DeclModule && "hidden decl has no owning module");
@@ -2295,6 +2210,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
case LookupMemberName:
case LookupRedeclarationWithLinkage:
case LookupLocalFriendName:
+ case LookupDestructorName:
BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
break;
@@ -2959,7 +2875,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// These are fundamental types.
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
case Type::Complex:
+ case Type::ExtInt:
break;
// Non-deduced auto types only get here for error cases.
@@ -3985,14 +3903,12 @@ private:
}
}
- // FIXME: C++ [temp.local]p8
- DeclContext *Entity = nullptr;
- if (S->getEntity()) {
+ DeclContext *Entity = S->getLookupEntity();
+ if (Entity) {
// Look into this scope's declaration context, along with any of its
// parent lookup contexts (e.g., enclosing classes), up to the point
// where we hit the context stored in the next outer scope.
- Entity = S->getEntity();
- DeclContext *OuterCtx = findOuterContext(S).first; // FIXME
+ DeclContext *OuterCtx = findOuterContext(S);
for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx);
Ctx = Ctx->getLookupParent()) {
@@ -5158,9 +5074,9 @@ TypoExpr *Sema::CorrectTypoDelayed(
IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
if (!ExternalTypo && ED > 0 && Typo->getName().size() / ED < 3)
return nullptr;
-
ExprEvalContexts.back().NumTypos++;
- return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC));
+ return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC),
+ TypoName.getLoc());
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
@@ -5342,9 +5258,8 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
/// Get a "quoted.h" or <angled.h> include path to use in a diagnostic
/// suggesting the addition of a #include of the specified file.
-static std::string getIncludeStringForHeader(Preprocessor &PP,
- const FileEntry *E,
- llvm::StringRef IncludingFile) {
+static std::string getHeaderNameForHeader(Preprocessor &PP, const FileEntry *E,
+ llvm::StringRef IncludingFile) {
bool IsSystem = false;
auto Path = PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(
E, IncludingFile, &IsSystem);
@@ -5358,25 +5273,10 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
assert(!Modules.empty());
auto NotePrevious = [&] {
- unsigned DiagID;
- switch (MIK) {
- case MissingImportKind::Declaration:
- DiagID = diag::note_previous_declaration;
- break;
- case MissingImportKind::Definition:
- DiagID = diag::note_previous_definition;
- break;
- case MissingImportKind::DefaultArgument:
- DiagID = diag::note_default_argument_declared_here;
- break;
- case MissingImportKind::ExplicitSpecialization:
- DiagID = diag::note_explicit_specialization_declared_here;
- break;
- case MissingImportKind::PartialSpecialization:
- DiagID = diag::note_partial_specialization_declared_here;
- break;
- }
- Diag(DeclLoc, DiagID);
+ // FIXME: Suppress the note backtrace even under
+ // -fdiagnostics-show-note-include-stack. We don't care how this
+ // declaration was previously reached.
+ Diag(DeclLoc, diag::note_unreachable_entity) << (int)MIK;
};
// Weed out duplicates from module list.
@@ -5389,26 +5289,24 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
UniqueModules.push_back(M);
}
- llvm::StringRef IncludingFile;
- if (const FileEntry *FE =
- SourceMgr.getFileEntryForID(SourceMgr.getFileID(UseLoc)))
- IncludingFile = FE->tryGetRealPathName();
+ // Try to find a suitable header-name to #include.
+ std::string HeaderName;
+ if (const FileEntry *Header =
+ PP.getHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) {
+ if (const FileEntry *FE =
+ SourceMgr.getFileEntryForID(SourceMgr.getFileID(UseLoc)))
+ HeaderName = getHeaderNameForHeader(PP, Header, FE->tryGetRealPathName());
+ }
- if (UniqueModules.empty()) {
- // All candidates were global module fragments. Try to suggest a #include.
- const FileEntry *E =
- PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, Modules[0], DeclLoc);
+ // If we have a #include we should suggest, or if all definition locations
+ // were in global module fragments, don't suggest an import.
+ if (!HeaderName.empty() || UniqueModules.empty()) {
// FIXME: Find a smart place to suggest inserting a #include, and add
// a FixItHint there.
- Diag(UseLoc, diag::err_module_unimported_use_global_module_fragment)
- << (int)MIK << Decl << !!E
- << (E ? getIncludeStringForHeader(PP, E, IncludingFile) : "");
- // Produce a "previous" note if it will point to a header rather than some
- // random global module fragment.
- // FIXME: Suppress the note backtrace even under
- // -fdiagnostics-show-note-include-stack.
- if (E)
- NotePrevious();
+ Diag(UseLoc, diag::err_module_unimported_use_header)
+ << (int)MIK << Decl << !HeaderName.empty() << HeaderName;
+ // Produce a note showing where the entity was declared.
+ NotePrevious();
if (Recover)
createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]);
return;
@@ -5430,16 +5328,6 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
Diag(UseLoc, diag::err_module_unimported_use_multiple)
<< (int)MIK << Decl << ModuleList;
- } else if (const FileEntry *E = PP.getModuleHeaderToIncludeForDiagnostics(
- UseLoc, Modules[0], DeclLoc)) {
- // The right way to make the declaration visible is to include a header;
- // suggest doing so.
- //
- // FIXME: Find a smart place to suggest inserting a #include, and add
- // a FixItHint there.
- Diag(UseLoc, diag::err_module_unimported_use_header)
- << (int)MIK << Decl << Modules[0]->getFullModuleName()
- << getIncludeStringForHeader(PP, E, IncludingFile);
} else {
// FIXME: Add a FixItHint that imports the corresponding module.
Diag(UseLoc, diag::err_module_unimported_use)
@@ -5500,9 +5388,10 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG,
- TypoRecoveryCallback TRC) {
+ TypoRecoveryCallback TRC,
+ SourceLocation TypoLoc) {
assert(TCC && "createDelayedTypo requires a valid TypoCorrectionConsumer");
- auto TE = new (Context) TypoExpr(Context.DependentTy);
+ auto TE = new (Context) TypoExpr(Context.DependentTy, TypoLoc);
auto &State = DelayedTypos[TE];
State.Consumer = std::move(TCC);
State.DiagHandler = std::move(TDG);