Keep track of function template specializations, to eliminate
redundant, implicit instantiations of function templates and provide a
place where we can hang function template specializations.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74454 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index c201409..2b42239 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -809,9 +809,7 @@
     return PreviousDeclaration;
   }
 
-  void setPreviousDeclaration(FunctionDecl * PrevDecl) {
-    PreviousDeclaration = PrevDecl;
-  }
+  void setPreviousDeclaration(FunctionDecl * PrevDecl);
 
   unsigned getBuiltinID(ASTContext &Context) const;
 
@@ -961,7 +959,8 @@
   /// function template specialization from the template.
   void setFunctionTemplateSpecialization(ASTContext &Context,
                                          FunctionTemplateDecl *Template,
-                                      const TemplateArgumentList *TemplateArgs);
+                                      const TemplateArgumentList *TemplateArgs,
+                                         void *InsertPos);
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 9a633ef..531525d 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -100,6 +100,352 @@
   }
 };
 
+/// \brief Represents a template argument within a class template
+/// specialization.
+class TemplateArgument {
+  union {
+    uintptr_t TypeOrValue;
+    struct {
+      char Value[sizeof(llvm::APSInt)];
+      void *Type;
+    } Integer;
+    struct {
+      TemplateArgument *Args;
+      unsigned NumArgs;
+      bool CopyArgs;
+    } Args;
+  };
+  
+  /// \brief Location of the beginning of this template argument.
+  SourceLocation StartLoc;
+  
+public:
+  /// \brief The type of template argument we're storing.
+  enum ArgKind {
+    Null = 0,
+    /// The template argument is a type. Its value is stored in the
+    /// TypeOrValue field.
+    Type = 1,
+    /// The template argument is a declaration
+    Declaration = 2,
+    /// The template argument is an integral value stored in an llvm::APSInt.
+    Integral = 3,
+    /// The template argument is a value- or type-dependent expression
+    /// stored in an Expr*.
+    Expression = 4,
+    
+    /// The template argument is actually a parameter pack. Arguments are stored
+    /// in the Args struct.
+    Pack = 5
+  } Kind;
+  
+  /// \brief Construct an empty, invalid template argument.
+  TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
+  
+  /// \brief Construct a template type argument.
+  TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
+    TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+    StartLoc = Loc;
+  }
+  
+  /// \brief Construct a template argument that refers to a
+  /// declaration, which is either an external declaration or a
+  /// template declaration.
+  TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
+    // FIXME: Need to be sure we have the "canonical" declaration!
+    TypeOrValue = reinterpret_cast<uintptr_t>(D);
+    StartLoc = Loc;
+  }
+  
+  /// \brief Construct an integral constant template argument.
+  TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
+                   QualType Type)
+  : Kind(Integral) {
+    new (Integer.Value) llvm::APSInt(Value);
+    Integer.Type = Type.getAsOpaquePtr();
+    StartLoc = Loc;
+  }
+  
+  /// \brief Construct a template argument that is an expression. 
+  ///
+  /// This form of template argument only occurs in template argument
+  /// lists used for dependent types and for expression; it will not
+  /// occur in a non-dependent, canonical template argument list.
+  TemplateArgument(Expr *E);
+  
+  /// \brief Copy constructor for a template argument.
+  TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+    if (Kind == Integral) {
+      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+      Integer.Type = Other.Integer.Type;
+    } else if (Kind == Pack) {
+      Args.NumArgs = Other.Args.NumArgs;
+      Args.Args = new TemplateArgument[Args.NumArgs];
+      for (unsigned I = 0; I != Args.NumArgs; ++I)
+        Args.Args[I] = Other.Args.Args[I];
+    }
+    else
+      TypeOrValue = Other.TypeOrValue;
+    StartLoc = Other.StartLoc;
+  }
+  
+  TemplateArgument& operator=(const TemplateArgument& Other) {
+    // FIXME: Does not provide the strong guarantee for exception
+    // safety.
+    using llvm::APSInt;
+    
+    // FIXME: Handle Packs
+    assert(Kind != Pack && "FIXME: Handle packs");
+    assert(Other.Kind != Pack && "FIXME: Handle packs");
+    
+    if (Kind == Other.Kind && Kind == Integral) {
+      // Copy integral values.
+      *this->getAsIntegral() = *Other.getAsIntegral();
+      Integer.Type = Other.Integer.Type; 
+    } else {
+      // Destroy the current integral value, if that's what we're holding.
+      if (Kind == Integral)
+        getAsIntegral()->~APSInt();
+      
+      Kind = Other.Kind;
+      
+      if (Other.Kind == Integral) {
+        new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+        Integer.Type = Other.Integer.Type;
+      } else
+        TypeOrValue = Other.TypeOrValue;
+    }
+    StartLoc = Other.StartLoc;
+    
+    return *this;
+  }
+  
+  ~TemplateArgument() {
+    using llvm::APSInt;
+    
+    if (Kind == Integral)
+      getAsIntegral()->~APSInt();
+    else if (Kind == Pack && Args.CopyArgs)
+      delete[] Args.Args;
+  }
+  
+  /// \brief Return the kind of stored template argument.
+  ArgKind getKind() const { return Kind; }
+  
+  /// \brief Determine whether this template argument has no value.
+  bool isNull() const { return Kind == Null; }
+  
+  /// \brief Retrieve the template argument as a type.
+  QualType getAsType() const {
+    if (Kind != Type)
+      return QualType();
+    
+    return QualType::getFromOpaquePtr(
+                                      reinterpret_cast<void*>(TypeOrValue));
+  }
+  
+  /// \brief Retrieve the template argument as a declaration.
+  Decl *getAsDecl() const {
+    if (Kind != Declaration)
+      return 0;
+    return reinterpret_cast<Decl *>(TypeOrValue);
+  }
+  
+  /// \brief Retrieve the template argument as an integral value.
+  llvm::APSInt *getAsIntegral() {
+    if (Kind != Integral)
+      return 0;
+    return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
+  }
+  
+  const llvm::APSInt *getAsIntegral() const {
+    return const_cast<TemplateArgument*>(this)->getAsIntegral();
+  }
+  
+  /// \brief Retrieve the type of the integral value.
+  QualType getIntegralType() const {
+    if (Kind != Integral)
+      return QualType();
+    
+    return QualType::getFromOpaquePtr(Integer.Type);
+  }
+  
+  void setIntegralType(QualType T) {
+    assert(Kind == Integral && 
+           "Cannot set the integral type of a non-integral template argument");
+    Integer.Type = T.getAsOpaquePtr();
+  };
+  
+  /// \brief Retrieve the template argument as an expression.
+  Expr *getAsExpr() const {
+    if (Kind != Expression)
+      return 0;
+    
+    return reinterpret_cast<Expr *>(TypeOrValue);
+  }
+  
+  /// \brief Iterator that traverses the elements of a template argument pack.
+  typedef const TemplateArgument * pack_iterator;
+  
+  /// \brief Iterator referencing the first argument of a template argument 
+  /// pack.
+  pack_iterator pack_begin() const {
+    assert(Kind == Pack);
+    return Args.Args;
+  }
+  
+  /// \brief Iterator referencing one past the last argument of a template
+  /// argument pack.
+  pack_iterator pack_end() const {
+    assert(Kind == Pack);
+    return Args.Args + Args.NumArgs;
+  }
+  
+  /// \brief The number of template arguments in the given template argument
+  /// pack.
+  unsigned pack_size() const {
+    assert(Kind == Pack);
+    return Args.NumArgs;
+  }
+  
+  /// \brief Retrieve the location where the template argument starts.
+  SourceLocation getLocation() const { return StartLoc; }
+  
+  /// \brief Construct a template argument pack.
+  void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+  
+  /// \brief Used to insert TemplateArguments into FoldingSets.
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(Kind);
+    switch (Kind) {
+      case Null:
+        break;
+        
+      case Type:
+        getAsType().Profile(ID);
+        break;
+        
+      case Declaration:
+        ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
+        break;
+        
+      case Integral:
+        getAsIntegral()->Profile(ID);
+        getIntegralType().Profile(ID);
+        break;
+        
+      case Expression:
+        // FIXME: We need a canonical representation of expressions.
+        ID.AddPointer(getAsExpr());
+        break;
+        
+      case Pack:
+        ID.AddInteger(Args.NumArgs);
+        for (unsigned I = 0; I != Args.NumArgs; ++I)
+          Args.Args[I].Profile(ID);
+    }
+  }
+};
+
+/// \brief A helper class for making template argument lists.
+class TemplateArgumentListBuilder {
+  TemplateArgument *StructuredArgs;
+  unsigned MaxStructuredArgs;
+  unsigned NumStructuredArgs;
+  
+  TemplateArgument *FlatArgs;
+  unsigned MaxFlatArgs;
+  unsigned NumFlatArgs;
+  
+  bool AddingToPack;
+  unsigned PackBeginIndex;
+  
+public:
+  TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
+                              unsigned NumTemplateArgs)
+  : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), 
+  NumStructuredArgs(0), FlatArgs(0), 
+  MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
+  AddingToPack(false), PackBeginIndex(0) { }
+  
+  void Append(const TemplateArgument& Arg);
+  void BeginPack();
+  void EndPack();
+  
+  void ReleaseArgs();
+  
+  unsigned flatSize() const { 
+    return NumFlatArgs;
+  }
+  const TemplateArgument *getFlatArguments() const {
+    return FlatArgs;
+  }
+  
+  unsigned structuredSize() const {
+    // If we don't have any structured args, just reuse the flat size.
+    if (!StructuredArgs)
+      return flatSize();
+    
+    return NumStructuredArgs;
+  }
+  const TemplateArgument *getStructuredArguments() const {
+    // If we don't have any structured args, just reuse the flat args.
+    if (!StructuredArgs)
+      return getFlatArguments();
+    
+    return StructuredArgs;
+  }
+};
+
+/// \brief A template argument list.
+///
+/// FIXME: In the future, this class will be extended to support
+/// variadic templates and member templates, which will make some of
+/// the function names below make more sense.
+class TemplateArgumentList {
+  /// \brief The template argument list.
+  ///
+  /// The integer value will be non-zero to indicate that this
+  /// template argument list does not own the pointer.
+  llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
+  
+  /// \brief The number of template arguments in this template
+  /// argument list.
+  unsigned NumFlatArguments;
+  
+  llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
+  unsigned NumStructuredArguments;
+  
+public:
+  TemplateArgumentList(ASTContext &Context,
+                       TemplateArgumentListBuilder &Builder,
+                       bool TakeArgs);
+  
+  ~TemplateArgumentList();
+  
+  /// \brief Retrieve the template argument at a given index.
+  const TemplateArgument &get(unsigned Idx) const { 
+    assert(Idx < NumFlatArguments && "Invalid template argument index");
+    return getFlatArgumentList()[Idx];
+  }
+  
+  /// \brief Retrieve the template argument at a given index.
+  const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
+  
+  /// \brief Retrieve the number of template arguments in this
+  /// template argument list.
+  unsigned size() const { return NumFlatArguments; }
+  
+  /// \brief Retrieve the number of template arguments in the
+  /// flattened template argument list.
+  unsigned flat_size() const { return NumFlatArguments; }
+  
+  /// \brief Retrieve the flattened template argument list.
+  const TemplateArgument *getFlatArgumentList() const { 
+    return FlatArguments.getPointer();
+  }
+};
+  
 //===----------------------------------------------------------------------===//
 // Kinds of Templates
 //===----------------------------------------------------------------------===//
