[cfe-commits] r74213 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/Sema/ test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/ test/Parser/ test/SemaCXX/ test/SemaTemplate/

Douglas Gregor dgregor at apple.com
Thu Jun 25 15:08:13 PDT 2009


Author: dgregor
Date: Thu Jun 25 17:08:12 2009
New Revision: 74213

URL: http://llvm.org/viewvc/llvm-project?rev=74213&view=rev
Log:
Improved semantic analysis and AST respresentation for function
templates.

For example, this now type-checks (but does not instantiate the body
of deref<int>):

  template<typename T> T& deref(T* t) { return *t; }

  void test(int *ip) {
    int &ir = deref(ip);
  }

Specific changes/additions:
  * Template argument deduction from a call to a function template.
  * Instantiation of a function template specializations (just the
  declarations) from the template arguments deduced from a call.
  * FunctionTemplateDecls are stored directly in declaration contexts
  and found via name lookup (all forms), rather than finding the
  FunctionDecl and then realizing it is a template. This is
  responsible for most of the churn, since some of the core
  declaration matching and lookup code assumes that all functions are
  FunctionDecls.


Added:
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/Parser/cxx-template-decl.cpp
    cfe/trunk/test/SemaCXX/template-specialization.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_template.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Jun 25 17:08:12 2009
@@ -329,6 +329,9 @@
   /// template parameter pack.
   bool isTemplateParameterPack() const;
 
+  /// \brief Whether this declaration is a function or function template.
+  bool isFunctionOrFunctionTemplate() const;
+  
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *) { return true; }
   static DeclContext *castToDeclContext(const Decl *);

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Jun 25 17:08:12 2009
@@ -27,6 +27,40 @@
 class CXXMethodDecl;
 class ClassTemplateSpecializationDecl;
 
+/// \brief Represents any kind of function declaration, whether it is a 
+/// concrete function or a function template.
+class AnyFunctionDecl {
+  NamedDecl *Function;
+  
+public:
+  AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
+  AnyFunctionDecl(FunctionTemplateDecl *FTD);
+  
+  /// \brief Implicily converts any function or function template into a 
+  /// named declaration.
+  operator NamedDecl *() const { return Function; }
+  
+  /// \brief Retrieve the underlying function or function template.
+  NamedDecl *get() const { return Function; }
+};
+  
+} // end namespace clang
+
+namespace llvm {
+  /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from 
+  /// AnyFunctionDecl to any function or function template declaration.
+  template<> struct simplify_type<const ::clang::AnyFunctionDecl> {
+    typedef ::clang::NamedDecl* SimpleType;
+    static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) {
+      return Val;
+    }
+  };
+  template<> struct simplify_type< ::clang::AnyFunctionDecl>
+  : public simplify_type<const ::clang::AnyFunctionDecl> {};
+} // end namespace llvm
+
+namespace clang {
+  
 /// OverloadedFunctionDecl - An instance of this class represents a
 /// set of overloaded functions. All of the functions have the same
 /// name and occur within the same scope.
@@ -43,15 +77,15 @@
 
   /// Functions - the set of overloaded functions contained in this
   /// overload set.
-  llvm::SmallVector<FunctionDecl *, 4> Functions;
+  llvm::SmallVector<AnyFunctionDecl, 4> Functions;
 
   // FIXME: This should go away when we stop using
   // OverloadedFunctionDecl to store conversions in CXXRecordDecl.
   friend class CXXRecordDecl;
 
 public:
-  typedef llvm::SmallVector<FunctionDecl *, 4>::iterator function_iterator;
-  typedef llvm::SmallVector<FunctionDecl *, 4>::const_iterator
+  typedef llvm::SmallVector<AnyFunctionDecl, 4>::iterator function_iterator;
+  typedef llvm::SmallVector<AnyFunctionDecl, 4>::const_iterator
     function_const_iterator;
 
   static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
@@ -71,30 +105,18 @@
       this->setLocation(FD->getLocation());
   }
 
+  /// addOverload - Add an overloaded function template FTD to this set of
+  /// overloaded functions.
+  void addOverload(FunctionTemplateDecl *FTD);
+  
   function_iterator function_begin() { return Functions.begin(); }
   function_iterator function_end() { return Functions.end(); }
   function_const_iterator function_begin() const { return Functions.begin(); }
   function_const_iterator function_end() const { return Functions.end(); }
 
-  /// getNumFunctions - the number of overloaded functions stored in
+  /// \brief Returns the number of overloaded functions stored in
   /// this set.
