[cfe-commits] r63733 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/AST/StmtNodes.def lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtSerialization.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/basic_lookup_argdep.cpp test/SemaCXX/conversion-function.cpp test/SemaCXX/type-dependent-exprs.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 4 07:01:20 PST 2009


Author: dgregor
Date: Wed Feb  4 09:01:18 2009
New Revision: 63733

URL: http://llvm.org/viewvc/llvm-project?rev=63733&view=rev
Log:
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)



Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtSerialization.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/basic_lookup_argdep.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp
    cfe/trunk/test/SemaCXX/type-dependent-exprs.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Feb  4 09:01:18 2009
@@ -727,28 +727,35 @@
   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 @@
   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

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Wed Feb  4 09:01:18 2009
@@ -115,7 +115,7 @@
 STMT(CXXConditionDeclExpr   , DeclRefExpr)
 STMT(CXXNewExpr             , Expr)
 STMT(CXXDeleteExpr          , Expr)
-STMT(CXXDependentNameExpr   , Expr)
+STMT(UnresolvedFunctionNameExpr , Expr)
 STMT(UnaryTypeTraitExpr     , Expr)
 STMT(QualifiedDeclRefExpr   , DeclRefExpr)
 

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Feb  4 09:01:18 2009
@@ -120,11 +120,11 @@
 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();
 }
 

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Feb  4 09:01:18 2009
@@ -1101,8 +1101,8 @@
   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) {

Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Wed Feb  4 09:01:18 2009
@@ -245,8 +245,8 @@
     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 @@
                            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 {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb  4 09:01:18 2009
@@ -517,12 +517,13 @@
                                                    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 @@
                                             DeclarationName Name,
                                             bool HasTrailingLParen,
                                             const CXXScopeSpec *SS,
-                                            bool ForceResolution = false,
                                             bool isAddressOfOperand = false);
 
   virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb  4 09:01:18 2009
@@ -366,7 +366,7 @@
                                                  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 @@
 /// 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::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 @@
   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));
-
-  // 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));
+    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 (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 @@
     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 @@
                  == 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 @@
       // 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,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb  4 09:01:18 2009
@@ -35,7 +35,7 @@
   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 @@
                                      bool isAddressOfOperand) {
   DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op);
   return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS,
-                                  /*ForceRes*/false, isAddressOfOperand);
+                                  isAddressOfOperand);
 }
 
 /// ActOnCXXTypeidOfType - Parse typeid( type-id ).

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb  4 09:01:18 2009
@@ -3503,20 +3503,56 @@
 /// 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 @@
   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;
   }

Modified: cfe/trunk/test/SemaCXX/basic_lookup_argdep.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/basic_lookup_argdep.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/basic_lookup_argdep.cpp (original)
+++ cfe/trunk/test/SemaCXX/basic_lookup_argdep.cpp Wed Feb  4 09:01:18 2009
@@ -6,7 +6,7 @@
   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 @@
 
 
 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);
 }

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Wed Feb  4 09:01:18 2009
@@ -9,7 +9,7 @@
   }
 
   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'}}
   }
 };
 

Modified: cfe/trunk/test/SemaCXX/type-dependent-exprs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-dependent-exprs.cpp?rev=63733&r1=63732&r2=63733&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/type-dependent-exprs.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-dependent-exprs.cpp Wed Feb  4 09:01:18 2009
@@ -19,6 +19,6 @@
   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;
 }





More information about the cfe-commits mailing list