@@ -157,40 +503,92 @@
 /// \brief Provides information about a function template specialization, 
 /// which is a FunctionDecl that has been explicitly specialization or
 /// instantiated from a function template.
-class FunctionTemplateSpecializationInfo {
+class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
 public:
+  /// \brief The function template specialization that this structure 
+  /// describes.
+  FunctionDecl *Function;
+  
+  /// \brief The function template from which this function template 
+  /// specialization was generated.
   FunctionTemplateDecl *Template;
+  
+  /// \brief The template arguments used to produce the function template
+  /// specialization from the function template.
   const TemplateArgumentList *TemplateArguments;
+  
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, TemplateArguments->getFlatArgumentList(), 
+            TemplateArguments->flat_size());    
+  }
+  
+  static void 
+  Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, 
+          unsigned NumTemplateArgs) {
+    ID.AddInteger(NumTemplateArgs);
+    for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+      TemplateArgs[Arg].Profile(ID);
+  }  
 };
   
 /// Declaration of a template function.
-class FunctionTemplateDecl : public TemplateDecl {
+class FunctionTemplateDecl : public TemplateDecl {  
 protected:
   /// \brief Data that is common to all of the declarations of a given
-  /// class template.
+  /// function template.
   struct Common {
-    /// \brief The class template specializations for this class
+    /// \brief The function template specializations for this function
     /// template, including explicit specializations and instantiations.
-    llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
-    
-    /// \brief The class template partial specializations for this class
-    /// template.
-    llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> 
-    PartialSpecializations;
-    
-    /// \brief The injected-class-name type for this class template.
-    QualType InjectedClassNameType;
+    llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
   };
   
+  /// \brief A pointer to the previous declaration (if this is a redeclaration)
+  /// or to the data that is common to all declarations of this function
+  /// template.
+  llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
+  
+  /// \brief Retrieves the "common" pointer shared by all 
+  /// (re-)declarations of the same function template. Calling this routine
+  /// may implicitly allocate memory for the common pointer.
+  Common *getCommonPtr();
+  
   FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
                        TemplateParameterList *Params, NamedDecl *Decl)
-    : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+    : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
+      CommonOrPrev((Common*)0) { }
+  
 public:
-  /// Get the underling function declaration of the template.
+  void Destroy(ASTContext &C);
+  
+  /// Get the underlying function declaration of the template.
   FunctionDecl *getTemplatedDecl() const {
     return static_cast<FunctionDecl*>(TemplatedDecl);
   }
 
+  /// \brief Retrieve the set of function template specializations of this
+  /// function template.
+  llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
+    return getCommonPtr()->Specializations;
+  }
+  
+  /// \brief Retrieve the previous declaration of this function template, or
+  /// NULL if no such declaration exists.
+  const FunctionTemplateDecl *getPreviousDeclaration() const {
+    return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
+  }
+
+  /// \brief Retrieve the previous declaration of this function template, or
+  /// NULL if no such declaration exists.
+  FunctionTemplateDecl *getPreviousDeclaration() {
+    return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
+  }
+  
+  /// \brief Set the previous declaration of this function template.
+  void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
+    if (Prev)
+      CommonOrPrev = Prev;
+  }
+  
   /// Create a template function node.
   static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
                                       SourceLocation L,
