summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp825
1 files changed, 518 insertions, 307 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index d5bee1d..966eb90 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -25,26 +25,28 @@
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclLookups.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/edit_distance.h"
#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <iterator>
#include <limits>
#include <list>
+#include <map>
#include <set>
-#include <vector>
-#include <iterator>
#include <utility>
-#include <algorithm>
-#include <map>
+#include <vector>
using namespace clang;
using namespace sema;
@@ -105,13 +107,15 @@ namespace {
assert(InnermostFileDC && InnermostFileDC->isFileContext());
for (; S; S = S->getParent()) {
- if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
- DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
- visit(Ctx, EffectiveDC);
- } else {
+ // 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());
+ if (Ctx && Ctx->isFileContext()) {
+ visit(Ctx, Ctx);
+ } else if (!Ctx || Ctx->isFunctionOrMethod()) {
Scope::udir_iterator I = S->using_directives_begin(),
End = S->using_directives_end();
-
for (; I != End; ++I)
visit(*I, InnermostFileDC);
}
@@ -280,7 +284,7 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
}
void LookupResult::configure() {
- IDNS = getIDNS(LookupKind, SemaRef.getLangOptions().CPlusPlus,
+ IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus,
isForRedeclaration());
// If we're looking for one of the allocation or deallocation
@@ -301,7 +305,9 @@ void LookupResult::configure() {
}
}
-void LookupResult::sanity() const {
+void LookupResult::sanityImpl() const {
+ // Note that this function is never called by NDEBUG builds. See
+ // LookupResult::sanity().
assert(ResultKind != NotFound || Decls.size() == 0);
assert(ResultKind != Found || Decls.size() == 1);
assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
@@ -321,6 +327,12 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) {
delete Paths;
}
+static NamedDecl *getVisibleDecl(NamedDecl *D);
+
+NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
+ return getVisibleDecl(D);
+}
+
/// Resolves the result kind of this lookup.
void LookupResult::resolveKind() {
unsigned N = Decls.size();
@@ -488,7 +500,7 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
if (unsigned BuiltinID = II->getBuiltinID()) {
// In C++, we don't have any predefined library functions like
// 'malloc'. Instead, we'll just error.
- if (S.getLangOptions().CPlusPlus &&
+ if (S.getLangOpts().CPlusPlus &&
S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return false;
@@ -518,10 +530,6 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
/// the class at this point.
static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
const CXXRecordDecl *Class) {
- // Don't do it if the class is invalid.
- if (Class->isInvalidDecl())
- return false;
-
// We need to have a definition for the class.
if (!Class->getDefinition() || Class->isDependentContext())
return false;
@@ -550,7 +558,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
if (!Class->hasDeclaredCopyAssignment())
DeclareImplicitCopyAssignment(Class);
- if (getLangOptions().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus0x) {
// If the move constructor has not yet been declared, do so now.
if (Class->needsImplicitMoveConstructor())
DeclareImplicitMoveConstructor(Class); // might not actually do it
@@ -601,7 +609,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,
S.DeclareImplicitDefaultConstructor(Class);
if (!Record->hasDeclaredCopyConstructor())
S.DeclareImplicitCopyConstructor(Class);
- if (S.getLangOptions().CPlusPlus0x &&
+ if (S.getLangOpts().CPlusPlus0x &&
Record->needsImplicitMoveConstructor())
S.DeclareImplicitMoveConstructor(Class);
}
@@ -624,7 +632,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,
CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record);
if (!Record->hasDeclaredCopyAssignment())
S.DeclareImplicitCopyAssignment(Class);
- if (S.getLangOptions().CPlusPlus0x &&
+ if (S.getLangOpts().CPlusPlus0x &&
Record->needsImplicitMoveAssignment())
S.DeclareImplicitMoveAssignment(Class);
}
@@ -642,14 +650,14 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
bool Found = false;
// Lazily declare C++ special member functions.
- if (S.getLangOptions().CPlusPlus)
+ if (S.getLangOpts().CPlusPlus)
DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC);
// Perform lookup into this declaration context.
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
NamedDecl *D = *I;
- if (R.isAcceptableDecl(D)) {
+ if ((D = R.getAcceptableDecl(D))) {
R.addDecl(D);
Found = true;
}
@@ -830,7 +838,7 @@ static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
}
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
- assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup");
+ assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
DeclarationName Name = R.getLookupName();
@@ -875,9 +883,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(*I); ++I) {
- if (R.isAcceptableDecl(*I)) {
+ if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
Found = true;
- R.addDecl(*I);
+ R.addDecl(ND);
}
}
if (Found) {
@@ -926,8 +934,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(
Name.getAsIdentifierInfo(),
ClassDeclared)) {
- if (R.isAcceptableDecl(Ivar)) {
- R.addDecl(Ivar);
+ if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) {
+ R.addDecl(ND);
R.resolveKind();
return true;
}
@@ -977,13 +985,13 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(*I); ++I) {
- if (R.isAcceptableDecl(*I)) {
+ if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
// namespace, so that we can construct an overload set if we
// need to.
Found = true;
- R.addDecl(*I);
+ R.addDecl(ND);
}
}
@@ -1047,6 +1055,29 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return !R.empty();
}
+/// \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;
+
+ 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))
+ return ND;
+ }
+ }
+
+ return 0;
+}
+
/// @brief Perform unqualified name lookup starting from a given
/// scope.
///
@@ -1084,7 +1115,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
LookupNameKind NameKind = R.getLookupKind();
- if (!getLangOptions().CPlusPlus) {
+ if (!getLangOpts().CPlusPlus) {
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
if (NameKind == Sema::LookupRedeclarationWithLinkage) {
@@ -1123,29 +1154,58 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
!isa<ImplicitParamDecl>(*I))
continue;
- R.addDecl(*I);
-
- if ((*I)->getAttr<OverloadableAttr>()) {
- // If this declaration has the "overloadable" attribute, we
- // might have a set of overloaded functions.
-
- // Figure out what scope the identifier is in.
- while (!(S->getFlags() & Scope::DeclScope) ||
- !S->isDeclScope(*I))
+ // 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
+ // and in the same scope.
+ if (I != IEnd) {
+ // Find the scope in which this declaration was declared (if it
+ // actually exists in a Scope).
+ while (S && !S->isDeclScope(D))
S = S->getParent();
-
- // Find the last declaration in this scope (with the same
- // name, naturally).
+
+ // If the scope containing the declaration is the translation unit,
+ // then we'll need to perform our checks based on the matching
+ // DeclContexts rather than matching scopes.
+ if (S && isNamespaceOrTranslationUnitScope(S))
+ S = 0;
+
+ // Compute the DeclContext, if we need it.
+ DeclContext *DC = 0;
+ if (!S)
+ DC = (*I)->getDeclContext()->getRedeclContext();
+
IdentifierResolver::iterator LastI = I;
for (++LastI; LastI != IEnd; ++LastI) {
- if (!S->isDeclScope(*LastI))
- break;
- R.addDecl(*LastI);
+ if (S) {
+ // Match based on scope.
+ if (!S->isDeclScope(*LastI))
+ break;
+ } else {
+ // Match based on DeclContext.
+ DeclContext *LastDC
+ = (*LastI)->getDeclContext()->getRedeclContext();
+ 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);
}
- }
-
- R.resolveKind();
+ R.resolveKind();
+ }
return true;
}
} else {
@@ -1203,7 +1263,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
if (I == E) return false;
// We have at least added all these contexts to the queue.
- llvm::DenseSet<DeclContext*> Visited;
+ llvm::SmallPtrSet<DeclContext*, 8> Visited;
Visited.insert(StartDC);
// We have not yet looked into these namespaces, much less added
@@ -1214,7 +1274,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
// with its using-children.
for (; I != E; ++I) {
NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
- if (Visited.insert(ND).second)
+ if (Visited.insert(ND))
Queue.push_back(ND);
}
@@ -1263,7 +1323,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
NamespaceDecl *Nom = (*I)->getNominatedNamespace();
- if (Visited.insert(Nom).second)
+ if (Visited.insert(Nom))
Queue.push_back(Nom);
}
}
@@ -1354,8 +1414,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
assert((!isa<TagDecl>(LookupCtx) ||
LookupCtx->isDependentContext() ||
cast<TagDecl>(LookupCtx)->isCompleteDefinition() ||
- Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>()
- ->isBeingDefined()) &&
+ cast<TagDecl>(LookupCtx)->isBeingDefined()) &&
"Declaration context must already be complete!");
// Perform qualified name lookup into the LookupCtx.
@@ -1561,13 +1620,14 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
return false;
R.setContextRange(SS->getRange());
-
return LookupQualifiedName(R, DC);
}
// We could not resolve the scope specified to a specific declaration
// context, which means that SS refers to an unknown specialization.
// Name lookup can't find anything in this case.
+ R.setNotFoundInCurrentInstantiation();
+ R.setContextRange(SS->getRange());
return false;
}
@@ -1673,7 +1733,6 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
}
llvm_unreachable("unknown ambiguity kind");
- return true;
}
namespace {
@@ -2022,7 +2081,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
/// namespaces searched by argument-dependent lookup
/// (C++ [basic.lookup.argdep]) for a given set of arguments.
void
-Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
+Sema::FindAssociatedClassesAndNamespaces(llvm::ArrayRef<Expr *> Args,
AssociatedNamespaceSet &AssociatedNamespaces,
AssociatedClassSet &AssociatedClasses) {
AssociatedNamespaces.clear();
@@ -2037,7 +2096,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
// classes is determined entirely by the types of the function
// arguments (and the namespace of any template template
// argument).
- for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) {
+ for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
Expr *Arg = Args[ArgIdx];
if (Arg->getType() != Context.OverloadTy) {
@@ -2124,9 +2183,10 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
/// \brief Find the protocol with the given name, if any.
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
- SourceLocation IdLoc) {
+ SourceLocation IdLoc,
+ RedeclarationKind Redecl) {
Decl *D = LookupSingleName(TUScope, II, IdLoc,
- LookupObjCProtocolName);
+ LookupObjCProtocolName, Redecl);
return cast_or_null<ObjCProtocolDecl>(D);
}
@@ -2215,8 +2275,9 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
CXXDestructorDecl *DD = RD->getDestructor();
assert(DD && "record without a destructor");
Result->setMethod(DD);
- Result->setSuccess(DD->isDeleted());
- Result->setConstParamMatch(false);
+ Result->setKind(DD->isDeleted() ?
+ SpecialMemberOverloadResult::NoMemberOrDeleted :
+ SpecialMemberOverloadResult::SuccessNonConst);
return Result;
}
@@ -2237,13 +2298,13 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
Name = Context.DeclarationNames.getCXXConstructorName(CanTy);
if (!RD->hasDeclaredCopyConstructor())
DeclareImplicitCopyConstructor(RD);
- if (getLangOptions().CPlusPlus0x && RD->needsImplicitMoveConstructor())
+ if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor())
DeclareImplicitMoveConstructor(RD);
} else {
Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
if (!RD->hasDeclaredCopyAssignment())
DeclareImplicitCopyAssignment(RD);
- if (getLangOptions().CPlusPlus0x && RD->needsImplicitMoveAssignment())
+ if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment())
DeclareImplicitMoveAssignment(RD);
}
@@ -2286,7 +2347,8 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// will always be a (possibly implicit) declaration to shadow any others.
OverloadCandidateSet OCS((SourceLocation()));
DeclContext::lookup_iterator I, E;
- Result->setConstParamMatch(false);
+ SpecialMemberOverloadResult::Kind SuccessKind =
+ SpecialMemberOverloadResult::SuccessNonConst;
llvm::tie(I, E) = RD->lookup(Name);
assert((I != E) &&
@@ -2311,10 +2373,11 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand)) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD, ThisTy,
- Classification, &Arg, NumArgs, OCS, true);
+ Classification, llvm::makeArrayRef(&Arg, NumArgs),
+ OCS, true);
else
- AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), &Arg,
- NumArgs, OCS, true);
+ AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public),
+ llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
// Here we're looking for a const parameter to speed up creation of
// implicit copy methods.
@@ -2324,17 +2387,19 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0);
if (!ArgType->isReferenceType() ||
ArgType->getPointeeType().isConstQualified())
- Result->setConstParamMatch(true);
+ SuccessKind = SpecialMemberOverloadResult::SuccessConst;
}
} else if (FunctionTemplateDecl *Tmpl =
dyn_cast<FunctionTemplateDecl>(Cand)) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- RD, 0, ThisTy, Classification, &Arg, NumArgs,
+ RD, 0, ThisTy, Classification,
+ llvm::makeArrayRef(&Arg, NumArgs),
OCS, true);
else
AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- 0, &Arg, NumArgs, OCS, true);
+ 0, llvm::makeArrayRef(&Arg, NumArgs),
+ OCS, true);
} else {
assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl");
}
@@ -2344,18 +2409,22 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) {
case OR_Success:
Result->setMethod(cast<CXXMethodDecl>(Best->Function));
- Result->setSuccess(true);
+ Result->setKind(SuccessKind);
break;
case OR_Deleted:
Result->setMethod(cast<CXXMethodDecl>(Best->Function));
- Result->setSuccess(false);
+ Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
break;
case OR_Ambiguous:
+ Result->setMethod(0);
+ Result->setKind(SpecialMemberOverloadResult::Ambiguous);
+ break;
+
case OR_No_Viable_Function:
Result->setMethod(0);
- Result->setSuccess(false);
+ Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
break;
}
@@ -2404,7 +2473,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
DeclareImplicitDefaultConstructor(Class);
if (!Class->hasDeclaredCopyConstructor())
DeclareImplicitCopyConstructor(Class);
- if (getLangOptions().CPlusPlus0x && Class->needsImplicitMoveConstructor())
+ if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor())
DeclareImplicitMoveConstructor(Class);
}
@@ -2460,6 +2529,105 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
false, false)->getMethod());
}
+/// LookupLiteralOperator - Determine which literal operator should be used for
+/// a user-defined literal, per C++11 [lex.ext].
+///
+/// Normal overload resolution is not used to select which literal operator to
+/// call for a user-defined literal. Look up the provided literal operator name,
+/// and filter the results to the appropriate set for the given argument types.
+Sema::LiteralOperatorLookupResult
+Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
+ ArrayRef<QualType> ArgTys,
+ bool AllowRawAndTemplate) {
+ LookupName(R, S);
+ assert(R.getResultKind() != LookupResult::Ambiguous &&
+ "literal operator lookup can't be ambiguous");
+
+ // Filter the lookup results appropriately.
+ LookupResult::Filter F = R.makeFilter();
+
+ bool FoundTemplate = false;
+ bool FoundRaw = false;
+ bool FoundExactMatch = false;
+
+ while (F.hasNext()) {
+ Decl *D = F.next();
+ if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
+ D = USD->getTargetDecl();
+
+ bool IsTemplate = isa<FunctionTemplateDecl>(D);
+ bool IsRaw = false;
+ bool IsExactMatch = false;
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getNumParams() == 1 &&
+ FD->getParamDecl(0)->getType()->getAs<PointerType>())
+ IsRaw = true;
+ else {
+ IsExactMatch = true;
+ for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) {
+ QualType ParamTy = FD->getParamDecl(ArgIdx)->getType();
+ if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) {
+ IsExactMatch = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (IsExactMatch) {
+ FoundExactMatch = true;
+ AllowRawAndTemplate = false;
+ if (FoundRaw || FoundTemplate) {
+ // Go through again and remove the raw and template decls we've
+ // already found.
+ F.restart();
+ FoundRaw = FoundTemplate = false;
+ }
+ } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) {
+ FoundTemplate |= IsTemplate;
+ FoundRaw |= IsRaw;
+ } else {
+ F.erase();
+ }
+ }
+
+ F.done();
+
+ // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching
+ // parameter type, that is used in preference to a raw literal operator
+ // or literal operator template.
+ if (FoundExactMatch)
+ return LOLR_Cooked;
+
+ // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal
+ // operator template, but not both.
+ 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) {
+ Decl *D = *I;
+ if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
+ D = USD->getTargetDecl();
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+ D = FunTmpl->getTemplatedDecl();
+ NoteOverloadCandidate(cast<FunctionDecl>(D));
+ }
+ return LOLR_Error;
+ }
+
+ if (FoundRaw)
+ return LOLR_Raw;
+
+ if (FoundTemplate)
+ return LOLR_Template;
+
+ // 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;
+ return LOLR_Error;
+}
+
void ADLResult::insert(NamedDecl *New) {
NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
@@ -2482,7 +2650,7 @@ void ADLResult::insert(NamedDecl *New) {
FunctionDecl *Cursor = NewFD;
while (true) {
- Cursor = Cursor->getPreviousDeclaration();
+ Cursor = Cursor->getPreviousDecl();
// If we got to the end without finding OldFD, OldFD is the newer
// declaration; leave things as they are.
@@ -2498,14 +2666,15 @@ void ADLResult::insert(NamedDecl *New) {
}
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
- Expr **Args, unsigned NumArgs,
+ SourceLocation Loc,
+ llvm::ArrayRef<Expr *> Args,
ADLResult &Result,
bool StdNamespaceIsAssociated) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
AssociatedClassSet AssociatedClasses;
- FindAssociatedClassesAndNamespaces(Args, NumArgs,
+ FindAssociatedClassesAndNamespaces(Args,
AssociatedNamespaces,
AssociatedClasses);
if (StdNamespaceIsAssociated && StdNamespace)
@@ -2514,10 +2683,17 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
QualType T1, T2;
if (Operator) {
T1 = Args[0]->getType();
- if (NumArgs >= 2)
+ if (Args.size() >= 2)
T2 = Args[1]->getType();
}
+ // Try to complete all associated classes, in case they contain a
+ // declaration of a friend function.
+ for (AssociatedClassSet::iterator C = AssociatedClasses.begin(),
+ CEnd = AssociatedClasses.end();
+ C != CEnd; ++C)
+ RequireCompleteType(Loc, Context.getRecordType(*C), 0);
+
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
@@ -2700,42 +2876,15 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
// Enumerate all of the results in this context.
- for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
- CurCtx = CurCtx->getNextContext()) {
- for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
- DEnd = CurCtx->decls_end();
- D != DEnd; ++D) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
- if (Result.isAcceptableDecl(ND)) {
+ for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(),
+ LEnd = Ctx->lookups_end();
+ L != LEnd; ++L) {
+ for (DeclContext::lookup_result R = *L; R.first != R.second; ++R.first) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*R.first)) {
+ if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
Visited.add(ND);
}
- } else if (ObjCForwardProtocolDecl *ForwardProto
- = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
- for (ObjCForwardProtocolDecl::protocol_iterator
- P = ForwardProto->protocol_begin(),
- PEnd = ForwardProto->protocol_end();
- P != PEnd;
- ++P) {
- if (Result.isAcceptableDecl(*P)) {
- Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass);
- Visited.add(*P);
- }
- }
- } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
- ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
- if (Result.isAcceptableDecl(IFace)) {
- Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx,
- InBaseClass);
- Visited.add(IFace);
- }
- }
-
- // Visit transparent contexts and inline namespaces inside this context.
- if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
- if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
- LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass,
- Consumer, Visited);
}
}
}
@@ -2826,7 +2975,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (IFace->getImplementation()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(IFace->getImplementation(), Result,
- QualifiedNameLookup, true, Consumer, Visited);
+ QualifiedNameLookup, InBaseClass, Consumer, Visited);
}
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
@@ -2867,7 +3016,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
- if (Result.isAcceptableDecl(ND)) {
+ if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
Visited.add(ND);
}
@@ -2946,7 +3095,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
// unqualified name lookup.
Scope *Initial = S;
UnqualUsingDirectiveSet UDirs;
- if (getLangOptions().CPlusPlus) {
+ if (getLangOpts().CPlusPlus) {
// Find the first namespace or translation-unit scope.
while (S && !isNamespaceOrTranslationUnitScope(S))
S = S->getParent();
@@ -3031,15 +3180,11 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
/// whether there is a keyword with this name.
TypoEditDistanceMap BestResults;
- /// \brief The worst of the best N edit distances found so far.
- unsigned MaxEditDistance;
-
Sema &SemaRef;
public:
explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)
: Typo(Typo->getName()),
- MaxEditDistance((std::numeric_limits<unsigned>::max)()),
SemaRef(SemaRef) { }
~TypoCorrectionConsumer() {
@@ -3070,12 +3215,12 @@ public:
return (*BestResults.begin()->second)[Name];
}
- unsigned getMaxEditDistance() const {
- return MaxEditDistance;
- }
+ unsigned getBestEditDistance(bool Normalized) {
+ if (BestResults.empty())
+ return (std::numeric_limits<unsigned>::max)();
- unsigned getBestEditDistance() {
- return (BestResults.empty()) ? MaxEditDistance : BestResults.begin()->first;
+ unsigned BestED = BestResults.begin()->first;
+ return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
}
};
@@ -3101,40 +3246,22 @@ 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 > MaxEditDistance || (MinED && Typo.size() / MinED < 3))
+ 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 =
- std::min(unsigned((Typo.size() + 2) / 3), MaxEditDistance);
+ unsigned UpperBound = (Typo.size() + 2) / 3;
// Compute the edit distance between the typo and the name of this
- // entity. If this edit distance is not worse than the best edit
- // distance we've seen so far, add it to the list of results.
- unsigned ED = Typo.edit_distance(Name, true, UpperBound);
-
- if (ED > MaxEditDistance) {
- // This result is worse than the best results we've seen so far;
- // ignore it.
- return;
- }
-
- addName(Name, NULL, ED);
+ // entity, and add the identifier to the list of results.
+ addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound));
}
void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
- // Compute the edit distance between the typo and this keyword.
- // If this edit distance is not worse than the best edit
- // distance we've seen so far, add it to the list of results.
- unsigned ED = Typo.edit_distance(Keyword);
- if (ED > MaxEditDistance) {
- // This result is worse than the best results we've seen so far;
- // ignore it.
- return;
- }
-
- addName(Keyword, NULL, ED, NULL, true);
+ // 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);
}
void TypoCorrectionConsumer::addName(StringRef Name,
@@ -3149,7 +3276,7 @@ void TypoCorrectionConsumer::addName(StringRef Name,
void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
- TypoResultsMap *& Map = BestResults[Correction.getEditDistance()];
+ TypoResultsMap *& Map = BestResults[Correction.getEditDistance(false)];
if (!Map)
Map = new TypoResultsMap;
@@ -3158,8 +3285,8 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
// FIXME: The following should be rolled up into an operator< on
// TypoCorrection with a more principled definition.
CurrentCorrection.isKeyword() < Correction.isKeyword() ||
- Correction.getAsString(SemaRef.getLangOptions()) <
- CurrentCorrection.getAsString(SemaRef.getLangOptions()))
+ Correction.getAsString(SemaRef.getLangOpts()) <
+ CurrentCorrection.getAsString(SemaRef.getLangOpts()))
CurrentCorrection = Correction;
while (BestResults.size() > MaxTypoDistanceResultSets) {
@@ -3170,6 +3297,47 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
}
}
+// Fill the supplied vector with the IdentifierInfo pointers for each piece of
+// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
+// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
+static void getNestedNameSpecifierIdentifiers(
+ NestedNameSpecifier *NNS,
+ SmallVectorImpl<const IdentifierInfo*> &Identifiers) {
+ if (NestedNameSpecifier *Prefix = NNS->getPrefix())
+ getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
+ else
+ Identifiers.clear();
+
+ const IdentifierInfo *II = NULL;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ II = NNS->getAsIdentifier();
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ if (NNS->getAsNamespace()->isAnonymousNamespace())
+ return;
+ II = NNS->getAsNamespace()->getIdentifier();
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ II = NNS->getAsNamespaceAlias()->getIdentifier();
+ break;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec:
+ II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
+ break;
+
+ case NestedNameSpecifier::Global:
+ return;
+ }
+
+ if (II)
+ Identifiers.push_back(II);
+}
+
namespace {
class SpecifierInfo {
@@ -3188,6 +3356,8 @@ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
class NamespaceSpecifierSet {
ASTContext &Context;
DeclContextList CurContextChain;
+ SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
+ SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
bool isSorted;
SpecifierInfoList Specifiers;
@@ -3201,9 +3371,23 @@ class NamespaceSpecifierSet {
void SortNamespaces();
public:
- explicit NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext)
+ NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
+ CXXScopeSpec *CurScopeSpec)
: Context(Context), CurContextChain(BuildContextChain(CurContext)),
- isSorted(true) {}
+ isSorted(true) {
+ if (CurScopeSpec && CurScopeSpec->getScopeRep())
+ getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(),
+ CurNameSpecifierIdentifiers);
+ // Build the list of identifiers that would be used for an absolute
+ // (from the global context) NestedNameSpecifier refering 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))
+ CurContextIdentifiers.push_back(ND->getIdentifier());
+ }
+ }
/// \brief Add the namespace to the set, computing the corresponding
/// NestedNameSpecifier and its distance in the process.
@@ -3241,7 +3425,7 @@ void NamespaceSpecifierSet::SortNamespaces() {
Specifiers.clear();
for (SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(),
- DIEnd = sortedDistances.end();
+ DIEnd = sortedDistances.end();
DI != DIEnd; ++DI) {
SpecifierInfoList &SpecList = DistanceMap[*DI];
Specifiers.append(SpecList.begin(), SpecList.end());
@@ -3255,8 +3439,9 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
NestedNameSpecifier *NNS = NULL;
unsigned NumSpecifiers = 0;
DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));
+ DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
- // Eliminate common elements from the two DeclContext chains
+ // Eliminate common elements from the two DeclContext chains.
for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
CEnd = CurContextChain.rend();
C != CEnd && !NamespaceDeclChain.empty() &&
@@ -3264,6 +3449,21 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
NamespaceDeclChain.pop_back();
}
+ // Add an explicit leading '::' specifier if needed.
+ if (NamespaceDecl *ND =
+ NamespaceDeclChain.empty() ? NULL :
+ dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) {
+ IdentifierInfo *Name = ND->getIdentifier();
+ if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(),
+ Name) != CurContextIdentifiers.end() ||
+ std::find(CurNameSpecifierIdentifiers.begin(),
+ CurNameSpecifierIdentifiers.end(),
+ Name) != CurNameSpecifierIdentifiers.end()) {
+ NamespaceDeclChain = FullNamespaceDeclChain;
+ NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ }
+ }
+
// Build the NestedNameSpecifier from what is left of the NamespaceDeclChain
for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(),
CEnd = NamespaceDeclChain.rend();
@@ -3275,6 +3475,18 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
}
}
+ // If the built NestedNameSpecifier would be replacing an existing
+ // NestedNameSpecifier, use the number of component identifiers that
+ // would need to be changed as the edit distance instead of the number
+ // of components in the built NestedNameSpecifier.
+ if (NNS && !CurNameSpecifierIdentifiers.empty()) {
+ SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers;
+ getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
+ NumSpecifiers = llvm::ComputeEditDistance(
+ llvm::ArrayRef<const IdentifierInfo*>(CurNameSpecifierIdentifiers),
+ llvm::ArrayRef<const IdentifierInfo*>(NewNameSpecifierIdentifiers));
+ }
+
isSorted = false;
Distances.insert(NumSpecifiers);
DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers));
@@ -3287,13 +3499,13 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
Scope *S, CXXScopeSpec *SS,
DeclContext *MemberContext,
bool EnteringContext,
- Sema::CorrectTypoContext CTC) {
+ bool isObjCIvarLookup) {
Res.suppressDiagnostics();
Res.clear();
Res.setLookupName(Name);
if (MemberContext) {
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
- if (CTC == Sema::CTC_ObjCIvarLookup) {
+ if (isObjCIvarLookup) {
if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) {
Res.addDecl(Ivar);
Res.resolveKind();
@@ -3334,61 +3546,11 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
/// \brief Add keywords to the consumer as possible typo corrections.
static void AddKeywordsToConsumer(Sema &SemaRef,
TypoCorrectionConsumer &Consumer,
- Scope *S, Sema::CorrectTypoContext CTC) {
- // Add context-dependent keywords.
- bool WantTypeSpecifiers = false;
- bool WantExpressionKeywords = false;
- bool WantCXXNamedCasts = false;
- bool WantRemainingKeywords = false;
- switch (CTC) {
- case Sema::CTC_Unknown:
- WantTypeSpecifiers = true;
- WantExpressionKeywords = true;
- WantCXXNamedCasts = true;
- WantRemainingKeywords = true;
-
- if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
- if (Method->getClassInterface() &&
- Method->getClassInterface()->getSuperClass())
- Consumer.addKeywordResult("super");
-
- break;
-
- case Sema::CTC_NoKeywords:
- break;
-
- case Sema::CTC_Type:
- WantTypeSpecifiers = true;
- break;
-
- case Sema::CTC_ObjCMessageReceiver:
- Consumer.addKeywordResult("super");
- // Fall through to handle message receivers like expressions.
-
- case Sema::CTC_Expression:
- if (SemaRef.getLangOptions().CPlusPlus)
- WantTypeSpecifiers = true;
- WantExpressionKeywords = true;
- // Fall through to get C++ named casts.
-
- case Sema::CTC_CXXCasts:
- WantCXXNamedCasts = true;
- break;
-
- case Sema::CTC_ObjCPropertyLookup:
- // FIXME: Add "isa"?
- break;
-
- case Sema::CTC_MemberLookup:
- if (SemaRef.getLangOptions().CPlusPlus)
- Consumer.addKeywordResult("template");
- break;
-
- case Sema::CTC_ObjCIvarLookup:
- break;
- }
+ Scope *S, CorrectionCandidateCallback &CCC) {
+ if (CCC.WantObjCSuper)
+ Consumer.addKeywordResult("super");
- if (WantTypeSpecifiers) {
+ if (CCC.WantTypeSpecifiers) {
// Add type-specifier keywords to the set of results.
const char *CTypeSpecs[] = {
"char", "const", "double", "enum", "float", "int", "long", "short",
@@ -3402,19 +3564,19 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
for (unsigned I = 0; I != NumCTypeSpecs; ++I)
Consumer.addKeywordResult(CTypeSpecs[I]);
- if (SemaRef.getLangOptions().C99)
+ if (SemaRef.getLangOpts().C99)
Consumer.addKeywordResult("restrict");
- if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus)
+ if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus)
Consumer.addKeywordResult("bool");
- else if (SemaRef.getLangOptions().C99)
+ else if (SemaRef.getLangOpts().C99)
Consumer.addKeywordResult("_Bool");
- if (SemaRef.getLangOptions().CPlusPlus) {
+ if (SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("class");
Consumer.addKeywordResult("typename");
Consumer.addKeywordResult("wchar_t");
- if (SemaRef.getLangOptions().CPlusPlus0x) {
+ if (SemaRef.getLangOpts().CPlusPlus0x) {
Consumer.addKeywordResult("char16_t");
Consumer.addKeywordResult("char32_t");
Consumer.addKeywordResult("constexpr");
@@ -3423,25 +3585,25 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
- if (SemaRef.getLangOptions().GNUMode)
+ if (SemaRef.getLangOpts().GNUMode)
Consumer.addKeywordResult("typeof");
}
- if (WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {
+ if (CCC.WantCXXNamedCasts && SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("const_cast");
Consumer.addKeywordResult("dynamic_cast");
Consumer.addKeywordResult("reinterpret_cast");
Consumer.addKeywordResult("static_cast");
}
- if (WantExpressionKeywords) {
+ if (CCC.WantExpressionKeywords) {
Consumer.addKeywordResult("sizeof");
- if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) {
+ if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("false");
Consumer.addKeywordResult("true");
}
- if (SemaRef.getLangOptions().CPlusPlus) {
+ if (SemaRef.getLangOpts().CPlusPlus) {
const char *CXXExprs[] = {
"delete", "new", "operator", "throw", "typeid"
};
@@ -3453,14 +3615,14 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance())
Consumer.addKeywordResult("this");
- if (SemaRef.getLangOptions().CPlusPlus0x) {
+ if (SemaRef.getLangOpts().CPlusPlus0x) {
Consumer.addKeywordResult("alignof");
Consumer.addKeywordResult("nullptr");
}
}
}
- if (WantRemainingKeywords) {
+ if (CCC.WantRemainingKeywords) {
if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
// Statements.
const char *CStmts[] = {
@@ -3469,7 +3631,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
for (unsigned I = 0; I != NumCStmts; ++I)
Consumer.addKeywordResult(CStmts[I]);
- if (SemaRef.getLangOptions().CPlusPlus) {
+ if (SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("catch");
Consumer.addKeywordResult("try");
}
@@ -3485,7 +3647,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
Consumer.addKeywordResult("default");
}
} else {
- if (SemaRef.getLangOptions().CPlusPlus) {
+ if (SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("namespace");
Consumer.addKeywordResult("template");
}
@@ -3501,15 +3663,21 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
- if (SemaRef.getLangOptions().CPlusPlus) {
+ if (SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("using");
- if (SemaRef.getLangOptions().CPlusPlus0x)
+ if (SemaRef.getLangOpts().CPlusPlus0x)
Consumer.addKeywordResult("static_assert");
}
}
}
+static bool isCandidateViable(CorrectionCandidateCallback &CCC,
+ TypoCorrection &Candidate) {
+ Candidate.setCallbackDistance(CCC.RankCandidate(Candidate));
+ return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance;
+}
+
/// \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.
@@ -3524,15 +3692,16 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
/// \param SS the nested-name-specifier that precedes the name we're
/// looking for, if present.
///
+/// \param CCC A CorrectionCandidateCallback object that provides further
+/// validation of typo correction candidates. It also provides flags for
+/// determining the set of keywords permitted.
+///
/// \param MemberContext if non-NULL, the context in which to look for
/// a member access expression.
///
/// \param EnteringContext whether we're entering the context described by
/// the nested-name-specifier SS.
///
-/// \param CTC The context in which typo correction occurs, which impacts the
-/// set of keywords permitted.
-///
/// \param OPT when non-NULL, the search for visible declarations will
/// also walk the protocols in the qualified interfaces of \p OPT.
///
@@ -3543,11 +3712,18 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
DeclContext *MemberContext,
bool EnteringContext,
- CorrectTypoContext CTC,
const ObjCObjectPointerType *OPT) {
- if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
+ if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking)
+ return TypoCorrection();
+
+ // In Microsoft mode, don't perform typo correction in a template member
+ // function dependent context because it interferes with the "lookup into
+ // dependent bases of class templates" feature.
+ if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+ isa<CXXMethodDecl>(CurContext))
return TypoCorrection();
// We only attempt to correct typos for identifiers.
@@ -3565,12 +3741,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (!ActiveTemplateInstantiations.empty())
return TypoCorrection();
- NamespaceSpecifierSet Namespaces(Context, CurContext);
+ NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
TypoCorrectionConsumer Consumer(*this, Typo);
+ // If a callback object considers an empty typo correction candidate to be
+ // viable, assume it does not do any actual validation of the candidates.
+ TypoCorrection EmptyCorrection;
+ bool ValidatingCallback = !isCandidateViable(CCC, EmptyCorrection);
+
// Perform name lookup to find visible, similarly-named entities.
bool IsUnqualifiedLookup = false;
+ DeclContext *QualifiedDC = MemberContext;
if (MemberContext) {
LookupVisibleDecls(MemberContext, LookupKind, Consumer);
@@ -3582,8 +3764,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
LookupVisibleDecls(*I, LookupKind, Consumer);
}
} else if (SS && SS->isSet()) {
- DeclContext *DC = computeDeclContext(*SS, EnteringContext);
- if (!DC)
+ QualifiedDC = computeDeclContext(*SS, EnteringContext);
+ if (!QualifiedDC)
return TypoCorrection();
// Provide a stop gap for files that are just seriously broken. Trying
@@ -3593,49 +3775,65 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return TypoCorrection();
++TyposCorrected;
- LookupVisibleDecls(DC, LookupKind, Consumer);
+ LookupVisibleDecls(QualifiedDC, LookupKind, Consumer);
} else {
IsUnqualifiedLookup = true;
UnqualifiedTyposCorrectedMap::iterator Cached
= UnqualifiedTyposCorrected.find(Typo);
+ if (Cached != UnqualifiedTyposCorrected.end()) {
+ // Add the cached value, unless it's a keyword or fails validation. In the
+ // 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);
+ } else {
+ // Only honor no-correction cache hits when a callback that will validate
+ // correction candidates is not being used.
+ if (!ValidatingCallback)
+ return TypoCorrection();
+ }
+ }
if (Cached == UnqualifiedTyposCorrected.end()) {
// Provide a stop gap for files that are just seriously broken. Trying
// to correct all typos can turn into a HUGE performance penalty, causing
// some files to take minutes to get rejected by the parser.
if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
return TypoCorrection();
+ }
+ }
- // For unqualified lookup, look through all of the names that we have
- // seen in this translation unit.
- for (IdentifierTable::iterator I = Context.Idents.begin(),
- IEnd = Context.Idents.end();
- I != IEnd; ++I)
- Consumer.FoundName(I->getKey());
-
- // Walk through identifiers in external identifier sources.
- if (IdentifierInfoLookup *External
- = Context.Idents.getExternalIdentifierLookup()) {
- llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
- do {
- StringRef Name = Iter->Next();
- if (Name.empty())
- break;
+ // Determine whether we are going to search in the various namespaces for
+ // corrections.
+ bool SearchNamespaces
+ = getLangOpts().CPlusPlus &&
+ (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace()));
+
+ if (IsUnqualifiedLookup || SearchNamespaces) {
+ // For unqualified lookup, look through all of the names that we have
+ // seen in this translation unit.
+ // FIXME: Re-add the ability to skip very unlikely potential corrections.
+ for (IdentifierTable::iterator I = Context.Idents.begin(),
+ IEnd = Context.Idents.end();
+ I != IEnd; ++I)
+ Consumer.FoundName(I->getKey());
- Consumer.FoundName(Name);
- } while (true);
- }
- } else {
- // Use the cached value, unless it's a keyword. In the keyword case, we'll
- // end up adding the keyword below.
- if (!Cached->second)
- return TypoCorrection();
+ // Walk through identifiers in external identifier sources.
+ // FIXME: Re-add the ability to skip very unlikely potential corrections.
+ if (IdentifierInfoLookup *External
+ = Context.Idents.getExternalIdentifierLookup()) {
+ OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
+ do {
+ StringRef Name = Iter->Next();
+ if (Name.empty())
+ break;
- if (!Cached->second.isKeyword())
- Consumer.addCorrection(Cached->second);
+ Consumer.FoundName(Name);
+ } while (true);
}
}
- AddKeywordsToConsumer(*this, Consumer, S, CTC);
+ AddKeywordsToConsumer(*this, Consumer, S, CCC);
// If we haven't found anything, we're done.
if (Consumer.empty()) {
@@ -3648,7 +3846,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Make sure that the user typed at least 3 characters for each correction
// made. Otherwise, we don't even both looking at the results.
- unsigned ED = Consumer.getBestEditDistance();
+ 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)
@@ -3657,8 +3855,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return TypoCorrection();
}
- // Build the NestedNameSpecifiers for the KnownNamespaces
- if (getLangOptions().CPlusPlus) {
+ // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
+ // to search those namespaces.
+ if (SearchNamespaces) {
// Load any externally-known namespaces.
if (ExternalSource && !LoadedExternalKnownNamespaces) {
SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces;
@@ -3675,8 +3874,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
Namespaces.AddNamespace(KNI->first);
}
- // Weed out any names that could not be found by name lookup.
- llvm::SmallPtrSet<IdentifierInfo*, 16> QualifiedResults;
+ // Weed out any names that could not be found by name lookup or, if a
+ // CorrectionCandidateCallback object was provided, failed validation.
+ llvm::SmallVector<TypoCorrection, 16> QualifiedResults;
LookupResult TmpRes(*this, TypoName, LookupKind);
TmpRes.suppressDiagnostics();
while (!Consumer.empty()) {
@@ -3685,22 +3885,27 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(),
IEnd = DI->second->end();
I != IEnd; /* Increment in loop. */) {
- // If the item already has been looked up or is a keyword, keep it
+ // If the item already has been looked up or is a keyword, keep it.
+ // If a validator callback object was given, drop the correction
+ // unless it passes validation.
if (I->second.isResolved()) {
+ TypoCorrectionConsumer::result_iterator Prev = I;
++I;
+ if (!isCandidateViable(CCC, Prev->second))
+ DI->second->erase(Prev);
continue;
}
// Perform name lookup on this name.
IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();
LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
- EnteringContext, CTC);
+ EnteringContext, CCC.IsObjCIvarLookup);
switch (TmpRes.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::FoundUnresolvedValue:
- QualifiedResults.insert(Name);
+ QualifiedResults.push_back(I->second);
// We didn't find this name in our scope, or didn't like what we found;
// ignore it.
{
@@ -3716,32 +3921,40 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return TypoCorrection();
case LookupResult::FoundOverloaded: {
+ TypoCorrectionConsumer::result_iterator Prev = I;
// Store all of the Decls for overloaded symbols
for (LookupResult::iterator TRD = TmpRes.begin(),
TRDEnd = TmpRes.end();
TRD != TRDEnd; ++TRD)
I->second.addCorrectionDecl(*TRD);
++I;
+ if (!isCandidateViable(CCC, Prev->second))
+ DI->second->erase(Prev);
break;
}
- case LookupResult::Found:
+ case LookupResult::Found: {
+ TypoCorrectionConsumer::result_iterator Prev = I;
I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
++I;
+ if (!isCandidateViable(CCC, Prev->second))
+ DI->second->erase(Prev);
break;
}
+
+ }
}
if (DI->second->empty())
Consumer.erase(DI);
- else if (!getLangOptions().CPlusPlus || QualifiedResults.empty() || !ED)
+ else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED)
// If there are results in the closest possible bucket, stop
break;
// Only perform the qualified lookups for C++
- if (getLangOptions().CPlusPlus) {
+ if (SearchNamespaces) {
TmpRes.suppressDiagnostics();
- for (llvm::SmallPtrSet<IdentifierInfo*,
+ for (llvm::SmallVector<TypoCorrection,
16>::iterator QRI = QualifiedResults.begin(),
QRIEnd = QualifiedResults.end();
QRI != QRIEnd; ++QRI) {
@@ -3749,30 +3962,35 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
NIEnd = Namespaces.end();
NI != NIEnd; ++NI) {
DeclContext *Ctx = NI->DeclCtx;
- unsigned QualifiedED = ED + NI->EditDistance;
- // Stop searching once the namespaces are too far away to create
+ // 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)
- if (QualifiedED > Consumer.getMaxEditDistance()) break;
+ // are sorted in ascending order by edit distance).
TmpRes.clear();
- TmpRes.setLookupName(*QRI);
+ TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo());
if (!LookupQualifiedName(TmpRes, Ctx)) continue;
+ // 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:
- Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(),
- QualifiedED, NI->NameSpecifier);
+ 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::FoundOverloaded: {
- TypoCorrection corr(&Context.Idents.get((*QRI)->getName()), NULL,
- NI->NameSpecifier, QualifiedED);
+ TypoCorrection TC(*QRI);
+ TC.setCorrectionSpecifier(NI->NameSpecifier);
+ TC.setQualifierDistance(NI->EditDistance);
for (LookupResult::iterator TRD = TmpRes.begin(),
TRDEnd = TmpRes.end();
TRD != TRDEnd; ++TRD)
- corr.addCorrectionDecl(*TRD);
- Consumer.addCorrection(corr);
+ TC.addCorrectionDecl(*TRD);
+ Consumer.addCorrection(TC);
break;
}
case LookupResult::NotFound:
@@ -3792,32 +4010,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (Consumer.empty()) return TypoCorrection();
TypoResultsMap &BestResults = *Consumer.begin()->second;
- ED = Consumer.begin()->first;
+ ED = TypoCorrection::NormalizeEditDistance(Consumer.begin()->first);
if (ED > 0 && Typo->getName().size() / ED < 3) {
- // If this was an unqualified lookup, note that no correction was found.
- if (IsUnqualifiedLookup)
+ // 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();
}
- // If we have multiple possible corrections, eliminate the ones where we
- // added namespace qualifiers to try to resolve the ambiguity (and to favor
- // corrections without additional namespace qualifiers)
- if (getLangOptions().CPlusPlus && BestResults.size() > 1) {
- TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
- for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(),
- IEnd = DI->second->end();
- I != IEnd; /* Increment in loop. */) {
- if (I->second.getCorrectionSpecifier() != NULL) {
- TypoCorrectionConsumer::result_iterator Cur = I;
- ++I;
- DI->second->erase(Cur);
- } else ++I;
- }
- }
-
// If only a single name remains, return that result.
if (BestResults.size() == 1) {
const llvm::StringMapEntry<TypoCorrection> &Correction = *(BestResults.begin());
@@ -3833,7 +4037,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return Result;
}
- else if (BestResults.size() > 1 && CTC == CTC_ObjCMessageReceiver
+ else if (BestResults.size() > 1
+ // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
+ // 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.
+ && CCC.WantObjCSuper && !CCC.WantRemainingKeywords
&& BestResults["super"].isKeyword()) {
// Prefer 'super' when we're completing in a message-receiver
// context.
@@ -3849,7 +4058,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return BestResults["super"];
}
- if (IsUnqualifiedLookup)
+ // If this was an unqualified lookup and we believe the callback object did
+ // not filter out possible corrections, note that no correction was found.
+ if (IsUnqualifiedLookup && !ValidatingCallback)
(void)UnqualifiedTyposCorrected[Typo];
return TypoCorrection();
OpenPOWER on IntegriCloud