]> granicus.if.org Git - clang/commitdiff
Shift things around so that it's easier to recover from a missing
authorJohn McCall <rjmccall@apple.com>
Wed, 16 Dec 2009 12:17:52 +0000 (12:17 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 16 Dec 2009 12:17:52 +0000 (12:17 +0000)
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

include/clang/AST/Decl.h
lib/Sema/Sema.h
lib/Sema/SemaCodeComplete.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaOverload.cpp
test/SemaTemplate/dependent-names.cpp

index 40603516ffffc839f3075a1cc43d8ab7f9b9218f..e1c708974e69a3ca9569d9e5578ac152e2d4c723 100644 (file)
@@ -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 {
index f1897909448f9135247cd650fc080b6f1bb408b9..a756bb44b6497f4062e8d0f2720cd2af7361fce5 100644 (file)
@@ -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.
index 4ce9330fc1420f08053d193a3a0b724483c0d0c9..6b485ba7a9df8ada9d14e8e81b6b8ceb7242fa85 100644 (file)
@@ -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(),
index ac3703eac9da5019c9595ee0861457f60f89b2cd..dfd9555d03a87c88ae70be44b998c19f0459577a 100644 (file)
@@ -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.
 ///
index d01bca718d0a282b24634c69b7ea670c0605e26f..a37f86dd34a82baa8e6bac3ec9be0ea9725abf95 100644 (file)
@@ -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) {
index fbe78e27030b1a9dd029d4107a4bd801d5b57d03..a2d3c56501e821c510d01f7e92a25dfd153ba7e0 100644 (file)
@@ -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}}
     }
   };