-  unsigned getNumFunctions() const { return Functions.size(); }
-
-  /// getFunction - retrieve the ith function in the overload set.
-  const FunctionDecl *getFunction(unsigned i) const {
-    assert(i < getNumFunctions() && "Illegal function #");
-    return Functions[i];
-  }
-  FunctionDecl *getFunction(unsigned i) {
-    assert(i < getNumFunctions() && "Illegal function #");
-    return Functions[i];
-  }
-
-  // getDeclContext - Get the context of these overloaded functions.
-  DeclContext *getDeclContext() {
-    assert(getNumFunctions() > 0 && "Context of an empty overload set");
-    return getFunction(0)->getDeclContext();
-  }
+  unsigned size() const { return Functions.size(); }
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { 

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Jun 25 17:08:12 2009
@@ -957,6 +957,10 @@
   virtual void Destroy(ASTContext& C);
 };
 
+/// Implementation of inline functions that require the template declarations
+inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) 
+  : Function(FTD) { }
+
 } /* end of namespace clang */
 
 #endif

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=74213&r1=74212&r2=74213&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jun 25 17:08:12 2009
@@ -704,14 +704,15 @@
 def err_template_arg_nontype_ambig : Error<
   "template argument for non-type template parameter is treated as type %0">;
 def err_template_arg_must_be_template : Error<
-  "template argument for template template parameter must be a template">;
+  "template argument for template template parameter must be a class template">;
 def err_template_arg_local_type : Error<"template argument uses local type %0">;
 def err_template_arg_unnamed_type : Error<
   "template argument uses unnamed type">;
 def note_template_unnamed_type_here : Note<
   "unnamed type used in template argument was declared here">;
 def err_template_arg_not_class_template : Error<
-  "template argument does not refer to a class template">;
+  "template argument does not refer to a class template or template "
+  "template parameter">;
 def note_template_arg_refers_here_func : Note<
   "template argument refers to function template %0, here">;
 def err_template_arg_template_params_mismatch : Error<

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

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Jun 25 17:08:12 2009
@@ -269,6 +269,14 @@
     // For function declarations, we keep track of redeclarations.
     return FD->getPreviousDeclaration() == OldD;
 
+  // For function templates, the underlying function declarations are linked.
+  if (const FunctionTemplateDecl *FunctionTemplate
+        = dyn_cast<FunctionTemplateDecl>(this))
+    if (const FunctionTemplateDecl *OldFunctionTemplate
+          = dyn_cast<FunctionTemplateDecl>(OldD))
+      return FunctionTemplate->getTemplatedDecl()
+               ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl());
+  
   // For method declarations, we keep track of redeclarations.
   if (isa<ObjCMethodDecl>(this))
     return false;

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

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Jun 25 17:08:12 2009
@@ -96,6 +96,10 @@
   return false;
 }
 
+bool Decl::isFunctionOrFunctionTemplate() const {
+  return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
+}
+
 //===----------------------------------------------------------------------===//
 // PrettyStackTraceDecl Implementation
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Jun 25 17:08:12 2009
@@ -420,6 +420,15 @@
   return new (C) OverloadedFunctionDecl(DC, N);
 }
 
+void OverloadedFunctionDecl::addOverload(FunctionTemplateDecl *FTD) {
+  Functions.push_back(FTD);
+  
+  // An overloaded function declaration always has the location of
+  // the most-recently-added function declaration.
+  if (FTD->getLocation().isValid())
+    this->setLocation(FTD->getLocation());  
+}
+
 LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
                                          DeclContext *DC, 
                                          SourceLocation L,

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jun 25 17:08:12 2009
@@ -697,6 +697,11 @@
                           OverloadCandidateSet& CandidateSet,
                           bool SuppressUserConversions = false,
                           bool ForceRValue = false);
+  void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                    Expr **Args, unsigned NumArgs,
+                                    OverloadCandidateSet& CandidateSet,
+                                    bool SuppressUserConversions = false,
+                                    bool ForceRValue = false);
   void AddConversionCandidate(CXXConversionDecl *Conversion,
                               Expr *From, QualType ToType,
                               OverloadCandidateSet& CandidateSet);
@@ -2204,7 +2209,13 @@
     /// into a non-deduced context produced a type or value that
     /// produces a type that does not match the original template
     /// arguments provided.
-    TDK_NonDeducedMismatch
+    TDK_NonDeducedMismatch,
+    /// \brief When performing template argument deduction for a function 
+    /// template, there were too many call arguments.
+    TDK_TooManyArguments,
+    /// \brief When performing template argument deduction for a class 
+    /// template, there were too few call arguments.
+    TDK_TooFewArguments
   };
 
   /// \brief Provides information about an attempted template argument
