diff options
author | John McCall <rjmccall@apple.com> | 2009-12-16 12:17:52 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-12-16 12:17:52 +0000 |
commit | 3b4294e5c1e904a2e0f74449dbc3f52f69cc8e9f (patch) | |
tree | 8dd6c9741fc7f0e77d7b47efd1c0de70295a77ca | |
parent | 3055be7e5a706c669dc97f94abe42f68ce8e81e5 (diff) |
Shift things around so that it's easier to recover from a missing
function in a C++ call using an arbitrary call-expression type.
Actually exploit this to fix the recovery implemented earlier.
The diagnostic is still iffy, though.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91538 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 14 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 34 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 35 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 216 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 159 | ||||
-rw-r--r-- | test/SemaTemplate/dependent-names.cpp | 3 |
6 files changed, 197 insertions, 264 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 40603516ff..e1c708974e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -206,6 +206,20 @@ public: /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; + /// \brief Determine whether this declaration is a C++ class member. + bool isCXXClassMember() const { + const DeclContext *DC = getDeclContext(); + + // C++0x [class.mem]p1: + // The enumerators of an unscoped enumeration defined in + // the class are members of the class. + // FIXME: support C++0x scoped enumerations. + if (isa<EnumDecl>(DC)) + DC = DC->getParent(); + + return DC->isRecord(); + } + /// \brief Describes the different kinds of linkage /// (C++ [basic.link], C99 6.2.2) that an entity may have. enum Linkage { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f189790944..a756bb44b6 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -58,6 +58,7 @@ namespace clang { class DesignatedInitExpr; class CallExpr; class DeclRefExpr; + class UnresolvedLookupExpr; class VarDecl; class ParmVarDecl; class TypedefDecl; @@ -1038,23 +1039,17 @@ public: OwningExprResult FixOverloadedFunctionReference(OwningExprResult, FunctionDecl *Fn); - void AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*>& Callees, - DeclarationName &UnqualifiedName, - bool ArgumentDependentLookup, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); - FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, - llvm::SmallVectorImpl<NamedDecl*> &Fns, - DeclarationName UnqualifiedName, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc, - bool ArgumentDependentLookup); + OwningExprResult BuildOverloadedCallExpr(Expr *Fn, + UnresolvedLookupExpr *Fn, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, @@ -1501,6 +1496,9 @@ public: FieldDecl *Field, Expr *BaseObjectExpr = 0, SourceLocation OpLoc = SourceLocation()); + OwningExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); OwningExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, @@ -1627,16 +1625,6 @@ public: Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); - void DeconstructCallFunction(Expr *FnExpr, - llvm::SmallVectorImpl<NamedDecl*>& Fns, - DeclarationName &Name, - NestedNameSpecifier *&Qualifier, - SourceRange &QualifierRange, - bool &ArgumentDependentLookup, - bool &Overloaded, - bool &HasExplicitTemplateArgs, - TemplateArgumentListInfo &ExplicitTemplateArgs); - /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 4ce9330fc1..6b485ba7a9 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1706,33 +1706,24 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, CodeCompleteOrdinaryName(S); return; } - - llvm::SmallVector<NamedDecl*,8> Fns; - DeclarationName UnqualifiedName; - NestedNameSpecifier *Qualifier; - SourceRange QualifierRange; - bool ArgumentDependentLookup; - bool Overloaded; - bool HasExplicitTemplateArgs; - TemplateArgumentListInfo ExplicitTemplateArgs; - - DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, - ArgumentDependentLookup, Overloaded, - HasExplicitTemplateArgs, ExplicitTemplateArgs); - + // Build an overload candidate set based on the functions we find. + OverloadCandidateSet CandidateSet; + // FIXME: What if we're calling something that isn't a function declaration? // FIXME: What if we're calling a pseudo-destructor? // FIXME: What if we're calling a member function? - // Build an overload candidate set based on the functions we find. - OverloadCandidateSet CandidateSet; - AddOverloadedCallCandidates(Fns, UnqualifiedName, - ArgumentDependentLookup, - (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), - Args, NumArgs, - CandidateSet, - /*PartialOverloading=*/true); + Expr *NakedFn = Fn->IgnoreParenCasts(); + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) + AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet, + /*PartialOverloading=*/ true); + else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (FDecl) + AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet, + false, false, /*PartialOverloading*/ true); + } // Sort the overload candidate set by placing the best overloads first. std::stable_sort(CandidateSet.begin(), CandidateSet.end(), diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ac3703eac9..dfd9555d03 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -762,23 +762,9 @@ static bool IsProvablyNotDerivedFrom(Sema &SemaRef, return true; } -/// Determines if this a C++ class member. -static bool IsClassMember(NamedDecl *D) { - DeclContext *DC = D->getDeclContext(); - - // C++0x [class.mem]p1: - // The enumerators of an unscoped enumeration defined in - // the class are members of the class. - // FIXME: support C++0x scoped enumerations. - if (isa<EnumDecl>(DC)) - DC = DC->getParent(); - - return DC->isRecord(); -} - /// Determines if this is an instance member of a class. static bool IsInstanceMember(NamedDecl *D) { - assert(IsClassMember(D) && + assert(D->isCXXClassMember() && "checking whether non-member is instance member"); if (isa<FieldDecl>(D)) return true; @@ -840,7 +826,7 @@ enum IMAKind { /// not be caught until template-instantiation. static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, const LookupResult &R) { - assert(!R.empty() && IsClassMember(*R.begin())); + assert(!R.empty() && (*R.begin())->isCXXClassMember()); bool isStaticContext = (!isa<CXXMethodDecl>(SemaRef.CurContext) || @@ -1108,35 +1094,10 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // class member access expression. // But note that &SomeClass::foo is grammatically distinct, even // though we don't parse it that way. - if (!R.empty() && IsClassMember(*R.begin())) { + if (!R.empty() && (*R.begin())->isCXXClassMember()) { bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty()); - - if (!isAbstractMemberPointer) { - switch (ClassifyImplicitMemberAccess(*this, R)) { - case IMA_Instance: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); - - case IMA_AnonymousMember: - assert(R.isSingleResult()); - return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), - R.getAsSingle<FieldDecl>()); - - case IMA_Mixed: - case IMA_Mixed_Unrelated: - case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); - - case IMA_Static: - case IMA_Mixed_StaticContext: - case IMA_Unresolved_StaticContext: - break; - - case IMA_Error_StaticContext: - case IMA_Error_Unrelated: - DiagnoseInstanceReference(*this, SS, R); - return ExprError(); - } - } + if (!isAbstractMemberPointer) + return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); } if (TemplateArgs) @@ -1145,6 +1106,42 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, return BuildDeclarationNameExpr(SS, R, ADL); } +/// Builds an expression which might be an implicit member expression. +Sema::OwningExprResult +Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + switch (ClassifyImplicitMemberAccess(*this, R)) { + case IMA_Instance: + return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); + + case IMA_AnonymousMember: + assert(R.isSingleResult()); + return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), + R.getAsSingle<FieldDecl>()); + + case IMA_Mixed: + case IMA_Mixed_Unrelated: + case IMA_Unresolved: + return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); + + case IMA_Static: + case IMA_Mixed_StaticContext: + case IMA_Unresolved_StaticContext: + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, false, *TemplateArgs); + return BuildDeclarationNameExpr(SS, R, false); + + case IMA_Error_StaticContext: + case IMA_Error_Unrelated: + DiagnoseInstanceReference(*this, SS, R); + return ExprError(); + } + + llvm_unreachable("unexpected instance member access kind"); + return ExprError(); +} + /// BuildQualifiedDeclarationNameExpr - Build a C++ qualified /// declaration name, generally during template instantiation. /// There's a large number of things which don't need to be done along @@ -1372,7 +1369,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, // -- a declaration of a class member // Since using decls preserve this property, we check this on the // original decl. - if (IsClassMember(D)) + if (D->isCXXClassMember()) return false; // C++0x [basic.lookup.argdep]p3: @@ -3241,64 +3238,6 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, return Invalid; } -/// \brief "Deconstruct" the function argument of a call expression to find -/// the underlying declaration (if any), the name of the called function, -/// whether argument-dependent lookup is available, whether it has explicit -/// template arguments, etc. -void Sema::DeconstructCallFunction(Expr *FnExpr, - llvm::SmallVectorImpl<NamedDecl*> &Fns, - DeclarationName &Name, - NestedNameSpecifier *&Qualifier, - SourceRange &QualifierRange, - bool &ArgumentDependentLookup, - bool &Overloaded, - bool &HasExplicitTemplateArguments, - TemplateArgumentListInfo &ExplicitTemplateArgs) { - // Set defaults for all of the output parameters. - Name = DeclarationName(); - Qualifier = 0; - QualifierRange = SourceRange(); - ArgumentDependentLookup = false; - Overloaded = false; - HasExplicitTemplateArguments = false; - - // If we're directly calling a function, get the appropriate declaration. - // Also, in C++, keep track of whether we should perform argument-dependent - // lookup and whether there were any explicitly-specified template arguments. - while (true) { - if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) - FnExpr = IcExpr->getSubExpr(); - else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - FnExpr = PExpr->getSubExpr(); - } else if (isa<UnaryOperator>(FnExpr) && - cast<UnaryOperator>(FnExpr)->getOpcode() - == UnaryOperator::AddrOf) { - FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { - Fns.push_back(cast<NamedDecl>(DRExpr->getDecl())); - ArgumentDependentLookup = false; - if ((Qualifier = DRExpr->getQualifier())) - QualifierRange = DRExpr->getQualifierRange(); - break; - } else if (UnresolvedLookupExpr *UnresLookup - = dyn_cast<UnresolvedLookupExpr>(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(); - if (UnresLookup->hasExplicitTemplateArgs()) { - HasExplicitTemplateArguments = true; - UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } - break; - } else { - break; - } - } -} - /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -3413,72 +3352,23 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. - llvm::SmallVector<NamedDecl*,8> Fns; - DeclarationName UnqualifiedName; - bool Overloaded; - bool ADL; - bool HasExplicitTemplateArgs = 0; - TemplateArgumentListInfo ExplicitTemplateArgs; - NestedNameSpecifier *Qualifier = 0; - SourceRange QualifierRange; - DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, - ADL, Overloaded, HasExplicitTemplateArgs, - ExplicitTemplateArgs); - - 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<FunctionDecl>(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 (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<FunctionTemplateDecl>(Fns[0]->getUnderlyingDecl()))) - && "unrecognized overload situation"); - } -#endif - - FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName, - (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), - LParenLoc, Args, NumArgs, CommaLocs, - RParenLoc, ADL); - if (!FDecl) - return ExprError(); - Fn = FixOverloadedFunctionReference(Fn, FDecl); - - NDecl = FDecl; - } else { - assert(Fns.size() <= 1 && "overloaded without Overloaded flag"); - if (Fns.empty()) - NDecl = 0; - else { - NDecl = Fns[0]; - } + Expr *NakedFn = Fn->IgnoreParenCasts(); + if (isa<UnresolvedLookupExpr>(NakedFn)) { + UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn); + return BuildOverloadedCallExpr(Fn, ULE, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc); } + NamedDecl *NDecl = 0; + if (isa<DeclRefExpr>(NakedFn)) + NDecl = cast<DeclRefExpr>(NakedFn)->getDecl(); + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc); } -/// BuildCallExpr - Build a call to a resolved expression, i.e. an -/// expression not of \p OverloadTy. The expression should +/// BuildResolvedCallExpr - Build a call to a resolved expression, +/// i.e. an expression not of \p OverloadTy. The expression should /// unary-convert to an expression of function-pointer or /// block-pointer type. /// diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index d01bca718d..a37f86dd34 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4596,10 +4596,7 @@ static void AddOverloadedCallCandidate(Sema &S, /// \brief Add the overload candidates named by callee and/or found by argument /// dependent lookup to the given overload set. -void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*> &Fns, - DeclarationName &UnqualifiedName, - bool ArgumentDependentLookup, - const TemplateArgumentListInfo *ExplicitTemplateArgs, +void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { @@ -4622,38 +4619,56 @@ void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*> &Fns, // // then Y is empty. - if (ArgumentDependentLookup) { - for (unsigned I = 0; I < Fns.size(); ++I) { - assert(!Fns[I]->getDeclContext()->isRecord()); - assert(isa<UsingShadowDecl>(Fns[I]) || - !Fns[I]->getDeclContext()->isFunctionOrMethod()); - assert(Fns[I]->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); + if (ULE->requiresADL()) { + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) { + assert(!(*I)->getDeclContext()->isRecord()); + assert(isa<UsingShadowDecl>(*I) || + !(*I)->getDeclContext()->isFunctionOrMethod()); + assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); } } #endif - for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(), - E = Fns.end(); I != E; ++I) + // It would be nice to avoid this copy. + TemplateArgumentListInfo TABuffer; + const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) AddOverloadedCallCandidate(*this, *I, ExplicitTemplateArgs, Args, NumArgs, CandidateSet, PartialOverloading); - if (ArgumentDependentLookup) - AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, + if (ULE->requiresADL()) + AddArgumentDependentLookupCandidates(ULE->getName(), Args, NumArgs, ExplicitTemplateArgs, CandidateSet, PartialOverloading); } +static Sema::OwningExprResult Destroy(Sema &SemaRef, Expr *Fn, + Expr **Args, unsigned NumArgs) { + Fn->Destroy(SemaRef.Context); + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) + Args[Arg]->Destroy(SemaRef.Context); + return SemaRef.ExprError(); +} + /// Attempts to recover from a call where no functions were found. /// /// Returns true if new candidates were found. -static bool AddRecoveryCallCandidates(Sema &SemaRef, Expr *Fn, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, - OverloadCandidateSet &CandidateSet) { - UnresolvedLookupExpr *ULE - = cast<UnresolvedLookupExpr>(Fn->IgnoreParenCasts()); +static Sema::OwningExprResult +BuildRecoveryCallExpr(Sema &SemaRef, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { CXXScopeSpec SS; if (ULE->getQualifier()) { @@ -4661,16 +4676,41 @@ static bool AddRecoveryCallCandidates(Sema &SemaRef, Expr *Fn, SS.setRange(ULE->getQualifierRange()); } + TemplateArgumentListInfo TABuffer; + const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); if (SemaRef.DiagnoseEmptyLookup(SS, R)) - return false; + return Destroy(SemaRef, Fn, Args, NumArgs); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - AddOverloadedCallCandidate(SemaRef, *I, ExplicitTemplateArgs, - Args, NumArgs, CandidateSet, false); - } - return true; + assert(!R.empty() && "lookup results empty despite recovery"); + + // Build an implicit member call if appropriate. Just drop the + // casts and such from the call, we don't really care. + Sema::OwningExprResult NewFn = SemaRef.ExprError(); + if ((*R.begin())->isCXXClassMember()) + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs); + else if (ExplicitTemplateArgs) + NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs); + else + NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false); + + if (NewFn.isInvalid()) + return Destroy(SemaRef, Fn, Args, NumArgs); + + Fn->Destroy(SemaRef.Context); + + // This shouldn't cause an infinite loop because we're giving it + // an expression with non-empty lookup results, which should never + // end up here. + return SemaRef.ActOnCallExpr(/*Scope*/ 0, move(NewFn), LParenLoc, + Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs), + CommaLocs, RParenLoc); } /// ResolveOverloadedCallFn - Given the call expression that calls Fn @@ -4680,57 +4720,68 @@ static bool AddRecoveryCallCandidates(Sema &SemaRef, Expr *Fn, /// the function declaration produced by overload /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. -FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, - llvm::SmallVectorImpl<NamedDecl*> &Fns, - DeclarationName UnqualifiedName, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc, - bool ArgumentDependentLookup) { +Sema::OwningExprResult +Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { +#ifndef NDEBUG + if (ULE->requiresADL()) { + // To do ADL, we must have found an unqualified name. + assert(!ULE->getQualifier() && "qualified name with ADL"); + + // We don't perform ADL for implicit declarations of builtins. + // Verify that this was correctly set up. + FunctionDecl *F; + if (ULE->decls_begin() + 1 == ULE->decls_end() && + (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) && + F->getBuiltinID() && F->isImplicit()) + assert(0 && "performing ADL for builtin"); + + // We don't perform ADL in C. + assert(getLangOptions().CPlusPlus && "ADL enabled in C"); + } +#endif + OverloadCandidateSet CandidateSet; - // Add the functions denoted by Callee to the set of candidate - // functions. - AddOverloadedCallCandidates(Fns, UnqualifiedName, ArgumentDependentLookup, - ExplicitTemplateArgs, Args, NumArgs, - CandidateSet); + // Add the functions denoted by the callee to the set of candidate + // functions, including those from argument-dependent lookup. + AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet); // If we found nothing, try to recover. // AddRecoveryCallCandidates diagnoses the error itself, so we just // bailout out if it fails. - if (CandidateSet.empty() && - !AddRecoveryCallCandidates(*this, Fn, ExplicitTemplateArgs, - Args, NumArgs, CandidateSet)) { - Fn->Destroy(Context); - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) - Args[Arg]->Destroy(Context); - return 0; - } + if (CandidateSet.empty()) + return BuildRecoveryCallExpr(*this, Fn, ULE, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc); OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { - case OR_Success: - return Best->Function; + case OR_Success: { + FunctionDecl *FDecl = Best->Function; + Fn = FixOverloadedFunctionReference(Fn, FDecl); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); + } case OR_No_Viable_Function: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_no_viable_function_in_call) - << UnqualifiedName << Fn->getSourceRange(); + << ULE->getName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); break; case OR_Ambiguous: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) - << UnqualifiedName << Fn->getSourceRange(); + << ULE->getName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; case OR_Deleted: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) << Best->Function->isDeleted() - << UnqualifiedName + << ULE->getName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; @@ -4741,7 +4792,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, Fn->Destroy(Context); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) Args[Arg]->Destroy(Context); - return 0; + return ExprError(); } static bool IsOverloaded(const Sema::FunctionSet &Functions) { diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp index fbe78e2703..a2d3c56501 100644 --- a/test/SemaTemplate/dependent-names.cpp +++ b/test/SemaTemplate/dependent-names.cpp @@ -92,8 +92,7 @@ namespace test1 { template <class T> struct Derived : Base<T> { void doFoo(T v) { - // FIXME: the second error here is from a broken recovery attempt - foo(v); // expected-error {{use of undeclared identifier}} expected-error {{call to non-static member function without an object}} + foo(v); // expected-error {{use of undeclared identifier}} } }; |