@@ -421,352 +819,6 @@
   static bool classof(const TemplateTemplateParmDecl *D) { return true; }
 };
 
-/// \brief Represents a template argument within a class template
-/// specialization.
-class TemplateArgument {
-  union {
-    uintptr_t TypeOrValue;
-    struct {
-      char Value[sizeof(llvm::APSInt)];
-      void *Type;
-    } Integer;
-    struct {
-      TemplateArgument *Args;
-      unsigned NumArgs;
-      bool CopyArgs;
-    } Args;
-  };
-
-  /// \brief Location of the beginning of this template argument.
-  SourceLocation StartLoc;
-
-public:
-  /// \brief The type of template argument we're storing.
-  enum ArgKind {
-    Null = 0,
-    /// The template argument is a type. Its value is stored in the
-    /// TypeOrValue field.
-    Type = 1,
-    /// The template argument is a declaration
-    Declaration = 2,
-    /// The template argument is an integral value stored in an llvm::APSInt.
-    Integral = 3,
-    /// The template argument is a value- or type-dependent expression
-    /// stored in an Expr*.
-    Expression = 4,
-
-    /// The template argument is actually a parameter pack. Arguments are stored
-    /// in the Args struct.
-    Pack = 5
-  } Kind;
-
-  /// \brief Construct an empty, invalid template argument.
-  TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
-
-  /// \brief Construct a template type argument.
-  TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
-    TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
-    StartLoc = Loc;
-  }
-
-  /// \brief Construct a template argument that refers to a
-  /// declaration, which is either an external declaration or a
-  /// template declaration.
-  TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
-    // FIXME: Need to be sure we have the "canonical" declaration!
-    TypeOrValue = reinterpret_cast<uintptr_t>(D);
-    StartLoc = Loc;
-  }
-
-  /// \brief Construct an integral constant template argument.
-  TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
-                   QualType Type)
-    : Kind(Integral) {
-    new (Integer.Value) llvm::APSInt(Value);
-    Integer.Type = Type.getAsOpaquePtr();
-    StartLoc = Loc;
-  }
-
-  /// \brief Construct a template argument that is an expression. 
-  ///
-  /// This form of template argument only occurs in template argument
-  /// lists used for dependent types and for expression; it will not
-  /// occur in a non-dependent, canonical template argument list.
-  TemplateArgument(Expr *E);
-
-  /// \brief Copy constructor for a template argument.
-  TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
-    if (Kind == Integral) {
-      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
-      Integer.Type = Other.Integer.Type;
-    } else if (Kind == Pack) {
-      Args.NumArgs = Other.Args.NumArgs;
-      Args.Args = new TemplateArgument[Args.NumArgs];
-      for (unsigned I = 0; I != Args.NumArgs; ++I)
-            Args.Args[I] = Other.Args.Args[I];
-    }
-    else
-      TypeOrValue = Other.TypeOrValue;
-    StartLoc = Other.StartLoc;
-  }
-
-  TemplateArgument& operator=(const TemplateArgument& Other) {
-    // FIXME: Does not provide the strong guarantee for exception
-    // safety.
-    using llvm::APSInt;
-
-    // FIXME: Handle Packs
-    assert(Kind != Pack && "FIXME: Handle packs");
-    assert(Other.Kind != Pack && "FIXME: Handle packs");
-
-    if (Kind == Other.Kind && Kind == Integral) {
-      // Copy integral values.
-      *this->getAsIntegral() = *Other.getAsIntegral();
-      Integer.Type = Other.Integer.Type; 
-    } else {
-      // Destroy the current integral value, if that's what we're holding.
-      if (Kind == Integral)
-        getAsIntegral()->~APSInt();
-      
-      Kind = Other.Kind;
-      
-      if (Other.Kind == Integral) {
-        new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
-        Integer.Type = Other.Integer.Type;
-      } else
-        TypeOrValue = Other.TypeOrValue;
-    }
-    StartLoc = Other.StartLoc;
-
-    return *this;
-  }
-
-  ~TemplateArgument() {
-    using llvm::APSInt;
-
-    if (Kind == Integral)
-      getAsIntegral()->~APSInt();
-    else if (Kind == Pack && Args.CopyArgs)
-      delete[] Args.Args;
-  }
-
-  /// \brief Return the kind of stored template argument.
-  ArgKind getKind() const { return Kind; }
-
-  /// \brief Determine whether this template argument has no value.
-  bool isNull() const { return Kind == Null; }
-  
-  /// \brief Retrieve the template argument as a type.
-  QualType getAsType() const {
-    if (Kind != Type)
-      return QualType();
-
-    return QualType::getFromOpaquePtr(
-                                 reinterpret_cast<void*>(TypeOrValue));
-  }
-
-  /// \brief Retrieve the template argument as a declaration.
-  Decl *getAsDecl() const {
-    if (Kind != Declaration)
-      return 0;
-    return reinterpret_cast<Decl *>(TypeOrValue);
-  }
-
-  /// \brief Retrieve the template argument as an integral value.
-  llvm::APSInt *getAsIntegral() {
-    if (Kind != Integral)
-      return 0;
-    return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
-  }
-
-  const llvm::APSInt *getAsIntegral() const {
-    return const_cast<TemplateArgument*>(this)->getAsIntegral();
-  }
-
-  /// \brief Retrieve the type of the integral value.
-  QualType getIntegralType() const {
-    if (Kind != Integral)
-      return QualType();
-
-    return QualType::getFromOpaquePtr(Integer.Type);
-  }
-
-  void setIntegralType(QualType T) {
-    assert(Kind == Integral && 
-           "Cannot set the integral type of a non-integral template argument");
-    Integer.Type = T.getAsOpaquePtr();
-  };
-
-  /// \brief Retrieve the template argument as an expression.
-  Expr *getAsExpr() const {
-    if (Kind != Expression)
-      return 0;
-
-    return reinterpret_cast<Expr *>(TypeOrValue);
-  }
-
-  /// \brief Iterator that traverses the elements of a template argument pack.
-  typedef const TemplateArgument * pack_iterator;
-  
-  /// \brief Iterator referencing the first argument of a template argument 
-  /// pack.
-  pack_iterator pack_begin() const {
-    assert(Kind == Pack);
-    return Args.Args;
-  }
-
-  /// \brief Iterator referencing one past the last argument of a template
-  /// argument pack.
-  pack_iterator pack_end() const {
-    assert(Kind == Pack);
-    return Args.Args + Args.NumArgs;
-  }
-  
-  /// \brief The number of template arguments in the given template argument
-  /// pack.
-  unsigned pack_size() const {
-    assert(Kind == Pack);
-    return Args.NumArgs;
-  }
-  
-  /// \brief Retrieve the location where the template argument starts.
-  SourceLocation getLocation() const { return StartLoc; }
-
-  /// \brief Construct a template argument pack.
-  void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
-
-  /// \brief Used to insert TemplateArguments into FoldingSets.
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    ID.AddInteger(Kind);
-    switch (Kind) {
-    case Null:
-      break;
-        
-    case Type:
-      getAsType().Profile(ID);
-      break;
-
-    case Declaration:
-      ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
-      break;
-
-    case Integral:
-      getAsIntegral()->Profile(ID);
-      getIntegralType().Profile(ID);
-      break;
-
-    case Expression:
-      // FIXME: We need a canonical representation of expressions.
-      ID.AddPointer(getAsExpr());
-      break;
-    
-    case Pack:
-      ID.AddInteger(Args.NumArgs);
-      for (unsigned I = 0; I != Args.NumArgs; ++I)
-        Args.Args[I].Profile(ID);
-    }
-  }
-};
-
-/// \brief A helper class for making template argument lists.
-class TemplateArgumentListBuilder {
-  TemplateArgument *StructuredArgs;
-  unsigned MaxStructuredArgs;
-  unsigned NumStructuredArgs;
-    
-  TemplateArgument *FlatArgs;
-  unsigned MaxFlatArgs;
-  unsigned NumFlatArgs;
-  
-  bool AddingToPack;
-  unsigned PackBeginIndex;
-  
-public:
-  TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
-                              unsigned NumTemplateArgs)
-    : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), 
-    NumStructuredArgs(0), FlatArgs(0), 
-    MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
-    AddingToPack(false), PackBeginIndex(0) { }
-  
-  void Append(const TemplateArgument& Arg);
-  void BeginPack();
-  void EndPack();
-
-  void ReleaseArgs();
-  
-  unsigned flatSize() const { 
-    return NumFlatArgs;
-  }
-  const TemplateArgument *getFlatArguments() const {
-    return FlatArgs;
-  }
-  
-  unsigned structuredSize() const {
-    // If we don't have any structured args, just reuse the flat size.
-    if (!StructuredArgs)
-      return flatSize();
-
-    return NumStructuredArgs;
-  }
-  const TemplateArgument *getStructuredArguments() const {
-    // If we don't have any structured args, just reuse the flat args.
-    if (!StructuredArgs)
-      return getFlatArguments();
-    
-    return StructuredArgs;
-  }
-};
-
-/// \brief A template argument list.
-///
-/// FIXME: In the future, this class will be extended to support
-/// variadic templates and member templates, which will make some of
-/// the function names below make more sense.
-class TemplateArgumentList {
-  /// \brief The template argument list.
-  ///
-  /// The integer value will be non-zero to indicate that this
-  /// template argument list does not own the pointer.
-  llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
-
-  /// \brief The number of template arguments in this template
-  /// argument list.
-  unsigned NumFlatArguments;
-
-  llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
-  unsigned NumStructuredArguments;
-  
-public:
-  TemplateArgumentList(ASTContext &Context,
-                       TemplateArgumentListBuilder &Builder,
-                       bool TakeArgs);
-
-  ~TemplateArgumentList();
-
-  /// \brief Retrieve the template argument at a given index.
-  const TemplateArgument &get(unsigned Idx) const { 
-    assert(Idx < NumFlatArguments && "Invalid template argument index");
-    return getFlatArgumentList()[Idx];
-  }
-
-  /// \brief Retrieve the template argument at a given index.
-  const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
-
-  /// \brief Retrieve the number of template arguments in this
-  /// template argument list.
-  unsigned size() const { return NumFlatArguments; }
-
-  /// \brief Retrieve the number of template arguments in the
-  /// flattened template argument list.
-  unsigned flat_size() const { return NumFlatArguments; }
-
-  /// \brief Retrieve the flattened template argument list.
-  const TemplateArgument *getFlatArgumentList() const { 
-    return FlatArguments.getPointer();
-  }
-};
-
 // \brief Describes the kind of template specialization that a
 // particular template specialization declaration represents.
 enum TemplateSpecializationKind {
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 86b5817..7683d5a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1806,6 +1806,12 @@
     return const_cast<FunctionDecl *>(Function);
   }
 
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
+    while (FunTmpl->getPreviousDeclaration())
+      FunTmpl = FunTmpl->getPreviousDeclaration();
+    return FunTmpl;
+  }
+  
   if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
     while (Var->getPreviousDeclaration())
       Var = Var->getPreviousDeclaration();
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 725b066..e25fe90 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -372,11 +372,6 @@
 
   C.Deallocate(ParamInfo);
 