@@ -2284,6 +2295,12 @@
                           const TemplateArgumentList &TemplateArgs,
                           TemplateDeductionInfo &Info);
                    
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          Expr **Args, unsigned NumArgs,
+                          FunctionDecl *&Specialization,
+                          TemplateDeductionInfo &Info);
+  
   void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
                                      llvm::SmallVectorImpl<bool> &Deduced);
           

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun 25 17:08:12 2009
@@ -319,16 +319,16 @@
         return;
       }
     }
-  } else if (isa<FunctionDecl>(D) &&
-             AllowOverloadingOfFunction(D, Context)) {
-    // We are pushing the name of a function, which might be an
-    // overloaded name.
-    FunctionDecl *FD = cast<FunctionDecl>(D);
+  } else if ((isa<FunctionDecl>(D) &&
+              AllowOverloadingOfFunction(D, Context)) ||
+             isa<FunctionTemplateDecl>(D)) {
+    // We are pushing the name of a function or function template,
+    // which might be an overloaded name.
     IdentifierResolver::iterator Redecl
-      = std::find_if(IdResolver.begin(FD->getDeclName()),
+      = std::find_if(IdResolver.begin(D->getDeclName()),
                      IdResolver.end(),
                      std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
-                                  FD));
+                                  D));
     if (Redecl != IdResolver.end() &&
         S->isDeclScope(DeclPtrTy::make(*Redecl))) {
       // There is already a declaration of a function on our
@@ -655,7 +655,12 @@
          "Cannot merge with an overloaded function declaration");
 
   // Verify the old decl was also a function.
-  FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
+  FunctionDecl *Old = 0;
+  if (FunctionTemplateDecl *OldFunctionTemplate 
+        = dyn_cast<FunctionTemplateDecl>(OldD))
+    Old = OldFunctionTemplate->getTemplatedDecl();
+  else 
+    Old = dyn_cast<FunctionDecl>(OldD);
   if (!Old) {
     Diag(New->getLocation(), diag::err_redefinition_different_kind)
       << New->getDeclName();
@@ -2304,8 +2309,6 @@
   }
   // Finally, we know we have the right number of parameters, install them.
   NewFD->setParams(Context, Params.data(), Params.size());
-
-  
     
   // If name lookup finds a previous declaration that is not in the
   // same scope as the new declaration, this may still be an
@@ -2388,6 +2391,12 @@
   // Set this FunctionDecl's range up to the right paren.
   NewFD->setLocEnd(D.getSourceRange().getEnd());
 
+  if (FunctionTemplate && NewFD->isInvalidDecl())
+    FunctionTemplate->setInvalidDecl();
+  
+  if (FunctionTemplate)
+    return FunctionTemplate;
+  
   return NewFD;
 }
 
@@ -2516,7 +2525,11 @@
       if (MergeFunctionDecl(NewFD, OldDecl))
         return NewFD->setInvalidDecl();
 
-      NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+      if (FunctionTemplateDecl *OldTemplateDecl
+            = dyn_cast<FunctionTemplateDecl>(OldDecl))
+        NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+      else
+        NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
     }
   }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jun 25 17:08:12 2009
@@ -1625,7 +1625,8 @@
            Conv = Conversions->function_begin(),
            ConvEnd = Conversions->function_end();
          Conv != ConvEnd; ++Conv) {
-      if (*Conv == Conversion->getPreviousDeclaration()) {
+      if (*Conv 
+            == cast_or_null<NamedDecl>(Conversion->getPreviousDeclaration())) {
         *Conv = Conversion;
         return DeclPtrTy::make(Conversion);
       }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jun 25 17:08:12 2009
@@ -2605,11 +2605,16 @@
                                                 CommaLocs, RParenLoc));
 
     // Determine whether this is a call to a member function.
-    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens()))
-      if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
-          isa<CXXMethodDecl>(MemExpr->getMemberDecl()))
+    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) {
+      NamedDecl *MemDecl = MemExpr->getMemberDecl();
+      if (isa<OverloadedFunctionDecl>(MemDecl) ||
+          isa<CXXMethodDecl>(MemDecl) ||
+          (isa<FunctionTemplateDecl>(MemDecl) &&
+           isa<CXXMethodDecl>(
+                cast<FunctionTemplateDecl>(MemDecl)->getTemplatedDecl())))
         return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
                                                CommaLocs, RParenLoc));
+    }
   }
 
   // If we're directly calling a function, get the appropriate declaration.
@@ -2645,13 +2650,19 @@
   }
 
   OverloadedFunctionDecl *Ovl = 0;
