From: John McCall Date: Sun, 22 Nov 2009 00:44:51 +0000 (+0000) Subject: Consider a FunctionTemplate to be an overload all on its lonesome. Track X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7453ed4cb2cab113de3378df371b1c6f1243d832;p=clang Consider a FunctionTemplate to be an overload all on its lonesome. Track this information through lookup rather than rederiving it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89570 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 85a99c0b73..a180c7c32b 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1050,13 +1050,17 @@ class UnresolvedLookupExpr : public Expr { /// call. bool RequiresADL; + /// True if these lookup results are overloaded. This is pretty + /// trivially rederivable if we urgently need to kill this field. + bool Overloaded; + UnresolvedLookupExpr(QualType T, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, - bool RequiresADL) + bool RequiresADL, bool Overloaded) : Expr(UnresolvedLookupExprClass, T, false, false), Name(Name), Qualifier(Qualifier), QualifierRange(QRange), - NameLoc(NameLoc), RequiresADL(RequiresADL) + NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded) {} public: @@ -1065,9 +1069,9 @@ public: SourceRange QualifierRange, DeclarationName Name, SourceLocation NameLoc, - bool ADL) { + bool ADL, bool Overloaded) { return new(C) UnresolvedLookupExpr(C.OverloadTy, Qualifier, QualifierRange, - Name, NameLoc, ADL); + Name, NameLoc, ADL, Overloaded); } void addDecl(NamedDecl *Decl) { @@ -1082,6 +1086,9 @@ public: /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } + /// True if this lookup is overloaded. + bool isOverloaded() const { return Overloaded; } + /// Fetches the name looked up. DeclarationName getName() const { return Name; } diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 6366a4c854..87d0c0d05c 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -208,6 +208,11 @@ public: return getResultKind() == Found; } + /// Determines if the results are overloaded. + bool isOverloadedResult() const { + return getResultKind() == FoundOverloaded; + } + LookupResultKind getResultKind() const { sanity(); return ResultKind; @@ -444,15 +449,24 @@ private: void sanity() const { assert(ResultKind != NotFound || Decls.size() == 0); assert(ResultKind != Found || Decls.size() == 1); - assert(ResultKind == NotFound || ResultKind == Found || - ResultKind == FoundUnresolvedValue || - (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects) - || Decls.size() > 1); + assert(ResultKind != FoundOverloaded || Decls.size() > 1 || + (Decls.size() == 1 && isa(Decls[0]))); + assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved()); + assert(ResultKind != Ambiguous || Decls.size() > 1 || + (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects)); assert((Paths != NULL) == (ResultKind == Ambiguous && (Ambiguity == AmbiguousBaseSubobjectTypes || Ambiguity == AmbiguousBaseSubobjects))); } + bool sanityCheckUnresolved() const { + for (DeclsTy::const_iterator I = Decls.begin(), E = Decls.end(); + I != E; ++I) + if (isa(*I)) + return true; + return false; + } + static void deletePaths(CXXBasePaths *); // Results. diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index d3acc5f710..b3cf86a185 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1423,6 +1423,7 @@ public: SourceLocation Loc, DeclarationName Name, bool NeedsADL, + bool IsOverloaded, NamedDecl * const *Decls, unsigned NumDecls); OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, @@ -1531,6 +1532,7 @@ public: NestedNameSpecifier *&Qualifier, SourceRange &QualifierRange, bool &ArgumentDependentLookup, + bool &Overloaded, bool &HasExplicitTemplateArguments, const TemplateArgumentLoc *&ExplicitTemplateArgs, unsigned &NumExplicitTemplateArgs); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 203b421c91..6bf38e0233 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1472,13 +1472,15 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, NestedNameSpecifier *Qualifier; SourceRange QualifierRange; bool ArgumentDependentLookup; + bool Overloaded; bool HasExplicitTemplateArgs; const TemplateArgumentLoc *ExplicitTemplateArgs; unsigned NumExplicitTemplateArgs; DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, - ArgumentDependentLookup, HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs); + ArgumentDependentLookup, Overloaded, + HasExplicitTemplateArgs, ExplicitTemplateArgs, + NumExplicitTemplateArgs); // FIXME: What if we're calling something that isn't a function declaration? diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 12e0c592e0..2223761c39 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -954,7 +954,7 @@ Sema::OwningExprResult BuildImplicitMemberExpr(Sema &S, LookupResult &R, } return S.BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getLookupName(), - /*ADL*/ false, + /*ADL*/ false, R.isOverloadedResult(), R.begin(), R.end() - R.begin()); } @@ -1042,7 +1042,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, bool ADL = UseArgumentDependentLookup(*this, SS, HasTrailingLParen, R); - return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getLookupName(), ADL, + return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getLookupName(), + ADL, R.isOverloadedResult(), R.begin(), R.end() - R.begin()); } @@ -1074,23 +1075,24 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, SourceLocation Loc, DeclarationName Name, bool NeedsADL, + bool IsOverloaded, NamedDecl * const *Decls, unsigned NumDecls) { - if (!NeedsADL && NumDecls == 1) + if (!NeedsADL && !IsOverloaded) return BuildDeclarationNameExpr(SS, Loc, Decls[0]->getUnderlyingDecl()); // We only need to check the declaration if there's exactly one // result, because in the overloaded case the results can only be // functions and function templates. - if (NumDecls == 1 && + if (!IsOverloaded && NumDecls == 1 && CheckDeclInExpr(*this, Loc, Decls[0]->getUnderlyingDecl())) return ExprError(); UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, SS ? (NestedNameSpecifier *)SS->getScopeRep() : 0, - SS ? SS->getRange() : SourceRange(), - Name, Loc, NeedsADL); + SS ? SS->getRange() : SourceRange(), + Name, Loc, NeedsADL, IsOverloaded); for (unsigned I = 0; I != NumDecls; ++I) ULE->addDecl(Decls[I]); @@ -1103,16 +1105,13 @@ Sema::OwningExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, SourceLocation Loc, NamedDecl *D) { assert(D && "Cannot refer to a NULL declaration"); + assert(!isa(D) && + "Cannot refer unambiguously to a function template"); DeclarationName Name = D->getDeclName(); if (CheckDeclInExpr(*this, Loc, D)) return ExprError(); - // Make the DeclRefExpr or BlockDeclRefExpr for the decl. - if (TemplateDecl *Template = dyn_cast(D)) - return BuildDeclRefExpr(Template, Context.OverloadTy, Loc, - false, false, SS); - ValueDecl *VD = cast(D); // Check whether this declaration can be used. Note that we suppress @@ -2689,6 +2688,7 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, NestedNameSpecifier *&Qualifier, SourceRange &QualifierRange, bool &ArgumentDependentLookup, + bool &Overloaded, bool &HasExplicitTemplateArguments, const TemplateArgumentLoc *&ExplicitTemplateArgs, unsigned &NumExplicitTemplateArgs) { @@ -2697,7 +2697,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, Qualifier = 0; QualifierRange = SourceRange(); ArgumentDependentLookup = getLangOptions().CPlusPlus; + Overloaded = false; HasExplicitTemplateArguments = false; + + // Most of the explicit tracking of ArgumentDependentLookup in this + // function can disappear when we handle unresolved + // TemplateIdRefExprs properly. // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent @@ -2725,19 +2730,24 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, Name = UnresLookup->getName(); Fns.append(UnresLookup->decls_begin(), UnresLookup->decls_end()); ArgumentDependentLookup = UnresLookup->requiresADL(); + Overloaded = UnresLookup->isOverloaded(); if ((Qualifier = UnresLookup->getQualifier())) QualifierRange = UnresLookup->getQualifierRange(); break; } else if (TemplateIdRefExpr *TemplateIdRef = dyn_cast(FnExpr)) { if (NamedDecl *Function - = TemplateIdRef->getTemplateName().getAsTemplateDecl()) + = TemplateIdRef->getTemplateName().getAsTemplateDecl()) { + Name = Function->getDeclName(); Fns.push_back(Function); + } else { OverloadedFunctionDecl *Overload = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); + Name = Overload->getDeclName(); Fns.append(Overload->function_begin(), Overload->function_end()); } + Overloaded = true; HasExplicitTemplateArguments = true; ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); @@ -2875,52 +2885,66 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // lookup and whether there were any explicitly-specified template arguments. llvm::SmallVector Fns; DeclarationName UnqualifiedName; - bool ADL = true; + bool Overloaded; + bool ADL; bool HasExplicitTemplateArgs = 0; const TemplateArgumentLoc *ExplicitTemplateArgs = 0; unsigned NumExplicitTemplateArgs = 0; NestedNameSpecifier *Qualifier = 0; SourceRange QualifierRange; DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, - ADL,HasExplicitTemplateArgs, ExplicitTemplateArgs, - NumExplicitTemplateArgs); - - NamedDecl *NDecl = 0; // the specific declaration we're calling, if applicable - FunctionDecl *FDecl = 0; // same, if it's a function or function template - FunctionTemplateDecl *FunctionTemplate = 0; - - if (Fns.size() == 1) { - NDecl = Fns[0]; - FDecl = dyn_cast(NDecl); - if ((FunctionTemplate = dyn_cast(NDecl))) - FDecl = FunctionTemplate->getTemplatedDecl(); - else - FDecl = dyn_cast(NDecl); - } + ADL, Overloaded, HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs); + + NamedDecl *NDecl; // the specific declaration we're calling, if applicable + FunctionDecl *FDecl; // same, if it's known to be a function + + if (Overloaded || ADL) { +#ifndef NDEBUG + if (ADL) { + // To do ADL, we must have found an unqualified name. + assert(UnqualifiedName && "found no unqualified name for ADL"); + + // We don't perform ADL for implicit declarations of builtins. + // Verify that this was correctly set up. + if (Fns.size() == 1 && (FDecl = dyn_cast(Fns[0])) && + FDecl->getBuiltinID() && FDecl->isImplicit()) + assert(0 && "performing ADL for builtin"); + + // We don't perform ADL in C. + assert(getLangOptions().CPlusPlus && "ADL enabled in C"); + } - if (Fns.size() > 1 || FunctionTemplate || - (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) { - // We don't perform ADL for implicit declarations of builtins. - if (FDecl && FDecl->getBuiltinID() && FDecl->isImplicit()) - assert(!ADL); // this should be guaranteed earlier - - // We don't perform ADL in C. - if (!getLangOptions().CPlusPlus) - assert(!ADL); // ditto - - if (Fns.size() > 1 || FunctionTemplate || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName, - HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - LParenLoc, Args, NumArgs, CommaLocs, - RParenLoc, ADL); - if (!FDecl) - return ExprError(); + if (Overloaded) { + // To be overloaded, we must either have multiple functions or + // at least one function template (which is effectively an + // infinite set of functions). + assert((Fns.size() > 1 || + (Fns.size() == 1 && + isa(Fns[0]->getUnderlyingDecl()))) + && "unrecognized overload situation"); + } +#endif + + FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName, + HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + LParenLoc, Args, NumArgs, CommaLocs, + RParenLoc, ADL); + if (!FDecl) + return ExprError(); - Fn = FixOverloadedFunctionReference(Fn, FDecl); + Fn = FixOverloadedFunctionReference(Fn, FDecl); - NDecl = FDecl; + NDecl = FDecl; + } else { + assert(Fns.size() <= 1 && "overloaded without Overloaded flag"); + if (Fns.empty()) + NDecl = FDecl = 0; + else { + NDecl = Fns[0]; + FDecl = dyn_cast(NDecl); } } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 99f9f55249..08e9dc3c63 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -242,6 +242,7 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } +/// Resolves the result kind of this lookup. void LookupResult::resolveKind() { unsigned N = Decls.size(); @@ -251,8 +252,12 @@ void LookupResult::resolveKind() { return; } + // If there's a single decl, we need to examine it to decide what + // kind of lookup this is. if (N == 1) { - if (isa(Decls[0])) + if (isa(Decls[0])) + ResultKind = FoundOverloaded; + else if (isa(Decls[0])) ResultKind = FoundUnresolvedValue; return; } @@ -264,7 +269,7 @@ void LookupResult::resolveKind() { bool Ambiguous = false; bool HasTag = false, HasFunction = false, HasNonFunction = false; - bool HasUnresolved = false; + bool HasFunctionTemplate = false, HasUnresolved = false; unsigned UniqueTagIndex = 0; @@ -290,7 +295,10 @@ void LookupResult::resolveKind() { Ambiguous = true; UniqueTagIndex = I; HasTag = true; - } else if (D->isFunctionOrFunctionTemplate()) { + } else if (isa(D)) { + HasFunction = true; + HasFunctionTemplate = true; + } else if (isa(D)) { HasFunction = true; } else { if (HasNonFunction) @@ -323,7 +331,7 @@ void LookupResult::resolveKind() { setAmbiguous(LookupResult::AmbiguousReference); else if (HasUnresolved) ResultKind = LookupResult::FoundUnresolvedValue; - else if (N > 1) + else if (N > 1 || HasFunctionTemplate) ResultKind = LookupResult::FoundOverloaded; else ResultKind = LookupResult::Found; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5e9d101d38..7d238f316f 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4656,6 +4656,11 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, return 0; } +static bool IsOverloaded(const Sema::FunctionSet &Functions) { + return Functions.size() > 1 || + (Functions.size() == 1 && isa(*Functions.begin())); +} + /// \brief Create a unary operation that may resolve to an overloaded /// operator. /// @@ -4699,7 +4704,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, if (Input->isTypeDependent()) { UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc, - /*ADL*/ true); + /*ADL*/ true, IsOverloaded(Functions)); for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); Func != FuncEnd; ++Func) @@ -4855,7 +4860,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc, - /* ADL */ true); + /* ADL */ true, IsOverloaded(Functions)); for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); @@ -5020,7 +5025,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, LLoc, - /*ADL*/ true); + /*ADL*/ true, /*Overloaded*/ false); // Can't add an actual overloads yet Base.release(); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c61481f83d..47110c180b 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -701,30 +701,20 @@ TemplateInstantiator::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, bool isAddressOfOperand) { llvm::SmallVector InstDecls; - bool HasUnresolved = false; - for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), E = Old->decls_end(); I != E; ++I) { NamedDecl *InstD = SemaRef.FindInstantiatedDecl(*I, TemplateArgs); if (!InstD) return SemaRef.ExprError(); - // Expand using declarations. - if (isa(InstD)) { - UsingDecl *UD = cast(InstD); - for (UsingDecl::shadow_iterator UI = UD->shadow_begin(), - UE = UD->shadow_end(); UI != UE; ++UI) { - UsingShadowDecl *Shadow = *UI; - if (isa(Shadow->getUnderlyingDecl())) - HasUnresolved = true; - InstDecls.push_back(Shadow); - } + // The lookup values can never instantiate to a UsingDecl, because + // only UnresolvedUsingValueDecls do that, and those can never + // appear in UnresolvedLookupExprs (only UnresolvedMemberLookupExprs). + assert(!isa(InstD)); - continue; - } + // Analogously. + assert(!isa(InstD->getUnderlyingDecl())); - if (isa(InstD->getUnderlyingDecl())) - HasUnresolved = true; InstDecls.push_back(InstD); } @@ -742,6 +732,7 @@ TemplateInstantiator::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, return SemaRef.BuildDeclarationNameExpr(&SS, Old->getNameLoc(), Old->getName(), Old->requiresADL(), + Old->isOverloaded(), InstDecls.data(), InstDecls.size()); }