-  if (FunctionTemplateSpecializationInfo *Info 
-        = TemplateOrSpecialization
-            .dyn_cast<FunctionTemplateSpecializationInfo*>())
-    C.Deallocate(Info);
-  
   Decl::Destroy(C);
 }
 
@@ -564,6 +559,18 @@
   return false;
 }
 
+void 
+FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
+  PreviousDeclaration = PrevDecl;
+  
+  if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
+    FunctionTemplateDecl *PrevFunTmpl 
+      = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
+    assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
+    FunTmpl->setPreviousDeclaration(PrevFunTmpl);
+  }
+}
+
 /// getOverloadedOperator - Which C++ overloaded operator this
 /// function represents, if any.
 OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
@@ -595,15 +602,21 @@
 void 
 FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
                                                 FunctionTemplateDecl *Template,
-                                     const TemplateArgumentList *TemplateArgs) {
+                                     const TemplateArgumentList *TemplateArgs,
+                                                void *InsertPos) {
   FunctionTemplateSpecializationInfo *Info 
     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
   if (!Info)
     Info = new (Context) FunctionTemplateSpecializationInfo;
   
+  Info->Function = this;
   Info->Template = Template;
   Info->TemplateArguments = TemplateArgs;
   TemplateOrSpecialization = Info;
+  
+  // Insert this function template specialization into the set of known
+  // function template specialiations.
+  Template->getSpecializations().InsertNode(Info, InsertPos);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 165672d..f1bd1b6 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -81,11 +81,36 @@
                                                    DeclContext *DC,
                                                    SourceLocation L,
                                                    DeclarationName Name,
-                                                   TemplateParameterList *Params,
+                                               TemplateParameterList *Params,
                                                    NamedDecl *Decl) {
   return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
 }
 