+  FunctionTemplateDecl *FunctionTemplate = 0;
   if (DRExpr) {
     FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
+    if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DRExpr->getDecl())))
+      FDecl = FunctionTemplate->getTemplatedDecl();
+    else
+      FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
     Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl());
     NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl());
   }
 
-  if (Ovl || (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
+  if (Ovl || FunctionTemplate || 
+      (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
     // We don't perform ADL for implicit declarations of builtins.
     if (FDecl && FDecl->getBuiltinID(Context) && FDecl->isImplicit())
       ADL = false;
@@ -2660,7 +2671,7 @@
     if (!getLangOptions().CPlusPlus)
       ADL = false;
 
-    if (Ovl || ADL) {
+    if (Ovl || FunctionTemplate || ADL) {
       FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0,
                                       UnqualifiedName, LParenLoc, Args,
                                       NumArgs, CommaLocs, RParenLoc, ADL);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jun 25 17:08:12 2009
@@ -125,21 +125,30 @@
   assert(!isa<OverloadedFunctionDecl>(*I) && 
          "Cannot have an overloaded function");
 
-  if (isa<FunctionDecl>(*I)) {
+  if ((*I)->isFunctionOrFunctionTemplate()) {
     // If we found a function, there might be more functions. If
     // so, collect them into an overload set.
     DeclIterator Last = I;
     OverloadedFunctionDecl *Ovl = 0;
-    for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
+    for (++Last; 
+         Last != IEnd && (*Last)->isFunctionOrFunctionTemplate(); 
+         ++Last) {
       if (!Ovl) {
         // FIXME: We leak this overload set. Eventually, we want to stop
         // building the declarations for these overload sets, so there will be
         // nothing to leak.
         Ovl = OverloadedFunctionDecl::Create(Context, (*I)->getDeclContext(),
                                              (*I)->getDeclName());
-        Ovl->addOverload(cast<FunctionDecl>(*I));
+        if (isa<FunctionDecl>(*I))
+          Ovl->addOverload(cast<FunctionDecl>(*I));
+        else
+          Ovl->addOverload(cast<FunctionTemplateDecl>(*I));
       }
-      Ovl->addOverload(cast<FunctionDecl>(*Last));
+
+      if (isa<FunctionDecl>(*Last))
+        Ovl->addOverload(cast<FunctionDecl>(*Last));
+      else
+        Ovl->addOverload(cast<FunctionTemplateDecl>(*Last));
     }
     
     // If we had more than one function, we built an overload
@@ -206,7 +215,7 @@
       if (TagDecl *TD = dyn_cast<TagDecl>(ND)) {
         TagFound = Context.getCanonicalDecl(TD);
         TagNames += FoundDecls.insert(TagFound)?  1 : 0;
-      } else if (isa<FunctionDecl>(ND))
+      } else if (ND->isFunctionOrFunctionTemplate())
         Functions += FoundDecls.insert(ND)? 1 : 0;
       else
         FoundDecls.insert(ND);
@@ -334,10 +343,10 @@
   LookupResult Result;
   Result.Context = &Context;
 
-  if (F != L && isa<FunctionDecl>(*F)) {
+  if (F != L && (*F)->isFunctionOrFunctionTemplate()) {
     IdentifierResolver::iterator Next = F;
     ++Next;
-    if (Next != L && isa<FunctionDecl>(*Next)) {
+    if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) {
       Result.StoredKind = OverloadedDeclFromIdResolver;
       Result.First = F.getAsOpaqueValue();
       Result.Last = L.getAsOpaqueValue();
@@ -363,10 +372,10 @@
   LookupResult Result;
   Result.Context = &Context;
 
-  if (F != L && isa<FunctionDecl>(*F)) {
+  if (F != L && (*F)->isFunctionOrFunctionTemplate()) {
     DeclContext::lookup_iterator Next = F;
     ++Next;
-    if (Next != L && isa<FunctionDecl>(*Next)) {
+    if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) {
       Result.StoredKind = OverloadedDeclFromDeclContext;
       Result.First = reinterpret_cast<uintptr_t>(F);
       Result.Last = reinterpret_cast<uintptr_t>(L);
@@ -1083,7 +1092,7 @@
   // Lookup in a base class succeeded; return these results.
 
   // If we found a function declaration, return an overload set.
-  if (isa<FunctionDecl>(*Paths.front().Decls.first))
+  if ((*Paths.front().Decls.first)->isFunctionOrFunctionTemplate())
     return LookupResult::CreateLookupResult(Context, 
                         Paths.front().Decls.first, Paths.front().Decls.second);
 
@@ -1489,7 +1498,9 @@
     for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
                                                 FuncEnd = Ovl->function_end();
          Func != FuncEnd; ++Func) {
-      FunctionDecl *FDecl = cast<FunctionDecl>(*Func);
+      FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*Func);
+      if (!FDecl)
+        FDecl = cast<FunctionTemplateDecl>(*Func)->getTemplatedDecl();
 
       // Add the namespace in which this function was defined. Note
       // that, if this is a member function, we do *not* consider the

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Jun 25 17:08:12 2009
@@ -300,7 +300,9 @@
 
     // This function overloads every function in the overload set.
     return true;
-  } else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
+  } else if (FunctionTemplateDecl *Old = dyn_cast<FunctionTemplateDecl>(OldD))
+    return IsOverload(New, Old->getTemplatedDecl(), MatchedDecl);
+  else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
     FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
     FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); 
     
@@ -2073,7 +2075,9 @@
   assert(Proto && "Functions without a prototype cannot be overloaded");
   assert(!isa<CXXConversionDecl>(Function) && 
          "Use AddConversionCandidate for conversion functions");
-
+  assert(!Function->getDescribedFunctionTemplate() && 
+         "Use AddTemplateOverloadCandidate for function templates");
+  
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
     if (!isa<CXXConstructorDecl>(Method)) {
       // If we get here, it's because we're calling a member function
@@ -2258,6 +2262,42 @@
   }
 }
 
+/// \brief Add a C++ function template as a candidate in the candidate set,
+/// using template argument deduction to produce an appropriate function
+/// template specialization.
+void 
+Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                   Expr **Args, unsigned NumArgs,
+                                   OverloadCandidateSet& CandidateSet,
+                                   bool SuppressUserConversions,
+                                   bool ForceRValue) {
+  // C++ [over.match.funcs]p7:
+  //   In each case where a candidate is a function template, candidate 
+  //   function template specializations are generated using template argument
+  //   deduction (14.8.3, 14.8.2). Those candidates are then handled as 
+  //   candidate functions in the usual way.113) A given name can refer to one
+  //   or more function templates and also to a set of overloaded non-template
+  //   functions. In such a case, the candidate functions generated from each
+  //   function template are combined with the set of non-template candidate
+  //   functions.
+  TemplateDeductionInfo Info(Context);
+  FunctionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArguments(FunctionTemplate, Args, NumArgs, 
+                                  Specialization, Info)) {
+    // FIXME: Record what happened with template argument deduction, so
+    // that we can give the user a beautiful diagnostic.
+    (void)Result;
+    return;
+  }
+                            
+  // Add the function template specialization produced by template argument
+  // deduction as a candidate.
+  assert(Specialization && "Missing function template specialization?");
+  AddOverloadCandidate(Specialization, Args, NumArgs, CandidateSet,
+                       SuppressUserConversions, ForceRValue);
+}
+  
 /// AddConversionCandidate - Add a C++ conversion function as a
 /// candidate in the candidate set (C++ [over.match.conv], 
 /// C++ [over.match.copy]). From is the expression we're converting from,
@@ -3678,8 +3718,15 @@
     } else if (IsMember)
       continue;
 
-    if (FunctionType == Context.getCanonicalType((*Fun)->getType()))
-      return *Fun;
+    if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
+      if (FunctionType == Context.getCanonicalType(FunDecl->getType()))
+        return FunDecl;
+    } else {
+      unsigned DiagID 
+        = PP.getDiagnostics().getCustomDiagID(Diagnostic::Warning,
+                   "Clang does not yet support templated conversion functions");
+      Diag(From->getLocStart(), DiagID);
+    }
   }
 
   return 0;
@@ -3724,10 +3771,18 @@
     for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
                                                 FuncEnd = Ovl->function_end();
          Func != FuncEnd; ++Func) {
-      AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
+      DeclContext *Ctx = 0;
+      if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) {
+        AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet);
+        Ctx = FunDecl->getDeclContext();
+      } else {
+        FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func);
+        AddTemplateOverloadCandidate(FunTmpl, Args, NumArgs, CandidateSet);
+        Ctx = FunTmpl->getDeclContext();
+      }
+
 
