summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r--lib/Sema/SemaLookup.cpp268
1 files changed, 169 insertions, 99 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index effccc2f3d..2b7924d244 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1,9 +1,8 @@
//===--------------------- SemaLookup.cpp - Name Lookup ------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -279,6 +278,10 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
IDNS = Decl::IDNS_OMPReduction;
break;
+ case Sema::LookupOMPMapperName:
+ IDNS = Decl::IDNS_OMPMapper;
+ break;
+
case Sema::LookupAnyName:
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member
| Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol
@@ -1540,8 +1543,21 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
// and in C we must not because each declaration of a function gets its own
// set of declarations for tags in prototype scope.
bool VisibleWithinParent;
- if (D->isTemplateParameter() || isa<ParmVarDecl>(D) ||
- (isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus))
+ if (D->isTemplateParameter()) {
+ bool SearchDefinitions = true;
+ if (const auto *DCD = dyn_cast<Decl>(DC)) {
+ if (const auto *TD = DCD->getDescribedTemplate()) {
+ TemplateParameterList *TPL = TD->getTemplateParameters();
+ auto Index = getDepthAndIndex(D).second;
+ SearchDefinitions = Index >= TPL->size() || TPL->getParam(Index) != D;
+ }
+ }
+ if (SearchDefinitions)
+ VisibleWithinParent = SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC));
+ else
+ VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC));
+ } else if (isa<ParmVarDecl>(D) ||
+ (isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus))
VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC));
else if (D->isModulePrivate()) {
// A module-private declaration is only visible if an enclosing lexical
@@ -2104,6 +2120,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
BaseCallback = &CXXRecordDecl::FindOMPReductionMember;
break;
+ case LookupOMPMapperName:
+ BaseCallback = &CXXRecordDecl::FindOMPMapperMember;
+ break;
+
case LookupUsingDeclName:
// This lookup is for redeclarations only.
@@ -2165,11 +2185,27 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin();
DeclContext::lookup_iterator CurrentD = Path->Decls.begin();
+ // Get the decl that we should use for deduplicating this lookup.
+ auto GetRepresentativeDecl = [&](NamedDecl *D) -> Decl * {
+ // C++ [temp.local]p3:
+ // A lookup that finds an injected-class-name (10.2) can result in
+ // an ambiguity in certain cases (for example, if it is found in
+ // more than one base class). If all of the injected-class-names
+ // that are found refer to specializations of the same class
+ // template, and if the name is used as a template-name, the
+ // reference refers to the class template itself and not a
+ // specialization thereof, and is not ambiguous.
+ if (R.isTemplateNameLookup())
+ if (auto *TD = getAsTemplateNameDecl(D))
+ D = TD;
+ return D->getUnderlyingDecl()->getCanonicalDecl();
+ };
+
while (FirstD != FirstPath->Decls.end() &&
CurrentD != Path->Decls.end()) {
- if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() !=
- (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl())
- break;
+ if (GetRepresentativeDecl(*FirstD) !=
+ GetRepresentativeDecl(*CurrentD))
+ break;
++FirstD;
++CurrentD;
@@ -2417,40 +2453,56 @@ namespace {
InstantiationLoc(InstantiationLoc) {
}
+ bool addClassTransitive(CXXRecordDecl *RD) {
+ Classes.insert(RD);
+ return ClassesTransitive.insert(RD);
+ }
+
Sema &S;
Sema::AssociatedNamespaceSet &Namespaces;
Sema::AssociatedClassSet &Classes;
SourceLocation InstantiationLoc;
+
+ private:
+ Sema::AssociatedClassSet ClassesTransitive;
};
} // end anonymous namespace
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
+// Given the declaration context \param Ctx of a class, class template or
+// enumeration, add the associated namespaces to \param Namespaces as described
+// in [basic.lookup.argdep]p2.
static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
DeclContext *Ctx) {
- // Add the associated namespace for this class.
-
- // We don't use DeclContext::getEnclosingNamespaceContext() as this may
- // be a locally scoped record.
+ // The exact wording has been changed in C++14 as a result of
+ // CWG 1691 (see also CWG 1690 and CWG 1692). We apply it unconditionally
+ // to all language versions since it is possible to return a local type
+ // from a lambda in C++11.
+ //
+ // C++14 [basic.lookup.argdep]p2:
+ // If T is a class type [...]. Its associated namespaces are the innermost
+ // enclosing namespaces of its associated classes. [...]
+ //
+ // If T is an enumeration type, its associated namespace is the innermost
+ // enclosing namespace of its declaration. [...]
- // We skip out of inline namespaces. The innermost non-inline namespace
+ // We additionally skip inline namespaces. The innermost non-inline namespace
// contains all names of all its nested inline namespaces anyway, so we can
// replace the entire inline namespace tree with its root.
- while (Ctx->isRecord() || Ctx->isTransparentContext() ||
- Ctx->isInlineNamespace())
+ while (!Ctx->isFileContext() || Ctx->isInlineNamespace())
Ctx = Ctx->getParent();
- if (Ctx->isFileContext())
- Namespaces.insert(Ctx->getPrimaryContext());
+ Namespaces.insert(Ctx->getPrimaryContext());
}
// Add the associated classes and namespaces for argument-dependent
-// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
+// lookup that involves a template argument (C++ [basic.lookup.argdep]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
const TemplateArgument &Arg) {
- // C++ [basic.lookup.koenig]p2, last bullet:
+ // C++ [basic.lookup.argdep]p2, last bullet:
// -- [...] ;
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -2495,9 +2547,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
}
-// Add the associated classes and namespaces for
-// argument-dependent lookup with an argument of class type
-// (C++ [basic.lookup.koenig]p2).
+// Add the associated classes and namespaces for argument-dependent lookup
+// with an argument of class type (C++ [basic.lookup.argdep]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
CXXRecordDecl *Class) {
@@ -2506,30 +2557,22 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
if (Class->getDeclName() == Result.S.VAListTagName)
return;
- // C++ [basic.lookup.koenig]p2:
+ // C++ [basic.lookup.argdep]p2:
// [...]
// -- If T is a class type (including unions), its associated
// classes are: the class itself; the class of which it is a
- // member, if any; and its direct and indirect base
- // classes. Its associated namespaces are the namespaces in
- // which its associated classes are defined.
+ // member, if any; and its direct and indirect base classes.
+ // Its associated namespaces are the innermost enclosing
+ // namespaces of its associated classes.
// Add the class of which it is a member, if any.
DeclContext *Ctx = Class->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
Result.Classes.insert(EnclosingClass);
+
// Add the associated namespace for this class.
CollectEnclosingNamespace(Result.Namespaces, Ctx);
- // Add the class itself. If we've already seen this class, we don't
- // need to visit base classes.
- //
- // FIXME: That's not correct, we may have added this class only because it
- // was the enclosing class of another class, and in that case we won't have
- // added its base classes yet.
- if (!Result.Classes.insert(Class))
- return;
-
// -- If T is a template-id, its associated namespaces and classes are
// the namespace in which the template is defined; for member
// templates, the member template's class; the namespaces and classes
@@ -2552,6 +2595,11 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]);
}
+ // Add the class itself. If we've already transitively visited this class,
+ // we don't need to visit base classes.
+ if (!Result.addClassTransitive(Class))
+ return;
+
// Only recurse into base classes for complete types.
if (!Result.S.isCompleteType(Result.InstantiationLoc,
Result.S.Context.getRecordType(Class)))
@@ -2577,7 +2625,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
if (!BaseType)
continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (Result.Classes.insert(BaseDecl)) {
+ if (Result.addClassTransitive(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
@@ -2642,10 +2690,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
break;
// -- If T is a class type (including unions), its associated
- // classes are: the class itself; the class of which it is a
- // member, if any; and its direct and indirect base
- // classes. Its associated namespaces are the namespaces in
- // which its associated classes are defined.
+ // classes are: the class itself; the class of which it is
+ // a member, if any; and its direct and indirect base classes.
+ // Its associated namespaces are the innermost enclosing
+ // namespaces of its associated classes.
case Type::Record: {
CXXRecordDecl *Class =
cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
@@ -2653,10 +2701,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
break;
}
- // -- If T is an enumeration type, its associated namespace is
- // the namespace in which it is defined. If it is class
- // member, its associated class is the member's class; else
- // it has no associated class.
+ // -- If T is an enumeration type, its associated namespace
+ // is the innermost enclosing namespace of its declaration.
+ // If it is a class member, its associated class is the
+ // member’s class; else it has no associated class.
case Type::Enum: {
EnumDecl *Enum = cast<EnumType>(T)->getDecl();
@@ -2664,7 +2712,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
Result.Classes.insert(EnclosingClass);
- // Add the associated namespace for this class.
+ // Add the associated namespace for this enumeration.
CollectEnclosingNamespace(Result.Namespaces, Ctx);
break;
@@ -2793,15 +2841,9 @@ void Sema::FindAssociatedClassesAndNamespaces(
// in which the function or function template is defined and the
// classes and namespaces associated with its (non-dependent)
// parameter types and return type.
- Arg = Arg->IgnoreParens();
- if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
- if (unaryOp->getOpcode() == UO_AddrOf)
- Arg = unaryOp->getSubExpr();
+ OverloadExpr *OE = OverloadExpr::find(Arg).Expression;
- UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg);
- if (!ULE) continue;
-
- for (const auto *D : ULE->decls()) {
+ for (const NamedDecl *D : OE->decls()) {
// Look through any using declarations to find the underlying function.
const FunctionDecl *FDecl = D->getUnderlyingDecl()->getAsFunction();
@@ -4317,9 +4359,8 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
SpecifierOStream.flush();
SameNameSpecifier = NewNameSpecifier == CurNameSpecifier;
}
- if (SameNameSpecifier ||
- std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(),
- Name) != CurContextIdentifiers.end()) {
+ if (SameNameSpecifier || llvm::find(CurContextIdentifiers, Name) !=
+ CurContextIdentifiers.end()) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
NNS = NestedNameSpecifier::GlobalSpecifier(Context);
NumSpecifiers =
@@ -4551,8 +4592,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
- Scope *S, CXXScopeSpec *SS,
- std::unique_ptr<CorrectionCandidateCallback> CCC,
+ Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT, bool ErrorRecovery) {
@@ -4614,9 +4654,13 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
TypoName.getBeginLoc());
}
- CorrectionCandidateCallback &CCCRef = *CCC;
+ // Extend the lifetime of the callback. We delayed this until here
+ // to avoid allocations in the hot path (which is where no typo correction
+ // occurs). Note that CorrectionCandidateCallback is polymorphic and
+ // initially stack-allocated.
+ std::unique_ptr<CorrectionCandidateCallback> ClonedCCC = CCC.clone();
auto Consumer = llvm::make_unique<TypoCorrectionConsumer>(
- *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
+ *this, TypoName, LookupKind, S, SS, std::move(ClonedCCC), MemberContext,
EnteringContext);
// Perform name lookup to find visible, similarly-named entities.
@@ -4668,7 +4712,9 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
}
}
- AddKeywordsToConsumer(*this, *Consumer, S, CCCRef, SS && SS->isNotEmpty());
+ AddKeywordsToConsumer(*this, *Consumer, S,
+ *Consumer->getCorrectionValidator(),
+ SS && SS->isNotEmpty());
// Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
// to search those namespaces.
@@ -4722,19 +4768,18 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
- std::unique_ptr<CorrectionCandidateCallback> CCC,
+ CorrectionCandidateCallback &CCC,
CorrectTypoKind Mode,
DeclContext *MemberContext,
bool EnteringContext,
const ObjCObjectPointerType *OPT,
bool RecordFailure) {
- assert(CCC && "CorrectTypo requires a CorrectionCandidateCallback");
-
// Always let the ExternalSource have the first chance at correction, even
// if we would otherwise have given up.
if (ExternalSource) {
- if (TypoCorrection Correction = ExternalSource->CorrectTypo(
- TypoName, LookupKind, S, SS, *CCC, MemberContext, EnteringContext, OPT))
+ if (TypoCorrection Correction =
+ ExternalSource->CorrectTypo(TypoName, LookupKind, S, SS, CCC,
+ MemberContext, EnteringContext, OPT))
return Correction;
}
@@ -4742,12 +4787,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
// some instances of CTC_Unknown, while WantRemainingKeywords is true
// for CTC_Unknown but not for CTC_ObjCMessageReceiver.
- bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords;
+ bool ObjCMessageReceiver = CCC.WantObjCSuper && !CCC.WantRemainingKeywords;
IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
- auto Consumer = makeTypoCorrectionConsumer(
- TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
- EnteringContext, OPT, Mode == CTK_ErrorRecovery);
+ auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC,
+ MemberContext, EnteringContext,
+ OPT, Mode == CTK_ErrorRecovery);
if (!Consumer)
return TypoCorrection();
@@ -4857,16 +4902,13 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
/// needed.
TypoExpr *Sema::CorrectTypoDelayed(
const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
- Scope *S, CXXScopeSpec *SS,
- std::unique_ptr<CorrectionCandidateCallback> CCC,
+ Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT) {
- assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
-
- auto Consumer = makeTypoCorrectionConsumer(
- TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
- EnteringContext, OPT, Mode == CTK_ErrorRecovery);
+ auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC,
+ MemberContext, EnteringContext,
+ OPT, Mode == CTK_ErrorRecovery);
// Give the external sema source a chance to correct the typo.
TypoCorrection ExternalTypo;
@@ -5052,7 +5094,7 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
auto Merged = Context.getModulesWithMergedDefinition(Def);
OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end());
- diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK,
+ diagnoseMissingImport(Loc, Def, Def->getLocation(), OwningModules, MIK,
Recover);
}
@@ -5072,12 +5114,58 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
MissingImportKind MIK, bool Recover) {
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);
+ };
+
// Weed out duplicates from module list.
llvm::SmallVector<Module*, 8> UniqueModules;
llvm::SmallDenseSet<Module*, 8> UniqueModuleSet;
- for (auto *M : Modules)
+ for (auto *M : Modules) {
+ if (M->Kind == Module::GlobalModuleFragment)
+ continue;
if (UniqueModuleSet.insert(M).second)
UniqueModules.push_back(M);
+ }
+
+ if (UniqueModules.empty()) {
+ // All candidates were global module fragments. Try to suggest a #include.
+ const FileEntry *E =
+ PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, Modules[0], DeclLoc);
+ // 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) : "");
+ // 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();
+ if (Recover)
+ createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]);
+ return;
+ }
+
Modules = UniqueModules;
if (Modules.size() > 1) {
@@ -5110,25 +5198,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
<< (int)MIK << Decl << Modules[0]->getFullModuleName();
}
- 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);
+ NotePrevious();
// Try to recover by implicitly importing this module.
if (Recover)