+void FunctionTemplateDecl::Destroy(ASTContext &C) {
+  if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
+    for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
+              Spec = CommonPtr->Specializations.begin(),
+           SpecEnd = CommonPtr->Specializations.end();
+         Spec != SpecEnd; ++Spec)
+      C.Deallocate(&*Spec);
+  }
+  
+  Decl::Destroy(C);
+}
+
+FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
+  // Find the first declaration of this function template.
+  FunctionTemplateDecl *First = this;
+  while (First->getPreviousDeclaration())
+    First = First->getPreviousDeclaration();
+  
+  if (First->CommonOrPrev.isNull()) {
+    // FIXME: Allocate with the ASTContext
+    First->CommonOrPrev = new Common;
+  }
+  return First->CommonOrPrev.get<Common*>();
+}
+
 //===----------------------------------------------------------------------===//
 // ClassTemplateDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index a823248..acd90e2 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1500,6 +1500,8 @@
     break;
     // No code generation needed.
   case Decl::Using:
+  case Decl::ClassTemplate:
+  case Decl::FunctionTemplate:
     break;
   case Decl::CXXConstructor:
     EmitCXXConstructors(cast<CXXConstructorDecl>(D));
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 3d909bb..5300385 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1036,14 +1036,22 @@
                          InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
                                          FunctionTemplate->getDeclContext(),
                                          *DeducedArgumentList));
