diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp | 924 |
1 files changed, 707 insertions, 217 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 9ab3b2d..919c6ad 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -102,15 +102,14 @@ namespace { // During unqualified name lookup, the names appear as if they // were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. - DeclContext *InnermostFileDC - = static_cast<DeclContext*>(InnermostFileScope->getEntity()); + DeclContext *InnermostFileDC = InnermostFileScope->getEntity(); assert(InnermostFileDC && InnermostFileDC->isFileContext()); for (; S; S = S->getParent()) { // C++ [namespace.udir]p1: // A using-directive shall not appear in class scope, but may // appear in namespace scope or in block scope. - DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + DeclContext *Ctx = S->getEntity(); if (Ctx && Ctx->isFileContext()) { visit(Ctx, Ctx); } else if (!Ctx || Ctx->isFunctionOrMethod()) { @@ -167,8 +166,7 @@ namespace { if (queue.empty()) return; - DC = queue.back(); - queue.pop_back(); + DC = queue.pop_back_val(); } } @@ -217,12 +215,15 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, case Sema::LookupObjCImplicitSelfParam: case Sema::LookupOrdinaryName: case Sema::LookupRedeclarationWithLinkage: + case Sema::LookupLocalFriendName: IDNS = Decl::IDNS_Ordinary; if (CPlusPlus) { IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; } + if (Redeclaration) + IDNS |= Decl::IDNS_LocalExtern; break; case Sema::LookupOperatorName: @@ -336,10 +337,19 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } -static NamedDecl *getVisibleDecl(NamedDecl *D); - -NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { - return getVisibleDecl(D); +/// Get a representative context for a declaration such that two declarations +/// will have the same context if they were found within the same scope. +static DeclContext *getContextForScopeMatching(Decl *D) { + // For function-local declarations, use that function as the context. This + // doesn't account for scopes within the function; the caller must deal with + // those. + DeclContext *DC = D->getLexicalDeclContext(); + if (DC->isFunctionOrMethod()) + return DC; + + // Otherwise, look at the semantic context of the declaration. The + // declaration must have been found there. + return D->getDeclContext()->getRedeclContext(); } /// Resolves the result kind of this lookup. @@ -442,8 +452,8 @@ void LookupResult::resolveKind() { // even if they're not visible. (ref?) if (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction || HasUnresolved)) { - if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals( - Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext())) + if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals( + getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1]))) Decls[UniqueTagIndex] = Decls[--N]; else Ambiguous = true; @@ -511,6 +521,14 @@ 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 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 @@ -726,7 +744,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // function to have, if it were to match the name given. // FIXME: Calling convention! FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); - EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C); EPI.ExceptionSpecType = EST_None; EPI.NumExceptions = 0; QualType ExpectedType @@ -771,7 +789,7 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, } static bool isNamespaceOrTranslationUnitScope(Scope *S) { - if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) + if (DeclContext *Ctx = S->getEntity()) return Ctx->isFileContext(); return false; } @@ -784,12 +802,12 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) { // 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 = static_cast<DeclContext *>(S->getEntity()); + DeclContext *DC = S->getEntity(); DeclContext *Lexical = 0; for (Scope *OuterS = S->getParent(); OuterS; OuterS = OuterS->getParent()) { if (OuterS->getEntity()) { - Lexical = static_cast<DeclContext *>(OuterS->getEntity()); + Lexical = OuterS->getEntity(); break; } } @@ -845,16 +863,37 @@ static std::pair<DeclContext *, bool> findOuterContext(Scope *S) { return std::make_pair(Lexical, false); } +namespace { +/// An RAII object to specify that we want to find block scope extern +/// declarations. +struct FindLocalExternScope { + FindLocalExternScope(LookupResult &R) + : R(R), OldFindLocalExtern(R.getIdentifierNamespace() & + Decl::IDNS_LocalExtern) { + R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary); + } + void restore() { + R.setFindLocalExtern(OldFindLocalExtern); + } + ~FindLocalExternScope() { + restore(); + } + LookupResult &R; + bool OldFindLocalExtern; +}; +} + bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); + Sema::LookupNameKind NameKind = R.getLookupKind(); // If this is the name of an implicitly-declared special member function, // go through the scope stack to implicitly declare if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) - if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity())) + if (DeclContext *DC = PreS->getEntity()) DeclareImplicitMemberFunctionsWithName(*this, Name, DC); } @@ -886,14 +925,35 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // UnqualUsingDirectiveSet UDirs; bool VisitedUsingDirectives = false; + bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = 0; + + // When performing a scope lookup, we want to find local extern decls. + FindLocalExternScope FindLocals(R); + for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { - DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + DeclContext *Ctx = S->getEntity(); // 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) { + // 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()) { + R.setShadowed(); + continue; + } + } + Found = true; R.addDecl(ND); } @@ -906,6 +966,15 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return true; } + if (NameKind == LookupLocalFriendName && !S->isClassScope()) { + // C++11 [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. + return false; + } + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and @@ -1007,7 +1076,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { if (!S) return false; // If we are looking for members, no need to look into global/namespace scope. - if (R.getLookupKind() == LookupMemberName) + if (NameKind == LookupMemberName) return false; // Collect UsingDirectiveDecls in all scopes, and recursively all @@ -1019,7 +1088,12 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { UDirs.visitScopeChain(Initial, S); UDirs.done(); } - + + // If we're not performing redeclaration lookup, do not look for local + // extern declarations outside of a function scope. + if (!R.isForRedeclaration()) + FindLocals.restore(); + // Lookup namespace scope, and global scope. // Unqualified name lookup in C++ requires looking into scopes // that aren't strictly lexical, and therefore we walk through the @@ -1043,7 +1117,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return true; } - DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); + DeclContext *Ctx = S->getEntity(); if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and @@ -1098,29 +1172,127 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return !R.empty(); } +/// \brief Find the declaration that a class temploid member specialization was +/// instantiated from, or the member itself if it is an explicit specialization. +static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { + return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); +} + +/// \brief Find the module in which the given declaration was defined. +static Module *getDefiningModule(Decl *Entity) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) { + // If this function was instantiated from a template, the defining module is + // the module containing the pattern. + if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern()) + Entity = Pattern; + } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Entity)) { + // If it's a class template specialization, find the template or partial + // specialization from which it was instantiated. + if (ClassTemplateSpecializationDecl *SpecRD = + dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + llvm::PointerUnion<ClassTemplateDecl*, + ClassTemplatePartialSpecializationDecl*> From = + SpecRD->getInstantiatedFrom(); + if (ClassTemplateDecl *FromTemplate = From.dyn_cast<ClassTemplateDecl*>()) + Entity = FromTemplate->getTemplatedDecl(); + else if (From) + Entity = From.get<ClassTemplatePartialSpecializationDecl*>(); + // Otherwise, it's an explicit specialization. + } else if (MemberSpecializationInfo *MSInfo = + RD->getMemberSpecializationInfo()) + Entity = getInstantiatedFrom(RD, MSInfo); + } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) { + if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo()) + Entity = getInstantiatedFrom(ED, MSInfo); + } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) { + // FIXME: Map from variable template specializations back to the template. + if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) + Entity = getInstantiatedFrom(VD, MSInfo); + } + + // Walk up to the containing context. That might also have been instantiated + // from a template. + DeclContext *Context = Entity->getDeclContext(); + if (Context->isFileContext()) + return Entity->getOwningModule(); + return getDefiningModule(cast<Decl>(Context)); +} + +llvm::DenseSet<Module*> &Sema::getLookupModules() { + unsigned N = ActiveTemplateInstantiations.size(); + for (unsigned I = ActiveTemplateInstantiationLookupModules.size(); + I != N; ++I) { + Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity); + if (M && !LookupModulesCache.insert(M).second) + M = 0; + ActiveTemplateInstantiationLookupModules.push_back(M); + } + return LookupModulesCache; +} + +/// \brief Determine whether a declaration is visible to name lookup. +/// +/// This routine determines whether the declaration D is visible in the current +/// lookup context, taking into account the current template instantiation +/// stack. During template instantiation, a declaration is visible if it is +/// visible from a module containing any entity on the template instantiation +/// 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() && !SemaRef.ActiveTemplateInstantiations.empty() && + "should not call this: not in slow case"); + Module *DeclModule = D->getOwningModule(); + assert(DeclModule && "hidden decl not from a module"); + + // Find the extra places where we need to look. + llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules(); + if (LookupModules.empty()) + return false; + + // If our lookup set contains the decl's module, it's visible. + if (LookupModules.count(DeclModule)) + return true; + + // If the declaration isn't exported, it's not visible in any other module. + if (D->isModulePrivate()) + return false; + + // Check whether DeclModule is transitively exported to an import of + // the lookup set. + for (llvm::DenseSet<Module *>::iterator I = LookupModules.begin(), + E = LookupModules.end(); + I != E; ++I) + if ((*I)->isModuleVisible(DeclModule)) + return true; + return false; +} + /// \brief Retrieve the visible declaration corresponding to D, if any. /// /// This routine determines whether the declaration D is visible in the current /// module, with the current imports. If not, it checks whether any /// redeclaration of D is visible, and if so, returns that declaration. -/// +/// /// \returns D, or a visible previous declaration of D, whichever is more recent /// and visible. If no declaration of D is visible, returns null. -static NamedDecl *getVisibleDecl(NamedDecl *D) { - if (LookupResult::isVisible(D)) - return D; - +static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { + assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); + for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end(); RD != RDEnd; ++RD) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) { - if (LookupResult::isVisible(ND)) + if (LookupResult::isVisible(SemaRef, ND)) return ND; } } - + return 0; } +NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + return findAcceptableDecl(SemaRef, D); +} + /// @brief Perform unqualified name lookup starting from a given /// scope. /// @@ -1161,13 +1333,12 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (NameKind == Sema::LookupRedeclarationWithLinkage) { // Find the nearest non-transparent declaration scope. while (!(S->getFlags() & Scope::DeclScope) || - (S->getEntity() && - static_cast<DeclContext *>(S->getEntity()) - ->isTransparentContext())) + (S->getEntity() && S->getEntity()->isTransparentContext())) S = S->getParent(); } - unsigned IDNS = R.getIdentifierNamespace(); + // When performing a scope lookup, we want to find local extern decls. + FindLocalExternScope FindLocals(R); // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search @@ -1178,7 +1349,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { for (IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); I != IEnd; ++I) - if ((*I)->isInIdentifierNamespace(IDNS)) { + if (NamedDecl *D = R.getAcceptableDecl(*I)) { if (NameKind == LookupRedeclarationWithLinkage) { // Determine whether this (or a previous) declaration is // out-of-scope. @@ -1187,19 +1358,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If we found something outside of our starting scope that // does not have linkage, skip it. - if (LeftStartingScope && !((*I)->hasLinkage())) + if (LeftStartingScope && !((*I)->hasLinkage())) { + R.setShadowed(); continue; + } } else if (NameKind == LookupObjCImplicitSelfParam && !isa<ImplicitParamDecl>(*I)) continue; - - // If this declaration is module-private and it came from an AST - // file, we can't see it. - NamedDecl *D = R.isHiddenDeclarationVisible()? *I : getVisibleDecl(*I); - if (!D) - continue; - + R.addDecl(D); // Check whether there are any other declarations with the same name @@ -1234,18 +1401,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (!LastDC->Equals(DC)) break; } - - // If the declaration isn't in the right namespace, skip it. - if (!(*LastI)->isInIdentifierNamespace(IDNS)) - continue; - - D = R.isHiddenDeclarationVisible()? *LastI : getVisibleDecl(*LastI); - if (D) - R.addDecl(D); + + // If the declaration is in the right namespace and visible, add it. + if (NamedDecl *LastD = R.getAcceptableDecl(*LastI)) + R.addDecl(LastD); } R.resolveKind(); } + return true; } } else { @@ -1330,8 +1494,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, bool Found = false; while (!Queue.empty()) { - NamespaceDecl *ND = Queue.back(); - Queue.pop_back(); + NamespaceDecl *ND = Queue.pop_back_val(); // We go through some convolutions here to avoid copying results // between LookupResults. @@ -1510,6 +1673,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, case LookupOrdinaryName: case LookupMemberName: case LookupRedeclarationWithLinkage: + case LookupLocalFriendName: BaseCallback = &CXXRecordDecl::FindOrdinaryMember; break; @@ -1681,9 +1845,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, /// from name lookup. /// /// \param Result The result of the ambiguous lookup to be diagnosed. -/// -/// \returns true -bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { +void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); DeclarationName Name = Result.getLookupName(); @@ -1704,8 +1866,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { ++Found; Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); - - return true; + break; } case LookupResult::AmbiguousBaseSubobjectTypes: { @@ -1721,8 +1882,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { if (DeclsPrinted.insert(D).second) Diag(D->getLocation(), diag::note_ambiguous_member_found); } - - return true; + break; } case LookupResult::AmbiguousTagHiding: { @@ -1748,8 +1908,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { F.erase(); } F.done(); - - return true; + break; } case LookupResult::AmbiguousReference: { @@ -1758,12 +1917,9 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { LookupResult::iterator DI = Result.begin(), DE = Result.end(); for (; DI != DE; ++DI) Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; - - return true; + break; } } - - llvm_unreachable("unknown ambiguity kind"); } namespace { @@ -1922,8 +2078,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, Bases.push_back(Class); while (!Bases.empty()) { // Pop this class off the stack. - Class = Bases.back(); - Bases.pop_back(); + Class = Bases.pop_back_val(); // Visit the base classes. for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(), @@ -2107,9 +2262,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { continue; } - if (Queue.empty()) break; - T = Queue.back(); - Queue.pop_back(); + if (Queue.empty()) + break; + T = Queue.pop_back_val(); } } @@ -2120,11 +2275,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { /// This routine computes the sets of associated classes and associated /// namespaces searched by argument-dependent lookup /// (C++ [basic.lookup.argdep]) for a given set of arguments. -void -Sema::FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, - llvm::ArrayRef<Expr *> Args, - AssociatedNamespaceSet &AssociatedNamespaces, - AssociatedClassSet &AssociatedClasses) { +void Sema::FindAssociatedClassesAndNamespaces( + SourceLocation InstantiationLoc, ArrayRef<Expr *> Args, + AssociatedNamespaceSet &AssociatedNamespaces, + AssociatedClassSet &AssociatedClasses) { AssociatedNamespaces.clear(); AssociatedClasses.clear(); @@ -2393,11 +2547,17 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, // will always be a (possibly implicit) declaration to shadow any others. OverloadCandidateSet OCS((SourceLocation())); DeclContext::lookup_result R = RD->lookup(Name); - assert(!R.empty() && "lookup for a constructor or assignment operator was empty"); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - Decl *Cand = *I; + + // Copy the candidates as our processing of them may load new declarations + // from an external source and invalidate lookup_result. + SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end()); + + for (SmallVectorImpl<NamedDecl *>::iterator I = Candidates.begin(), + E = Candidates.end(); + I != E; ++I) { + NamedDecl *Cand = *I; if (Cand->isInvalidDecl()) continue; @@ -2565,7 +2725,8 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, - bool AllowRawAndTemplate) { + bool AllowRaw, bool AllowTemplate, + bool AllowStringTemplate) { LookupName(R, S); assert(R.getResultKind() != LookupResult::Ambiguous && "literal operator lookup can't be ambiguous"); @@ -2573,8 +2734,9 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, // Filter the lookup results appropriately. LookupResult::Filter F = R.makeFilter(); - bool FoundTemplate = false; bool FoundRaw = false; + bool FoundTemplate = false; + bool FoundStringTemplate = false; bool FoundExactMatch = false; while (F.hasNext()) { @@ -2582,16 +2744,17 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) D = USD->getTargetDecl(); - bool IsTemplate = isa<FunctionTemplateDecl>(D); - bool IsRaw = false; - bool IsExactMatch = false; - // If the declaration we found is invalid, skip it. if (D->isInvalidDecl()) { F.erase(); continue; } + bool IsRaw = false; + bool IsTemplate = false; + bool IsStringTemplate = false; + bool IsExactMatch = false; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getNumParams() == 1 && FD->getParamDecl(0)->getType()->getAs<PointerType>()) @@ -2607,19 +2770,31 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, } } } + if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) { + TemplateParameterList *Params = FD->getTemplateParameters(); + if (Params->size() == 1) + IsTemplate = true; + else + IsStringTemplate = true; + } if (IsExactMatch) { FoundExactMatch = true; - AllowRawAndTemplate = false; - if (FoundRaw || FoundTemplate) { + AllowRaw = false; + AllowTemplate = false; + AllowStringTemplate = false; + if (FoundRaw || FoundTemplate || FoundStringTemplate) { // Go through again and remove the raw and template decls we've // already found. F.restart(); - FoundRaw = FoundTemplate = false; + FoundRaw = FoundTemplate = FoundStringTemplate = false; } - } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) { - FoundTemplate |= IsTemplate; - FoundRaw |= IsRaw; + } else if (AllowRaw && IsRaw) { + FoundRaw = true; + } else if (AllowTemplate && IsTemplate) { + FoundTemplate = true; + } else if (AllowStringTemplate && IsStringTemplate) { + FoundStringTemplate = true; } else { F.erase(); } @@ -2654,10 +2829,14 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FoundTemplate) return LOLR_Template; + if (FoundStringTemplate) + return LOLR_StringTemplate; + // Didn't find anything we could use. Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] - << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate; + << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw + << (AllowTemplate || AllowStringTemplate); return LOLR_Error; } @@ -2699,8 +2878,7 @@ void ADLResult::insert(NamedDecl *New) { } void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, - SourceLocation Loc, - llvm::ArrayRef<Expr *> Args, + SourceLocation Loc, ArrayRef<Expr *> Args, ADLResult &Result) { // Find all of the associated namespaces and classes based on the // arguments we have. @@ -2748,9 +2926,21 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, NamedDecl *D = *I; // If the only declaration here is an ordinary friend, consider // it only if it was declared in an associated classes. - if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { - DeclContext *LexDC = D->getLexicalDeclContext(); - if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) + if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) { + // If it's neither ordinarily visible nor a friend, we can't find it. + if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0) + continue; + + bool DeclaredInAssociatedClass = false; + for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) { + DeclContext *LexDC = DI->getLexicalDeclContext(); + if (isa<CXXRecordDecl>(LexDC) && + AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) { + DeclaredInAssociatedClass = true; + break; + } + } + if (!DeclaredInAssociatedClass) continue; } @@ -2775,6 +2965,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, //---------------------------------------------------------------------------- VisibleDeclConsumer::~VisibleDeclConsumer() { } +bool VisibleDeclConsumer::includeHiddenDecls() const { return false; } + namespace { class ShadowContextRAII; @@ -3038,8 +3230,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, if (!S->getEntity() || (!S->getParent() && - !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) || - ((DeclContext *)S->getEntity())->isFunctionOrMethod()) { + !Visited.alreadyVisitedContext(S->getEntity())) || + (S->getEntity())->isFunctionOrMethod()) { + FindLocalExternScope FindLocals(Result); // Walk through the declarations in this Scope. for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { @@ -3057,7 +3250,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, // 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 = (DeclContext *)S->getEntity(); + Entity = S->getEntity(); DeclContext *OuterCtx = findOuterContext(S).first; // FIXME for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx); @@ -3069,7 +3262,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, Result.getNameLoc(), Sema::LookupMemberName); if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited); } } @@ -3134,6 +3327,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, // Look for visible declarations. LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); @@ -3145,6 +3339,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); @@ -3214,14 +3409,16 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { public: explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo) : Typo(Typo->getName()), - SemaRef(SemaRef) { } + SemaRef(SemaRef) {} + + bool includeHiddenDecls() const { return true; } virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass); void FoundName(StringRef Name); void addKeywordResult(StringRef Keyword); - void addName(StringRef Name, NamedDecl *ND, unsigned Distance, - NestedNameSpecifier *NNS=NULL, bool isKeyword=false); + void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = NULL, + bool isKeyword = false); void addCorrection(TypoCorrection Correction); typedef TypoResultsMap::iterator result_iterator; @@ -3265,37 +3462,42 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, if (!Name) return; + // Only consider visible declarations and declarations from modules with + // names that exactly match. + if (!LookupResult::isVisible(SemaRef, ND) && Name->getName() != Typo && + !findAcceptableDecl(SemaRef, ND)) + return; + FoundName(Name->getName()); } void TypoCorrectionConsumer::FoundName(StringRef Name) { - // Use a simple length-based heuristic to determine the minimum possible - // edit distance. If the minimum isn't good enough, bail out early. - unsigned MinED = abs((int)Name.size() - (int)Typo.size()); - if (MinED && Typo.size() / MinED < 3) - return; - - // Compute an upper bound on the allowable edit distance, so that the - // edit-distance algorithm can short-circuit. - unsigned UpperBound = (Typo.size() + 2) / 3; - // Compute the edit distance between the typo and the name of this // entity, and add the identifier to the list of results. - addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound)); + addName(Name, NULL); } void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) { // Compute the edit distance between the typo and this keyword, // and add the keyword to the list of results. - addName(Keyword, NULL, Typo.edit_distance(Keyword), NULL, true); + addName(Keyword, NULL, NULL, true); } -void TypoCorrectionConsumer::addName(StringRef Name, - NamedDecl *ND, - unsigned Distance, - NestedNameSpecifier *NNS, - bool isKeyword) { - TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, Distance); +void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND, + NestedNameSpecifier *NNS, bool isKeyword) { + // Use a simple length-based heuristic to determine the minimum possible + // edit distance. If the minimum isn't good enough, bail out early. + unsigned MinED = abs((int)Name.size() - (int)Typo.size()); + if (MinED && Typo.size() / MinED < 3) + return; + + // Compute an upper bound on the allowable edit distance, so that the + // edit-distance algorithm can short-circuit. + unsigned UpperBound = (Typo.size() + 2) / 3 + 1; + unsigned ED = Typo.edit_distance(Name, true, UpperBound); + if (ED >= UpperBound) return; + + TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED); if (isKeyword) TC.makeKeyword(); addCorrection(TC); } @@ -3388,6 +3590,7 @@ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList; class NamespaceSpecifierSet { ASTContext &Context; DeclContextList CurContextChain; + std::string CurNameSpecifier; SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers; SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers; bool isSorted; @@ -3406,10 +3609,14 @@ class NamespaceSpecifierSet { NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec) : Context(Context), CurContextChain(BuildContextChain(CurContext)), - isSorted(true) { - if (CurScopeSpec && CurScopeSpec->getScopeRep()) - getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(), - CurNameSpecifierIdentifiers); + isSorted(false) { + if (NestedNameSpecifier *NNS = + CurScopeSpec ? CurScopeSpec->getScopeRep() : 0) { + llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); + NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + + getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers); + } // Build the list of identifiers that would be used for an absolute // (from the global context) NestedNameSpecifier referring to the current // context. @@ -3419,11 +3626,17 @@ class NamespaceSpecifierSet { if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) CurContextIdentifiers.push_back(ND->getIdentifier()); } + + // Add the global context as a NestedNameSpecifier + Distances.insert(1); + DistanceMap[1].push_back( + SpecifierInfo(cast<DeclContext>(Context.getTranslationUnitDecl()), + NestedNameSpecifier::GlobalSpecifier(Context), 1)); } - /// \brief Add the namespace to the set, computing the corresponding - /// NestedNameSpecifier and its distance in the process. - void AddNamespace(NamespaceDecl *ND); + /// \brief Add the DeclContext (a namespace or record) to the set, computing + /// the corresponding NestedNameSpecifier and its distance in the process. + void AddNameSpecifier(DeclContext *Ctx); typedef SpecifierInfoList::iterator iterator; iterator begin() { @@ -3456,8 +3669,8 @@ void NamespaceSpecifierSet::SortNamespaces() { std::sort(sortedDistances.begin(), sortedDistances.end()); Specifiers.clear(); - for (SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(), - DIEnd = sortedDistances.end(); + for (SmallVectorImpl<unsigned>::iterator DI = sortedDistances.begin(), + DIEnd = sortedDistances.end(); DI != DIEnd; ++DI) { SpecifierInfoList &SpecList = DistanceMap[*DI]; Specifiers.append(SpecList.begin(), SpecList.end()); @@ -3466,8 +3679,26 @@ void NamespaceSpecifierSet::SortNamespaces() { isSorted = true; } -void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { - DeclContext *Ctx = cast<DeclContext>(ND); +static unsigned BuildNestedNameSpecifier(ASTContext &Context, + 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)) { + NNS = NestedNameSpecifier::Create(Context, NNS, ND); + ++NumSpecifiers; + } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) { + NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), + RD->getTypeForDecl()); + ++NumSpecifiers; + } + } + return NumSpecifiers; +} + +void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) { NestedNameSpecifier *NNS = NULL; unsigned NumSpecifiers = 0; DeclContextList NamespaceDeclChain(BuildContextChain(Ctx)); @@ -3481,29 +3712,37 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { NamespaceDeclChain.pop_back(); } + // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain + NumSpecifiers = BuildNestedNameSpecifier(Context, NamespaceDeclChain, NNS); + // Add an explicit leading '::' specifier if needed. - if (NamespaceDecl *ND = - NamespaceDeclChain.empty() ? NULL : - dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) { + if (NamespaceDeclChain.empty()) { + // Rebuild the NestedNameSpecifier as a globally-qualified specifier. + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NumSpecifiers = + BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS); + } else if (NamedDecl *ND = + dyn_cast_or_null<NamedDecl>(NamespaceDeclChain.back())) { IdentifierInfo *Name = ND->getIdentifier(); - if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), - Name) != CurContextIdentifiers.end() || - std::find(CurNameSpecifierIdentifiers.begin(), + bool SameNameSpecifier = false; + if (std::find(CurNameSpecifierIdentifiers.begin(), CurNameSpecifierIdentifiers.end(), Name) != CurNameSpecifierIdentifiers.end()) { - NamespaceDeclChain = FullNamespaceDeclChain; - NNS = NestedNameSpecifier::GlobalSpecifier(Context); + std::string NewNameSpecifier; + llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier); + SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers; + getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); + NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + SpecifierOStream.flush(); + SameNameSpecifier = NewNameSpecifier == CurNameSpecifier; } - } - - // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain - for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(), - CEnd = NamespaceDeclChain.rend(); - C != CEnd; ++C) { - NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C); - if (ND) { - NNS = NestedNameSpecifier::Create(Context, NNS, ND); - ++NumSpecifiers; + if (SameNameSpecifier || + std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), + Name) != CurContextIdentifiers.end()) { + // Rebuild the NestedNameSpecifier as a globally-qualified specifier. + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NumSpecifiers = + BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS); } } @@ -3515,8 +3754,8 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers; getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); NumSpecifiers = llvm::ComputeEditDistance( - llvm::ArrayRef<const IdentifierInfo*>(CurNameSpecifierIdentifiers), - llvm::ArrayRef<const IdentifierInfo*>(NewNameSpecifierIdentifiers)); + ArrayRef<const IdentifierInfo *>(CurNameSpecifierIdentifiers), + ArrayRef<const IdentifierInfo *>(NewNameSpecifierIdentifiers)); } isSorted = false; @@ -3531,10 +3770,12 @@ static void LookupPotentialTypoResult(Sema &SemaRef, Scope *S, CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, - bool isObjCIvarLookup) { + bool isObjCIvarLookup, + bool FindHidden) { Res.suppressDiagnostics(); Res.clear(); Res.setLookupName(Name); + Res.setAllowHidden(FindHidden); if (MemberContext) { if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) { if (isObjCIvarLookup) { @@ -3593,7 +3834,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, if (CCC.WantTypeSpecifiers) { // Add type-specifier keywords to the set of results. - const char *CTypeSpecs[] = { + static const char *const CTypeSpecs[] = { "char", "const", "double", "enum", "float", "int", "long", "short", "signed", "struct", "union", "unsigned", "void", "volatile", "_Complex", "_Imaginary", @@ -3601,7 +3842,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, "extern", "inline", "static", "typedef" }; - const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]); + const unsigned NumCTypeSpecs = llvm::array_lengthof(CTypeSpecs); for (unsigned I = 0; I != NumCTypeSpecs; ++I) Consumer.addKeywordResult(CTypeSpecs[I]); @@ -3645,10 +3886,10 @@ static void AddKeywordsToConsumer(Sema &SemaRef, } if (SemaRef.getLangOpts().CPlusPlus) { - const char *CXXExprs[] = { + static const char *const CXXExprs[] = { "delete", "new", "operator", "throw", "typeid" }; - const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]); + const unsigned NumCXXExprs = llvm::array_lengthof(CXXExprs); for (unsigned I = 0; I != NumCXXExprs; ++I) Consumer.addKeywordResult(CXXExprs[I]); @@ -3672,9 +3913,9 @@ static void AddKeywordsToConsumer(Sema &SemaRef, if (CCC.WantRemainingKeywords) { if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) { // Statements. - const char *CStmts[] = { + static const char *const CStmts[] = { "do", "else", "for", "goto", "if", "return", "switch", "while" }; - const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]); + const unsigned NumCStmts = llvm::array_lengthof(CStmts); for (unsigned I = 0; I != NumCStmts; ++I) Consumer.addKeywordResult(CStmts[I]); @@ -3725,6 +3966,50 @@ static bool isCandidateViable(CorrectionCandidateCallback &CCC, return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance; } +/// \brief Check whether the declarations found for a typo correction are +/// visible, and if none of them are, convert the correction to an 'import +/// a module' correction. +static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC, + DeclarationName TypoName) { + if (TC.begin() == TC.end()) + return; + + TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); + + for (/**/; DI != DE; ++DI) + if (!LookupResult::isVisible(SemaRef, *DI)) + break; + // Nothing to do if all decls are visible. + if (DI == DE) + return; + + llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI); + bool AnyVisibleDecls = !NewDecls.empty(); + + for (/**/; DI != DE; ++DI) { + NamedDecl *VisibleDecl = *DI; + if (!LookupResult::isVisible(SemaRef, *DI)) + VisibleDecl = findAcceptableDecl(SemaRef, *DI); + + if (VisibleDecl) { + if (!AnyVisibleDecls) { + // Found a visible decl, discard all hidden ones. + AnyVisibleDecls = true; + NewDecls.clear(); + } + NewDecls.push_back(VisibleDecl); + } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate()) + NewDecls.push_back(*DI); + } + + if (NewDecls.empty()) + TC = TypoCorrection(); + else { + TC.setCorrectionDecls(NewDecls); + TC.setRequiresImport(!AnyVisibleDecls); + } +} + /// \brief Try to "correct" a typo in the source code by finding /// visible declarations whose names are similar to the name that was /// present in the source code. @@ -3762,8 +4047,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, - const ObjCObjectPointerType *OPT) { - if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking) + const ObjCObjectPointerType *OPT, + bool RecordFailure) { + // 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)) + return Correction; + } + + if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking || + DisableTypoCorrection) return TypoCorrection(); // In Microsoft mode, don't perform typo correction in a template member @@ -3792,6 +4087,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier()) return TypoCorrection(); + // Abort if typo correction already failed for this specific typo. + IdentifierSourceLocations::iterator locs = TypoCorrectionFailures.find(Typo); + if (locs != TypoCorrectionFailures.end() && + locs->second.count(TypoName.getLoc())) + return TypoCorrection(); + + // Don't try to correct the identifier "vector" when in AltiVec mode. + // TODO: Figure out why typo correction misbehaves in this case, fix it, and + // remove this workaround. + if (getLangOpts().AltiVec && Typo->isStr("vector")) + return TypoCorrection(); + NamespaceSpecifierSet Namespaces(Context, CurContext, SS); TypoCorrectionConsumer Consumer(*this, Typo); @@ -3836,8 +4143,15 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // keyword case, we'll end up adding the keyword below. if (Cached->second) { if (!Cached->second.isKeyword() && - isCandidateViable(CCC, Cached->second)) - Consumer.addCorrection(Cached->second); + isCandidateViable(CCC, Cached->second)) { + // Do not use correction that is unaccessible in the given scope. + NamedDecl *CorrectionDecl = Cached->second.getCorrectionDecl(); + DeclarationNameInfo NameInfo(CorrectionDecl->getDeclName(), + CorrectionDecl->getLocation()); + LookupResult R(*this, NameInfo, LookupOrdinaryName); + if (LookupName(R, S)) + Consumer.addCorrection(Cached->second); + } } else { // Only honor no-correction cache hits when a callback that will validate // correction candidates is not being used. @@ -3858,11 +4172,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // corrections. bool SearchNamespaces = getLangOpts().CPlusPlus && - (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace())); - // In a few cases we *only* want to search for corrections bases on just + (IsUnqualifiedLookup || (SS && SS->isSet())); + // In a few cases we *only* want to search for corrections based on just // adding or changing the nested name specifier. - bool AllowOnlyNNSChanges = Typo->getName().size() < 3; - + unsigned TypoLen = Typo->getName().size(); + bool AllowOnlyNNSChanges = TypoLen < 3; + if (IsUnqualifiedLookup || SearchNamespaces) { // For unqualified lookup, look through all of the names that we have // seen in this translation unit. @@ -3890,24 +4205,16 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, AddKeywordsToConsumer(*this, Consumer, S, CCC, SS && SS->isNotEmpty()); // If we haven't found anything, we're done. - if (Consumer.empty()) { - // If this was an unqualified lookup, note that no correction was found. - if (IsUnqualifiedLookup) - (void)UnqualifiedTyposCorrected[Typo]; - - return TypoCorrection(); - } + if (Consumer.empty()) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure, + IsUnqualifiedLookup); // Make sure the best edit distance (prior to adding any namespace qualifiers) // is not more that about a third of the length of the typo's identifier. unsigned ED = Consumer.getBestEditDistance(true); - if (ED > 0 && Typo->getName().size() / ED < 3) { - // If this was an unqualified lookup, note that no correction was found. - if (IsUnqualifiedLookup) - (void)UnqualifiedTyposCorrected[Typo]; - - return TypoCorrection(); - } + if (ED > 0 && TypoLen / ED < 3) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure, + IsUnqualifiedLookup); // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going // to search those namespaces. @@ -3920,12 +4227,24 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I) KnownNamespaces[ExternalKnownNamespaces[I]] = true; } - - for (llvm::MapVector<NamespaceDecl*, bool>::iterator + + for (llvm::MapVector<NamespaceDecl*, bool>::iterator KNI = KnownNamespaces.begin(), KNIEnd = KnownNamespaces.end(); KNI != KNIEnd; ++KNI) - Namespaces.AddNamespace(KNI->first); + Namespaces.AddNameSpecifier(KNI->first); + + for (ASTContext::type_iterator TI = Context.types_begin(), + TIEnd = Context.types_end(); + TI != TIEnd; ++TI) { + if (CXXRecordDecl *CD = (*TI)->getAsCXXRecordDecl()) { + CD = CD->getCanonicalDecl(); + if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() && + !CD->isUnion() && + (CD->isBeingDefined() || CD->isCompleteDefinition())) + Namespaces.AddNameSpecifier(CD); + } + } } // Weed out any names that could not be found by name lookup or, if a @@ -3935,7 +4254,6 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TmpRes.suppressDiagnostics(); while (!Consumer.empty()) { TypoCorrectionConsumer::distance_iterator DI = Consumer.begin(); - unsigned ED = DI->first; for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(), IEnd = DI->second.end(); I != IEnd; /* Increment in loop. */) { @@ -3976,13 +4294,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Perform name lookup on this name. TypoCorrection &Candidate = I->second.front(); IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo(); - LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext, - EnteringContext, CCC.IsObjCIvarLookup); + DeclContext *TempMemberContext = MemberContext; + CXXScopeSpec *TempSS = SS; +retry_lookup: + LookupPotentialTypoResult(*this, TmpRes, Name, S, TempSS, + TempMemberContext, EnteringContext, + CCC.IsObjCIvarLookup, + Name == TypoName.getName() && + !Candidate.WillReplaceSpecifier()); switch (TmpRes.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundUnresolvedValue: + if (TempSS) { + // Immediately retry the lookup without the given CXXScopeSpec + TempSS = NULL; + Candidate.WillReplaceSpecifier(true); + goto retry_lookup; + } + if (TempMemberContext) { + if (SS && !TempSS) + TempSS = SS; + TempMemberContext = NULL; + goto retry_lookup; + } QualifiedResults.push_back(Candidate); // We didn't find this name in our scope, or didn't like what we found; // ignore it. @@ -3996,7 +4332,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, case LookupResult::Ambiguous: // We don't deal with ambiguities. - return TypoCorrection(); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); case LookupResult::FoundOverloaded: { TypoCorrectionConsumer::result_iterator Prev = I; @@ -4006,8 +4342,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TRD != TRDEnd; ++TRD) Candidate.addCorrectionDecl(*TRD); ++I; - if (!isCandidateViable(CCC, Candidate)) + if (!isCandidateViable(CCC, Candidate)) { + QualifiedResults.push_back(Candidate); DI->second.erase(Prev); + } break; } @@ -4015,8 +4353,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TypoCorrectionConsumer::result_iterator Prev = I; Candidate.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>()); ++I; - if (!isCandidateViable(CCC, Candidate)) + if (!isCandidateViable(CCC, Candidate)) { + QualifiedResults.push_back(Candidate); DI->second.erase(Prev); + } break; } @@ -4025,7 +4365,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (DI->second.empty()) Consumer.erase(DI); - else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED) + else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !DI->first) // If there are results in the closest possible bucket, stop break; @@ -4040,10 +4380,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, NIEnd = Namespaces.end(); NI != NIEnd; ++NI) { DeclContext *Ctx = NI->DeclCtx; + const Type *NSType = NI->NameSpecifier->getAsType(); + + // If the current NestedNameSpecifier refers to a class and the + // current correction candidate is the name of that class, then skip + // it as it is unlikely a qualified version of the class' constructor + // is an appropriate correction. + if (CXXRecordDecl *NSDecl = + NSType ? NSType->getAsCXXRecordDecl() : 0) { + if (NSDecl->getIdentifier() == QRI->getCorrectionAsIdentifierInfo()) + continue; + } - // FIXME: Stop searching once the namespaces are too far away to create - // acceptable corrections for this identifier (since the namespaces - // are sorted in ascending order by edit distance). + TypoCorrection TC(*QRI); + TC.ClearCorrectionDecls(); + TC.setCorrectionSpecifier(NI->NameSpecifier); + TC.setQualifierDistance(NI->EditDistance); + TC.setCallbackDistance(0); // Reset the callback distance + + // If the current correction candidate and namespace combination are + // too far away from the original typo based on the normalized edit + // distance, then skip performing a qualified name lookup. + unsigned TmpED = TC.getEditDistance(true); + if (QRI->getCorrectionAsIdentifierInfo() != Typo && + TmpED && TypoLen / TmpED < 3) + continue; TmpRes.clear(); TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo()); @@ -4052,23 +4413,30 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Any corrections added below will be validated in subsequent // iterations of the main while() loop over the Consumer's contents. switch (TmpRes.getResultKind()) { - case LookupResult::Found: { - TypoCorrection TC(*QRI); - TC.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>()); - TC.setCorrectionSpecifier(NI->NameSpecifier); - TC.setQualifierDistance(NI->EditDistance); - Consumer.addCorrection(TC); - break; - } + case LookupResult::Found: case LookupResult::FoundOverloaded: { - TypoCorrection TC(*QRI); - TC.setCorrectionSpecifier(NI->NameSpecifier); - TC.setQualifierDistance(NI->EditDistance); + if (SS && SS->isValid()) { + std::string NewQualified = TC.getAsString(getLangOpts()); + std::string OldQualified; + llvm::raw_string_ostream OldOStream(OldQualified); + SS->getScopeRep()->print(OldOStream, getPrintingPolicy()); + OldOStream << TypoName; + // If correction candidate would be an identical written qualified + // identifer, then the existing CXXScopeSpec probably included a + // typedef that didn't get accounted for properly. + if (OldOStream.str() == NewQualified) + break; + } for (LookupResult::iterator TRD = TmpRes.begin(), TRDEnd = TmpRes.end(); - TRD != TRDEnd; ++TRD) - TC.addCorrectionDecl(*TRD); - Consumer.addCorrection(TC); + TRD != TRDEnd; ++TRD) { + if (CheckMemberAccess(TC.getCorrectionRange().getBegin(), + NSType ? NSType->getAsCXXRecordDecl() : 0, + TRD.getPair()) == AR_accessible) + TC.addCorrectionDecl(*TRD); + } + if (TC.isResolved()) + Consumer.addCorrection(TC); break; } case LookupResult::NotFound: @@ -4085,30 +4453,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, } // No corrections remain... - if (Consumer.empty()) return TypoCorrection(); + if (Consumer.empty()) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); TypoResultsMap &BestResults = Consumer.getBestResults(); ED = Consumer.getBestEditDistance(true); - if (!AllowOnlyNNSChanges && ED > 0 && Typo->getName().size() / ED < 3) { + if (!AllowOnlyNNSChanges && ED > 0 && TypoLen / ED < 3) { // If this was an unqualified lookup and we believe the callback // object wouldn't have filtered out possible corrections, note // that no correction was found. - if (IsUnqualifiedLookup && !ValidatingCallback) - (void)UnqualifiedTyposCorrected[Typo]; - - return TypoCorrection(); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure, + IsUnqualifiedLookup && !ValidatingCallback); } // If only a single name remains, return that result. if (BestResults.size() == 1) { const TypoResultList &CorrectionList = BestResults.begin()->second; const TypoCorrection &Result = CorrectionList.front(); - if (CorrectionList.size() != 1) return TypoCorrection(); + if (CorrectionList.size() != 1) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Don't correct to a keyword that's the same as the typo; the keyword // wasn't actually in scope. - if (ED == 0 && Result.isKeyword()) return TypoCorrection(); + if (ED == 0 && Result.isKeyword()) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Record the correction for unqualified lookup. if (IsUnqualifiedLookup) @@ -4116,6 +4485,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TypoCorrection TC = Result; TC.setCorrectionRange(SS, TypoName); + checkCorrectionVisibility(*this, TC, TypoName.getName()); return TC; } else if (BestResults.size() > 1 @@ -4130,7 +4500,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Don't correct to a keyword that's the same as the typo; the keyword // wasn't actually in scope. - if (ED == 0) return TypoCorrection(); + if (ED == 0) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Record the correction for unqualified lookup. if (IsUnqualifiedLookup) @@ -4146,7 +4517,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (IsUnqualifiedLookup && !ValidatingCallback) (void)UnqualifiedTyposCorrected[Typo]; - return TypoCorrection(); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); } void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { @@ -4166,7 +4537,7 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const { std::string tmpBuffer; llvm::raw_string_ostream PrefixOStream(tmpBuffer); CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO)); - CorrectionName.printName(PrefixOStream); + PrefixOStream << CorrectionName; return PrefixOStream.str(); } @@ -4190,3 +4561,122 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid return WantTypeSpecifiers; } + +FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, + bool HasExplicitTemplateArgs) + : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) { + WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus; + WantRemainingKeywords = false; +} + +bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) { + if (!candidate.getCorrectionDecl()) + return candidate.isKeyword(); + + for (TypoCorrection::const_decl_iterator DI = candidate.begin(), + DIEnd = candidate.end(); + DI != DIEnd; ++DI) { + FunctionDecl *FD = 0; + NamedDecl *ND = (*DI)->getUnderlyingDecl(); + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + FD = FTD->getTemplatedDecl(); + if (!HasExplicitTemplateArgs && !FD) { + if (!(FD = dyn_cast<FunctionDecl>(ND)) && isa<ValueDecl>(ND)) { + // If the Decl is neither a function nor a template function, + // determine if it is a pointer or reference to a function. If so, + // check against the number of arguments expected for the pointee. + QualType ValType = cast<ValueDecl>(ND)->getType(); + if (ValType->isAnyPointerType() || ValType->isReferenceType()) + ValType = ValType->getPointeeType(); + if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>()) + if (FPT->getNumArgs() == NumArgs) + return true; + } + } + if (FD && FD->getNumParams() >= NumArgs && + FD->getMinRequiredArguments() <= NumArgs) + return true; + } + return false; +} + +void Sema::diagnoseTypo(const TypoCorrection &Correction, + const PartialDiagnostic &TypoDiag, + bool ErrorRecovery) { + diagnoseTypo(Correction, TypoDiag, PDiag(diag::note_previous_decl), + ErrorRecovery); +} + +/// Find which declaration we should import to provide the definition of +/// the given declaration. +static const NamedDecl *getDefinitionToImport(const NamedDecl *D) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + return VD->getDefinition(); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return FD->isDefined(FD) ? FD : 0; + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) + return TD->getDefinition(); + if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) + return ID->getDefinition(); + if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + return PD->getDefinition(); + if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) + return getDefinitionToImport(TD->getTemplatedDecl()); + return 0; +} + +/// \brief Diagnose a successfully-corrected typo. Separated from the correction +/// itself to allow external validation of the result, etc. +/// +/// \param Correction The result of performing typo correction. +/// \param TypoDiag The diagnostic to produce. This will have the corrected +/// string added to it (and usually also a fixit). +/// \param PrevNote A note to use when indicating the location of the entity to +/// which we are correcting. Will have the correction string added to it. +/// \param ErrorRecovery If \c true (the default), the caller is going to +/// recover from the typo as if the corrected string had been typed. +/// In this case, \c PDiag must be an error, and we will attach a fixit +/// to it. +void Sema::diagnoseTypo(const TypoCorrection &Correction, + const PartialDiagnostic &TypoDiag, + const PartialDiagnostic &PrevNote, + bool ErrorRecovery) { + std::string CorrectedStr = Correction.getAsString(getLangOpts()); + std::string CorrectedQuotedStr = Correction.getQuoted(getLangOpts()); + FixItHint FixTypo = FixItHint::CreateReplacement( + Correction.getCorrectionRange(), CorrectedStr); + + // Maybe we're just missing a module import. + if (Correction.requiresImport()) { + NamedDecl *Decl = Correction.getCorrectionDecl(); + assert(Decl && "import required but no declaration to import"); + + // Suggest importing a module providing the definition of this entity, if + // possible. + const NamedDecl *Def = getDefinitionToImport(Decl); + if (!Def) + Def = Decl; + Module *Owner = Def->getOwningModule(); + assert(Owner && "definition of hidden declaration is not in a module"); + + Diag(Correction.getCorrectionRange().getBegin(), + diag::err_module_private_declaration) + << Def << Owner->getFullModuleName(); + Diag(Def->getLocation(), diag::note_previous_declaration); + + // Recover by implicitly importing this module. + if (!isSFINAEContext() && ErrorRecovery) + createImplicitModuleImport(Correction.getCorrectionRange().getBegin(), + Owner); + return; + } + + Diag(Correction.getCorrectionRange().getBegin(), TypoDiag) + << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint()); + + NamedDecl *ChosenDecl = + Correction.isKeyword() ? 0 : Correction.getCorrectionDecl(); + if (PrevNote.getDiagID() && ChosenDecl) + Diag(ChosenDecl->getLocation(), PrevNote) + << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); +} |