-      if ((*Func)->getDeclContext()->isRecord() ||
-          (*Func)->getDeclContext()->isFunctionOrMethod())
+      if (Ctx->isRecord() || Ctx->isFunctionOrMethod())
         ArgumentDependentLookup = false;
     }
   } else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) {
@@ -3736,7 +3791,13 @@
     if (Func->getDeclContext()->isRecord() ||
         Func->getDeclContext()->isFunctionOrMethod())
       ArgumentDependentLookup = false;
-  } 
+  } else if (FunctionTemplateDecl *FuncTemplate 
+               = dyn_cast_or_null<FunctionTemplateDecl>(Callee)) {
+    AddTemplateOverloadCandidate(FuncTemplate, Args, NumArgs, CandidateSet);
+
+    if (FuncTemplate->getDeclContext()->isRecord())
+      ArgumentDependentLookup = false;
+  }
 
   if (Callee)
     UnqualifiedName = Callee->getDeclName();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jun 25 17:08:12 2009
@@ -79,7 +79,7 @@
       for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
                                                   FEnd = Ovl->function_end();
            F != FEnd; ++F) {
-        if ((*F)->getDescribedFunctionTemplate()) {
+        if (isa<FunctionTemplateDecl>(*F)) {
           TemplateResult = TemplateTy::make(Ovl);
           return TNK_Function_template;
         }
@@ -1809,8 +1809,8 @@
       !isa<TemplateTemplateParmDecl>(Template)) {
     assert(isa<FunctionTemplateDecl>(Template) && 
            "Only function templates are possible here");
-    Diag(Arg->getSourceRange().getBegin(), 
-         diag::note_template_arg_refers_here_func)
+    Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template);
+    Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
       << Template;
   }
 
