summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp299
1 files changed, 203 insertions, 96 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 45dc2e33da9..e2550824fb6 100644
--- a/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -29,7 +29,6 @@
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
@@ -280,6 +279,10 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
IDNS = Decl::IDNS_ObjCProtocol;
break;
+ case Sema::LookupOMPReductionName:
+ IDNS = Decl::IDNS_OMPReduction;
+ break;
+
case Sema::LookupAnyName:
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member
| Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol
@@ -419,6 +422,18 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
}
}
+ // VarDecl can have incomplete array types, prefer the one with more complete
+ // array type.
+ if (VarDecl *DVD = dyn_cast<VarDecl>(DUnderlying)) {
+ VarDecl *EVD = cast<VarDecl>(EUnderlying);
+ if (EVD->getType()->isIncompleteType() &&
+ !DVD->getType()->isIncompleteType()) {
+ // Prefer the decl with a more complete type if visible.
+ return S.isVisible(DVD);
+ }
+ return false; // Avoid picking up a newer decl, just because it was newer.
+ }
+
// For most kinds of declaration, it doesn't really matter which one we pick.
if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) {
// If the existing declaration is hidden, prefer the new one. Otherwise,
@@ -432,10 +447,6 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
if (Prev == EUnderlying)
return true;
return false;
-
- // If the existing declaration is hidden, prefer the new one. Otherwise,
- // keep what we've got.
- return !S.isVisible(Existing);
}
/// Determine whether \p D can hide a tag declaration.
@@ -669,24 +680,21 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
NameKind == Sema::LookupRedeclarationWithLinkage) {
IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
if (II) {
- if (S.getLangOpts().CPlusPlus11 && S.getLangOpts().GNUMode &&
- II == S.getFloat128Identifier()) {
- // libstdc++4.7's type_traits expects type __float128 to exist, so
- // insert a dummy type to make that header build in gnu++11 mode.
- R.addDecl(S.getASTContext().getFloat128StubType());
- return true;
- }
- if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName &&
- II == S.getASTContext().getMakeIntegerSeqName()) {
- R.addDecl(S.getASTContext().getMakeIntegerSeqDecl());
- return true;
+ if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName) {
+ if (II == S.getASTContext().getMakeIntegerSeqName()) {
+ R.addDecl(S.getASTContext().getMakeIntegerSeqDecl());
+ return true;
+ } else if (II == S.getASTContext().getTypePackElementName()) {
+ R.addDecl(S.getASTContext().getTypePackElementDecl());
+ return true;
+ }
}
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
- // In C++, we don't have any predefined library functions like
- // 'malloc'. Instead, we'll just error.
- if (S.getLangOpts().CPlusPlus &&
+ // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined
+ // library functions like 'malloc'. Instead, we'll just error.
+ if ((S.getLangOpts().CPlusPlus || S.getLangOpts().OpenCL) &&
S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return false;
@@ -734,11 +742,11 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
if (getLangOpts().CPlusPlus11) {
// If the move constructor has not yet been declared, do so now.
if (Class->needsImplicitMoveConstructor())
- DeclareImplicitMoveConstructor(Class); // might not actually do it
+ DeclareImplicitMoveConstructor(Class);
// If the move assignment operator has not yet been declared, do so now.
if (Class->needsImplicitMoveAssignment())
- DeclareImplicitMoveAssignment(Class); // might not actually do it
+ DeclareImplicitMoveAssignment(Class);
}
// If the destructor has not yet been declared, do so now.
@@ -1074,32 +1082,35 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
DeclContext *Ctx = S->getEntity();
-
+ bool SearchNamespaceScope = true;
// Check whether the IdResolver has anything in this scope.
- bool Found = false;
for (; I != IEnd && S->isDeclScope(*I); ++I) {
if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
- if (NameKind == LookupRedeclarationWithLinkage) {
+ if (NameKind == LookupRedeclarationWithLinkage &&
+ !(*I)->isTemplateParameter()) {
+ // If it's a template parameter, we still find it, so we can diagnose
+ // the invalid redeclaration.
+
// Determine whether this (or a previous) declaration is
// out-of-scope.
if (!LeftStartingScope && !Initial->isDeclScope(*I))
LeftStartingScope = true;
// If we found something outside of our starting scope that
- // does not have linkage, skip it. If it's a template parameter,
- // we still find it, so we can diagnose the invalid redeclaration.
- if (LeftStartingScope && !((*I)->hasLinkage()) &&
- !(*I)->isTemplateParameter()) {
+ // does not have linkage, skip it.
+ if (LeftStartingScope && !((*I)->hasLinkage())) {
R.setShadowed();
continue;
}
+ } else {
+ // We found something in this scope, we should not look at the
+ // namespace scope
+ SearchNamespaceScope = false;
}
-
- Found = true;
R.addDecl(ND);
}
}
- if (Found) {
+ if (!SearchNamespaceScope) {
R.resolveKind();
if (S->isClassScope())
if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx))
@@ -1470,6 +1481,35 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D,
Modules);
}
+bool Sema::hasVisibleMemberSpecialization(
+ const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
+ assert(isa<CXXRecordDecl>(D->getDeclContext()) &&
+ "not a member specialization");
+ for (auto *Redecl : D->redecls()) {
+ // If the specialization is declared at namespace scope, then it's a member
+ // specialization declaration. If it's lexically inside the class
+ // definition then it was instantiated.
+ //
+ // FIXME: This is a hack. There should be a better way to determine this.
+ // FIXME: What about MS-style explicit specializations declared within a
+ // class definition?
+ if (Redecl->getLexicalDeclContext()->isFileContext()) {
+ auto *NonConstR = const_cast<NamedDecl*>(cast<NamedDecl>(Redecl));
+
+ if (isVisible(NonConstR))
+ return true;
+
+ if (Modules) {
+ Modules->push_back(getOwningModule(NonConstR));
+ const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR);
+ Modules->insert(Modules->end(), Merged.begin(), Merged.end());
+ }
+ }
+ }
+
+ return false;
+}
+
/// \brief Determine whether a declaration is visible to name lookup.
///
/// This routine determines whether the declaration D is visible in the current
@@ -1570,19 +1610,58 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
for (auto RD : D->redecls()) {
- if (auto ND = dyn_cast<NamedDecl>(RD)) {
- // FIXME: This is wrong in the case where the previous declaration is not
- // visible in the same scope as D. This needs to be done much more
- // carefully.
- if (LookupResult::isVisible(SemaRef, ND))
- return ND;
- }
+ // Don't bother with extra checks if we already know this one isn't visible.
+ if (RD == D)
+ continue;
+
+ auto ND = cast<NamedDecl>(RD);
+ // FIXME: This is wrong in the case where the previous declaration is not
+ // visible in the same scope as D. This needs to be done much more
+ // carefully.
+ if (LookupResult::isVisible(SemaRef, ND))
+ return ND;
}
return nullptr;
}
+bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules) {
+ assert(!isVisible(D) && "not in slow case");
+
+ for (auto *Redecl : D->redecls()) {
+ auto *NonConstR = const_cast<NamedDecl*>(cast<NamedDecl>(Redecl));
+ if (isVisible(NonConstR))
+ return true;
+
+ if (Modules) {
+ Modules->push_back(getOwningModule(NonConstR));
+ const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR);
+ Modules->insert(Modules->end(), Merged.begin(), Merged.end());
+ }
+ }
+
+ return false;
+}
+
NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
+ if (auto *ND = dyn_cast<NamespaceDecl>(D)) {
+ // Namespaces are a bit of a special case: we expect there to be a lot of
+ // redeclarations of some namespaces, all declarations of a namespace are
+ // essentially interchangeable, all declarations are found by name lookup
+ // if any is, and namespaces are never looked up during template
+ // instantiation. So we benefit from caching the check in this case, and
+ // it is correct to do so.
+ auto *Key = ND->getCanonicalDecl();
+ if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key))
+ return Acceptable;
+ auto *Acceptable =
+ isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key);
+ if (Acceptable)
+ getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable));
+ return Acceptable;
+ }
+
return findAcceptableDecl(getSema(), D);
}
@@ -1986,6 +2065,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
BaseCallback = &LookupAnyMember;
break;
+ case LookupOMPReductionName:
+ BaseCallback = &CXXRecordDecl::FindOMPReductionMember;
+ break;
+
case LookupUsingDeclName:
// This lookup is for redeclarations only.
@@ -2409,7 +2492,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// 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).second)
+ if (!Result.Classes.insert(Class))
return;
// -- If T is a template-id, its associated namespaces and classes are
@@ -2459,7 +2542,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
if (!BaseType)
continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (Result.Classes.insert(BaseDecl).second) {
+ if (Result.Classes.insert(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
@@ -2864,42 +2947,38 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// from an external source and invalidate lookup_result.
SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());
- for (auto *Cand : Candidates) {
- if (Cand->isInvalidDecl())
+ for (NamedDecl *CandDecl : Candidates) {
+ if (CandDecl->isInvalidDecl())
continue;
- if (UsingShadowDecl *U = dyn_cast<UsingShadowDecl>(Cand)) {
- // FIXME: [namespace.udecl]p15 says that we should only consider a
- // using declaration here if it does not match a declaration in the
- // derived class. We do not implement this correctly in other cases
- // either.
- Cand = U->getTargetDecl();
-
- if (Cand->isInvalidDecl())
- continue;
- }
-
- if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand)) {
+ DeclAccessPair Cand = DeclAccessPair::make(CandDecl, AS_public);
+ auto CtorInfo = getConstructorInfo(Cand);
+ if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
- AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD, ThisTy,
- Classification, llvm::makeArrayRef(&Arg, NumArgs),
- OCS, true);
- else
- AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public),
+ AddMethodCandidate(M, Cand, RD, ThisTy, Classification,
+ llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
+ else if (CtorInfo)
+ AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,
llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
+ else
+ AddOverloadCandidate(M, Cand, llvm::makeArrayRef(&Arg, NumArgs), OCS,
+ true);
} else if (FunctionTemplateDecl *Tmpl =
- dyn_cast<FunctionTemplateDecl>(Cand)) {
+ dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
- AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- RD, nullptr, ThisTy, Classification,
- llvm::makeArrayRef(&Arg, NumArgs),
- OCS, true);
+ AddMethodTemplateCandidate(
+ Tmpl, Cand, RD, nullptr, ThisTy, Classification,
+ llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
+ else if (CtorInfo)
+ AddTemplateOverloadCandidate(
+ CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,
+ llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
else
- AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- nullptr, llvm::makeArrayRef(&Arg, NumArgs),
- OCS, true);
+ AddTemplateOverloadCandidate(
+ Tmpl, Cand, nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
} else {
- assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl");
+ assert(isa<UsingDecl>(Cand.getDecl()) &&
+ "illegal Kind of operator = Decl");
}
}
@@ -3119,7 +3198,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (FoundRaw && FoundTemplate) {
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction());
+ NoteOverloadCandidate(*I, (*I)->getUnderlyingDecl()->getAsFunction());
return LOLR_Error;
}
@@ -3984,8 +4063,8 @@ retry_lookup:
void TypoCorrectionConsumer::performQualifiedLookups() {
unsigned TypoLen = Typo->getName().size();
- for (auto QR : QualifiedResults) {
- for (auto NSI : Namespaces) {
+ for (const TypoCorrection &QR : QualifiedResults) {
+ for (const auto &NSI : Namespaces) {
DeclContext *Ctx = NSI.DeclCtx;
const Type *NSType = NSI.NameSpecifier->getAsType();
@@ -4073,10 +4152,8 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
// Build the list of identifiers that would be used for an absolute
// (from the global context) NestedNameSpecifier referring to the current
// context.
- for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
- CEnd = CurContextChain.rend();
- C != CEnd; ++C) {
- if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C))
+ for (DeclContext *C : llvm::reverse(CurContextChain)) {
+ if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C))
CurContextIdentifiers.push_back(ND->getIdentifier());
}
@@ -4104,13 +4181,11 @@ unsigned
TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
DeclContextList &DeclChain, NestedNameSpecifier *&NNS) {
unsigned NumSpecifiers = 0;
- for (DeclContextList::reverse_iterator C = DeclChain.rbegin(),
- CEnd = DeclChain.rend();
- C != CEnd; ++C) {
- if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) {
+ for (DeclContext *C : llvm::reverse(DeclChain)) {
+ if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C)) {
NNS = NestedNameSpecifier::Create(Context, NNS, ND);
++NumSpecifiers;
- } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) {
+ } else if (auto *RD = dyn_cast_or_null<RecordDecl>(C)) {
NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(),
RD->getTypeForDecl());
++NumSpecifiers;
@@ -4127,10 +4202,9 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
// Eliminate common elements from the two DeclContext chains.
- for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
- CEnd = CurContextChain.rend();
- C != CEnd && !NamespaceDeclChain.empty() &&
- NamespaceDeclChain.back() == *C; ++C) {
+ for (DeclContext *C : llvm::reverse(CurContextChain)) {
+ if (NamespaceDeclChain.empty() || NamespaceDeclChain.back() != C)
+ break;
NamespaceDeclChain.pop_back();
}
@@ -4207,7 +4281,8 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
}
}
- if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) {
+ if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(
+ Name, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Res.addDecl(Prop);
Res.resolveKind();
return;
@@ -4704,11 +4779,20 @@ TypoExpr *Sema::CorrectTypoDelayed(
const ObjCObjectPointerType *OPT) {
assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
- TypoCorrection Empty;
auto Consumer = makeTypoCorrectionConsumer(
TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
EnteringContext, OPT, Mode == CTK_ErrorRecovery);
+ // Give the external sema source a chance to correct the typo.
+ TypoCorrection ExternalTypo;
+ if (ExternalSource && Consumer) {
+ ExternalTypo = ExternalSource->CorrectTypo(
+ TypoName, LookupKind, S, SS, *Consumer->getCorrectionValidator(),
+ MemberContext, EnteringContext, OPT);
+ if (ExternalTypo)
+ Consumer->addCorrection(ExternalTypo);
+ }
+
if (!Consumer || Consumer->empty())
return nullptr;
@@ -4716,7 +4800,7 @@ TypoExpr *Sema::CorrectTypoDelayed(
// is not more that about a third of the length of the typo's identifier.
unsigned ED = Consumer->getBestEditDistance(true);
IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
- if (ED > 0 && Typo->getName().size() / ED < 3)
+ if (!ExternalTypo && ED > 0 && Typo->getName().size() / ED < 3)
return nullptr;
ExprEvalContexts.back().NumTypos++;
@@ -4852,8 +4936,8 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
static NamedDecl *getDefinitionToImport(NamedDecl *D) {
if (VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->getDefinition();
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->isDefined(FD) ? const_cast<FunctionDecl*>(FD) : nullptr;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->getDefinition();
if (TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
@@ -4866,7 +4950,7 @@ static NamedDecl *getDefinitionToImport(NamedDecl *D) {
}
void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
- bool NeedDefinition, bool Recover) {
+ MissingImportKind MIK, bool Recover) {
assert(!isVisible(Decl) && "missing import for non-hidden decl?");
// Suggest importing a module providing the definition of this entity, if
@@ -4875,8 +4959,6 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
if (!Def)
Def = Decl;
- // FIXME: Add a Fix-It that imports the corresponding module or includes
- // the header.
Module *Owner = getOwningModule(Decl);
assert(Owner && "definition of hidden declaration is not in a module");
@@ -4885,12 +4967,20 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
auto Merged = Context.getModulesWithMergedDefinition(Decl);
OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end());
- diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules,
- NeedDefinition ? MissingImportKind::Definition
- : MissingImportKind::Declaration,
+ diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK,
Recover);
}
+/// \brief 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) {
+ bool IsSystem;
+ auto Path =
+ PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(E, &IsSystem);
+ return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"');
+}
+
void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
SourceLocation DeclLoc,
ArrayRef<Module *> Modules,
@@ -4911,7 +5001,18 @@ 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, 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);
} else {
+ // FIXME: Add a FixItHint that imports the corresponding module.
Diag(UseLoc, diag::err_module_unimported_use)
<< (int)MIK << Decl << Modules[0]->getFullModuleName();
}
@@ -4927,6 +5028,12 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
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);
@@ -4962,7 +5069,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
assert(Decl && "import required but no declaration to import");
diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl,
- /*NeedDefinition*/ false, ErrorRecovery);
+ MissingImportKind::Declaration, ErrorRecovery);
return;
}