-  
-  if (!Specialization || Trap.hasErrorOccurred())
+  if (!Specialization)
     return TDK_SubstitutionFailure;
+  
+  // If the template argument list is owned by the function template 
+  // specialization, release it.
+  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
+    Info.take();
 
-  // Turn the specialization into an actual function template specialization.
-  Specialization->setFunctionTemplateSpecialization(Context,
-                                                    FunctionTemplate,
-                                                    Info.take());
+  // There may have been an error that did not prevent us from constructing a
+  // declaration. Mark the declaration invalid and return with a substitution
+  // failure.
+  if (Trap.hasErrorOccurred()) {
+    Specialization->setInvalidDecl(true);
+    return TDK_SubstitutionFailure;
+  }
+  
   return TDK_Success;
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a05095f..ac0f46e 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -294,7 +294,24 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
-  // FIXME: Look for existing specializations (explicit or otherwise).
+  // Check whether there is already a function template specialization for
+  // this declaration.
+  FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+  void *InsertPos = 0;
+  if (FunctionTemplate) {
+    llvm::FoldingSetNodeID ID;
+    FunctionTemplateSpecializationInfo::Profile(ID, 
+                                          TemplateArgs.getFlatArgumentList(),
+                                                TemplateArgs.flat_size());
+    
+    FunctionTemplateSpecializationInfo *Info 
+      = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, 
+                                                                   InsertPos);
+    
+    // If we already have a function template specialization, return it.
+    if (Info)
+      return Info->Function;
+  }
   
   Sema::LocalInstantiationScope Scope(SemaRef);
   
