aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r--lib/Sema/SemaLookup.cpp318
1 files changed, 197 insertions, 121 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index f5d2a7d89988..c7569d6eda25 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -404,7 +404,7 @@ void LookupResult::resolveKind() {
}
void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
- CXXBasePaths::paths_iterator I, E;
+ CXXBasePaths::const_paths_iterator I, E;
DeclContext::lookup_iterator DI, DE;
for (I = P.begin(), E = P.end(); I != E; ++I)
for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
@@ -438,9 +438,42 @@ void LookupResult::print(llvm::raw_ostream &Out) {
}
}
+/// \brief Lookup a builtin function, when name lookup would otherwise
+/// fail.
+static bool LookupBuiltin(Sema &S, LookupResult &R) {
+ Sema::LookupNameKind NameKind = R.getLookupKind();
+
+ // If we didn't find a use of this identifier, and if the identifier
+ // corresponds to a compiler builtin, create the decl object for the builtin
+ // now, injecting it into translation unit scope, and return it.
+ if (NameKind == Sema::LookupOrdinaryName ||
+ NameKind == Sema::LookupRedeclarationWithLinkage) {
+ IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
+ if (II) {
+ // If this is a builtin on this (or all) targets, create the decl.
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ // In C++, we don't have any predefined library functions like
+ // 'malloc'. Instead, we'll just error.
+ if (S.getLangOptions().CPlusPlus &&
+ S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return false;
+
+ NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+ S.TUScope, R.isForRedeclaration(),
+ R.getNameLoc());
+ if (D)
+ R.addDecl(D);
+ return (D != NULL);
+ }
+ }
+ }
+
+ return false;
+}
+
// Adds all qualifying matches for a name within a decl context to the
// given lookup result. Returns true if any matches were found.
-static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
+static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
bool Found = false;
DeclContext::lookup_const_iterator I, E;
@@ -452,87 +485,89 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
}
}
+ if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R))
+ return true;
+
if (R.getLookupName().getNameKind()
- == DeclarationName::CXXConversionFunctionName &&
- !R.getLookupName().getCXXNameType()->isDependentType() &&
- isa<CXXRecordDecl>(DC)) {
+ != DeclarationName::CXXConversionFunctionName ||
+ R.getLookupName().getCXXNameType()->isDependentType() ||
+ !isa<CXXRecordDecl>(DC))
+ return Found;
+
+ // C++ [temp.mem]p6:
+ // A specialization of a conversion function template is not found by
+ // name lookup. Instead, any conversion function templates visible in the
+ // context of the use are considered. [...]
+ const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+ if (!Record->isDefinition())
+ return Found;
+
+ const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
+ for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
+ UEnd = Unresolved->end(); U != UEnd; ++U) {
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
+ if (!ConvTemplate)
+ continue;
+
+ // When we're performing lookup for the purposes of redeclaration, just
+ // add the conversion function template. When we deduce template
+ // arguments for specializations, we'll end up unifying the return
+ // type of the new declaration with the type of the function template.
+ if (R.isForRedeclaration()) {
+ R.addDecl(ConvTemplate);
+ Found = true;
+ continue;
+ }
+
// C++ [temp.mem]p6:
- // A specialization of a conversion function template is not found by
- // name lookup. Instead, any conversion function templates visible in the
- // context of the use are considered. [...]
- const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
- if (!Record->isDefinition())
- return Found;
-
- const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
- for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
- UEnd = Unresolved->end(); U != UEnd; ++U) {
- FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
- if (!ConvTemplate)
- continue;
-
- // When we're performing lookup for the purposes of redeclaration, just
- // add the conversion function template. When we deduce template
- // arguments for specializations, we'll end up unifying the return
- // type of the new declaration with the type of the function template.
- if (R.isForRedeclaration()) {
- R.addDecl(ConvTemplate);
- Found = true;
- continue;
- }
-
- // C++ [temp.mem]p6:
- // [...] For each such operator, if argument deduction succeeds
- // (14.9.2.3), the resulting specialization is used as if found by
- // name lookup.
- //
- // When referencing a conversion function for any purpose other than
- // a redeclaration (such that we'll be building an expression with the
- // result), perform template argument deduction and place the
- // specialization into the result set. We do this to avoid forcing all
- // callers to perform special deduction for conversion functions.
- Sema::TemplateDeductionInfo Info(R.getSema().Context);
- FunctionDecl *Specialization = 0;
-
- const FunctionProtoType *ConvProto
- = ConvTemplate->getTemplatedDecl()->getType()
- ->getAs<FunctionProtoType>();
- assert(ConvProto && "Nonsensical conversion function template type");
-
- // Compute the type of the function that we would expect the conversion
- // function to have, if it were to match the name given.
- // FIXME: Calling convention!
- QualType ExpectedType
- = R.getSema().Context.getFunctionType(
- R.getLookupName().getCXXNameType(),
- 0, 0, ConvProto->isVariadic(),
- ConvProto->getTypeQuals(),
- false, false, 0, 0,
- ConvProto->getNoReturnAttr());
-
- // Perform template argument deduction against the type that we would
- // expect the function to have.
- if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
- Specialization, Info)
- == Sema::TDK_Success) {
- R.addDecl(Specialization);
- Found = true;
- }
+ // [...] For each such operator, if argument deduction succeeds
+ // (14.9.2.3), the resulting specialization is used as if found by
+ // name lookup.
+ //
+ // When referencing a conversion function for any purpose other than
+ // a redeclaration (such that we'll be building an expression with the
+ // result), perform template argument deduction and place the
+ // specialization into the result set. We do this to avoid forcing all
+ // callers to perform special deduction for conversion functions.
+ Sema::TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
+ FunctionDecl *Specialization = 0;
+
+ const FunctionProtoType *ConvProto
+ = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
+ assert(ConvProto && "Nonsensical conversion function template type");
+
+ // Compute the type of the function that we would expect the conversion
+ // function to have, if it were to match the name given.
+ // FIXME: Calling convention!
+ QualType ExpectedType
+ = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
+ 0, 0, ConvProto->isVariadic(),
+ ConvProto->getTypeQuals(),
+ false, false, 0, 0,
+ ConvProto->getNoReturnAttr());
+
+ // Perform template argument deduction against the type that we would
+ // expect the function to have.
+ if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+ Specialization, Info)
+ == Sema::TDK_Success) {
+ R.addDecl(Specialization);
+ Found = true;
}
}
-
+
return Found;
}
// Performs C++ unqualified lookup into the given file context.
static bool
-CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
- UnqualUsingDirectiveSet &UDirs) {
+CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
+ DeclContext *NS, UnqualUsingDirectiveSet &UDirs) {
assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
// Perform direct name lookup into the LookupCtx.
- bool Found = LookupDirect(R, NS);
+ bool Found = LookupDirect(S, R, NS);
// Perform direct name lookup into the namespaces nominated by the
// using directives whose common ancestor is this namespace.
@@ -540,7 +575,7 @@ CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
for (; UI != UEnd; ++UI)
- if (LookupDirect(R, UI->getNominatedNamespace()))
+ if (LookupDirect(S, R, UI->getNominatedNamespace()))
Found = true;
R.resolveKind();
@@ -650,12 +685,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
for (; S; S = S->getParent()) {
DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
- if (!Ctx || Ctx->isTransparentContext())
+ if (Ctx && Ctx->isTransparentContext())
continue;
- assert(Ctx && Ctx->isFileContext() &&
- "We should have been looking only at file context here already.");
-
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
@@ -669,16 +701,21 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
}
}
- // Look into context considering using-directives.
- if (CppNamespaceLookup(R, Context, Ctx, UDirs))
- Found = true;
+ if (Ctx) {
+ assert(Ctx->isFileContext() &&
+ "We should have been looking only at file context here already.");
+
+ // Look into context considering using-directives.
+ if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+ Found = true;
+ }
if (Found) {
R.resolveKind();
return true;
}
- if (R.isForRedeclaration() && !Ctx->isTransparentContext())
+ if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
return false;
}
@@ -793,26 +830,9 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
- if (NameKind == LookupOrdinaryName ||
- NameKind == LookupRedeclarationWithLinkage) {
- IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (II && AllowBuiltinCreation) {
- // If this is a builtin on this (or all) targets, create the decl.
- if (unsigned BuiltinID = II->getBuiltinID()) {
- // In C++, we don't have any predefined library functions like
- // 'malloc'. Instead, we'll just error.
- if (getLangOptions().CPlusPlus &&
- Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- return false;
+ if (AllowBuiltinCreation)
+ return LookupBuiltin(*this, R);
- NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
- S, R.isForRedeclaration(),
- R.getNameLoc());
- if (D) R.addDecl(D);
- return (D != NULL);
- }
- }
- }
return false;
}
@@ -842,7 +862,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
/// class or enumeration name if and only if the declarations are
/// from the same namespace; otherwise (the declarations are from
/// different namespaces), the program is ill-formed.
-static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
+static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
DeclContext *StartDC) {
assert(StartDC->isFileContext() && "start context is not a file context");
@@ -885,7 +905,7 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
// between LookupResults.
bool UseLocal = !R.empty();
LookupResult &DirectR = UseLocal ? LocalR : R;
- bool FoundDirect = LookupDirect(DirectR, ND);
+ bool FoundDirect = LookupDirect(S, DirectR, ND);
if (FoundDirect) {
// First do any local hiding.
@@ -965,7 +985,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
"Declaration context must already be complete!");
// Perform qualified name lookup into the LookupCtx.
- if (LookupDirect(R, LookupCtx)) {
+ if (LookupDirect(*this, R, LookupCtx)) {
R.resolveKind();
if (isa<CXXRecordDecl>(LookupCtx))
R.setNamingClass(cast<CXXRecordDecl>(LookupCtx));
@@ -986,7 +1006,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// If this is a namespace, look it up in the implied namespaces.
if (LookupCtx->isFileContext())
- return LookupQualifiedNameInUsingDirectives(R, LookupCtx);
+ return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx);
// If this isn't a C++ class, we aren't allowed to look into base
// classes, we're done.
@@ -1407,6 +1427,12 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
AssociatedClasses);
}
+ // Only recurse into base classes for complete types.
+ if (!Class->hasDefinition()) {
+ // FIXME: we might need to instantiate templates here
+ return;
+ }
+
// Add direct and indirect base classes along with their associated
// namespaces.
llvm::SmallVector<CXXRecordDecl *, 32> Bases;
@@ -1693,7 +1719,7 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
- FunctionSet &Functions) {
+ UnresolvedSetImpl &Functions) {
// C++ [over.match.oper]p3:
// -- The set of non-member candidates is the result of the
// unqualified lookup of operator@ in the context of the
@@ -1719,29 +1745,58 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
Op != OpEnd; ++Op) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
- Functions.insert(FD); // FIXME: canonical FD
+ Functions.addDecl(FD, Op.getAccess()); // FIXME: canonical FD
} else if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(*Op)) {
// FIXME: friend operators?
// FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
// later?
if (!FunTmpl->getDeclContext()->isRecord())
- Functions.insert(FunTmpl);
+ Functions.addDecl(FunTmpl, Op.getAccess());
}
}
}
-static void CollectFunctionDecl(Sema::FunctionSet &Functions,
- Decl *D) {
- if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
- Functions.insert(Func);
- else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
- Functions.insert(FunTmpl);
+void ADLResult::insert(NamedDecl *New) {
+ NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
+
+ // If we haven't yet seen a decl for this key, or the last decl
+ // was exactly this one, we're done.
+ if (Old == 0 || Old == New) {
+ Old = New;
+ return;
+ }
+
+ // Otherwise, decide which is a more recent redeclaration.
+ FunctionDecl *OldFD, *NewFD;
+ if (isa<FunctionTemplateDecl>(New)) {
+ OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
+ NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
+ } else {
+ OldFD = cast<FunctionDecl>(Old);
+ NewFD = cast<FunctionDecl>(New);
+ }
+
+ FunctionDecl *Cursor = NewFD;
+ while (true) {
+ Cursor = Cursor->getPreviousDeclaration();
+
+ // If we got to the end without finding OldFD, OldFD is the newer
+ // declaration; leave things as they are.
+ if (!Cursor) return;
+
+ // If we do find OldFD, then NewFD is newer.
+ if (Cursor == OldFD) break;
+
+ // Otherwise, keep looking.
+ }
+
+ Old = New;
}
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
- FunctionSet &Functions) {
+ ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@@ -1784,7 +1839,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
// lookup (11.4).
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
- Decl *D = *I;
+ 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) {
@@ -1793,10 +1848,18 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
continue;
}
- FunctionDecl *Fn;
- if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
- IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
- CollectFunctionDecl(Functions, D);
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ if (isa<FunctionDecl>(D)) {
+ if (Operator &&
+ !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
+ T1, T2, Context))
+ continue;
+ } else if (!isa<FunctionTemplateDecl>(D))
+ continue;
+
+ Result.insert(D);
}
}
}
@@ -1985,6 +2048,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
bool InBaseClass,
VisibleDeclConsumer &Consumer,
VisibleDeclsRecord &Visited) {
+ if (!Ctx)
+ return;
+
// Make sure we don't visit the same context twice.
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
@@ -2022,6 +2088,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse the contexts of inherited C++ classes.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (!Record->hasDefinition())
+ return;
+
for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
BEnd = Record->bases_end();
B != BEnd; ++B) {
@@ -2138,9 +2207,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// For instance methods, look for ivars in the method's interface.
LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
Result.getNameLoc(), Sema::LookupMemberName);
- ObjCInterfaceDecl *IFace = Method->getClassInterface();
- LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ if (ObjCInterfaceDecl *IFace = Method->getClassInterface())
+ LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
+ /*InBaseClass=*/false, Consumer, Visited);
}
// We've already performed all of the name lookup that we need
@@ -2312,9 +2381,16 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT) {
-
if (Diags.hasFatalErrorOccurred())
return false;
+
+ // 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.
+ // FIXME: Is this the right solution?
+ if (TyposCorrected == 20)
+ return false;
+ ++TyposCorrected;
// We only attempt to correct typos for identifiers.
IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();