@@ -2527,7 +2527,13 @@
   DeclPtrTy DP = HandleDeclarator(ParentScope, D, 
                                   move(TemplateParameterLists),
                                   /*IsFunctionDefinition=*/true);
-  return ActOnStartOfFunctionDef(FnBodyScope, DP);  
+  FunctionTemplateDecl *FunctionTemplate 
+    = cast_or_null<FunctionTemplateDecl>(DP.getAs<Decl>());
+  if (FunctionTemplate)
+    return ActOnStartOfFunctionDef(FnBodyScope, 
+                      DeclPtrTy::make(FunctionTemplate->getTemplatedDecl()));
+
+  return DeclPtrTy();
 }
 
 // Explicit instantiation of a class template specialization

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Jun 25 17:08:12 2009
@@ -717,6 +717,162 @@
   return TDK_Success;
 }
 
+/// \brief Perform template argument deduction from a function call
+/// (C++ [temp.deduct.call]).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param Args the function call arguments
+///
+/// \param NumArgs the number of arguments in Args
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by 
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+///
+/// FIXME: We will also need to pass in any explicitly-specified template
+/// arguments.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              Expr **Args, unsigned NumArgs,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  
+  // C++ [temp.deduct.call]p1:
+  //   Template argument deduction is done by comparing each function template
+  //   parameter type (call it P) with the type of the corresponding argument
+  //   of the call (call it A) as described below.
+  unsigned CheckArgs = NumArgs;
+  if (NumArgs < Function->getNumParams())
+    return TDK_TooFewArguments;
+  else if (NumArgs > Function->getNumParams()) {
+    const FunctionProtoType *Proto 
+      = Function->getType()->getAsFunctionProtoType();
+    if (!Proto->isVariadic())
+      return TDK_TooManyArguments;
+    
+    CheckArgs = Function->getNumParams();
+  }
+  
+  SFINAETrap Trap(*this);
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  Deduced.resize(FunctionTemplate->getTemplateParameters()->size());  
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  for (unsigned I = 0; I != CheckArgs; ++I) {
+    QualType ParamType = Function->getParamDecl(I)->getType();
+    QualType ArgType = Args[I]->getType();
+
+    // C++ [temp.deduct.call]p2:
+    //   If P is not a reference type:
+    QualType CanonParamType = Context.getCanonicalType(ParamType);
+    if (!isa<ReferenceType>(CanonParamType)) {
+      //   - If A is an array type, the pointer type produced by the 
+      //     array-to-pointer standard conversion (4.2) is used in place of 
+      //     A for type deduction; otherwise,
+      if (ArgType->isArrayType())
+        ArgType = Context.getArrayDecayedType(ArgType);
+      //   - If A is a function type, the pointer type produced by the 
+      //     function-to-pointer standard conversion (4.3) is used in place 
+      //     of A for type deduction; otherwise,
+      else if (ArgType->isFunctionType())
+        ArgType = Context.getPointerType(ArgType);
+      else {
+        // - If A is a cv-qualified type, the top level cv-qualifiers of A’s
+        //   type are ignored for type deduction.
+        QualType CanonArgType = Context.getCanonicalType(ArgType);
+        if (CanonArgType.getCVRQualifiers())
+          ArgType = CanonArgType.getUnqualifiedType();
+      }
+    }
+    
+    // C++0x [temp.deduct.call]p3:
+    //   If P is a cv-qualified type, the top level cv-qualifiers of P’s type
+    //   are ignored for type deduction. 
+    if (CanonParamType.getCVRQualifiers())
+      ParamType = CanonParamType.getUnqualifiedType();
+    if (const ReferenceType *ParamRefType = ParamType->getAsReferenceType()) {
+      //   [...] If P is a reference type, the type referred to by P is used 
+      //   for type deduction. 
+      ParamType = ParamRefType->getPointeeType();
+      
+      //   [...] If P is of the form T&&, where T is a template parameter, and 
+      //   the argument is an lvalue, the type A& is used in place of A for 
+      //   type deduction.
+      if (isa<RValueReferenceType>(ParamRefType) &&
+          ParamRefType->getAsTemplateTypeParmType() &&
+          Args[I]->isLvalue(Context) == Expr::LV_Valid)
+        ArgType = Context.getLValueReferenceType(ArgType);
+    }
+    
+    // C++0x [temp.deduct.call]p4:
+    //   In general, the deduction process attempts to find template argument
+    //   values that will make the deduced A identical to A (after the type A
+    //   is transformed as described above). [...]
+    //
+    // FIXME: we'll pass down a flag to indicate when these cases may apply,
+    // and then deal with them in the code that deduces template
+    // arguments from a type.
+    if (TemplateDeductionResult Result
+        = ::DeduceTemplateArguments(Context, TemplateParams,
+                                    ParamType, ArgType, Info, Deduced))
+      return Result;
+    
+    // FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function
+    // pointer parameters. 
+  }
+
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), 
+                             FunctionTemplate, Deduced.data(), Deduced.size());
+  if (Inst)
+    return TDK_InstantiationDepth;
+  
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
+  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+    if (Deduced[I].isNull()) {
+      Decl *Param 
+      = const_cast<Decl *>(TemplateParams->getParam(I));
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+        Info.Param = TTP;
+      else if (NonTypeTemplateParmDecl *NTTP 
+               = dyn_cast<NonTypeTemplateParmDecl>(Param))
+        Info.Param = NTTP;
+      else
+        Info.Param = cast<TemplateTemplateParmDecl>(Param);
+      return TDK_Incomplete;
+    }
+    
+    Builder.Append(Deduced[I]);
+  }
+  
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList 
+    = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+  Info.reset(DeducedArgumentList);
+  
+  // Substitute the deduced template arguments into the function template 
+  // declaration to produce the function template specialization.
+  Specialization = cast_or_null<FunctionDecl>(
+                         InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
+                                         FunctionTemplate->getDeclContext(),
+                                         *DeducedArgumentList));
+  
+  if (!Specialization || Trap.hasErrorOccurred())
+    return TDK_SubstitutionFailure;
+
+  return TDK_Success;
+}
+
 static void 
 MarkDeducedTemplateParameters(Sema &SemaRef,
                               const TemplateArgument &TemplateArg,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jun 25 17:08:12 2009
@@ -44,6 +44,7 @@
     Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
     Decl *VisitEnumDecl(EnumDecl *D);
     Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+    Decl *VisitFunctionDecl(FunctionDecl *D);
     Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
     Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
     Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
@@ -61,6 +62,7 @@
     // Helper functions for instantiating methods.
     QualType InstantiateFunctionType(FunctionDecl *D,
                              llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+    bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
     bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
   };
 }