@@ -325,10 +342,15 @@
   NamedDecl *PrevDecl = 0;
   SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
                                    /*FIXME:*/OverloadableAttrRequired);
-  
 
-  // FIXME: link this to the function template from which it was instantiated.
-  
+  if (FunctionTemplate) {
+    // Record this function template specialization.
+    Function->setFunctionTemplateSpecialization(SemaRef.Context,
+                                                FunctionTemplate,
+                                                &TemplateArgs,
+                                                InsertPos);
+   }
+
   return Function;
 }
 
diff --git a/test/CodeGenCXX/function-template-specialization.cpp b/test/CodeGenCXX/function-template-specialization.cpp
new file mode 100644
index 0000000..685306f
--- /dev/null
+++ b/test/CodeGenCXX/function-template-specialization.cpp
@@ -0,0 +1,21 @@
+// RUN: clang-cc -emit-llvm %s -o -
+template<typename T, typename U>
+T* next(T* ptr, const U& diff);
+
+template<typename T, typename U>
+T* next(T* ptr, const U& diff) { 
+  return ptr + diff; 
+}
+
+void test(int *iptr, float *fptr, int diff) {
+  iptr = next(iptr, diff);
+  fptr = next(fptr, diff);
+}
+
+template<typename T, typename U>
+T* next(T* ptr, const U& diff);
+
+void test2(int *iptr, double *dptr, int diff) {
+  iptr = next(iptr, diff);
+  dptr = next(dptr, diff);
+}
\ No newline at end of file