diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-04 15:01:18 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-04 15:01:18 +0000 |
commit | b8a9a41dd6ea0b0d652edb5be0a78dd21e0e271d (patch) | |
tree | 73af2a895cd623e0261648fcb2cb3d7c31e9c9ee | |
parent | 82b7372941c4273d0bc4180b2b60c681fbcf63d1 (diff) | |
download | bcm5719-llvm-b8a9a41dd6ea0b0d652edb5be0a78dd21e0e271d.tar.gz bcm5719-llvm-b8a9a41dd6ea0b0d652edb5be0a78dd21e0e271d.zip |
Fix our semantic analysis of
unqualified-id '('
in C++. The unqualified-id might not refer to any declaration in our
current scope, but declarations by that name might be found via
argument-dependent lookup. We now do so properly.
As part of this change, CXXDependentNameExpr, which was previously
designed to express the unqualified-id in the above constructor within
templates, has become UnresolvedFunctionNameExpr, which does
effectively the same thing but will work for both templates and
non-templates.
Additionally, we cope with all unqualified-ids, since ADL also applies
in cases like
operator+(x, y)
llvm-svn: 63733
-rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 39 | ||||
-rw-r--r-- | clang/include/clang/AST/StmtNodes.def | 2 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/StmtSerialization.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 131 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 54 | ||||
-rw-r--r-- | clang/test/SemaCXX/basic_lookup_argdep.cpp | 23 | ||||
-rw-r--r-- | clang/test/SemaCXX/conversion-function.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/type-dependent-exprs.cpp | 2 |
12 files changed, 164 insertions, 123 deletions
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 4f48eb3716a..26f3b6c1610 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -727,28 +727,35 @@ public: static CXXDeleteExpr * CreateImpl(llvm::Deserializer& D, ASTContext& C); }; -/// CXXDependentNameExpr - Represents a dependent name in C++ for -/// which we could not locate any definition. These names can only -/// occur as in the example below, with an unqualified call to a -/// function name whose arguments are dependent. +/// \brief Represents the name of a function that has not been +/// resolved to any declaration. +/// +/// Unresolved function names occur when a function name is +/// encountered prior to an open parentheses ('(') in a C++ function +/// call, and the function name itself did not resolve to a +/// declaration. These function names can only be resolved when they +/// form the postfix-expression of a function call, so that +/// argument-dependent lookup finds declarations corresponding to +/// these functions. + /// @code /// template<typename T> void f(T x) { -/// g(x); // g is a dependent name. +/// g(x); // g is an unresolved function name (that is also a dependent name) /// } /// @endcode -class CXXDependentNameExpr : public Expr { - /// Name - The name that was present in the source code. - IdentifierInfo *Name; +class UnresolvedFunctionNameExpr : public Expr { + /// The name that was present in the source + DeclarationName Name; - /// Loc - The location + /// The location of this name in the source code SourceLocation Loc; public: - CXXDependentNameExpr(IdentifierInfo *N, QualType T, SourceLocation L) - : Expr(CXXDependentNameExprClass, T, true, true), Name(N), Loc(L) { } + UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L) + : Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { } - /// getName - Retrieves the name that occurred in the source code. - IdentifierInfo *getName() const { return Name; } + /// \brief Retrieves the name that occurred in the source code. + DeclarationName getName() const { return Name; } /// getLocation - Retrieves the location in the source code where /// the name occurred. @@ -757,16 +764,16 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(Loc); } static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXDependentNameExprClass; + return T->getStmtClass() == UnresolvedFunctionNameExprClass; } - static bool classof(const CXXDependentNameExpr *) { return true; } + static bool classof(const UnresolvedFunctionNameExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); virtual void EmitImpl(llvm::Serializer& S) const; - static CXXDependentNameExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C); + static UnresolvedFunctionNameExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C); }; /// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index 18b8dbebfed..0d289f55f3b 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/include/clang/AST/StmtNodes.def @@ -115,7 +115,7 @@ STMT(CXXZeroInitValueExpr , Expr) STMT(CXXConditionDeclExpr , DeclRefExpr) STMT(CXXNewExpr , Expr) STMT(CXXDeleteExpr , Expr) -STMT(CXXDependentNameExpr , Expr) +STMT(UnresolvedFunctionNameExpr , Expr) STMT(UnaryTypeTraitExpr , Expr) STMT(QualifiedDeclRefExpr , DeclRefExpr) diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index b21b4136898..dbc811a68b1 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -120,11 +120,11 @@ Stmt::child_iterator CXXNewExpr::child_end() { Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; } Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; } -// CXXDependentNameExpr -Stmt::child_iterator CXXDependentNameExpr::child_begin() { +// UnresolvedFunctionNameExpr +Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator CXXDependentNameExpr::child_end() { +Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() { return child_iterator(); } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 27bab206a4e..1f07db76925 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1101,8 +1101,8 @@ void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { PrintExpr(E->getArgument()); } -void StmtPrinter::VisitCXXDependentNameExpr(CXXDependentNameExpr *E) { - OS << E->getName()->getName(); +void StmtPrinter::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *E) { + OS << E->getName().getAsString(); } static const char *getTypeTraitName(UnaryTypeTrait UTT) { diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp index 8599a7aba90..3bb98b46f49 100644 --- a/clang/lib/AST/StmtSerialization.cpp +++ b/clang/lib/AST/StmtSerialization.cpp @@ -245,8 +245,8 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) { case CXXDeleteExprClass: return CXXDeleteExpr::CreateImpl(D, C); - case CXXDependentNameExprClass: - return CXXDependentNameExpr::CreateImpl(D, C); + case UnresolvedFunctionNameExprClass: + return UnresolvedFunctionNameExpr::CreateImpl(D, C); case CXXCatchStmtClass: return CXXCatchStmt::CreateImpl(D, C); @@ -1528,18 +1528,18 @@ CXXDeleteExpr::CreateImpl(Deserializer& D, ASTContext& C) { cast<Expr>(Argument), Loc); } -void CXXDependentNameExpr::EmitImpl(llvm::Serializer& S) const { +void UnresolvedFunctionNameExpr::EmitImpl(llvm::Serializer& S) const { S.Emit(getType()); - S.EmitPtr(Name); + S.EmitPtr(Name.getAsIdentifierInfo()); // FIXME: WRONG! S.Emit(Loc); } -CXXDependentNameExpr * -CXXDependentNameExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { +UnresolvedFunctionNameExpr * +UnresolvedFunctionNameExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { QualType Ty = QualType::ReadVal(D); IdentifierInfo *N = D.ReadPtr<IdentifierInfo>(); SourceLocation L = SourceLocation::ReadVal(D); - return new CXXDependentNameExpr(N, Ty, L); + return new UnresolvedFunctionNameExpr(N, Ty, L); } void UnaryTypeTraitExpr::EmitImpl(llvm::Serializer& S) const { diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3143b5c4829..6b8d852db39 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -517,12 +517,13 @@ public: bool Complain); void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); - FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Func, + FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, + DeclarationName UnqualifiedName, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc, - bool ArgumentDependentLookup); + bool &ArgumentDependentLookup); ExprResult BuildCallToMemberFunction(Scope *S, Expr *MemExpr, SourceLocation LParenLoc, Expr **Args, @@ -1068,7 +1069,6 @@ public: DeclarationName Name, bool HasTrailingLParen, const CXXScopeSpec *SS, - bool ForceResolution = false, bool isAddressOfOperand = false); virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 24f7965b63c..c1e4c0ecdd4 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -366,7 +366,7 @@ Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, const CXXScopeSpec *SS, bool isAddressOfOperand) { return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS, - /*ForceResolution*/false, isAddressOfOperand); + isAddressOfOperand); } /// BuildDeclRefExpr - Build either a DeclRefExpr or a @@ -535,10 +535,6 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, /// qualified-id (foo::bar) to indicate the class or namespace that /// the identifier must be a member of. /// -/// If ForceResolution is true, then we will attempt to resolve the -/// name even if it looks like a dependent name. This option is off by -/// default. -/// /// isAddressOfOperand means that this expression is the direct operand /// of an address-of operator. This matters because this is the only /// situation where a qualified name referencing a non-static member may @@ -546,27 +542,27 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, Sema::OwningExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS, bool ForceResolution, + const CXXScopeSpec *SS, bool isAddressOfOperand) { - if (S->getTemplateParamParent() && Name.getAsIdentifierInfo() && - HasTrailingLParen && !SS && !ForceResolution) { - // We've seen something of the form - // identifier( - // and we are in a template, so it is likely that 's' is a - // dependent name. However, we won't know until we've parsed all - // of the call arguments. So, build a CXXDependentNameExpr node - // to represent this name. Then, if it turns out that none of the - // arguments are type-dependent, we'll force the resolution of the - // dependent name at that point. - return Owned(new (Context) CXXDependentNameExpr(Name.getAsIdentifierInfo(), - Context.DependentTy, Loc)); - } - // Could be enum-constant, value decl, instance variable, etc. if (SS && SS->isInvalid()) return ExprError(); LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName); + if (getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && + HasTrailingLParen && Lookup.getKind() == LookupResult::NotFound) { + // We've seen something of the form + // + // identifier( + // + // and we did not find any entity by the name + // "identifier". However, this identifier is still subject to + // argument-dependent lookup, so keep track of the name. + return Owned(new (Context) UnresolvedFunctionNameExpr(Name, + Context.OverloadTy, + Loc)); + } + Decl *D = 0; if (Lookup.isAmbiguous()) { DiagnoseAmbiguousLookup(Lookup, Name, Loc, @@ -1839,48 +1835,27 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, Expr **Args = reinterpret_cast<Expr**>(args.release()); assert(Fn && "no function call expression"); FunctionDecl *FDecl = NULL; + DeclarationName UnqualifiedName; - // Determine whether this is a dependent call inside a C++ template, - // in which case we won't do any semantic analysis now. - bool Dependent = false; - if (Fn->isTypeDependent()) { - if (CXXDependentNameExpr *FnName = dyn_cast<CXXDependentNameExpr>(Fn)) { - if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) - Dependent = true; - else { - // Resolve the CXXDependentNameExpr to an actual identifier; - // it wasn't really a dependent name after all. - // FIXME: in the presence of ADL, this resolves too early. - OwningExprResult Resolved - = ActOnDeclarationNameExpr(S, FnName->getLocation(), - FnName->getName(), - /*HasTrailingLParen=*/true, - /*SS=*/0, - /*ForceResolution=*/true); - if (Resolved.isInvalid()) - return ExprError(); - else { - delete Fn; - Fn = (Expr *)Resolved.release(); - } - } - } else + if (getLangOptions().CPlusPlus) { + // Determine whether this is a dependent call inside a C++ template, + // in which case we won't do any semantic analysis now. + // FIXME: Will need to cache the results of name lookup (including ADL) in Fn. + bool Dependent = false; + if (Fn->isTypeDependent()) + Dependent = true; + else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) Dependent = true; - } else - Dependent = Expr::hasAnyTypeDependentArguments(Args, NumArgs); - // FIXME: Will need to cache the results of name lookup (including - // ADL) in Fn. - if (Dependent) - return Owned(new (Context) CallExpr(Fn, Args, NumArgs, - Context.DependentTy, RParenLoc)); + if (Dependent) + return Owned(new (Context) CallExpr(Fn, Args, NumArgs, + Context.DependentTy, RParenLoc)); - // Determine whether this is a call to an object (C++ [over.call.object]). - if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType()) - return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, - CommaLocs, RParenLoc)); + // Determine whether this is a call to an object (C++ [over.call.object]). + if (Fn->getType()->isRecordType()) + return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc)); - if (getLangOptions().CPlusPlus) { // Determine whether this is a call to a member function. if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) || @@ -1897,7 +1872,8 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) FnExpr = IcExpr->getSubExpr(); else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - // FIXME: Where does the C++ standard say this? + // Parentheses around a function disable ADL + // (C++0x [basic.lookup.argdep]p1). ADL = false; FnExpr = PExpr->getSubExpr(); } else if (isa<UnaryOperator>(FnExpr) && @@ -1905,32 +1881,39 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); } else { - DRExpr = dyn_cast<DeclRefExpr>(FnExpr); + if (isa<DeclRefExpr>(FnExpr)) { + DRExpr = cast<DeclRefExpr>(FnExpr); + + // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). + ADL = ADL && !isa<QualifiedDeclRefExpr>(DRExpr); + } + else if (UnresolvedFunctionNameExpr *DepName + = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) + UnqualifiedName = DepName->getName(); + else { + // Any kind of name that does not refer to a declaration (or + // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). + ADL = false; + } break; } } - if (DRExpr) + OverloadedFunctionDecl *Ovl = 0; + if (DRExpr) { FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); + Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl()); + } - if (getLangOptions().CPlusPlus && DRExpr && - (FDecl || isa<OverloadedFunctionDecl>(DRExpr->getDecl()))) { - // C++ [basic.lookup.argdep]p1: - // When an unqualified name is used as the postfix-expression in - // a function call (5.2.2), other namespaces not considered - // during the usual unqualified lookup (3.4.1) may be searched, - // and namespace-scope friend func- tion declarations (11.4) not - // otherwise visible may be found. - if (DRExpr && isa<QualifiedDeclRefExpr>(DRExpr)) - ADL = false; - + if (getLangOptions().CPlusPlus && (FDecl || Ovl || UnqualifiedName)) { // We don't perform ADL for builtins. if (FDecl && FDecl->getIdentifier() && FDecl->getIdentifier()->getBuiltinID()) ADL = false; - if ((DRExpr && isa<OverloadedFunctionDecl>(DRExpr->getDecl())) || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, DRExpr->getDecl(), LParenLoc, Args, + if (Ovl || ADL) { + FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0, + UnqualifiedName, LParenLoc, Args, NumArgs, CommaLocs, RParenLoc, ADL); if (!FDecl) return ExprError(); @@ -1938,7 +1921,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Update Fn to refer to the actual function selected. Expr *NewFn = 0; if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast<QualifiedDeclRefExpr>(DRExpr)) + = dyn_cast_or_null<QualifiedDeclRefExpr>(DRExpr)) NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), QDRExpr->getLocation(), false, false, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e9dbc849b00..2a7c9a85f00 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -35,7 +35,7 @@ Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc, DeclarationName ConvName = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon); return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen, - &SS, /*ForceRes*/false, isAddressOfOperand); + &SS, isAddressOfOperand); } /// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator @@ -51,7 +51,7 @@ Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc, bool isAddressOfOperand) { DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op); return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS, - /*ForceRes*/false, isAddressOfOperand); + isAddressOfOperand); } /// ActOnCXXTypeidOfType - Parse typeid( type-id ). diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 293e9c3c24b..01b9829c665 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3503,20 +3503,56 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, + DeclarationName UnqualifiedName, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc, - bool ArgumentDependentLookup) { + bool &ArgumentDependentLookup) { OverloadCandidateSet CandidateSet; + + // Add the functions denoted by Callee to the set of candidate + // functions. While we're doing so, track whether argument-dependent + // lookup still applies, per: + // + // C++0x [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 + // lookup (defined as follows). If X contains + // + // -- a declaration of a class member, or + // + // -- a block-scope function declaration that is not a + // using-declaration, or + // + // -- a declaration that is neither a function or a function + // template + // + // then Y is empty. if (OverloadedFunctionDecl *Ovl - = dyn_cast_or_null<OverloadedFunctionDecl>(Callee)) - AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet); - else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) - AddOverloadCandidate(cast<FunctionDecl>(Func), Args, NumArgs, CandidateSet); - + = dyn_cast_or_null<OverloadedFunctionDecl>(Callee)) { + for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), + FuncEnd = Ovl->function_end(); + Func != FuncEnd; ++Func) { + AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet); + + if ((*Func)->getDeclContext()->isRecord() || + (*Func)->getDeclContext()->isFunctionOrMethod()) + ArgumentDependentLookup = false; + } + } else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) { + AddOverloadCandidate(Func, Args, NumArgs, CandidateSet); + + if (Func->getDeclContext()->isRecord() || + Func->getDeclContext()->isFunctionOrMethod()) + ArgumentDependentLookup = false; + } + + if (Callee) + UnqualifiedName = Callee->getDeclName(); + if (ArgumentDependentLookup) - AddArgumentDependentLookupCandidates(Callee->getDeclName(), Args, NumArgs, + AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, CandidateSet); OverloadCandidateSet::iterator Best; @@ -3527,14 +3563,14 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, case OR_No_Viable_Function: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_no_viable_function_in_call) - << Callee->getDeclName() << (unsigned)CandidateSet.size() + << UnqualifiedName << (unsigned)CandidateSet.size() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); break; case OR_Ambiguous: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) - << Callee->getDeclName() << Fn->getSourceRange(); + << UnqualifiedName << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; } diff --git a/clang/test/SemaCXX/basic_lookup_argdep.cpp b/clang/test/SemaCXX/basic_lookup_argdep.cpp index 67f2b650339..53448d119a8 100644 --- a/clang/test/SemaCXX/basic_lookup_argdep.cpp +++ b/clang/test/SemaCXX/basic_lookup_argdep.cpp @@ -6,7 +6,7 @@ namespace N { X operator+(X, X); void f(X); - void g(X); + void g(X); // expected-note{{candidate function}} void test_multiadd(X x) { (void)(x + x); @@ -39,7 +39,22 @@ namespace N { void test_func_adl_only(N::X x) { - // FIXME: here, despite the fact that the name lookup for 'g' fails, - // this is well-formed code. The fix will go into Sema::ActOnCallExpr. - // g(x); + g(x); +} + +namespace M { + int g(N::X); // expected-note{{candidate function}} + + void test(N::X x) { + g(x); // expected-error{{call to 'g' is ambiguous; candidates are:}} + int i = (g)(x); + + int g(N::X); + g(x); // okay; calls locally-declared function, no ADL + } +} + + +void test_operator_name_adl(N::X x) { + (void)operator+(x, x); } diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp index 17e73bce9a6..f9dd6005b90 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -9,7 +9,7 @@ public: } float g() { - return operator float(); // expected-error{{use of undeclared 'operator float'}} + return operator float(); // expected-error{{no matching function for call to 'operator float'}} } }; diff --git a/clang/test/SemaCXX/type-dependent-exprs.cpp b/clang/test/SemaCXX/type-dependent-exprs.cpp index b3bfa8b6018..7c2de699127 100644 --- a/clang/test/SemaCXX/type-dependent-exprs.cpp +++ b/clang/test/SemaCXX/type-dependent-exprs.cpp @@ -19,6 +19,6 @@ T f(T x) { return g(x); h(x); // h is a dependent name g(1, 1); // expected-error{{no matching function for call}} - h(1); // expected-error{{use of undeclared identifier 'h'}} + h(1); // expected-error{{no matching function for call to 'h'}} return 0; } |