@@ -291,12 +293,47 @@
   return Record;
 }
 
-Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
-  // Only handle actual methods; we'll deal with constructors,
-  // destructors, etc. separately.
-  if (D->getKind() != Decl::CXXMethod)
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
+  // FIXME: Look for existing specializations (explicit or otherwise).
+  
+  Sema::LocalInstantiationScope Scope(SemaRef);
+  
+  llvm::SmallVector<ParmVarDecl *, 4> Params;
+  QualType T = InstantiateFunctionType(D, Params);
+  if (T.isNull())
     return 0;
+  
+  // Build the instantiated method declaration.
+  FunctionDecl *Function
+    = FunctionDecl::Create(SemaRef.Context, Owner, D->getLocation(), 
+                           D->getDeclName(), T, D->getStorageClass(),
+                           D->isInline(), D->hasWrittenPrototype(),
+                           D->getTypeSpecStartLoc());
+  
+  // FIXME: friend functions
+  
+  // Attach the parameters
+  for (unsigned P = 0; P < Params.size(); ++P)
+    Params[P]->setOwningFunction(Function);
+  Function->setParams(SemaRef.Context, Params.data(), Params.size());
+  
+  if (InitFunctionInstantiation(Function, D))
+    Function->setInvalidDecl();
+  
+  bool Redeclaration = false;
+  bool OverloadableAttrRequired = false;
+  NamedDecl *PrevDecl = 0;
+  SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
+  
+
+  // FIXME: link this to the function template from which it was instantiated.
+  
+  return Function;
+}
 
+Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
+  // FIXME: Look for existing, explicit specializations.
   Sema::LocalInstantiationScope Scope(SemaRef);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -340,6 +377,7 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  // FIXME: Look for existing, explicit specializations.
   Sema::LocalInstantiationScope Scope(SemaRef);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -387,6 +425,7 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+  // FIXME: Look for existing, explicit specializations.
   Sema::LocalInstantiationScope Scope(SemaRef);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -418,6 +457,7 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
+  // FIXME: Look for existing, explicit specializations.
   Sema::LocalInstantiationScope Scope(SemaRef);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -557,6 +597,18 @@
                                    D->getLocation(), D->getDeclName());
 }
 
+/// \brief Initializes the common fields of an instantiation function 
+/// declaration (New) from the corresponding fields of its template (Tmpl).
+///
+/// \returns true if there was an error
+bool 
+TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, 
+                                                    FunctionDecl *Tmpl) {
+  if (Tmpl->isDeleted())
+    New->setDeleted();
+  return false;
+}
+
 /// \brief Initializes common fields of an instantiated method
 /// declaration (New) from the corresponding fields of its template
 /// (Tmpl).
@@ -565,6 +617,9 @@
 bool 
 TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, 
                                                   CXXMethodDecl *Tmpl) {
+  if (InitFunctionInstantiation(New, Tmpl))
+    return true;
+  
   CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
   New->setAccess(Tmpl->getAccess());
   if (Tmpl->isVirtualAsWritten()) {
@@ -573,8 +628,6 @@
     Record->setPOD(false);
     Record->setPolymorphic(true);
   }
-  if (Tmpl->isDeleted())
-    New->setDeleted();
   if (Tmpl->isPure()) {
     New->setPure();
     Record->setAbstract(true);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Thu Jun 25 17:08:12 2009
@@ -400,7 +400,7 @@
          F = Overloads->function_begin(),
          FEnd = Overloads->function_end();
        F != FEnd; ++F)
-    Functions.insert(*F);
+    Functions.insert(cast<FunctionDecl>(*F));
   
   // Add any functions found via argument-dependent lookup.
   DeclarationName OpName 

Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp?rev=74213&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp Thu Jun 25 17:08:12 2009
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T> struct A { };
+
+template<typename T> A<T> f0(T*);
+
+void test_f0(int *ip, float const *cfp) {
+  A<int> a0 = f0(ip);
+  A<const float> a1 = f0(cfp);
+}
+

Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=74213&r1=74212&r2=74213&view=diff

==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Thu Jun 25 17:08:12 2009
@@ -33,8 +33,8 @@
 // Forward declarations w/template template parameters
 template <template <typename> class T> class TTP1;
 template <template <typename> class> class TTP2;
-template <template <typename> class T = foo> class TTP3; // FIXME:expected-error{{template argument for template template parameter must be a template}}
-template <template <typename> class = foo> class TTP3; // FIXME:expected-error{{template argument for template template parameter must be a template}}
+template <template <typename> class T = foo> class TTP3; // expected-error{{must be a class template}}
+template <template <typename> class = foo> class TTP3; // expected-error{{must be a class template}}
 template <template <typename X, typename Y> class T> class TTP5;
 
 // Forward declarations with non-type params

Modified: cfe/trunk/test/SemaCXX/template-specialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/template-specialization.cpp?rev=74213&r1=74212&r2=74213&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/template-specialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/template-specialization.cpp Thu Jun 25 17:08:12 2009
@@ -1,4 +1,5 @@
 // RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
 template<int N> void f(int (&array)[N]);
 
 template<> void f<1>(int (&array)[1]) { }

Modified: cfe/trunk/test/SemaTemplate/temp_arg_template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_template.cpp?rev=74213&r1=74212&r2=74213&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_template.cpp Thu Jun 25 17:08:12 2009
@@ -26,12 +26,12 @@
 C<Y> *a7;
 C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
 
-template<typename T> void f(int);
+template<typename T> void f(int); // expected-note{{function template}}
 
 // FIXME: we're right to provide an error message, but it should say
 // that we need a class template. We won't get this right until name
 // lookup of 'f' returns a TemplateDecl.
-A<f> *a9; // expected-error{{template argument for template template parameter must be a template}}
+A<f> *a9; // expected-error{{template argument does not refer to}}
 
 // FIXME: The code below is ill-formed, because of the evil digraph '<:'. 
 // We should provide a much better error message than we currently do.





More information about the cfe-commits mailing list