r187762 - Started implementing variable templates. Top level declarations should be fully supported, up to some limitations documented as FIXMEs or TODO. Static data member templates work very partially. Static data member templates of class templates need particular attention...

Larisse Voufo lvoufo at google.com
Mon Aug 5 18:03:06 PDT 2013


Author: lvoufo
Date: Mon Aug  5 20:03:05 2013
New Revision: 187762

URL: http://llvm.org/viewvc/llvm-project?rev=187762&view=rev
Log:
Started implementing variable templates. Top level declarations should be fully supported, up to some limitations documented as FIXMEs or TODO. Static data member templates work very partially. Static data member templates of class templates need particular attention...

Added:
    cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
    cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
    cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/ASTMutationListener.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DeclNodes.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TemplateKinds.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/Template.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTCommon.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp
    cfe/trunk/test/SemaCXX/cxx98-compat.cpp
    cfe/trunk/test/SemaCXX/for-range-examples.cpp
    cfe/trunk/test/SemaCXX/unknown-type-name.cpp
    cfe/trunk/test/SemaTemplate/class-template-decl.cpp
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/RecursiveASTVisitor.h

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug  5 20:03:05 2013
@@ -271,13 +271,25 @@ class ASTContext : public RefCountedBase
   /// wasting space in the Decl class.
   llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
 
-  /// \brief Keeps track of the static data member templates from which
-  /// static data members of class template specializations were instantiated.
-  ///
-  /// This data structure stores the mapping from instantiations of static
-  /// data members to the static data member representations within the
-  /// class template from which they were instantiated along with the kind
-  /// of instantiation or specialization (a TemplateSpecializationKind - 1).
+public:
+  /// \brief A type synonym for the TemplateOrInstantiation mapping.
+  typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
+  TemplateOrSpecializationInfo;
+
+private:
+
+  /// \brief A mapping to contain the template or declaration that
+  /// a variable declaration describes or was instantiated from,
+  /// respectively.
+  ///
+  /// For non-templates, this value will be NULL. For variable
+  /// declarations that describe a variable template, this will be a
+  /// pointer to a VarTemplateDecl. For static data members
+  /// of class template specializations, this will be the
+  /// MemberSpecializationInfo referring to the member variable that was
+  /// instantiated or specialized. Thus, the mapping will keep track of
+  /// the static data member templates from which static data members of
+  /// class template specializations were instantiated.
   ///
   /// Given the following example:
   ///
@@ -296,8 +308,8 @@ class ASTContext : public RefCountedBase
   /// This mapping will contain an entry that maps from the VarDecl for
   /// X<int>::value to the corresponding VarDecl for X<T>::value (within the
   /// class template X) and will be marked TSK_ImplicitInstantiation.
-  llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *> 
-    InstantiatedFromStaticDataMember;
+  llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>
+  TemplateOrInstantiation;
 
   /// \brief Keeps track of the declaration from which a UsingDecl was
   /// created during instantiation.
@@ -606,9 +618,13 @@ public:
   /// \brief If this variable is an instantiated static data member of a
   /// class template specialization, returns the templated static data member
   /// from which it was instantiated.
+  // FIXME: Remove ?
   MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
                                                            const VarDecl *Var);
 
+  TemplateOrSpecializationInfo
+  getTemplateOrSpecializationInfo(const VarDecl *Var);
+
   FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD);
 
   void setClassScopeSpecializationPattern(FunctionDecl *FD,
@@ -620,6 +636,9 @@ public:
                                            TemplateSpecializationKind TSK,
                         SourceLocation PointOfInstantiation = SourceLocation());
 
+  void setTemplateOrSpecializationInfo(VarDecl *Inst,
+                                       TemplateOrSpecializationInfo TSI);
+
   /// \brief If the given using decl \p Inst is an instantiation of a
   /// (possibly unresolved) using decl from a template instantiation,
   /// return it.

Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)
+++ cfe/trunk/include/clang/AST/ASTMutationListener.h Mon Aug  5 20:03:05 2013
@@ -30,6 +30,8 @@ namespace clang {
   class QualType;
   class TagDecl;
   class VarDecl;
+  class VarTemplateDecl;
+  class VarTemplateSpecializationDecl;
 
 /// \brief An abstract interface that should be implemented by listeners
 /// that want to be notified when an AST entity gets modified after its
@@ -54,6 +56,12 @@ public:
 
   /// \brief A template specialization (or partial one) was added to the
   /// template declaration.
+  virtual void
+  AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+                                 const VarTemplateSpecializationDecl *D) {}
+
+  /// \brief A template specialization (or partial one) was added to the
+  /// template declaration.
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D) {}
 

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Aug  5 20:03:05 2013
@@ -44,6 +44,7 @@ class TemplateArgumentList;
 class TemplateParameterList;
 class TypeLoc;
 class UnresolvedSetImpl;
+class VarTemplateDecl;
 
 /// \brief A container of type source information.
 ///
@@ -710,6 +711,7 @@ private:
 
   friend class ASTDeclReader;
   friend class StmtIteratorBase;
+  friend class ASTNodeImporter;
 
 protected:
   enum { NumParameterIndexBits = 8 };
@@ -748,15 +750,8 @@ protected:
   };
 
   VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
-          SourceLocation IdLoc, IdentifierInfo *Id,
-          QualType T, TypeSourceInfo *TInfo, StorageClass SC)
-    : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() {
-    assert(sizeof(VarDeclBitfields) <= sizeof(unsigned));
-    assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned));
-    AllBits = 0;
-    VarDeclBits.SClass = SC;
-    // Everything else is implicitly initialized to false.
-  }
+          SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
+          TypeSourceInfo *TInfo, StorageClass SC);
 
   typedef Redeclarable<VarDecl> redeclarable_base;
   virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@@ -955,7 +950,8 @@ public:
 
   /// isFileVarDecl - Returns true for file scoped variable declaration.
   bool isFileVarDecl() const {
-    if (getKind() != Decl::Var)
+    Kind K = getKind();
+    if (K == ParmVar || K == ImplicitParam)
       return false;
 
     if (getDeclContext()->getRedeclContext()->isFileContext())
@@ -1150,6 +1146,26 @@ public:
   void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                         SourceLocation PointOfInstantiation = SourceLocation());
 
+  /// \brief Specify that this variable is an instantiation of the
+  /// static data member VD.
+  void setInstantiationOfStaticDataMember(VarDecl *VD,
+                                          TemplateSpecializationKind TSK);
+
+  /// \brief Retrieves the variable template that is described by this
+  /// variable declaration.
+  ///
+  /// Every variable template is represented as a VarTemplateDecl and a
+  /// VarDecl. The former contains template properties (such as
+  /// the template parameter lists) while the latter contains the
+  /// actual description of the template's
+  /// contents. VarTemplateDecl::getTemplatedDecl() retrieves the
+  /// VarDecl that from a VarTemplateDecl, while
+  /// getDescribedVarTemplate() retrieves the VarTemplateDecl from
+  /// a VarDecl.
+  VarTemplateDecl *getDescribedVarTemplate() const;
+
+  void setDescribedVarTemplate(VarTemplateDecl *Template);
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Aug  5 20:03:05 2013
@@ -34,6 +34,8 @@ class TemplateTypeParmDecl;
 class NonTypeTemplateParmDecl;
 class TemplateTemplateParmDecl;
 class TypeAliasTemplateDecl;
+class VarTemplateDecl;
+class VarTemplatePartialSpecializationDecl;
 
 /// \brief Stores a template parameter of any kind.
 typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
@@ -2250,6 +2252,595 @@ public:
 inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
   : Function(FTD) { }
 
+/// \brief Represents a variable template specialization, which refers to
+/// a variable template with a given set of template arguments.
+///
+/// Variable template specializations represent both explicit
+/// specializations of variable templates, as in the example below, and
+/// implicit instantiations of variable templates.
+///
+/// \code
+/// template<typename T> constexpr T pi = T(3.1415926535897932385);
+///
+/// template<>
+/// constexpr float pi<float>; // variable template specialization pi<float>
+/// \endcode
+class VarTemplateSpecializationDecl : public VarDecl,
+                                      public llvm::FoldingSetNode {
+
+  /// \brief Structure that stores information about a variable template
+  /// specialization that was instantiated from a variable template partial
+  /// specialization.
+  struct SpecializedPartialSpecialization {
+    /// \brief The variable template partial specialization from which this
+    /// variable template specialization was instantiated.
+    VarTemplatePartialSpecializationDecl *PartialSpecialization;
+
+    /// \brief The template argument list deduced for the variable template
+    /// partial specialization itself.
+    TemplateArgumentList *TemplateArgs;
+  };
+
+  /// \brief The template that this specialization specializes.
+  llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *>
+  SpecializedTemplate;
+
+  /// \brief Further info for explicit template specialization/instantiation.
+  struct ExplicitSpecializationInfo {
+    /// \brief The type-as-written.
+    TypeSourceInfo *TypeAsWritten;
+    /// \brief The location of the extern keyword.
+    SourceLocation ExternLoc;
+    /// \brief The location of the template keyword.
+    SourceLocation TemplateKeywordLoc;
+
+    ExplicitSpecializationInfo()
+        : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
+  };
+
+  /// \brief Further info for explicit template specialization/instantiation.
+  /// Does not apply to implicit specializations.
+  ExplicitSpecializationInfo *ExplicitInfo;
+
+  /// \brief The template arguments used to describe this specialization.
+  TemplateArgumentList *TemplateArgs;
+  TemplateArgumentListInfo TemplateArgsInfo;
+
+  /// \brief The point where this template was instantiated (if any).
+  SourceLocation PointOfInstantiation;
+
+  /// \brief The kind of specialization this declaration refers to.
+  /// Really a value of type TemplateSpecializationKind.
+  unsigned SpecializationKind : 3;
+
+protected:
+  VarTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC,
+                                SourceLocation StartLoc, SourceLocation IdLoc,
+                                VarTemplateDecl *SpecializedTemplate,
+                                QualType T, TypeSourceInfo *TInfo,
+                                StorageClass S, const TemplateArgument *Args,
+                                unsigned NumArgs);
+
+  explicit VarTemplateSpecializationDecl(Kind DK);
+
+public:
+  static VarTemplateSpecializationDecl *
+  Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+         SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
+         TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+         unsigned NumArgs);
+  static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
+                                                           unsigned ID);
+
+  virtual void getNameForDiagnostic(raw_ostream &OS,
+                                    const PrintingPolicy &Policy,
+                                    bool Qualified) const;
+
+  VarTemplateSpecializationDecl *getMostRecentDecl() {
+    VarDecl *Recent = cast<VarDecl>(VarDecl::getMostRecentDecl());
+    return cast<VarTemplateSpecializationDecl>(Recent);
+  }
+
+  /// \brief Retrieve the template that this specialization specializes.
+  VarTemplateDecl *getSpecializedTemplate() const;
+
+  /// \brief Retrieve the template arguments of the variable template
+  /// specialization.
+  const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
+
+  // TODO: Always set this when creating the new specialization?
+  void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
+
+  const TemplateArgumentListInfo &getTemplateArgsInfo() const {
+    return TemplateArgsInfo;
+  }
+
+  /// \brief Determine the kind of specialization that this
+  /// declaration represents.
+  TemplateSpecializationKind getSpecializationKind() const {
+    return static_cast<TemplateSpecializationKind>(SpecializationKind);
+  }
+
+  bool isExplicitSpecialization() const {
+    return getSpecializationKind() == TSK_ExplicitSpecialization;
+  }
+
+  /// \brief True if this declaration is an explicit specialization,
+  /// explicit instantiation declaration, or explicit instantiation
+  /// definition.
+  bool isExplicitInstantiationOrSpecialization() const {
+    switch (getTemplateSpecializationKind()) {
+    case TSK_ExplicitSpecialization:
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      return true;
+
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      return false;
+    }
+    llvm_unreachable("bad template specialization kind");
+  }
+
+  void setSpecializationKind(TemplateSpecializationKind TSK) {
+    SpecializationKind = TSK;
+  }
+
+  /// \brief Get the point of instantiation (if any), or null if none.
+  SourceLocation getPointOfInstantiation() const {
+    return PointOfInstantiation;
+  }
+
+  void setPointOfInstantiation(SourceLocation Loc) {
+    assert(Loc.isValid() && "point of instantiation must be valid!");
+    PointOfInstantiation = Loc;
+  }
+
+  /// \brief If this variable template specialization is an instantiation of
+  /// a template (rather than an explicit specialization), return the
+  /// variable template or variable template partial specialization from which
+  /// it was instantiated.
+  llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+  getInstantiatedFrom() const {
+    if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+        getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+        getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+      return llvm::PointerUnion<VarTemplateDecl *,
+                                VarTemplatePartialSpecializationDecl *>();
+
+    if (SpecializedPartialSpecialization *PartialSpec =
+            SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+      return PartialSpec->PartialSpecialization;
+
+    return SpecializedTemplate.get<VarTemplateDecl *>();
+  }
+
+  /// \brief Retrieve the variable template or variable template partial
+  /// specialization which was specialized by this.
+  llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+  getSpecializedTemplateOrPartial() const {
+    if (SpecializedPartialSpecialization *PartialSpec =
+            SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+      return PartialSpec->PartialSpecialization;
+
+    return SpecializedTemplate.get<VarTemplateDecl *>();
+  }
+
+  /// \brief Retrieve the set of template arguments that should be used
+  /// to instantiate the initializer of the variable template or variable
+  /// template partial specialization from which this variable template
+  /// specialization was instantiated.
+  ///
+  /// \returns For a variable template specialization instantiated from the
+  /// primary template, this function will return the same template arguments
+  /// as getTemplateArgs(). For a variable template specialization instantiated
+  /// from a variable template partial specialization, this function will the
+  /// return deduced template arguments for the variable template partial
+  /// specialization itself.
+  const TemplateArgumentList &getTemplateInstantiationArgs() const {
+    if (SpecializedPartialSpecialization *PartialSpec =
+            SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+      return *PartialSpec->TemplateArgs;
+
+    return getTemplateArgs();
+  }
+
+  /// \brief Note that this variable template specialization is actually an
+  /// instantiation of the given variable template partial specialization whose
+  /// template arguments have been deduced.
+  void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
+                          TemplateArgumentList *TemplateArgs) {
+    assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+           "Already set to a variable template partial specialization!");
+    SpecializedPartialSpecialization *PS =
+        new (getASTContext()) SpecializedPartialSpecialization();
+    PS->PartialSpecialization = PartialSpec;
+    PS->TemplateArgs = TemplateArgs;
+    SpecializedTemplate = PS;
+  }
+
+  /// \brief Note that this variable template specialization is an instantiation
+  /// of the given variable template.
+  void setInstantiationOf(VarTemplateDecl *TemplDecl) {
+    assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+           "Previously set to a variable template partial specialization!");
+    SpecializedTemplate = TemplDecl;
+  }
+
+  /// \brief Sets the type of this specialization as it was written by
+  /// the user.
+  void setTypeAsWritten(TypeSourceInfo *T) {
+    if (!ExplicitInfo)
+      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+    ExplicitInfo->TypeAsWritten = T;
+  }
+  /// \brief Gets the type of this specialization as it was written by
+  /// the user, if it was so written.
+  TypeSourceInfo *getTypeAsWritten() const {
+    return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
+  }
+
+  /// \brief Gets the location of the extern keyword, if present.
+  SourceLocation getExternLoc() const {
+    return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+  }
+  /// \brief Sets the location of the extern keyword.
+  void setExternLoc(SourceLocation Loc) {
+    if (!ExplicitInfo)
+      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+    ExplicitInfo->ExternLoc = Loc;
+  }
+
+  /// \brief Sets the location of the template keyword.
+  void setTemplateKeywordLoc(SourceLocation Loc) {
+    if (!ExplicitInfo)
+      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+    ExplicitInfo->TemplateKeywordLoc = Loc;
+  }
+  /// \brief Gets the location of the template keyword, if present.
+  SourceLocation getTemplateKeywordLoc() const {
+    return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs, ASTContext &Context) {
+    ID.AddInteger(NumTemplateArgs);
+    for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+      TemplateArgs[Arg].Profile(ID, Context);
+  }
+
+  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+  static bool classofKind(Kind K) {
+    return K >= firstVarTemplateSpecialization &&
+           K <= lastVarTemplateSpecialization;
+  }
+
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
+};
+
+class VarTemplatePartialSpecializationDecl
+    : public VarTemplateSpecializationDecl {
+  virtual void anchor();
+
+  /// \brief The list of template parameters
+  TemplateParameterList *TemplateParams;
+
+  /// \brief The source info for the template arguments as written.
+  /// FIXME: redundant with TypeAsWritten?
+  TemplateArgumentLoc *ArgsAsWritten;
+  unsigned NumArgsAsWritten;
+
+  /// \brief Sequence number indicating when this variable template partial
+  /// specialization was added to the set of partial specializations for
+  /// its owning variable template.
+  unsigned SequenceNumber;
+
+  /// \brief The variable template partial specialization from which this
+  /// variable template partial specialization was instantiated.
+  ///
+  /// The boolean value will be true to indicate that this variable template
+  /// partial specialization was specialized at this level.
+  llvm::PointerIntPair<VarTemplatePartialSpecializationDecl *, 1, bool>
+  InstantiatedFromMember;
+
+  VarTemplatePartialSpecializationDecl(
+      ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+      SourceLocation IdLoc, TemplateParameterList *Params,
+      VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
+      StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
+      TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos,
+      unsigned SequenceNumber);
+
+  VarTemplatePartialSpecializationDecl()
+      : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization),
+        TemplateParams(0), ArgsAsWritten(0), NumArgsAsWritten(0),
+        SequenceNumber(SequenceNumber), InstantiatedFromMember(0, false) {}
+
+public:
+  static VarTemplatePartialSpecializationDecl *
+  Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+         SourceLocation IdLoc, TemplateParameterList *Params,
+         VarTemplateDecl *SpecializedTemplate, QualType T,
+         TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+         unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos,
+         unsigned SequenceNumber);
+
+  static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,
+                                                                  unsigned ID);
+
+  VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
+    return cast<VarTemplatePartialSpecializationDecl>(
+        VarTemplateSpecializationDecl::getMostRecentDecl());
+  }
+
+  /// Get the list of template parameters
+  TemplateParameterList *getTemplateParameters() const {
+    return TemplateParams;
+  }
+
+  /// Get the template arguments as written.
+  TemplateArgumentLoc *getTemplateArgsAsWritten() const {
+    return ArgsAsWritten;
+  }
+
+  /// Get the number of template arguments as written.
+  unsigned getNumTemplateArgsAsWritten() const { return NumArgsAsWritten; }
+
+  /// \brief Get the sequence number for this variable template partial
+  /// specialization.
+  unsigned getSequenceNumber() const { return SequenceNumber; }
+
+  /// \brief Retrieve the member variable template partial specialization from
+  /// which this particular variable template partial specialization was
+  /// instantiated.
+  ///
+  /// \code
+  /// template<typename T>
+  /// struct Outer {
+  ///   template<typename U> U Inner;
+  ///   template<typename U> U* Inner<U*> = (U*)(0); // #1
+  /// };
+  ///
+  /// template int* Outer<float>::Inner<int*>;
+  /// \endcode
+  ///
+  /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
+  /// end up instantiating the partial specialization
+  /// \c Outer<float>::Inner<U*>, which itself was instantiated from the
+  /// variable template partial specialization \c Outer<T>::Inner<U*>. Given
+  /// \c Outer<float>::Inner<U*>, this function would return
+  /// \c Outer<T>::Inner<U*>.
+  VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
+    VarTemplatePartialSpecializationDecl *First =
+        cast<VarTemplatePartialSpecializationDecl>(getFirstDeclaration());
+    return First->InstantiatedFromMember.getPointer();
+  }
+
+  void
+  setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
+    VarTemplatePartialSpecializationDecl *First =
+        cast<VarTemplatePartialSpecializationDecl>(getFirstDeclaration());
+    First->InstantiatedFromMember.setPointer(PartialSpec);
+  }
+
+  /// \brief Determines whether this variable template partial specialization
+  /// was a specialization of a member partial specialization.
+  ///
+  /// In the following example, the member template partial specialization
+  /// \c X<int>::Inner<T*> is a member specialization.
+  ///
+  /// \code
+  /// template<typename T>
+  /// struct X {
+  ///   template<typename U> U Inner;
+  ///   template<typename U> U* Inner<U*> = (U*)(0);
+  /// };
+  ///
+  /// template<> template<typename T>
+  /// U* X<int>::Inner<T*> = (T*)(0) + 1;
+  /// \endcode
+  bool isMemberSpecialization() {
+    VarTemplatePartialSpecializationDecl *First =
+        cast<VarTemplatePartialSpecializationDecl>(getFirstDeclaration());
+    return First->InstantiatedFromMember.getInt();
+  }
+
+  /// \brief Note that this member template is a specialization.
+  void setMemberSpecialization() {
+    VarTemplatePartialSpecializationDecl *First =
+        cast<VarTemplatePartialSpecializationDecl>(getFirstDeclaration());
+    assert(First->InstantiatedFromMember.getPointer() &&
+           "Only member templates can be member template specializations");
+    return First->InstantiatedFromMember.setInt(true);
+  }
+
+  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+  static bool classofKind(Kind K) {
+    return K == VarTemplatePartialSpecialization;
+  }
+
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
+};
+
+/// Declaration of a variable template.
+class VarTemplateDecl : public RedeclarableTemplateDecl {
+  static void DeallocateCommon(void *Ptr);
+
+protected:
+  /// \brief Data that is common to all of the declarations of a given
+  /// variable template.
+  struct Common : CommonBase {
+    Common() : LazySpecializations() {}
+
+    /// \brief The variable template specializations for this variable
+    /// template, including explicit specializations and instantiations.
+    llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
+
+    /// \brief The variable template partial specializations for this variable
+    /// template.
+    llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
+    PartialSpecializations;
+
+    /// \brief If non-null, points to an array of specializations (including
+    /// partial specializations) known ownly by their external declaration IDs.
+    ///
+    /// The first value in the array is the number of of specializations/
+    /// partial specializations that follow.
+    uint32_t *LazySpecializations;
+  };
+
+  /// \brief Load any lazily-loaded specializations from the external source.
+  void LoadLazySpecializations() const;
+
+  /// \brief Retrieve the set of specializations of this variable template.
+  llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
+  getSpecializations() const;
+
+  /// \brief Retrieve the set of partial specializations of this class
+  /// template.
+  llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
+  getPartialSpecializations();
+
+  VarTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+                  TemplateParameterList *Params, NamedDecl *Decl)
+      : RedeclarableTemplateDecl(VarTemplate, DC, L, Name, Params, Decl) {}
+
+  VarTemplateDecl(EmptyShell Empty)
+      : RedeclarableTemplateDecl(VarTemplate, 0, SourceLocation(),
+                                 DeclarationName(), 0, 0) {}
+
+  CommonBase *newCommon(ASTContext &C) const;
+
+  Common *getCommonPtr() const {
+    return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+  }
+
+public:
+  /// \brief Get the underlying variable declarations of the template.
+  VarDecl *getTemplatedDecl() const {
+    return static_cast<VarDecl *>(TemplatedDecl);
+  }
+
+  /// \brief Returns whether this template declaration defines the primary
+  /// variable pattern.
+  bool isThisDeclarationADefinition() const {
+    return getTemplatedDecl()->isThisDeclarationADefinition();
+  }
+
+  /// \brief Create a variable template node.
+  static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+                                 SourceLocation L, DeclarationName Name,
+                                 TemplateParameterList *Params, NamedDecl *Decl,
+                                 VarTemplateDecl *PrevDecl);
+
+  /// \brief Create an empty variable template node.
+  static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+  /// \brief Return the specialization with the provided arguments if it exists,
+  /// otherwise return the insertion point.
+  VarTemplateSpecializationDecl *
+  findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+                     void *&InsertPos);
+
+  /// \brief Insert the specified specialization knowing that it is not already
+  /// in. InsertPos must be obtained from findSpecialization.
+  void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos);
+
+  VarTemplateDecl *getCanonicalDecl() {
+    return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+  }
+  const VarTemplateDecl *getCanonicalDecl() const {
+    return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+  }
+
+  /// \brief Retrieve the previous declaration of this variable template, or
+  /// NULL if no such declaration exists.
+  VarTemplateDecl *getPreviousDecl() {
+    return cast_or_null<VarTemplateDecl>(
+        RedeclarableTemplateDecl::getPreviousDecl());
+  }
+
+  /// \brief Retrieve the previous declaration of this variable template, or
+  /// NULL if no such declaration exists.
+  const VarTemplateDecl *getPreviousDecl() const {
+    return cast_or_null<VarTemplateDecl>(
+        RedeclarableTemplateDecl::getPreviousDecl());
+  }
+
+  VarTemplateDecl *getInstantiatedFromMemberTemplate() {
+    return cast_or_null<VarTemplateDecl>(
+        RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+  }
+
+  /// \brief Return the partial specialization with the provided arguments if it
+  /// exists, otherwise return the insertion point.
+  VarTemplatePartialSpecializationDecl *
+  findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+                            void *&InsertPos);
+
+  /// \brief Insert the specified partial specialization knowing that it is not
+  /// already in. InsertPos must be obtained from findPartialSpecialization.
+  void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D,
+                                void *InsertPos);
+
+  /// \brief Return the next partial specialization sequence number.
+  unsigned getNextPartialSpecSequenceNumber() {
+    return getPartialSpecializations().size();
+  }
+
+  /// \brief Retrieve the partial specializations as an ordered list.
+  void getPartialSpecializations(
+      SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS);
+
+  /// \brief Find a variable template partial specialization which was
+  /// instantiated
+  /// from the given member partial specialization.
+  ///
+  /// \param D a member variable template partial specialization.
+  ///
+  /// \returns the variable template partial specialization which was
+  /// instantiated
+  /// from the given member partial specialization, or NULL if no such partial
+  /// specialization exists.
+  VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember(
+      VarTemplatePartialSpecializationDecl *D);
+
+  typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator;
+
+  spec_iterator spec_begin() const {
+    return makeSpecIterator(getSpecializations(), false);
+  }
+
+  spec_iterator spec_end() const {
+    return makeSpecIterator(getSpecializations(), true);
+  }
+
+  typedef SpecIterator<VarTemplatePartialSpecializationDecl>
+  partial_spec_iterator;
+
+  partial_spec_iterator partial_spec_begin() {
+    return makeSpecIterator(getPartialSpecializations(), false);
+  }
+
+  partial_spec_iterator partial_spec_end() {
+    return makeSpecIterator(getPartialSpecializations(), true);
+  }
+
+  // Implement isa/cast/dyncast support
+  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+  static bool classofKind(Kind K) { return K == VarTemplate; }
+
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
+};
+
 } /* end of namespace clang */
 
 #endif

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Aug  5 20:03:05 2013
@@ -408,6 +408,7 @@ private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
   bool TraverseClassInstantiations(ClassTemplateDecl *D);
+  bool TraverseVariableInstantiations(VarTemplateDecl *D);
   bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
   bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
                                           unsigned Count);
@@ -1500,6 +1501,57 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
     // it was instantiated, and thus should not be traversed.
   })
 
+// A helper method for traversing the implicit instantiations of a
+// variable template.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
+    VarTemplateDecl *D) {
+  VarTemplateDecl::spec_iterator end = D->spec_end();
+  for (VarTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+    VarTemplateSpecializationDecl *SD = *it;
+
+    switch (SD->getSpecializationKind()) {
+    // Visit the implicit instantiations with the requested pattern.
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      TRY_TO(TraverseDecl(SD));
+      break;
+
+    // We don't need to do anything on an explicit instantiation
+    // or explicit specialization because there will be an explicit
+    // node for it elsewhere.
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+    case TSK_ExplicitSpecialization:
+      break;
+    }
+  }
+
+  return true;
+}
+
+  // FIXME: Unify traversal for variable templates, class templates and function
+  // templates.
+DEF_TRAVERSE_DECL(VarTemplateDecl, {
+  VarDecl *TempDecl = D->getTemplatedDecl();
+  TRY_TO(TraverseDecl(TempDecl));
+  TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+  // By default, we do not traverse the instantiations of
+  // class templates since they do not appear in the user code. The
+  // following code optionally traverses them.
+  //
+  // We only traverse the class instantiations when we see the canonical
+  // declaration of the template, to ensure we only visit them once.
+  if (getDerived().shouldVisitTemplateInstantiations() &&
+      D == D->getCanonicalDecl())
+    TRY_TO(TraverseVariableInstantiations(D));
+
+      // Note that getInstantiatedFromMemberTemplate() is just a link
+      // from a template instantiation back to the template from which
+      // it was instantiated, and thus should not be traversed.
+})
+
 // A helper method for traversing the instantiations of a
 // function while skipping its specializations.
 template<typename Derived>
@@ -1830,6 +1882,42 @@ DEF_TRAVERSE_DECL(VarDecl, {
     TRY_TO(TraverseVarHelper(D));
   })
 
+DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
+  // For implicit instantiations, we don't want to
+  // recurse at all, since the instatiated class isn't written in
+  // the source code anywhere.
+  if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+
+  if (!getDerived().shouldVisitTemplateInstantiations() &&
+      D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+    // Returning from here skips traversing the
+    // declaration context of the VarTemplateSpecializationDecl
+    // (embedded in the DEF_TRAVERSE_DECL() macro).
+    return true;
+})
+
+DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, {
+  // The partial specialization.
+  if (TemplateParameterList *TPL = D->getTemplateParameters()) {
+    for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+         I != E; ++I) {
+      TRY_TO(TraverseDecl(*I));
+    }
+  }
+  // The args that remain unspecialized.
+  TRY_TO(TraverseTemplateArgumentLocsHelper(D->getTemplateArgsAsWritten(),
+                                            D->getNumTemplateArgsAsWritten()));
+
+  // Don't need the VarTemplatePartialSpecializationHelper, even
+  // though that's our parent class -- we already visit all the
+  // template args here.
+  TRY_TO(TraverseVarHelper(D));
+
+                    // Instantiations will have been visited with the primary
+                    // template.
+})
+
 DEF_TRAVERSE_DECL(ImplicitParamDecl, {
     TRY_TO(TraverseVarHelper(D));
   })

Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
+++ cfe/trunk/include/clang/Basic/DeclNodes.td Mon Aug  5 20:03:05 2013
@@ -44,6 +44,9 @@ def Named : Decl<1>;
           def CXXDestructor : DDecl<CXXMethod>;
           def CXXConversion : DDecl<CXXMethod>;
       def Var : DDecl<Declarator>;
+        def VarTemplateSpecialization : DDecl<Var>;
+          def VarTemplatePartialSpecialization
+            : DDecl<VarTemplateSpecialization>;
         def ImplicitParam : DDecl<Var>;
         def ParmVar : DDecl<Var>;
       def NonTypeTemplateParm : DDecl<Declarator>;
@@ -51,6 +54,7 @@ def Named : Decl<1>;
     def RedeclarableTemplate : DDecl<Template, 1>;
       def FunctionTemplate : DDecl<RedeclarableTemplate>;
       def ClassTemplate : DDecl<RedeclarableTemplate>;
+      def VarTemplate : DDecl<RedeclarableTemplate>;
       def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
     def TemplateTemplateParm : DDecl<Template>;
   def Using : DDecl<Named>;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Aug  5 20:03:05 2013
@@ -597,8 +597,8 @@ def err_explicit_instantiation_with_defi
     "definition is meant to be an explicit specialization, add '<>' after the "
     "'template' keyword">;
 def err_template_defn_explicit_instantiation : Error<
-  "%select{function|class}0 cannot be defined in an explicit instantiation; if this "
-  "declaration is meant to be a %select{function|class}0 definition, remove the 'template' keyword">;
+  "%select{function|class|variable}0 cannot be defined in an explicit instantiation; if this "
+  "declaration is meant to be a %select{function|class|variable}0 definition, remove the 'template' keyword">;
 def err_friend_explicit_instantiation : Error<
   "friend cannot be declared in an explicit instantiation; if this "
   "declaration is meant to be a friend declaration, remove the 'template' keyword">;
@@ -606,6 +606,10 @@ def err_explicit_instantiation_enum : Er
     "enumerations cannot be explicitly instantiated">;
 def err_expected_template_parameter : Error<"expected template parameter">;
 
+def err_forward_var_nested_name_specifier : Error<
+  "forward declaration of variable template%select{| partial specialization}0 cannot "
+  "have a nested name specifier">;
+
 def err_missing_dependent_template_keyword : Error<
   "use 'template' keyword to treat '%0' as a dependent template name">;
 def warn_missing_dependent_template_keyword : ExtWarn<

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Aug  5 20:03:05 2013
@@ -1461,6 +1461,8 @@ def err_auto_not_allowed : Error<
   "|in exception declaration|in template parameter|in block literal"
   "|in template argument|in typedef|in type alias|in function return type"
   "|in conversion function type|here}0">;
+def err_auto_not_allowed_var_inst : Error<
+  "'auto' variable template instantiation is not allowed">;
 def err_auto_var_requires_init : Error<
   "declaration of variable %0 with type %1 requires an initializer">;
 def err_auto_new_requires_ctor_arg : Error<
@@ -2779,6 +2781,8 @@ def err_template_linkage : Error<"templa
 def err_template_typedef : Error<"a typedef cannot be a template">;
 def err_template_unnamed_class : Error<
   "cannot declare a class template with no name">;
+def err_var_template_unnamed_class : Error<
+  "cannot declare a variable template with no name">;
 def err_template_param_list_different_arity : Error<
   "%select{too few|too many}0 template parameters in template "
   "%select{|template parameter }1redeclaration">;
@@ -2823,7 +2827,11 @@ def err_template_parameter_default_frien
 def err_template_template_parm_no_parms : Error<
   "template template parameter must have its own template parameters">;
 
-def err_template_variable : Error<"variable %0 declared as a template">;
+def ext_variable_template : ExtWarn<"variable templates are a C++1y extension">,
+  InGroup<CXX1y>;
+def warn_cxx11_compat_variable_template : Warning<
+  "variable templates are incompatible with C++ standards before C++1y">,
+  InGroup<CXXPre1yCompat>, DefaultIgnore;
 def err_template_variable_noparams : Error<
   "extraneous 'template<>' in declaration of variable %0">;
 def err_template_member : Error<"member %0 declared as a template">;
@@ -2832,7 +2840,7 @@ def err_template_member_noparams : Error
 def err_template_tag_noparams : Error<
   "extraneous 'template<>' in declaration of %0 %1">;
 def err_template_decl_ref : Error<
-  "cannot refer to class template %0 without a template argument list">;
+  "cannot refer to %select{class|variable}0 template %1 without a template argument list">;
 
 // C++ Template Argument Lists
 def err_template_missing_args : Error<
@@ -2964,7 +2972,7 @@ def err_pointer_to_member_oper_value_cla
 // C++ template specialization
 def err_template_spec_unknown_kind : Error<
   "can only provide an explicit specialization for a class template, function "
-  "template, or a member function, static data member, "
+  "template, variable template, or a member function, static data member, "
   "%select{or member class|member class, or member enumeration}0 of a "
   "class template">;
 def note_specialized_entity : Note<
@@ -2976,29 +2984,35 @@ def err_template_spec_decl_class_scope :
 def err_template_spec_decl_friend : Error<
   "cannot declare an explicit specialization in a friend">;
 def err_template_spec_decl_out_of_scope_global : Error<
-  "%select{class template|class template partial|function template|member "
-  "function|static data member|member class|member enumeration}0 "
+  "%select{class template|class template partial|variable template|"
+  "variable template partial|function template|member function|"
+  "static data member|member class|member enumeration}0 "
   "specialization of %1 must originally be declared in the global scope">;
 def err_template_spec_decl_out_of_scope : Error<
-  "%select{class template|class template partial|function template|member "
+  "%select{class template|class template partial|variable template|"
+  "variable template partial|function template|member "
   "function|static data member|member class|member enumeration}0 "
   "specialization of %1 must originally be declared in namespace %2">;
 def ext_template_spec_decl_out_of_scope : ExtWarn<
   "first declaration of %select{class template|class template partial|"
+  "variable template|variable template partial|"
   "function template|member function|static data member|member class|"
   "member enumeration}0 specialization of %1 outside namespace %2 is a "
   "C++11 extension">, InGroup<CXX11>;
 def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning<
-  "%select{class template|class template partial|function template|member "
+  "%select{class template|class template partial|variable template|"
+  "variable template partial|function template|member "
   "function|static data member|member class|member enumeration}0 "
   "specialization of %1 outside namespace %2 is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
 def err_template_spec_redecl_out_of_scope : Error<
-  "%select{class template|class template partial|function template|member "
+  "%select{class template|class template partial|variable template|"
+  "variable template partial|function template|member "
   "function|static data member|member class|member enumeration}0 "
   "specialization of %1 not in a namespace enclosing %2">;
 def err_template_spec_redecl_global_scope : Error<
-  "%select{class template|class template partial|function template|member "
+  "%select{class template|class template partial|variable template|"
+  "variable template partial|function template|member "
   "function|static data member|member class|member enumeration}0 "
   "specialization of %1 must occur at global scope">;
 def err_spec_member_not_instantiated : Error<
@@ -3081,6 +3095,16 @@ def note_prev_partial_spec_here : Note<
   "previous declaration of class template partial specialization %0 is here">;
 def err_partial_spec_fully_specialized : Error<
   "partial specialization of %0 does not use any of its template parameters">;
+
+// C++ Variable Template Partial Specialization
+def err_var_default_arg_in_partial_spec : Error<
+  "default template argument in a variable template partial specialization">;
+def err_var_partial_spec_redeclared : Error<
+  "variable template partial specialization %0 cannot be redefined">;
+def note_var_prev_partial_spec_here : Note<
+  "previous declaration of variable template partial specialization is here">;
+def err_var_spec_no_template : Error<
+  "no variable template matches%select{| partial}0 specialization">;
   
 // C++ Function template specializations
 def err_function_template_spec_no_match : Error<
@@ -3194,8 +3218,8 @@ def err_explicit_instantiation_of_typede
 def err_explicit_instantiation_storage_class : Error<
   "explicit instantiation cannot have a storage class">;
 def err_explicit_instantiation_not_known : Error<
-  "explicit instantiation of %0 does not refer to a function template, member "
-  "function, member class, or static data member">;
+  "explicit instantiation of %0 does not refer to a function template, "
+  "variable template, member function, member class, or static data member">;
 def note_explicit_instantiation_here : Note<
   "explicit instantiation refers here">;
 def err_explicit_instantiation_data_member_not_instantiated : Error<
@@ -3225,14 +3249,20 @@ def warn_explicit_instantiation_unqualif
   InGroup<CXX11Compat>, DefaultIgnore;
 def err_explicit_instantiation_undefined_member : Error<
   "explicit instantiation of undefined %select{member class|member function|"
-  "static data member}0 %1 of class template %2">;
+  "static data member|static data member template}0 %1 of class template %2">;
 def err_explicit_instantiation_undefined_func_template : Error<
   "explicit instantiation of undefined function template %0">;
+def err_explicit_instantiation_undefined_var_template : Error<
+  "explicit instantiation of undefined variable template %0">;
 def err_explicit_instantiation_declaration_after_definition : Error<
   "explicit instantiation declaration (with 'extern') follows explicit "
   "instantiation definition (without 'extern')">;
 def note_explicit_instantiation_definition_here : Note<
   "explicit instantiation definition is here">;
+def err_invalid_var_template_spec_type : Error<"type %2 "
+  "of %select{explicit instantiation|explicit specialization|"
+  "partial specialization|redeclaration}0 of %1 does not match"
+  " expected type %3">;
   
 // C++ typename-specifiers
 def err_typename_nested_not_found : Error<"no type named %0 in %1">;
@@ -3278,7 +3308,8 @@ def err_non_type_template_in_nested_name
 def err_template_id_not_a_type : Error<
   "template name refers to non-type template %0">;
 def note_template_declared_here : Note<
-  "%select{function template|class template|type alias template|template template parameter}0 "
+  "%select{function template|class template|variable template"
+  "|type alias template|template template parameter}0 "
   "%1 declared here">;
 def note_parameter_type : Note<
   "parameter of type %0 is declared here">;
@@ -5033,6 +5064,8 @@ def err_invalid_declarator_in_function :
   "definition or redeclaration of %0 not allowed inside a function">;
 def err_not_tag_in_scope : Error<
   "no %select{struct|interface|union|class|enum}0 named %1 in %2">;
+def err_not_var_in_scope : Error<
+  "no variable template named %0 in %1">;
 
 def err_no_typeid_with_fno_rtti : Error<
   "cannot use typeid with -fno-rtti">;

Modified: cfe/trunk/include/clang/Basic/TemplateKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TemplateKinds.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TemplateKinds.h (original)
+++ cfe/trunk/include/clang/Basic/TemplateKinds.h Mon Aug  5 20:03:05 2013
@@ -27,6 +27,9 @@ enum TemplateNameKind {
   /// type. The template itself could be a class template, template
   /// template parameter, or C++0x template alias.
   TNK_Type_template,
+  /// The name refers to a variable template whose specialization produces a
+  /// variable.
+  TNK_Var_template,
   /// The name refers to a dependent template name. Whether the
   /// template name is assumed to refer to a type template or a
   /// function template depends on the context in which the template

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug  5 20:03:05 2013
@@ -87,6 +87,7 @@ namespace clang {
   class ClassTemplateDecl;
   class ClassTemplatePartialSpecializationDecl;
   class ClassTemplateSpecializationDecl;
+  class VarTemplatePartialSpecializationDecl;
   class CodeCompleteConsumer;
   class CodeCompletionAllocator;
   class CodeCompletionTUInfo;
@@ -173,6 +174,7 @@ namespace clang {
   class UsingShadowDecl;
   class ValueDecl;
   class VarDecl;
+  class VarTemplateSpecializationDecl;
   class VisibilityAttr;
   class VisibleDeclConsumer;
   class IndirectFieldDecl;
@@ -1325,6 +1327,7 @@ public:
     NC_Expression,
     NC_NestedNameSpecifier,
     NC_TypeTemplate,
+    NC_VarTemplate,
     NC_FunctionTemplate
   };
 
@@ -1363,6 +1366,12 @@ public:
       return Result;
     }
 
+    static NameClassification VarTemplate(TemplateName Name) {
+      NameClassification Result(NC_VarTemplate);
+      Result.Template = Name;
+      return Result;
+    }
+
     static NameClassification FunctionTemplate(TemplateName Name) {
       NameClassification Result(NC_FunctionTemplate);
       Result.Template = Name;
@@ -1382,13 +1391,22 @@ public:
     }
 
     TemplateName getTemplateName() const {
-      assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate);
+      assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||
+             Kind == NC_VarTemplate);
       return Template;
     }
 
     TemplateNameKind getTemplateNameKind() const {
-      assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate);
-      return Kind == NC_TypeTemplate? TNK_Type_template : TNK_Function_template;
+      switch (Kind) {
+      case NC_TypeTemplate:
+        return TNK_Type_template;
+      case NC_FunctionTemplate:
+        return TNK_Function_template;
+      case NC_VarTemplate:
+        return TNK_Var_template;
+      default:
+        llvm_unreachable("unsuported name classification.");
+      }
     }
   };
 
@@ -1443,10 +1461,11 @@ public:
                                     LookupResult &Previous);
   NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D,
                                   LookupResult &Previous, bool &Redeclaration);
-  NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+  NamedDecl *ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                                      TypeSourceInfo *TInfo,
                                      LookupResult &Previous,
-                                     MultiTemplateParamsArg TemplateParamLists);
+                                     MultiTemplateParamsArg TemplateParamLists,
+                                     bool &AddToScope);
   // Returns true if the variable declaration is a redeclaration
   bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
   void CheckVariableDeclarationType(VarDecl *NewVD);
@@ -3151,11 +3170,10 @@ public:
                               ExprValueKind VK,
                               SourceLocation Loc,
                               const CXXScopeSpec *SS = 0);
-  ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
-                              ExprValueKind VK,
+  ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
                               const DeclarationNameInfo &NameInfo,
-                              const CXXScopeSpec *SS = 0,
-                              NamedDecl *FoundD = 0);
+                              const CXXScopeSpec *SS = 0, NamedDecl *FoundD = 0,
+                              const TemplateArgumentListInfo *TemplateArgs = 0);
   ExprResult
   BuildAnonymousStructUnionMemberReference(
       const CXXScopeSpec &SS,
@@ -3189,9 +3207,9 @@ public:
   ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
                                       LookupResult &R,
                                       bool NeedsADL);
-  ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
-                                      const DeclarationNameInfo &NameInfo,
-                                      NamedDecl *D, NamedDecl *FoundD = 0);
+  ExprResult BuildDeclarationNameExpr(
+      const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+      NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0);
 
   ExprResult BuildLiteralOperatorCall(LookupResult &R,
                                       DeclarationNameInfo &SuffixInfo,
@@ -4964,6 +4982,7 @@ public:
   /// \brief The context in which we are checking a template parameter list.
   enum TemplateParamListContext {
     TPC_ClassTemplate,
+    TPC_VarTemplate,
     TPC_FunctionTemplate,
     TPC_ClassTemplateMember,
     TPC_FriendClassTemplate,
@@ -5020,6 +5039,21 @@ public:
                                     ASTTemplateArgsPtr TemplateArgsIn,
                                     SourceLocation RAngleLoc);
 
+  DeclResult ActOnVarTemplateSpecialization(
+      Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
+      SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+      StorageClass SC, bool IsPartialSpecialization);
+
+  DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
+                                SourceLocation TemplateLoc,
+                                SourceLocation TemplateNameLoc,
+                                const TemplateArgumentListInfo &TemplateArgs);
+
+  ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
+                                const DeclarationNameInfo &NameInfo,
+                                VarTemplateDecl *Template,
+                                SourceLocation TemplateLoc,
+                                const TemplateArgumentListInfo *TemplateArgs);
 
   ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
                                  SourceLocation TemplateKWLoc,
@@ -5691,12 +5725,16 @@ public:
                           sema::TemplateDeductionInfo &Info);
 
   TemplateDeductionResult
-  SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                              TemplateArgumentListInfo &ExplicitTemplateArgs,
-                      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                                 SmallVectorImpl<QualType> &ParamTypes,
-                                      QualType *FunctionType,
-                                      sema::TemplateDeductionInfo &Info);
+  DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+                          const TemplateArgumentList &TemplateArgs,
+                          sema::TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult SubstituteExplicitTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate,
+      TemplateArgumentListInfo &ExplicitTemplateArgs,
+      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+      SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
+      sema::TemplateDeductionInfo &Info);
 
   /// brief A function argument from which we performed template argument
   // deduction for a call.
@@ -5789,6 +5827,10 @@ public:
                                   ClassTemplatePartialSpecializationDecl *PS2,
                                   SourceLocation Loc);
 
+  VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+      VarTemplatePartialSpecializationDecl *PS1,
+      VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+
   void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
                                   bool OnlyDeduced,
                                   unsigned Depth,
@@ -6063,6 +6105,15 @@ public:
                           sema::TemplateDeductionInfo &DeductionInfo,
                           SourceRange InstantiationRange = SourceRange());
 
+    /// \brief Note that we are instantiating as part of template
+    /// argument deduction for a variable template partial
+    /// specialization.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          VarTemplatePartialSpecializationDecl *PartialSpec,
+                          ArrayRef<TemplateArgument> TemplateArgs,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange = SourceRange());
+
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
                           ParmVarDecl *Param,
                           ArrayRef<TemplateArgument> TemplateArgs,
@@ -6344,6 +6395,29 @@ public:
                                      FunctionDecl *Function,
                                      bool Recursive = false,
                                      bool DefinitionRequired = false);
+  VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
+      VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+      const TemplateArgumentList &TemplateArgList,
+      const TemplateArgumentListInfo &TemplateArgsInfo,
+      SmallVectorImpl<TemplateArgument> &Converted,
+      SourceLocation PointOfInstantiation, void *InsertPos,
+      LateInstantiatedAttrVec *LateAttrs = 0,
+      LocalInstantiationScope *StartingScope = 0);
+  VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl(
+      VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+  void
+  BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                             LateInstantiatedAttrVec *LateAttrs = 0,
+                             LocalInstantiationScope *StartingScope = 0,
+                             bool ForVarTemplate = false);
+  void InstantiateVariableInitializer(
+      VarDecl *Var, VarDecl *OldVar,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+  void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
+                                     VarDecl *Var, bool Recursive = false,
+                                     bool DefinitionRequired = false);
   void InstantiateStaticDataMemberDefinition(
                                      SourceLocation PointOfInstantiation,
                                      VarDecl *Var,

Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Mon Aug  5 20:03:05 2013
@@ -378,6 +378,14 @@ namespace clang {
                                 ClassTemplatePartialSpecializationDecl *>, 4>
       OutOfLinePartialSpecs;
 
+    /// \brief A list of out-of-line variable template partial
+    /// specializations that will need to be instantiated after the
+    /// enclosing variable's instantiation is complete.
+    /// FIXME: Verify that this is needed.
+    SmallVector<
+        std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
+    OutOfLineVarPartialSpecs;
+
   public:
     TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
                              const MultiLevelTemplateArgumentList &TemplateArgs)
@@ -417,6 +425,7 @@ namespace clang {
     Decl *VisitFunctionDecl(FunctionDecl *D,
                             TemplateParameterList *TemplateParams);
     Decl *VisitDecl(Decl *D);
+    Decl *VisitVarDecl(VarDecl *D, bool ForVarTemplate);
 
     // Enable late instantiation of attributes.  Late instantiated attributes
     // will be stored in LA.
@@ -439,6 +448,10 @@ namespace clang {
         ::iterator
       delayed_partial_spec_iterator;
 
+    typedef SmallVectorImpl<std::pair<
+        VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> >::iterator
+    delayed_var_partial_spec_iterator;
+
     /// \brief Return an iterator to the beginning of the set of
     /// "delayed" partial specializations, which must be passed to
     /// InstantiateClassTemplatePartialSpecialization once the class
@@ -447,6 +460,10 @@ namespace clang {
       return OutOfLinePartialSpecs.begin();
     }
 
+    delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
+      return OutOfLineVarPartialSpecs.begin();
+    }
+
     /// \brief Return an iterator to the end of the set of
     /// "delayed" partial specializations, which must be passed to
     /// InstantiateClassTemplatePartialSpecialization once the class
@@ -455,6 +472,10 @@ namespace clang {
       return OutOfLinePartialSpecs.end();
     }
 
+    delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
+      return OutOfLineVarPartialSpecs.end();
+    }
+
     // Helper functions for instantiating methods.
     TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
                              SmallVectorImpl<ParmVarDecl *> &Params);
@@ -468,12 +489,21 @@ namespace clang {
                         DeclaratorDecl *NewDecl);
     bool SubstQualifier(const TagDecl *OldDecl,
                         TagDecl *NewDecl);
-      
+
+    Decl *VisitVarTemplateSpecializationDecl(
+        VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos,
+        const TemplateArgumentListInfo &TemplateArgsInfo,
+        SmallVectorImpl<TemplateArgument> &Converted);
+
     Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
     ClassTemplatePartialSpecializationDecl *
     InstantiateClassTemplatePartialSpecialization(
                                               ClassTemplateDecl *ClassTemplate,
                            ClassTemplatePartialSpecializationDecl *PartialSpec);
+    VarTemplatePartialSpecializationDecl *
+    InstantiateVarTemplatePartialSpecialization(
+        VarTemplateDecl *VarTemplate,
+        VarTemplatePartialSpecializationDecl *PartialSpec);
     void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
   };  
 }

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Mon Aug  5 20:03:05 2013
@@ -1027,6 +1027,12 @@ namespace clang {
       DECL_CLASS_TEMPLATE_SPECIALIZATION,
       /// \brief A ClassTemplatePartialSpecializationDecl record.
       DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+      /// \brief A VarTemplateDecl record.
+      DECL_VAR_TEMPLATE,
+      /// \brief A VarTemplateSpecializationDecl record.
+      DECL_VAR_TEMPLATE_SPECIALIZATION,
+      /// \brief A VarTemplatePartialSpecializationDecl record.
+      DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION,
       /// \brief A FunctionTemplateDecl record.
       DECL_FUNCTION_TEMPLATE,
       /// \brief A TemplateTypeParmDecl record.

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Aug  5 20:03:05 2013
@@ -724,6 +724,9 @@ public:
   virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
   virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
                                     const ClassTemplateSpecializationDecl *D);
+  virtual void
+  AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+                                 const VarTemplateSpecializationDecl *D);
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D);
   virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug  5 20:03:05 2013
@@ -1041,13 +1041,20 @@ void ASTContext::eraseDeclAttrs(const De
   }
 }
 
+// FIXME: Remove ?
 MemberSpecializationInfo *
 ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
   assert(Var->isStaticDataMember() && "Not a static data member");
-  llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos
-    = InstantiatedFromStaticDataMember.find(Var);
-  if (Pos == InstantiatedFromStaticDataMember.end())
-    return 0;
+  return getTemplateOrSpecializationInfo(Var)
+      .dyn_cast<MemberSpecializationInfo *>();
+}
+
+ASTContext::TemplateOrSpecializationInfo
+ASTContext::getTemplateOrSpecializationInfo(const VarDecl *Var) {
+  llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>::iterator Pos =
+      TemplateOrInstantiation.find(Var);
+  if (Pos == TemplateOrInstantiation.end())
+    return TemplateOrSpecializationInfo();
 
   return Pos->second;
 }
@@ -1058,10 +1065,16 @@ ASTContext::setInstantiatedFromStaticDat
                                           SourceLocation PointOfInstantiation) {
   assert(Inst->isStaticDataMember() && "Not a static data member");
   assert(Tmpl->isStaticDataMember() && "Not a static data member");
-  assert(!InstantiatedFromStaticDataMember[Inst] &&
-         "Already noted what static data member was instantiated from");
-  InstantiatedFromStaticDataMember[Inst] 
-    = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation);
+  setTemplateOrSpecializationInfo(Inst, new (*this) MemberSpecializationInfo(
+                                            Tmpl, TSK, PointOfInstantiation));
+}
+
+void
+ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst,
+                                            TemplateOrSpecializationInfo TSI) {
+  assert(!TemplateOrInstantiation[Inst] &&
+         "Already noted what the variable was instantiated from");
+  TemplateOrInstantiation[Inst] = TSI;
 }
 
 FunctionDecl *ASTContext::getClassScopeSpecializationPattern(
@@ -7973,20 +7986,20 @@ MangleContext *ASTContext::createMangleC
 CXXABI::~CXXABI() {}
 
 size_t ASTContext::getSideTableAllocatedMemory() const {
-  return ASTRecordLayouts.getMemorySize()
-    + llvm::capacity_in_bytes(ObjCLayouts)
-    + llvm::capacity_in_bytes(KeyFunctions)
-    + llvm::capacity_in_bytes(ObjCImpls)
-    + llvm::capacity_in_bytes(BlockVarCopyInits)
-    + llvm::capacity_in_bytes(DeclAttrs)
-    + llvm::capacity_in_bytes(InstantiatedFromStaticDataMember)
-    + llvm::capacity_in_bytes(InstantiatedFromUsingDecl)
-    + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl)
-    + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl)
-    + llvm::capacity_in_bytes(OverriddenMethods)
-    + llvm::capacity_in_bytes(Types)
-    + llvm::capacity_in_bytes(VariableArrayTypes)
-    + llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
+  return ASTRecordLayouts.getMemorySize() +
+         llvm::capacity_in_bytes(ObjCLayouts) +
+         llvm::capacity_in_bytes(KeyFunctions) +
+         llvm::capacity_in_bytes(ObjCImpls) +
+         llvm::capacity_in_bytes(BlockVarCopyInits) +
+         llvm::capacity_in_bytes(DeclAttrs) +
+         llvm::capacity_in_bytes(TemplateOrInstantiation) +
+         llvm::capacity_in_bytes(InstantiatedFromUsingDecl) +
+         llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl) +
+         llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) +
+         llvm::capacity_in_bytes(OverriddenMethods) +
+         llvm::capacity_in_bytes(Types) +
+         llvm::capacity_in_bytes(VariableArrayTypes) +
+         llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
 }
 
 void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) {

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Aug  5 20:03:05 2013
@@ -106,6 +106,8 @@ namespace clang {
 
     bool ImportDefinition(RecordDecl *From, RecordDecl *To, 
                           ImportDefinitionKind Kind = IDK_Default);
+    bool ImportDefinition(VarDecl *From, VarDecl *To,
+                          ImportDefinitionKind Kind = IDK_Default);
     bool ImportDefinition(EnumDecl *From, EnumDecl *To,
                           ImportDefinitionKind Kind = IDK_Default);
     bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
@@ -120,9 +122,12 @@ namespace clang {
                                SmallVectorImpl<TemplateArgument> &ToArgs);
     bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
                            bool Complain = true);
+    bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
+                           bool Complain = true);
     bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
     bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC);
     bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
+    bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
     Decl *VisitDecl(Decl *D);
     Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
     Decl *VisitNamespaceDecl(NamespaceDecl *D);
@@ -157,7 +162,9 @@ namespace clang {
     Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
     Decl *VisitClassTemplateSpecializationDecl(
                                             ClassTemplateSpecializationDecl *D);
-                            
+    Decl *VisitVarTemplateDecl(VarTemplateDecl *D);
+    Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
+
     // Importing statements
     Stmt *VisitStmt(Stmt *S);
 
@@ -2017,6 +2024,21 @@ bool ASTNodeImporter::ImportDefinition(R
   return false;
 }
 
+bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To,
+                                       ImportDefinitionKind Kind) {
+  if (To->getDefinition())
+    return false;
+
+  // FIXME: Can we really import any initializer? Alternatively, we could force
+  // ourselves to import every declaration of a variable and then only use
+  // getInit() here.
+  To->setInit(Importer.Import(const_cast<Expr *>(From->getAnyInitializer())));
+
+  // FIXME: Other bits to merge?
+
+  return false;
+}
+
 bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, 
                                        ImportDefinitionKind Kind) {
   if (To->getDefinition() || To->isBeingDefined()) {
@@ -2162,6 +2184,14 @@ bool ASTNodeImporter::IsStructuralMatch(
   return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
 }
 
+bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
+                                        bool Complain) {
+  StructuralEquivalenceContext Ctx(
+      Importer.getFromContext(), Importer.getToContext(),
+      Importer.getNonEquivalentDecls(), false, Complain);
+  return Ctx.IsStructurallyEquivalent(FromVar, ToVar);
+}
+
 bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
                                    Importer.getToContext(),
@@ -2188,6 +2218,14 @@ bool ASTNodeImporter::IsStructuralMatch(
   return Ctx.IsStructurallyEquivalent(From, To);  
 }
 
+bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
+                                        VarTemplateDecl *To) {
+  StructuralEquivalenceContext Ctx(Importer.getFromContext(),
+                                   Importer.getToContext(),
+                                   Importer.getNonEquivalentDecls());
+  return Ctx.IsStructurallyEquivalent(From, To);
+}
+
 Decl *ASTNodeImporter::VisitDecl(Decl *D) {
   Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
     << D->getDeclKindName();
@@ -3092,13 +3130,9 @@ Decl *ASTNodeImporter::VisitVarDecl(VarD
   LexicalDC->addDeclInternal(ToVar);
 
   // Merge the initializer.
-  // FIXME: Can we really import any initializer? Alternatively, we could force
-  // ourselves to import every declaration of a variable and then only use
-  // getInit() here.
-  ToVar->setInit(Importer.Import(const_cast<Expr *>(D->getAnyInitializer())));
+  if (ImportDefinition(D, ToVar))
+    return 0;
 
-  // FIXME: Other bits to merge?
-  
   return ToVar;
 }
 
@@ -4112,6 +4146,205 @@ Decl *ASTNodeImporter::VisitClassTemplat
   return D2;
 }
 
+Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
+  // If this variable has a definition in the translation unit we're coming
+  // from,
+  // but this particular declaration is not that definition, import the
+  // definition and map to that.
+  VarDecl *Definition =
+      cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition());
+  if (Definition && Definition != D->getTemplatedDecl()) {
+    Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate());
+    if (!ImportedDef)
+      return 0;
+
+    return Importer.Imported(D, ImportedDef);
+  }
+
+  // Import the major distinguishing characteristics of this variable template.
+  DeclContext *DC, *LexicalDC;
+  DeclarationName Name;
+  SourceLocation Loc;
+  if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+    return 0;
+
+  // We may already have a template of the same name; try to find and match it.
+  assert(!DC->isFunctionOrMethod() &&
+         "Variable templates cannot be declared at function scope");
+  SmallVector<NamedDecl *, 4> ConflictingDecls;
+  SmallVector<NamedDecl *, 2> FoundDecls;
+  DC->localUncachedLookup(Name, FoundDecls);
+  for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+    if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+      continue;
+
+    Decl *Found = FoundDecls[I];
+    if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
+      if (IsStructuralMatch(D, FoundTemplate)) {
+        // The variable templates structurally match; call it the same template.
+        Importer.Imported(D->getTemplatedDecl(),
+                          FoundTemplate->getTemplatedDecl());
+        return Importer.Imported(D, FoundTemplate);
+      }
+    }
+
+    ConflictingDecls.push_back(FoundDecls[I]);
+  }
+
+  if (!ConflictingDecls.empty()) {
+    Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
+                                       ConflictingDecls.data(),
+                                       ConflictingDecls.size());
+  }
+
+  if (!Name)
+    return 0;
+
+  VarDecl *DTemplated = D->getTemplatedDecl();
+
+  // Import the type.
+  QualType T = Importer.Import(DTemplated->getType());
+  if (T.isNull())
+    return 0;
+
+  // Create the declaration that is being templated.
+  SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
+  SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
+  TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo());
+  VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc,
+                                         IdLoc, Name.getAsIdentifierInfo(), T,
+                                         TInfo, DTemplated->getStorageClass());
+  D2Templated->setAccess(DTemplated->getAccess());
+  D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
+  D2Templated->setLexicalDeclContext(LexicalDC);
+
+  // Importer.Imported(DTemplated, D2Templated);
+  // LexicalDC->addDeclInternal(D2Templated);
+
+  // Merge the initializer.
+  if (ImportDefinition(DTemplated, D2Templated))
+    return 0;
+
+  // Create the variable template declaration itself.
+  TemplateParameterList *TemplateParams =
+      ImportTemplateParameterList(D->getTemplateParameters());
+  if (!TemplateParams)
+    return 0;
+
+  VarTemplateDecl *D2 = VarTemplateDecl::Create(
+      Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated,
+      /*PrevDecl=*/0);
+  D2Templated->setDescribedVarTemplate(D2);
+
+  D2->setAccess(D->getAccess());
+  D2->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(D2);
+
+  // Note the relationship between the variable templates.
+  Importer.Imported(D, D2);
+  Importer.Imported(DTemplated, D2Templated);
+
+  if (DTemplated->isThisDeclarationADefinition() &&
+      !D2Templated->isThisDeclarationADefinition()) {
+    // FIXME: Import definition!
+  }
+
+  return D2;
+}
+
+Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
+    VarTemplateSpecializationDecl *D) {
+  // If this record has a definition in the translation unit we're coming from,
+  // but this particular declaration is not that definition, import the
+  // definition and map to that.
+  VarDecl *Definition = D->getDefinition();
+  if (Definition && Definition != D) {
+    Decl *ImportedDef = Importer.Import(Definition);
+    if (!ImportedDef)
+      return 0;
+
+    return Importer.Imported(D, ImportedDef);
+  }
+
+  VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>(
+      Importer.Import(D->getSpecializedTemplate()));
+  if (!VarTemplate)
+    return 0;
+
+  // Import the context of this declaration.
+  DeclContext *DC = VarTemplate->getDeclContext();
+  if (!DC)
+    return 0;
+
+  DeclContext *LexicalDC = DC;
+  if (D->getDeclContext() != D->getLexicalDeclContext()) {
+    LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+    if (!LexicalDC)
+      return 0;
+  }
+
+  // Import the location of this declaration.
+  SourceLocation StartLoc = Importer.Import(D->getLocStart());
+  SourceLocation IdLoc = Importer.Import(D->getLocation());
+
+  // Import template arguments.
+  SmallVector<TemplateArgument, 2> TemplateArgs;
+  if (ImportTemplateArguments(D->getTemplateArgs().data(),
+                              D->getTemplateArgs().size(), TemplateArgs))
+    return 0;
+
+  // Try to find an existing specialization with these template arguments.
+  void *InsertPos = 0;
+  VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization(
+      TemplateArgs.data(), TemplateArgs.size(), InsertPos);
+  if (D2) {
+    // We already have a variable template specialization with these template
+    // arguments.
+
+    // FIXME: Check for specialization vs. instantiation errors.
+
+    if (VarDecl *FoundDef = D2->getDefinition()) {
+      if (!D->isThisDeclarationADefinition() ||
+          IsStructuralMatch(D, FoundDef)) {
+        // The record types structurally match, or the "from" translation
+        // unit only had a forward declaration anyway; call it the same
+        // variable.
+        return Importer.Imported(D, FoundDef);
+      }
+    }
+  } else {
+
+    // Import the type.
+    QualType T = Importer.Import(D->getType());
+    if (T.isNull())
+      return 0;
+    TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+
+    // Create a new specialization.
+    D2 = VarTemplateSpecializationDecl::Create(
+        Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
+        D->getStorageClass(), TemplateArgs.data(), TemplateArgs.size());
+    D2->setSpecializationKind(D->getSpecializationKind());
+    D2->setTemplateArgsInfo(D->getTemplateArgsInfo());
+
+    // Add this specialization to the class template.
+    VarTemplate->AddSpecialization(D2, InsertPos);
+
+    // Import the qualifier, if any.
+    D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+
+    // Add the specialization to this context.
+    D2->setLexicalDeclContext(LexicalDC);
+    LexicalDC->addDeclInternal(D2);
+  }
+  Importer.Imported(D, D2);
+
+  if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2))
+    return 0;
+
+  return D2;
+}
+
 //----------------------------------------------------------------------------
 // Import Statements
 //----------------------------------------------------------------------------

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Aug  5 20:03:05 2013
@@ -1557,6 +1557,17 @@ const char *VarDecl::getStorageClassSpec
   llvm_unreachable("Invalid storage class");
 }
 
+VarDecl::VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
+                 SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
+                 TypeSourceInfo *TInfo, StorageClass SC)
+    : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() {
+  assert(sizeof(VarDeclBitfields) <= sizeof(unsigned));
+  assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned));
+  AllBits = 0;
+  VarDeclBits.SClass = SC;
+  // Everything else is implicitly initialized to false.
+}
+
 VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
                          SourceLocation StartL, SourceLocation IdL,
                          IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
@@ -1952,28 +1963,63 @@ VarDecl *VarDecl::getInstantiatedFromSta
 }
 
 TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
+  if (const VarTemplateSpecializationDecl *Spec =
+          dyn_cast<VarTemplateSpecializationDecl>(this))
+    return Spec->getSpecializationKind();
+
   if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
     return MSI->getTemplateSpecializationKind();
   
   return TSK_Undeclared;
 }
 
+VarTemplateDecl *VarDecl::getDescribedVarTemplate() const {
+  return getASTContext().getTemplateOrSpecializationInfo(this)
+      .dyn_cast<VarTemplateDecl *>();
+}
+
+void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
+  getASTContext().setTemplateOrSpecializationInfo(this, Template);
+}
+
 MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
   if (isStaticDataMember())
-    return getASTContext().getInstantiatedFromStaticDataMember(this);
-
+    // FIXME: Remove ?
+    // return getASTContext().getInstantiatedFromStaticDataMember(this);
+    return getASTContext().getTemplateOrSpecializationInfo(this)
+        .dyn_cast<MemberSpecializationInfo *>();
   return 0;
 }
 
 void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                                          SourceLocation PointOfInstantiation) {
-  MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
-  assert(MSI && "Not an instantiated static data member?");
-  MSI->setTemplateSpecializationKind(TSK);
-  if (TSK != TSK_ExplicitSpecialization &&
-      PointOfInstantiation.isValid() &&
-      MSI->getPointOfInstantiation().isInvalid())
-    MSI->setPointOfInstantiation(PointOfInstantiation);
+  if (VarTemplateSpecializationDecl *Spec =
+          dyn_cast<VarTemplateSpecializationDecl>(this)) {
+    Spec->setSpecializationKind(TSK);
+    if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
+        Spec->getPointOfInstantiation().isInvalid())
+      Spec->setPointOfInstantiation(PointOfInstantiation);
+    return;
+  }
+
+  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
+    MSI->setTemplateSpecializationKind(TSK);
+    if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
+        MSI->getPointOfInstantiation().isInvalid())
+      MSI->setPointOfInstantiation(PointOfInstantiation);
+    return;
+  }
+
+  llvm_unreachable(
+      "Not a variable or static data member template specialization");
+}
+
+void
+VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD,
+                                            TemplateSpecializationKind TSK) {
+  assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() &&
+         "Previous template or instantiation?");
+  getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK);
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Aug  5 20:03:05 2013
@@ -538,6 +538,7 @@ unsigned Decl::getIdentifierNamespaceFor
       return IDNS_Namespace;
 
     case FunctionTemplate:
+    case VarTemplate:
       return IDNS_Ordinary;
 
     case ClassTemplate:
@@ -560,6 +561,8 @@ unsigned Decl::getIdentifierNamespaceFor
     case ClassTemplateSpecialization:
     case ClassTemplatePartialSpecialization:
     case ClassScopeFunctionSpecialization:
+    case VarTemplateSpecialization:
+    case VarTemplatePartialSpecialization:
     case ObjCImplementation:
     case ObjCCategory:
     case ObjCCategoryImpl:

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Mon Aug  5 20:03:05 2013
@@ -958,3 +958,248 @@ ClassScopeFunctionSpecializationDecl::Cr
   return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0,
                                              false, TemplateArgumentListInfo());
 }
+
+//===----------------------------------------------------------------------===//
+// VarTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void VarTemplateDecl::DeallocateCommon(void *Ptr) {
+  static_cast<Common *>(Ptr)->~Common();
+}
+
+VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
+                                         SourceLocation L, DeclarationName Name,
+                                         TemplateParameterList *Params,
+                                         NamedDecl *Decl,
+                                         VarTemplateDecl *PrevDecl) {
+  VarTemplateDecl *New = new (C) VarTemplateDecl(DC, L, Name, Params, Decl);
+  New->setPreviousDeclaration(PrevDecl);
+  return New;
+}
+
+VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
+                                                     unsigned ID) {
+  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarTemplateDecl));
+  return new (Mem) VarTemplateDecl(EmptyShell());
+}
+
+// FIXME: Should this be unified accross class, function and variable
+// templates? Perhaps also moved to RedeclarableTemplateDecl?
+void VarTemplateDecl::LoadLazySpecializations() const {
+  Common *CommonPtr = getCommonPtr();
+  if (CommonPtr->LazySpecializations) {
+    ASTContext &Context = getASTContext();
+    uint32_t *Specs = CommonPtr->LazySpecializations;
+    CommonPtr->LazySpecializations = 0;
+    for (uint32_t I = 0, N = *Specs++; I != N; ++I)
+      (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
+  }
+}
+
+llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
+VarTemplateDecl::getSpecializations() const {
+  LoadLazySpecializations();
+  return getCommonPtr()->Specializations;
+}
+
+llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
+VarTemplateDecl::getPartialSpecializations() {
+  LoadLazySpecializations();
+  return getCommonPtr()->PartialSpecializations;
+}
+
+RedeclarableTemplateDecl::CommonBase *
+VarTemplateDecl::newCommon(ASTContext &C) const {
+  Common *CommonPtr = new (C) Common;
+  C.AddDeallocation(DeallocateCommon, CommonPtr);
+  return CommonPtr;
+}
+
+VarTemplateSpecializationDecl *
+VarTemplateDecl::findSpecialization(const TemplateArgument *Args,
+                                    unsigned NumArgs, void *&InsertPos) {
+  return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
+}
+
+void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
+                                        void *InsertPos) {
+  if (InsertPos)
+    getSpecializations().InsertNode(D, InsertPos);
+  else {
+    VarTemplateSpecializationDecl *Existing =
+        getSpecializations().GetOrInsertNode(D);
+    (void)Existing;
+    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
+  }
+  if (ASTMutationListener *L = getASTMutationListener())
+    L->AddedCXXTemplateSpecialization(this, D);
+}
+
+VarTemplatePartialSpecializationDecl *
+VarTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
+                                           unsigned NumArgs, void *&InsertPos) {
+  return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
+                                InsertPos);
+}
+
+void VarTemplateDecl::AddPartialSpecialization(
+    VarTemplatePartialSpecializationDecl *D, void *InsertPos) {
+  if (InsertPos)
+    getPartialSpecializations().InsertNode(D, InsertPos);
+  else {
+    VarTemplatePartialSpecializationDecl *Existing =
+        getPartialSpecializations().GetOrInsertNode(D);
+    (void)Existing;
+    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
+  }
+
+  if (ASTMutationListener *L = getASTMutationListener())
+    L->AddedCXXTemplateSpecialization(this, D);
+}
+
+void VarTemplateDecl::getPartialSpecializations(
+    SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) {
+  llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
+      getPartialSpecializations();
+  PS.clear();
+  PS.resize(PartialSpecs.size());
+  for (llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>::iterator
+           P = PartialSpecs.begin(),
+           PEnd = PartialSpecs.end();
+       P != PEnd; ++P) {
+    assert(!PS[P->getSequenceNumber()]);
+    PS[P->getSequenceNumber()] = P->getMostRecentDecl();
+  }
+}
+
+VarTemplatePartialSpecializationDecl *
+VarTemplateDecl::findPartialSpecInstantiatedFromMember(
+    VarTemplatePartialSpecializationDecl *D) {
+  Decl *DCanon = D->getCanonicalDecl();
+  for (llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>::iterator
+           P = getPartialSpecializations().begin(),
+           PEnd = getPartialSpecializations().end();
+       P != PEnd; ++P) {
+    if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
+      return P->getMostRecentDecl();
+  }
+
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// VarTemplateSpecializationDecl Implementation
+//===----------------------------------------------------------------------===//
+VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
+    ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
+    TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+    unsigned NumArgs)
+    : VarDecl(DK, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T,
+              TInfo, S),
+      SpecializedTemplate(SpecializedTemplate), ExplicitInfo(0),
+      TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
+      SpecializationKind(TSK_Undeclared) {}
+
+VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK)
+    : VarDecl(DK, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0,
+              SC_None),
+      ExplicitInfo(0), SpecializationKind(TSK_Undeclared) {}
+
+VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
+    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
+    TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+    unsigned NumArgs) {
+  VarTemplateSpecializationDecl *Result = new (Context)
+      VarTemplateSpecializationDecl(Context, VarTemplateSpecialization, DC,
+                                    StartLoc, IdLoc, SpecializedTemplate, T,
+                                    TInfo, S, Args, NumArgs);
+  return Result;
+}
+
+VarTemplateSpecializationDecl *
+VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+  void *Mem =
+      AllocateDeserializedDecl(C, ID, sizeof(VarTemplateSpecializationDecl));
+  VarTemplateSpecializationDecl *Result =
+      new (Mem) VarTemplateSpecializationDecl(VarTemplateSpecialization);
+  return Result;
+}
+
+void VarTemplateSpecializationDecl::getNameForDiagnostic(
+    raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
+  NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
+
+  const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+  TemplateSpecializationType::PrintTemplateArgumentList(
+      OS, TemplateArgs.data(), TemplateArgs.size(), Policy);
+}
+
+VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
+  if (SpecializedPartialSpecialization *PartialSpec =
+          SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+    return PartialSpec->PartialSpecialization->getSpecializedTemplate();
+  return SpecializedTemplate.get<VarTemplateDecl *>();
+}
+
+void VarTemplateSpecializationDecl::setTemplateArgsInfo(
+    const TemplateArgumentListInfo &ArgsInfo) {
+  unsigned N = ArgsInfo.size();
+  TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc());
+  TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc());
+  for (unsigned I = 0; I != N; ++I)
+    TemplateArgsInfo.addArgument(ArgsInfo[I]);
+}
+
+//===----------------------------------------------------------------------===//
+// VarTemplatePartialSpecializationDecl Implementation
+//===----------------------------------------------------------------------===//
+void VarTemplatePartialSpecializationDecl::anchor() {}
+
+VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
+    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, TemplateParameterList *Params,
+    VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
+    StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
+    TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos,
+    unsigned SequenceNumber)
+    : VarTemplateSpecializationDecl(Context, VarTemplatePartialSpecialization,
+                                    DC, StartLoc, IdLoc, SpecializedTemplate, T,
+                                    TInfo, S, Args, NumArgs),
+      TemplateParams(Params), ArgsAsWritten(ArgInfos),
+      NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
+      InstantiatedFromMember(0, false) {
+  // TODO: The template parameters should be in DC by now. Verify.
+  // AdoptTemplateParameterList(Params, DC);
+}
+
+VarTemplatePartialSpecializationDecl *
+VarTemplatePartialSpecializationDecl::Create(
+    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, TemplateParameterList *Params,
+    VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
+    StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
+    const TemplateArgumentListInfo &ArgInfos, unsigned SequenceNumber) {
+  unsigned N = ArgInfos.size();
+  TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
+  for (unsigned I = 0; I != N; ++I)
+    ClonedArgs[I] = ArgInfos[I];
+
+  VarTemplatePartialSpecializationDecl *Result =
+      new (Context) VarTemplatePartialSpecializationDecl(
+          Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
+          S, Args, NumArgs, ClonedArgs, N, SequenceNumber);
+  Result->setSpecializationKind(TSK_ExplicitSpecialization);
+  return Result;
+}
+
+VarTemplatePartialSpecializationDecl *
+VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
+                                                         unsigned ID) {
+  void *Mem = AllocateDeserializedDecl(
+      C, ID, sizeof(VarTemplatePartialSpecializationDecl));
+  VarTemplatePartialSpecializationDecl *Result =
+      new (Mem) VarTemplatePartialSpecializationDecl();
+  return Result;
+}

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Aug  5 20:03:05 2013
@@ -432,7 +432,8 @@ bool ItaniumMangleContext::shouldMangleD
     if (DC->isFunctionOrMethod() && D->hasLinkage())
       while (!DC->isNamespace() && !DC->isTranslationUnit())
         DC = getEffectiveParentContext(DC);
-    if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage)
+    if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage &&
+        !isa<VarTemplateSpecializationDecl>(D))
       return false;
   }
 
@@ -553,6 +554,13 @@ isTemplate(const NamedDecl *ND, const Te
     TemplateArgs = &Spec->getTemplateArgs();
     return Spec->getSpecializedTemplate();
   }
+
+  // Check if we have a variable template.
+  if (const VarTemplateSpecializationDecl *Spec =
+          dyn_cast<VarTemplateSpecializationDecl>(ND)) {
+    TemplateArgs = &Spec->getTemplateArgs();
+    return Spec->getSpecializedTemplate();
+  }
 
   return 0;
 }

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Mon Aug  5 20:03:05 2013
@@ -37,6 +37,8 @@ void CodeGenFunction::EmitDecl(const Dec
   case Decl::UnresolvedUsingTypename:
   case Decl::ClassTemplateSpecialization:
   case Decl::ClassTemplatePartialSpecialization:
+  case Decl::VarTemplateSpecialization:
+  case Decl::VarTemplatePartialSpecialization:
   case Decl::TemplateTypeParm:
   case Decl::UnresolvedUsingValue:
   case Decl::NonTypeTemplateParm:
@@ -52,6 +54,7 @@ void CodeGenFunction::EmitDecl(const Dec
   case Decl::ParmVar:
   case Decl::ImplicitParam:
   case Decl::ClassTemplate:
+  case Decl::VarTemplate:
   case Decl::FunctionTemplate:
   case Decl::TypeAliasTemplate:
   case Decl::TemplateTemplateParm:

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Aug  5 20:03:05 2013
@@ -2841,8 +2841,12 @@ void CodeGenModule::EmitTopLevelDecl(Dec
 
     EmitGlobal(cast<FunctionDecl>(D));
     break;
-      
+
   case Decl::Var:
+    // Skip variable templates
+    if (cast<VarDecl>(D)->getDescribedVarTemplate())
+      return;
+  case Decl::VarTemplateSpecialization:
     EmitGlobal(cast<VarDecl>(D));
     break;
 
@@ -2859,6 +2863,8 @@ void CodeGenModule::EmitTopLevelDecl(Dec
   case Decl::UsingShadow:
   case Decl::Using:
   case Decl::ClassTemplate:
+  case Decl::VarTemplate:
+  case Decl::VarTemplatePartialSpecialization:
   case Decl::FunctionTemplate:
   case Decl::TypeAliasTemplate:
   case Decl::Block:

Modified: cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/MultiplexConsumer.cpp (original)
+++ cfe/trunk/lib/Frontend/MultiplexConsumer.cpp Mon Aug  5 20:03:05 2013
@@ -94,6 +94,9 @@ public:
   virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
   virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
                                     const ClassTemplateSpecializationDecl *D);
+  virtual void
+  AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+                                 const VarTemplateSpecializationDecl *D);
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D);
   virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
@@ -134,6 +137,11 @@ void MultiplexASTMutationListener::Added
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
     Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
 }
+void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
+    const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
+  for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+    Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
+}
 void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
     const FunctionTemplateDecl *TD, const FunctionDecl *D) {
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Mon Aug  5 20:03:05 2013
@@ -55,11 +55,11 @@ NamedDecl *Parser::ParseCXXInlineMethodD
                                            TemplateParams, 0,
                                            VS, ICIS_NoInit);
     if (FnD) {
-      Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs,
-                                       false, true);
+      Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs, false,
+                                       true);
       bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType();
       if (Init.isUsable())
-        Actions.AddInitializerToDecl(FnD, Init.get(), false, 
+        Actions.AddInitializerToDecl(FnD, Init.get(), false,
                                      TypeSpecContainsAuto);
       else
         Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto);

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Aug  5 20:03:05 2013
@@ -1797,24 +1797,69 @@ Decl *Parser::ParseDeclarationAfterDecla
     break;
 
   case ParsedTemplateInfo::Template:
-  case ParsedTemplateInfo::ExplicitSpecialization:
+  case ParsedTemplateInfo::ExplicitSpecialization: {
     ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
                                                *TemplateInfo.TemplateParams,
                                                D);
-    break;
 
-  case ParsedTemplateInfo::ExplicitInstantiation: {
-    DeclResult ThisRes
-      = Actions.ActOnExplicitInstantiation(getCurScope(),
-                                           TemplateInfo.ExternLoc,
-                                           TemplateInfo.TemplateLoc,
-                                           D);
-    if (ThisRes.isInvalid()) {
+    // If this is a forward declaration of a variable template or variable
+    // template partial specialization with nested name specifier, complain.
+    // FIXME: Move to Sema.
+    CXXScopeSpec &SS = D.getCXXScopeSpec();
+    if (Tok.is(tok::semi) && ThisDecl && SS.isNotEmpty() &&
+        (isa<VarTemplateDecl>(ThisDecl) ||
+         isa<VarTemplatePartialSpecializationDecl>(ThisDecl))) {
+      Diag(SS.getBeginLoc(), diag::err_forward_var_nested_name_specifier)
+          << isa<VarTemplatePartialSpecializationDecl>(ThisDecl)
+          << SS.getRange();
       SkipUntil(tok::semi, true, true);
       return 0;
     }
 
-    ThisDecl = ThisRes.get();
+    if (VarTemplateDecl *VT =
+            ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0)
+      // Re-direct this decl to refer to the templated decl so that we can
+      // initialize it.
+      ThisDecl = VT->getTemplatedDecl();
+    break;
+  }
+  case ParsedTemplateInfo::ExplicitInstantiation: {
+    if (Tok.is(tok::semi)) {
+      DeclResult ThisRes = Actions.ActOnExplicitInstantiation(
+          getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
+      if (ThisRes.isInvalid()) {
+        SkipUntil(tok::semi, true, true);
+        return 0;
+      }
+      ThisDecl = ThisRes.get();
+    } else {
+      // FIXME: This check should be for a variable template instantiation only.
+
+      // Check that this is a valid instantiation
+      if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+        // If the declarator-id is not a template-id, issue a diagnostic and
+        // recover by ignoring the 'template' keyword.
+        Diag(Tok, diag::err_template_defn_explicit_instantiation)
+            << 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
+        ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
+      } else {
+        SourceLocation LAngleLoc =
+            PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+        Diag(D.getIdentifierLoc(),
+             diag::err_explicit_instantiation_with_definition)
+            << SourceRange(TemplateInfo.TemplateLoc)
+            << FixItHint::CreateInsertion(LAngleLoc, "<>");
+
+        // Recover as if it were an explicit specialization.
+        TemplateParameterLists FakedParamLists;
+        FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
+            0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
+            LAngleLoc));
+
+        ThisDecl =
+            Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
+      }
+    }
     break;
     }
   }
@@ -1825,6 +1870,7 @@ Decl *Parser::ParseDeclarationAfterDecla
   // If a '==' or '+=' is found, suggest a fixit to '='.
   if (isTokenEqualOrEqualTypo()) {
     ConsumeToken();
+
     if (Tok.is(tok::kw_delete)) {
       if (D.isFunctionDeclarator())
         Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Aug  5 20:03:05 2013
@@ -15,6 +15,7 @@
 #include "RAIIObjectsForParser.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/OperatorKinds.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ParsedTemplate.h"
@@ -2264,6 +2265,13 @@ void Parser::ParseCXXClassMemberDeclarat
                                                   TemplateParams,
                                                   BitfieldSize.release(),
                                                   VS, HasInClassInit);
+
+      if (VarTemplateDecl *VT =
+              ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0)
+        // Re-direct this decl to refer to the templated decl so that we can
+        // initialize it.
+        ThisDecl = VT->getTemplatedDecl();
+
       if (ThisDecl && AccessAttrs)
         Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs,
                                          false, true);

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Aug  5 20:03:05 2013
@@ -465,8 +465,8 @@ bool Parser::ParseOptionalCXXScopeSpecif
                                     TemplateName, false))
           return true;
         continue;
-      } 
-      
+      }
+
       if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) && 
           (IsTypename || IsTemplateArgumentList(1))) {
         // We have something like t::getAs<T>, where getAs is a 
@@ -561,6 +561,12 @@ ExprResult Parser::ParseCXXIdExpression(
   //   '::' unqualified-id
   //
   CXXScopeSpec SS;
+  if (Tok.getKind() == tok::annot_template_id) {
+    TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
+    // FIXME: This is a hack for now. It may need to be done from within
+    // ParseUnqualifiedId(), or most likely ParseOptionalCXXScopeSpecifier();
+    SS = TemplateId->SS;
+  }
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
 
   SourceLocation TemplateKWLoc;

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon Aug  5 20:03:05 2013
@@ -242,32 +242,31 @@ Parser::ParseSingleDeclarationAfterTempl
         // If the declarator-id is not a template-id, issue a diagnostic and
         // recover by ignoring the 'template' keyword.
         Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
-	return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(),
-				       &LateParsedAttrs);
+        return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(),
+                                       &LateParsedAttrs);
       } else {
         SourceLocation LAngleLoc
           = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
-        Diag(DeclaratorInfo.getIdentifierLoc(), 
+        Diag(DeclaratorInfo.getIdentifierLoc(),
              diag::err_explicit_instantiation_with_definition)
-          << SourceRange(TemplateInfo.TemplateLoc)
-          << FixItHint::CreateInsertion(LAngleLoc, "<>");
+            << SourceRange(TemplateInfo.TemplateLoc)
+            << FixItHint::CreateInsertion(LAngleLoc, "<>");
 
-        // Recover as if it were an explicit specialization. 
+        // Recover as if it were an explicit specialization.
         TemplateParameterLists FakedParamLists;
-        FakedParamLists.push_back(
-	     Actions.ActOnTemplateParameterList(0, SourceLocation(),
-					        TemplateInfo.TemplateLoc, 
-						LAngleLoc, 0, 0, LAngleLoc));
+        FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
+            0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
+            LAngleLoc));
 
-        return ParseFunctionDefinition(DeclaratorInfo, 
-                                       ParsedTemplateInfo(&FakedParamLists,
-                                           /*isSpecialization=*/true,
-                                           /*LastParamListWasEmpty=*/true),
-                                       &LateParsedAttrs);
+        return ParseFunctionDefinition(
+            DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
+                                               /*isSpecialization=*/true,
+                                               /*LastParamListWasEmpty=*/true),
+            &LateParsedAttrs);
       }
     }
     return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
-				   &LateParsedAttrs);
+                                   &LateParsedAttrs);
   }
 
   // Parse this declaration.

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Aug  5 20:03:05 2013
@@ -1437,8 +1437,9 @@ Parser::TryAnnotateName(bool IsAddressOf
       return ANK_TemplateName;
     }
     // Fall through.
+  case Sema::NC_VarTemplate:
   case Sema::NC_FunctionTemplate: {
-    // We have a type or function template followed by '<'.
+    // We have a type, variable or function template followed by '<'.
     ConsumeToken();
     UnqualifiedId Id;
     Id.setIdentifier(Name, NameLoc);
@@ -1653,7 +1654,8 @@ bool Parser::TryAnnotateTypeOrScopeToken
       // annotation token to a type annotation token now.
       AnnotateTemplateIdTokenAsType();
       return false;
-    }
+    } else if (TemplateId->Kind == TNK_Var_template)
+      return false;
   }
 
   if (SS.isEmpty())

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug  5 20:03:05 2013
@@ -799,6 +799,7 @@ Corrected:
     
     if (!Result.empty()) {
       bool IsFunctionTemplate;
+      bool IsVarTemplate;
       TemplateName Template;
       if (Result.end() - Result.begin() > 1) {
         IsFunctionTemplate = true;
@@ -808,7 +809,8 @@ Corrected:
         TemplateDecl *TD
           = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
         IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
-        
+        IsVarTemplate = isa<VarTemplateDecl>(TD);
+
         if (SS.isSet() && !SS.isInvalid())
           Template = Context.getQualifiedTemplateName(SS.getScopeRep(), 
                                                     /*TemplateKeyword=*/false,
@@ -825,8 +827,9 @@ Corrected:
         
         return NameClassification::FunctionTemplate(Template);
       }
-      
-      return NameClassification::TypeTemplate(Template);
+
+      return IsVarTemplate ? NameClassification::VarTemplate(Template)
+                           : NameClassification::TypeTemplate(Template);
     }
   }
 
@@ -3013,8 +3016,7 @@ void Sema::MergeVarDecl(VarDecl *New, Lo
   if (getLangOpts().CPlusPlus &&
       New->isThisDeclarationADefinition() == VarDecl::Definition &&
       (Def = Old->getDefinition())) {
-    Diag(New->getLocation(), diag::err_redefinition)
-      << New->getDeclName();
+    Diag(New->getLocation(), diag::err_redefinition) << New;
     Diag(Def->getLocation(), diag::note_previous_definition);
     New->setInvalidDecl();
     return;
@@ -4258,8 +4260,8 @@ NamedDecl *Sema::HandleDeclarator(Scope
                                   TemplateParamLists,
                                   AddToScope);
   } else {
-    New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
-                                  TemplateParamLists);
+    New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists,
+                                  AddToScope);
   }
 
   if (New == 0)
@@ -4768,10 +4770,11 @@ static bool shouldConsiderLinkage(const
   llvm_unreachable("Unexpected context");
 }
 
-NamedDecl*
+NamedDecl *
 Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                               TypeSourceInfo *TInfo, LookupResult &Previous,
-                              MultiTemplateParamsArg TemplateParamLists) {
+                              MultiTemplateParamsArg TemplateParamLists,
+                              bool &AddToScope) {
   QualType R = TInfo->getType();
   DeclarationName Name = GetNameForDeclarator(D).getName();
 
@@ -4862,7 +4865,12 @@ Sema::ActOnVariableDeclarator(Scope *S,
     }
   }
 
-  bool isExplicitSpecialization = false;
+  bool IsExplicitSpecialization = false;
+  bool IsVariableTemplateSpecialization = false;
+  bool IsPartialSpecialization = false;
+  bool Invalid = false; // TODO: Can we remove this (error-prone)?
+  TemplateParameterList *TemplateParams = 0;
+  VarTemplateDecl *PrevVarTemplate = 0;
   VarDecl *NewVD;
   if (!getLangOpts().CPlusPlus) {
     NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
@@ -4922,23 +4930,20 @@ Sema::ActOnVariableDeclarator(Scope *S,
       }
     }
 
+    NamedDecl *PrevDecl = 0;
+    if (Previous.begin() != Previous.end())
+      PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+    PrevVarTemplate = dyn_cast_or_null<VarTemplateDecl>(PrevDecl);
+
     // Match up the template parameter lists with the scope specifier, then
     // determine whether we have a template or a template specialization.
-    isExplicitSpecialization = false;
-    bool Invalid = false;
-    if (TemplateParameterList *TemplateParams =
-            MatchTemplateParametersToScopeSpecifier(
-                D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
-                D.getCXXScopeSpec(), TemplateParamLists,
-                /*never a friend*/ false, isExplicitSpecialization, Invalid)) {
-      if (TemplateParams->size() > 0) {
-        // There is no such thing as a variable template.
-        Diag(D.getIdentifierLoc(), diag::err_template_variable)
-          << II
-          << SourceRange(TemplateParams->getTemplateLoc(),
-                         TemplateParams->getRAngleLoc());
-        return 0;
-      } else {
+    TemplateParams = MatchTemplateParametersToScopeSpecifier(
+        D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+        D.getCXXScopeSpec(), TemplateParamLists,
+        /*never a friend*/ false, IsExplicitSpecialization, Invalid);
+    if (TemplateParams) {
+      if (!TemplateParams->size() &&
+          D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
         // There is an extraneous 'template<>' for this variable. Complain
         // about it, but allow the declaration of the variable.
         Diag(TemplateParams->getTemplateLoc(),
@@ -4946,12 +4951,116 @@ Sema::ActOnVariableDeclarator(Scope *S,
           << II
           << SourceRange(TemplateParams->getTemplateLoc(),
                          TemplateParams->getRAngleLoc());
+      } else {
+        // Only C++1y supports variable templates (N3651).
+        Diag(D.getIdentifierLoc(),
+             getLangOpts().CPlusPlus1y
+                 ? diag::warn_cxx11_compat_variable_template
+                 : diag::ext_variable_template);
+
+        if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+          // This is an explicit specialization or a partial specialization.
+          // Check that we can declare a specialization here
+
+          IsVariableTemplateSpecialization = true;
+          IsPartialSpecialization = TemplateParams->size() > 0;
+
+        } else { // if (TemplateParams->size() > 0)
+                 // This is a template declaration.
+
+          // Check that we can declare a template here.
+          if (CheckTemplateDeclScope(S, TemplateParams))
+            return 0;
+
+          // If there is a previous declaration with the same name, check
+          // whether this is a valid redeclaration.
+          if (PrevDecl && !isDeclInScope(PrevDecl, DC, S))
+            PrevDecl = PrevVarTemplate = 0;
+
+          if (PrevVarTemplate) {
+            // Ensure that the template parameter lists are compatible.
+            if (!TemplateParameterListsAreEqual(
+                    TemplateParams, PrevVarTemplate->getTemplateParameters(),
+                    /*Complain=*/true, TPL_TemplateMatch))
+              return 0;
+          } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
+            // Maybe we will complain about the shadowed template parameter.
+            DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+
+            // Just pretend that we didn't see the previous declaration.
+            PrevDecl = 0;
+          } else if (PrevDecl) {
+            // C++ [temp]p5:
+            // ... a template name declared in namespace scope or in class
+            // scope shall be unique in that scope.
+            Diag(D.getIdentifierLoc(), diag::err_redefinition_different_kind)
+                << Name;
+            Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+            return 0;
+          }
+
+          // Check the template parameter list of this declaration, possibly
+          // merging in the template parameter list from the previous variable
+          // template declaration.
+          if (CheckTemplateParameterList(
+                  TemplateParams,
+                  PrevVarTemplate ? PrevVarTemplate->getTemplateParameters()
+                                  : 0,
+                  (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() &&
+                   DC->isDependentContext())
+                      ? TPC_ClassTemplateMember
+                      : TPC_VarTemplate))
+            Invalid = true;
+
+          if (D.getCXXScopeSpec().isSet()) {
+            // If the name of the template was qualified, we must be defining
+            // the template out-of-line.
+            if (!D.getCXXScopeSpec().isInvalid() && !Invalid &&
+                !PrevVarTemplate) {
+              Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
+                  << Name << DC << D.getCXXScopeSpec().getRange();
+              Invalid = true;
+            }
+          }
+        }
       }
+    } else if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+      TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+
+      // We have encountered something that the user meant to be a
+      // specialization (because it has explicitly-specified template
+      // arguments) but that was not introduced with a "template<>" (or had
+      // too few of them).
+      // FIXME: Differentiate between attempts for explicit instantiations
+      // (starting with "template") and the rest.
+      Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+          << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+          << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
+                                        "template<> ");
+      IsVariableTemplateSpecialization = true;
     }
 
-    NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
-                            D.getIdentifierLoc(), II,
-                            R, TInfo, SC);
+    if (IsVariableTemplateSpecialization) {
+      if (!PrevVarTemplate) {
+        Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
+            << IsPartialSpecialization;
+        return 0;
+      }
+
+      SourceLocation TemplateKWLoc =
+          TemplateParamLists.size() > 0
+              ? TemplateParamLists[0]->getTemplateLoc()
+              : SourceLocation();
+      DeclResult Res = ActOnVarTemplateSpecialization(
+          S, PrevVarTemplate, D, TInfo, TemplateKWLoc, TemplateParams, SC,
+          IsPartialSpecialization);
+      if (Res.isInvalid())
+        return 0;
+      NewVD = cast<VarDecl>(Res.get());
+      AddToScope = false;
+    } else
+      NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
+                              D.getIdentifierLoc(), II, R, TInfo, SC);
 
     // If this decl has an auto type in need of deduction, make a note of the
     // Decl so we can diagnose uses of it in its own initializer.
@@ -4963,7 +5072,14 @@ Sema::ActOnVariableDeclarator(Scope *S,
 
     SetNestedNameSpecifier(NewVD, D);
 
-    if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) {
+    // FIXME: Do we need D.getCXXScopeSpec().isSet()?
+    if (TemplateParams && TemplateParamLists.size() > 1 &&
+        (!IsVariableTemplateSpecialization || D.getCXXScopeSpec().isSet())) {
+      NewVD->setTemplateParameterListsInfo(
+          Context, TemplateParamLists.size() - 1, TemplateParamLists.data());
+    } else if (IsVariableTemplateSpecialization ||
+               (!TemplateParams && TemplateParamLists.size() > 0 &&
+                (D.getCXXScopeSpec().isSet()))) {
       NewVD->setTemplateParameterListsInfo(Context,
                                            TemplateParamLists.size(),
                                            TemplateParamLists.data());
@@ -5020,7 +5136,12 @@ Sema::ActOnVariableDeclarator(Scope *S,
   }
 
   if (D.getDeclSpec().isModulePrivateSpecified()) {
-    if (isExplicitSpecialization)
+    if (IsVariableTemplateSpecialization)
+      Diag(NewVD->getLocation(), diag::err_module_private_specialization)
+          << (IsPartialSpecialization ? 1 : 0)
+          << FixItHint::CreateRemoval(
+                 D.getDeclSpec().getModulePrivateSpecLoc());
+    else if (IsExplicitSpecialization)
       Diag(NewVD->getLocation(), diag::err_module_private_specialization)
         << 2
         << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
@@ -5089,15 +5210,17 @@ Sema::ActOnVariableDeclarator(Scope *S,
   }
 
   // Diagnose shadowed variables before filtering for scope.
+  // FIXME: Special treatment for static variable template members (?).
   if (!D.getCXXScopeSpec().isSet())
     CheckShadow(S, NewVD, Previous);
 
   // Don't consider existing declarations that are in a different
   // scope and are out-of-semantic-context declarations (if the new
   // declaration has linkage).
-  FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewVD),
-                       isExplicitSpecialization);
-  
+  FilterLookupForScope(
+      Previous, DC, S, shouldConsiderLinkage(NewVD),
+      IsExplicitSpecialization || IsVariableTemplateSpecialization);
+
   if (!getLangOpts().CPlusPlus) {
     D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
   } else {
@@ -5121,10 +5244,19 @@ Sema::ActOnVariableDeclarator(Scope *S,
       NewVD->setInvalidDecl();
     }
 
-    D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+    if (!IsVariableTemplateSpecialization) {
+      if (PrevVarTemplate) {
+        LookupResult PrevDecl(*this, GetNameForDeclarator(D),
+                              LookupOrdinaryName, ForRedeclaration);
+        PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl());
+        D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl));
+      } else
+        D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+    }
 
     // This is an explicit specialization of a static data member. Check it.
-    if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+    // FIXME: Special treatment for static variable template members (?).
+    if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
         CheckMemberSpecialization(NewVD, Previous))
       NewVD->setInvalidDecl();
   }
@@ -5147,7 +5279,45 @@ Sema::ActOnVariableDeclarator(Scope *S,
     }
   }
 
-  return NewVD;
+  // If this is not a variable template, return it now
+  if (!TemplateParams || IsVariableTemplateSpecialization)
+    return NewVD;
+
+  // If this is supposed to be a variable template, create it as such.
+  VarTemplateDecl *NewTemplate =
+      VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
+                              TemplateParams, NewVD, PrevVarTemplate);
+  NewVD->setDescribedVarTemplate(NewTemplate);
+
+  if (D.getDeclSpec().isModulePrivateSpecified())
+    NewTemplate->setModulePrivate();
+
+  // If we are providing an explicit specialization of a static variable
+  // template, make a note of that.
+  if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate())
+    NewTemplate->setMemberSpecialization();
+
+  // Set the lexical context of this template
+  NewTemplate->setLexicalDeclContext(CurContext);
+  if (NewVD->isStaticDataMember() && NewVD->isOutOfLine())
+    NewTemplate->setAccess(NewVD->getAccess());
+
+  if (PrevVarTemplate)
+    mergeDeclAttributes(NewVD, PrevVarTemplate->getTemplatedDecl());
+
+  AddPushedVisibilityAttribute(NewVD);
+
+  PushOnScopeChains(NewTemplate, S);
+  AddToScope = false;
+
+  if (Invalid) {
+    NewTemplate->setInvalidDecl();
+    NewVD->setInvalidDecl();
+  }
+
+  ActOnDocumentableDecl(NewTemplate);
+
+  return NewTemplate;
 }
 
 /// \brief Diagnose variable or built-in function shadowing.  Implements
@@ -6705,6 +6875,8 @@ Sema::ActOnFunctionDeclarator(Scope *S,
         // specialization (because it has explicitly-specified template
         // arguments) but that was not introduced with a "template<>" (or had
         // too few of them).
+        // FIXME: Differentiate between attempts for explicit instantiations
+        // (starting with "template") and the rest.
         Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
           << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
           << FixItHint::CreateInsertion(
@@ -7666,7 +7838,6 @@ void Sema::AddInitializerToDecl(Decl *Re
     RealDecl->setInvalidDecl();
     return;
   }
-
   ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
 
   // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Aug  5 20:03:05 2013
@@ -2001,10 +2001,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S,
 
     Member->setAccess(AS);
 
-    // If we have declared a member function template, set the access of the
-    // templated declaration as well.
+    // If we have declared a member function template or static data member
+    // template, set the access of the templated declaration as well.
     if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
       FunTmpl->getTemplatedDecl()->setAccess(AS);
+    else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
+      VarTmpl->getTemplatedDecl()->setAccess(AS);
   }
 
   if (VS.isOverrideSpecified())

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug  5 20:03:05 2013
@@ -1559,7 +1559,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua
 ExprResult
 Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
                        const DeclarationNameInfo &NameInfo,
-                       const CXXScopeSpec *SS, NamedDecl *FoundD) {
+                       const CXXScopeSpec *SS, NamedDecl *FoundD,
+                       const TemplateArgumentListInfo *TemplateArgs) {
   if (getLangOpts().CUDA)
     if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
       if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
@@ -1578,12 +1579,24 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua
     (CurContext != D->getDeclContext() &&
      D->getDeclContext()->isFunctionOrMethod());
 
-  DeclRefExpr *E = DeclRefExpr::Create(Context,
-                                       SS ? SS->getWithLocInContext(Context)
-                                              : NestedNameSpecifierLoc(),
-                                       SourceLocation(),
-                                       D, refersToEnclosingScope,
-                                       NameInfo, Ty, VK, FoundD);
+  DeclRefExpr *E;
+  if (isa<VarTemplateSpecializationDecl>(D)) {
+    VarTemplateSpecializationDecl *VarSpec =
+        cast<VarTemplateSpecializationDecl>(D);
+
+    E = DeclRefExpr::Create(
+        Context,
+        SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+        VarSpec->getTemplateKeywordLoc(), D, refersToEnclosingScope,
+        NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
+  } else {
+    assert(!TemplateArgs && "No template arguments for non-variable"
+                            " template specialization referrences");
+    E = DeclRefExpr::Create(
+        Context,
+        SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+        SourceLocation(), D, refersToEnclosingScope, NameInfo, Ty, VK, FoundD);
+  }
 
   MarkDeclRefReferenced(E);
 
@@ -1870,7 +1883,6 @@ ExprResult Sema::ActOnIdExpression(Scope
                                    bool IsInlineAsmIdentifier) {
   assert(!(IsAddressOfOperand && HasTrailingLParen) &&
          "cannot be direct & operand and have a trailing lparen");
-
   if (SS.isInvalid())
     return ExprError();
 
@@ -1961,6 +1973,7 @@ ExprResult Sema::ActOnIdExpression(Scope
   bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
 
   if (R.empty() && !ADL) {
+
     // Otherwise, this could be an implicitly declared function reference (legal
     // in C90, extension in C99, forbidden in C++).
     if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
@@ -2056,8 +2069,19 @@ ExprResult Sema::ActOnIdExpression(Scope
                                              R, TemplateArgs);
   }
 
-  if (TemplateArgs || TemplateKWLoc.isValid())
+  if (TemplateArgs || TemplateKWLoc.isValid()) {
+
+    // In C++1y, if this is a variable template id, then check it
+    // in BuildTemplateIdExpr().
+    // The single lookup result must be a variable template declaration.
+    if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId &&
+        Id.TemplateId->Kind == TNK_Var_template) {
+      assert(R.getAsSingle<VarTemplateDecl>() &&
+             "There should only be one declaration found.");
+    }
+
     return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
+  }
 
   return BuildDeclarationNameExpr(SS, R, ADL);
 }
@@ -2524,10 +2548,9 @@ Sema::BuildDeclarationNameExpr(const CXX
 }
 
 /// \brief Complete semantic analysis for a reference to the given declaration.
-ExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
-                               const DeclarationNameInfo &NameInfo,
-                               NamedDecl *D, NamedDecl *FoundD) {
+ExprResult Sema::BuildDeclarationNameExpr(
+    const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+    NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) {
   assert(D && "Cannot refer to a NULL declaration");
   assert(!isa<FunctionTemplateDecl>(D) &&
          "Cannot refer unambiguously to a function template");
@@ -2539,8 +2562,8 @@ Sema::BuildDeclarationNameExpr(const CXX
   if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
     // Specifically diagnose references to class templates that are missing
     // a template argument list.
-    Diag(Loc, diag::err_template_decl_ref)
-      << Template << SS.getRange();
+    Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0)
+                                           << Template << SS.getRange();
     Diag(Template->getLocation(), diag::note_template_decl_here);
     return ExprError();
   }
@@ -2630,6 +2653,8 @@ Sema::BuildDeclarationNameExpr(const CXX
     }
 
     case Decl::Var:
+    case Decl::VarTemplateSpecialization:
+    case Decl::VarTemplatePartialSpecialization:
       // In C, "extern void blah;" is valid and is an r-value.
       if (!getLangOpts().CPlusPlus &&
           !type.hasQualifiers() &&
@@ -2727,7 +2752,8 @@ Sema::BuildDeclarationNameExpr(const CXX
       break;
     }
 
-    return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD);
+    return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
+                            TemplateArgs);
   }
 }
 
@@ -11690,28 +11716,64 @@ static void DoMarkVarDeclReferenced(Sema
   if (!IsPotentiallyEvaluatedContext(SemaRef))
     return;
 
-  // Implicit instantiation of static data members of class templates.
-  if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) {
+  VarTemplateSpecializationDecl *VarSpec =
+      dyn_cast<VarTemplateSpecializationDecl>(Var);
+
+  // Implicit instantiation of static data members, static data member
+  // templates of class templates, and variable template specializations.
+  // Delay instantiations of variable templates, except for those
+  // that could be used in a constant expression.
+  if (VarSpec || (Var->isStaticDataMember() &&
+                  Var->getInstantiatedFromStaticDataMember())) {
     MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
-    assert(MSInfo && "Missing member specialization information?");
-    bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
-    if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
-        (!AlreadyInstantiated ||
-         Var->isUsableInConstantExpressions(SemaRef.Context))) {
-      if (!AlreadyInstantiated) {
-        // This is a modification of an existing AST node. Notify listeners.
-        if (ASTMutationListener *L = SemaRef.getASTMutationListener())
-          L->StaticDataMemberInstantiated(Var);
-        MSInfo->setPointOfInstantiation(Loc);
+    if (VarSpec)
+      assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
+             "Can't instantiate a partial template specialization.");
+    if (Var->isStaticDataMember())
+      assert(MSInfo && "Missing member specialization information?");
+
+    SourceLocation PointOfInstantiation;
+    bool InstantiationIsOkay = true;
+    if (MSInfo) {
+      bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
+      TemplateSpecializationKind TSK = MSInfo->getTemplateSpecializationKind();
+
+      if (TSK == TSK_ImplicitInstantiation &&
+          (!AlreadyInstantiated ||
+           Var->isUsableInConstantExpressions(SemaRef.Context))) {
+        if (!AlreadyInstantiated) {
+          // This is a modification of an existing AST node. Notify listeners.
+          if (ASTMutationListener *L = SemaRef.getASTMutationListener())
+            L->StaticDataMemberInstantiated(Var);
+          MSInfo->setPointOfInstantiation(Loc);
+        }
+        PointOfInstantiation = MSInfo->getPointOfInstantiation();
+      } else
+        InstantiationIsOkay = false;
+    } else {
+      if (VarSpec->getPointOfInstantiation().isInvalid())
+        VarSpec->setPointOfInstantiation(Loc);
+      PointOfInstantiation = VarSpec->getPointOfInstantiation();
+    }
+
+    if (InstantiationIsOkay) {
+      bool InstantiationDependent = false;
+      bool IsNonDependent =
+          VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
+                        VarSpec->getTemplateArgsInfo(), InstantiationDependent)
+                  : true;
+
+      // Do not instantiate specializations that are still type-dependent.
+      if (IsNonDependent) {
+        if (Var->isUsableInConstantExpressions(SemaRef.Context)) {
+          // Do not defer instantiations of variables which could be used in a
+          // constant expression.
+          SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
+        } else {
+          SemaRef.PendingInstantiations
+              .push_back(std::make_pair(Var, PointOfInstantiation));
+        }
       }
-      SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation();
-      if (Var->isUsableInConstantExpressions(SemaRef.Context))
-        // Do not defer instantiations of variables which could be used in a
-        // constant expression.
-        SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var);
-      else
-        SemaRef.PendingInstantiations.push_back(
-            std::make_pair(Var, PointOfInstantiation));
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Aug  5 20:03:05 2013
@@ -11,6 +11,7 @@
 
 #include "TreeTransform.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
@@ -207,8 +208,9 @@ TemplateNameKind Sema::isTemplateName(Sc
       R.suppressDiagnostics();
     } else {
       assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
-             isa<TypeAliasTemplateDecl>(TD));
-      TemplateKind = TNK_Type_template;
+             isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD));
+      TemplateKind =
+          isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
     }
   }
 
@@ -1159,6 +1161,7 @@ static bool DiagnoseDefaultTemplateArgum
                                             SourceRange DefArgRange) {
   switch (TPC) {
   case Sema::TPC_ClassTemplate:
+  case Sema::TPC_VarTemplate:
   case Sema::TPC_TypeAliasTemplate:
     return false;
 
@@ -1430,7 +1433,8 @@ bool Sema::CheckTemplateParameterList(Te
     //   If a template parameter of a primary class template or alias template
     //   is a template parameter pack, it shall be the last template parameter.
     if (SawParameterPack && (NewParam + 1) != NewParamEnd &&
-        (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
+        (TPC == TPC_ClassTemplate || TPC == TPC_VarTemplate ||
+         TPC == TPC_TypeAliasTemplate)) {
       Diag((*NewParam)->getLocation(),
            diag::err_template_param_pack_must_be_last_template_parameter);
       Invalid = true;
@@ -1924,11 +1928,14 @@ TemplateParameterList *Sema::MatchTempla
 void Sema::NoteAllFoundTemplates(TemplateName Name) {
   if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
     Diag(Template->getLocation(), diag::note_template_declared_here)
-      << (isa<FunctionTemplateDecl>(Template)? 0
-          : isa<ClassTemplateDecl>(Template)? 1
-          : isa<TypeAliasTemplateDecl>(Template)? 2
-          : 3)
-      << Template->getDeclName();
+        << (isa<FunctionTemplateDecl>(Template)
+                ? 0
+                : isa<ClassTemplateDecl>(Template)
+                      ? 1
+                      : isa<VarTemplateDecl>(Template)
+                            ? 2
+                            : isa<TypeAliasTemplateDecl>(Template) ? 3 : 4)
+        << Template->getDeclName();
     return;
   }
   
@@ -2263,6 +2270,452 @@ TypeResult Sema::ActOnTagTemplateIdType(
   return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
 }
 
+static bool CheckTemplatePartialSpecializationArgs(
+    Sema &S, TemplateParameterList *TemplateParams,
+    SmallVectorImpl<TemplateArgument> &TemplateArgs);
+
+static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
+                                             NamedDecl *PrevDecl,
+                                             SourceLocation Loc,
+                                             bool IsPartialSpecialization);
+
+static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D);
+/*
+/// \brief Check the new variable specialization against the parsed input.
+///
+/// FIXME: Model this against function specializations where
+/// a new function declaration is checked against the specialization
+/// as candidate for redefinition... (?)
+static bool CheckVariableTemplateSpecializationType() {
+
+  if (ExpectedType is undeduced &&  ParsedType is not undeduced)
+    ExpectedType = dedudeType();
+
+  if (both types are undeduced)
+    ???;
+
+  bool CheckType = !ExpectedType()->
+
+  if (!Context.hasSameType(DI->getType(), ExpectedDI->getType())) {
+    unsigned ErrStr = IsPartialSpecialization ? 2 : 1;
+    Diag(D.getIdentifierLoc(), diag::err_invalid_var_template_spec_type)
+        << ErrStr << VarTemplate << DI->getType() << ExpectedDI->getType();
+    Diag(VarTemplate->getLocation(), diag::note_template_declared_here)
+        << 2 << VarTemplate->getDeclName();
+    return true;
+  }
+}
+*/
+
+DeclResult Sema::ActOnVarTemplateSpecialization(
+    Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
+    SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+    VarDecl::StorageClass SC, bool IsPartialSpecialization) {
+  assert(VarTemplate && "A variable template id without template?");
+
+  // D must be variable template id.
+  assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
+         "Variable template specialization is declared with a template it.");
+
+  TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+  SourceLocation TemplateNameLoc = D.getIdentifierLoc();
+  SourceLocation LAngleLoc = TemplateId->LAngleLoc;
+  SourceLocation RAngleLoc = TemplateId->RAngleLoc;
+  ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+                                     TemplateId->NumArgs);
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+  TemplateName Name(VarTemplate);
+
+  // Check for unexpanded parameter packs in any of the template arguments.
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
+                                        UPPC_PartialSpecialization))
+      return true;
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  SmallVector<TemplateArgument, 4> Converted;
+  if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
+                                false, Converted))
+    return true;
+
+  // Check that the type of this variable template specialization
+  // matches the expected type.
+  TypeSourceInfo *ExpectedDI;
+  {
+    // Do substitution on the type of the declaration
+    TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
+                                         Converted.data(), Converted.size());
+    InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate);
+    if (Inst)
+      return true;
+    VarDecl *Templated = VarTemplate->getTemplatedDecl();
+    ExpectedDI =
+        SubstType(Templated->getTypeSourceInfo(),
+                  MultiLevelTemplateArgumentList(TemplateArgList),
+                  Templated->getTypeSpecStartLoc(), Templated->getDeclName());
+  }
+  if (!ExpectedDI)
+    return true;
+
+  /*
+  // Check the new variable specialization against the parsed input.
+  // (Attributes are merged later below.)
+  if (CheckVariableTemplateSpecializationType())
+    return true;
+  */
+
+  // Find the variable template (partial) specialization declaration that
+  // corresponds to these arguments.
+  if (IsPartialSpecialization) {
+    if (CheckTemplatePartialSpecializationArgs(
+            *this, VarTemplate->getTemplateParameters(), Converted))
+      return true;
+
+    bool InstantiationDependent;
+    if (!Name.isDependent() &&
+        !TemplateSpecializationType::anyDependentTemplateArguments(
+            TemplateArgs.getArgumentArray(), TemplateArgs.size(),
+            InstantiationDependent)) {
+      Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
+          << VarTemplate->getDeclName();
+      IsPartialSpecialization = false;
+    }
+  }
+
+  void *InsertPos = 0;
+  VarTemplateSpecializationDecl *PrevDecl = 0;
+
+  if (IsPartialSpecialization)
+    // FIXME: Template parameter list matters too
+    PrevDecl = VarTemplate->findPartialSpecialization(
+        Converted.data(), Converted.size(), InsertPos);
+  else
+    PrevDecl = VarTemplate->findSpecialization(Converted.data(),
+                                               Converted.size(), InsertPos);
+
+  VarTemplateSpecializationDecl *Specialization = 0;
+
+  // Check whether we can declare a variable template specialization in
+  // the current scope.
+  if (CheckTemplateSpecializationScope(*this, VarTemplate, PrevDecl,
+                                       TemplateNameLoc,
+                                       IsPartialSpecialization))
+    return true;
+
+  if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
+    // Since the only prior variable template specialization with these
+    // arguments was referenced but not declared,  reuse that
+    // declaration node as our own, updating its source location and
+    // the list of outer template parameters to reflect our new declaration.
+    Specialization = PrevDecl;
+    Specialization->setLocation(TemplateNameLoc);
+    PrevDecl = 0;
+  } else if (IsPartialSpecialization) {
+    // Create a new class template partial specialization declaration node.
+    VarTemplatePartialSpecializationDecl *PrevPartial =
+        cast_or_null<VarTemplatePartialSpecializationDecl>(PrevDecl);
+    unsigned SequenceNumber =
+        PrevPartial ? PrevPartial->getSequenceNumber()
+                    : VarTemplate->getNextPartialSpecSequenceNumber();
+    VarTemplatePartialSpecializationDecl *Partial =
+        VarTemplatePartialSpecializationDecl::Create(
+            Context, VarTemplate->getDeclContext(), TemplateKWLoc,
+            TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
+            Converted.data(), Converted.size(), TemplateArgs, SequenceNumber);
+
+    if (!PrevPartial)
+      VarTemplate->AddPartialSpecialization(Partial, InsertPos);
+    Specialization = Partial;
+
+    // If we are providing an explicit specialization of a member variable
+    // template specialization, make a note of that.
+    if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+      Partial->setMemberSpecialization();
+
+    // Check that all of the template parameters of the variable template
+    // partial specialization are deducible from the template
+    // arguments. If not, this variable template partial specialization
+    // will never be used.
+    llvm::SmallBitVector DeducibleParams(TemplateParams->size());
+    MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
+                               TemplateParams->getDepth(), DeducibleParams);
+
+    if (!DeducibleParams.all()) {
+      unsigned NumNonDeducible =
+          DeducibleParams.size() - DeducibleParams.count();
+      Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
+          << (NumNonDeducible > 1) << SourceRange(TemplateNameLoc, RAngleLoc);
+      for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+        if (!DeducibleParams[I]) {
+          NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+          if (Param->getDeclName())
+            Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
+                << Param->getDeclName();
+          else
+            Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
+                << "<anonymous>";
+        }
+      }
+    }
+  } else {
+    // Create a new class template specialization declaration node for
+    // this explicit specialization or friend declaration.
+    Specialization = VarTemplateSpecializationDecl::Create(
+        Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
+        VarTemplate, DI->getType(), DI, SC, Converted.data(), Converted.size());
+    Specialization->setTemplateArgsInfo(TemplateArgs);
+
+    if (!PrevDecl)
+      VarTemplate->AddSpecialization(Specialization, InsertPos);
+  }
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a
+  //   use occurs; no diagnostic is required.
+  if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+    bool Okay = false;
+    for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+      // Is there any previous explicit specialization declaration?
+      if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+        Okay = true;
+        break;
+      }
+    }
+
+    if (!Okay) {
+      SourceRange Range(TemplateNameLoc, RAngleLoc);
+      Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+          << Name << Range;
+
+      Diag(PrevDecl->getPointOfInstantiation(),
+           diag::note_instantiation_required_here)
+          << (PrevDecl->getTemplateSpecializationKind() !=
+              TSK_ImplicitInstantiation);
+      return true;
+    }
+  }
+
+  Specialization->setTemplateKeywordLoc(TemplateKWLoc);
+  Specialization->setLexicalDeclContext(CurContext);
+
+  // Add the specialization into its lexical context, so that it can
+  // be seen when iterating through the list of declarations in that
+  // context. However, specializations are not found by name lookup.
+  CurContext->addDecl(Specialization);
+
+  // Note that this is an explicit specialization.
+  Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
+
+  if (PrevDecl) {
+    // Check that this isn't a redefinition of this specialization,
+    // merging with previous declarations.
+    LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
+                          ForRedeclaration);
+    PrevSpec.addDecl(PrevDecl);
+    D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
+  }
+
+  // Link instantiations of static data members back to the template from
+  // which they were instantiated.
+  if (Specialization->isStaticDataMember())
+    Specialization->setInstantiationOfStaticDataMember(
+        VarTemplate->getTemplatedDecl(),
+        Specialization->getSpecializationKind());
+
+  return Specialization;
+}
+
+namespace {
+/// \brief A partial specialization whose template arguments have matched
+/// a given template-id.
+struct PartialSpecMatchResult {
+  VarTemplatePartialSpecializationDecl *Partial;
+  TemplateArgumentList *Args;
+};
+}
+
+DeclResult
+Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
+                         SourceLocation TemplateNameLoc,
+                         const TemplateArgumentListInfo &TemplateArgs) {
+  assert(Template && "A variable template id without template?");
+
+  // Check that the template argument list is well-formed for this template.
+  SmallVector<TemplateArgument, 4> Converted;
+  bool ExpansionIntoFixedList = false;
+  if (CheckTemplateArgumentList(
+          Template, TemplateNameLoc,
+          const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
+          Converted, &ExpansionIntoFixedList))
+    return true;
+
+  // Find the variable template specialization declaration that
+  // corresponds to these arguments.
+  void *InsertPos = 0;
+  if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
+          Converted.data(), Converted.size(), InsertPos))
+    // If we already have a variable template specialization, return it.
+    return Spec;
+
+  // This is the first time we have referenced this variable template
+  // specialization. Create the canonical declaration and add it to
+  // the set of specializations, based on the closest partial specialization
+  // that it represents. That is,
+  VarDecl *InstantiationPattern = Template->getTemplatedDecl();
+  TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
+                                       Converted.data(), Converted.size());
+  TemplateArgumentList *InstantiationArgs = &TemplateArgList;
+  bool AmbiguousPartialSpec = false;
+  typedef PartialSpecMatchResult MatchResult;
+  SmallVector<MatchResult, 4> Matched;
+  SourceLocation PointOfInstantiation = TemplateNameLoc;
+  TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
+
+  // 1. Attempt to find the closest partial specialization that this
+  // specializes, if any.
+  // If any of the template arguments is dependent, then this is probably
+  // a placeholder for an incomplete declarative context; which must be
+  // complete by instantiation time. Thus, do not search through the partial
+  // specializations yet.
+  // FIXME: Unify with InstantiateClassTemplateSpecialization()?
+  bool InstantiationDependent = false;
+  if (!TemplateSpecializationType::anyDependentTemplateArguments(
+          TemplateArgs, InstantiationDependent)) {
+
+    SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+    Template->getPartialSpecializations(PartialSpecs);
+
+    for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+      VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+      TemplateDeductionInfo Info(FailedCandidates.getLocation());
+
+      if (TemplateDeductionResult Result =
+              DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
+        // Store the failed-deduction information for use in diagnostics, later.
+        FailedCandidates.addCandidate()
+            .set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
+        (void)Result;
+      } else {
+        Matched.push_back(PartialSpecMatchResult());
+        Matched.back().Partial = Partial;
+        Matched.back().Args = Info.take();
+      }
+    }
+
+    // If we're dealing with a member template where the template parameters
+    // have been instantiated, this provides the original template parameters
+    // from which the member template's parameters were instantiated.
+    SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
+
+    if (Matched.size() >= 1) {
+      SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+      if (Matched.size() == 1) {
+        //   -- If exactly one matching specialization is found, the
+        //      instantiation is generated from that specialization.
+        // We don't need to do anything for this.
+      } else {
+        //   -- If more than one matching specialization is found, the
+        //      partial order rules (14.5.4.2) are used to determine
+        //      whether one of the specializations is more specialized
+        //      than the others. If none of the specializations is more
+        //      specialized than all of the other matching
+        //      specializations, then the use of the variable template is
+        //      ambiguous and the program is ill-formed.
+        for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
+                                                   PEnd = Matched.end();
+             P != PEnd; ++P) {
+          if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+                                                      PointOfInstantiation) ==
+              P->Partial)
+            Best = P;
+        }
+
+        // Determine if the best partial specialization is more specialized than
+        // the others.
+        for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+                                                   PEnd = Matched.end();
+             P != PEnd; ++P) {
+          if (P != Best && getMoreSpecializedPartialSpecialization(
+                               P->Partial, Best->Partial,
+                               PointOfInstantiation) != Best->Partial) {
+            AmbiguousPartialSpec = true;
+            break;
+          }
+        }
+      }
+
+      // Instantiate using the best variable template partial specialization.
+      InstantiationPattern = Best->Partial;
+      InstantiationArgs = Best->Args;
+    } else {
+      //   -- If no match is found, the instantiation is generated
+      //      from the primary template.
+      // InstantiationPattern = Template->getTemplatedDecl();
+    }
+  }
+
+  // FIXME: Actually use FailedCandidates.
+
+  // 2. Create the canonical declaration.
+  // Note that we do not instantiate the variable just yet, since
+  // instantiation is handled in DoMarkVarDeclReferenced().
+  // FIXME: LateAttrs et al.?
+  VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
+      Template, InstantiationPattern, *InstantiationArgs, TemplateArgs,
+      Converted, TemplateNameLoc, InsertPos /*, LateAttrs, StartingScope*/);
+  if (!Decl)
+    return true;
+
+  if (AmbiguousPartialSpec) {
+    // Partial ordering did not produce a clear winner. Complain.
+    Decl->setInvalidDecl();
+    Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+        << Decl;
+
+    // Print the matching partial specializations.
+    for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+                                               PEnd = Matched.end();
+         P != PEnd; ++P)
+      Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+          << getTemplateArgumentBindingsText(
+                 P->Partial->getTemplateParameters(), *P->Args);
+    return true;
+  }
+
+  if (VarTemplatePartialSpecializationDecl *D =
+          dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
+    Decl->setInstantiationOf(D, InstantiationArgs);
+
+  assert(Decl && "No variable template specialization?");
+  return Decl;
+}
+
+ExprResult
+Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
+                         const DeclarationNameInfo &NameInfo,
+                         VarTemplateDecl *Template, SourceLocation TemplateLoc,
+                         const TemplateArgumentListInfo *TemplateArgs) {
+
+  DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
+                                       *TemplateArgs);
+  if (Decl.isInvalid())
+    return ExprError();
+
+  VarDecl *Var = cast<VarDecl>(Decl.get());
+  if (!Var->getTemplateSpecializationKind())
+    Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation,
+                                       NameInfo.getLoc());
+
+  // Build an ordinary singleton decl ref.
+  return BuildDeclarationNameExpr(SS, NameInfo, Var,
+                                  /*FoundD=*/0, TemplateArgs);
+}
+
 ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
                                      SourceLocation TemplateKWLoc,
                                      LookupResult &R,
@@ -2282,6 +2735,13 @@ ExprResult Sema::BuildTemplateIdExpr(con
   assert(!R.empty() && "empty lookup results when building templateid");
   assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
 
+  // In C++1y, check variable template ids.
+  if (R.getAsSingle<VarTemplateDecl>()) {
+    return Owned(CheckVarTemplateId(SS, R.getLookupNameInfo(),
+                                    R.getAsSingle<VarTemplateDecl>(),
+                                    TemplateKWLoc, TemplateArgs));
+  }
+
   // We don't want lookup warnings at this point.
   R.suppressDiagnostics();
 
@@ -2302,6 +2762,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXSc
                                    SourceLocation TemplateKWLoc,
                                    const DeclarationNameInfo &NameInfo,
                              const TemplateArgumentListInfo *TemplateArgs) {
+
   assert(TemplateArgs || TemplateKWLoc.isValid());
   DeclContext *DC;
   if (!(DC = computeDeclContext(SS, false)) ||
@@ -4962,16 +5423,18 @@ static bool CheckTemplateSpecializationS
   int EntityKind = 0;
   if (isa<ClassTemplateDecl>(Specialized))
     EntityKind = IsPartialSpecialization? 1 : 0;
+  else if (isa<VarTemplateDecl>(Specialized))
+    EntityKind = IsPartialSpecialization ? 3 : 2;
   else if (isa<FunctionTemplateDecl>(Specialized))
-    EntityKind = 2;
+    EntityKind = 4;
   else if (isa<CXXMethodDecl>(Specialized))
-    EntityKind = 3;
+    EntityKind = 5;
   else if (isa<VarDecl>(Specialized))
-    EntityKind = 4;
+    EntityKind = 6;
   else if (isa<RecordDecl>(Specialized))
-    EntityKind = 5;
+    EntityKind = 7;
   else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11)
-    EntityKind = 6;
+    EntityKind = 8;
   else {
     S.Diag(Loc, diag::err_template_spec_unknown_kind)
       << S.getLangOpts().CPlusPlus11;
@@ -5095,17 +5558,15 @@ static bool CheckTemplateSpecializationS
   return false;
 }
 
-/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs
+/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs
 /// that checks non-type template partial specialization arguments.
-static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
-                                                NonTypeTemplateParmDecl *Param,
-                                                  const TemplateArgument *Args,
-                                                        unsigned NumArgs) {
+static bool CheckNonTypeTemplatePartialSpecializationArgs(
+    Sema &S, NonTypeTemplateParmDecl *Param, const TemplateArgument *Args,
+    unsigned NumArgs) {
   for (unsigned I = 0; I != NumArgs; ++I) {
     if (Args[I].getKind() == TemplateArgument::Pack) {
-      if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
-                                                           Args[I].pack_begin(),
-                                                           Args[I].pack_size()))
+      if (CheckNonTypeTemplatePartialSpecializationArgs(
+              S, Param, Args[I].pack_begin(), Args[I].pack_size()))
         return true;
 
       continue;
@@ -5176,9 +5637,9 @@ static bool CheckNonTypeClassTemplatePar
 /// partial specialization.
 ///
 /// \returns true if there was an error, false otherwise.
-static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
-                                        TemplateParameterList *TemplateParams,
-                       SmallVectorImpl<TemplateArgument> &TemplateArgs) {
+static bool CheckTemplatePartialSpecializationArgs(
+    Sema &S, TemplateParameterList *TemplateParams,
+    SmallVectorImpl<TemplateArgument> &TemplateArgs) {
   const TemplateArgument *ArgList = TemplateArgs.data();
 
   for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
@@ -5187,8 +5648,7 @@ static bool CheckClassTemplatePartialSpe
     if (!Param)
       continue;
 
-    if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
-                                                           &ArgList[I], 1))
+    if (CheckNonTypeTemplatePartialSpecializationArgs(S, Param, &ArgList[I], 1))
       return true;
   }
 
@@ -5334,9 +5794,8 @@ Sema::ActOnClassTemplateSpecialization(S
   // Find the class template (partial) specialization declaration that
   // corresponds to these arguments.
   if (isPartialSpecialization) {
-    if (CheckClassTemplatePartialSpecializationArgs(*this,
-                                         ClassTemplate->getTemplateParameters(),
-                                         Converted))
+    if (CheckTemplatePartialSpecializationArgs(
+            *this, ClassTemplate->getTemplateParameters(), Converted))
       return true;
 
     bool InstantiationDependent;
@@ -6207,9 +6666,8 @@ Sema::CheckMemberSpecialization(NamedDec
       InstantiationVar->setLocation(Member->getLocation());
     }
 
-    Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
-                                                cast<VarDecl>(InstantiatedFrom),
-                                                TSK_ExplicitSpecialization);
+    cast<VarDecl>(Member)->setInstantiationOfStaticDataMember(
+        cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
     MarkUnusedFileScopedDecl(InstantiationVar);
   } else if (isa<CXXRecordDecl>(Member)) {
     CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
@@ -6697,7 +7155,7 @@ DeclResult Sema::ActOnExplicitInstantiat
            diag::err_explicit_instantiation_inline :
            diag::warn_explicit_instantiation_inline_0x)
       << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
-  if (D.getDeclSpec().isConstexprSpecified())
+  if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType())
     // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
     // not already specified.
     Diag(D.getDeclSpec().getConstexprSpecLoc(),
@@ -6719,28 +7177,68 @@ DeclResult Sema::ActOnExplicitInstantiat
     //   A [...] static data member of a class template can be explicitly
     //   instantiated from the member definition associated with its class
     //   template.
+    // C++1y [temp.explicit]p1:
+    //   A [...] variable [...] template specialization can be explicitly
+    //   instantiated from its template.
     if (Previous.isAmbiguous())
       return true;
 
     VarDecl *Prev = Previous.getAsSingle<VarDecl>();
-    if (!Prev || !Prev->isStaticDataMember()) {
-      // We expect to see a data data member here.
-      Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
-        << Name;
-      for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
-           P != PEnd; ++P)
-        Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
-      return true;
-    }
+    VarTemplateDecl *PrevTemplate = Previous.getAsSingle<VarTemplateDecl>();
 
-    if (!Prev->getInstantiatedFromStaticDataMember()) {
-      // FIXME: Check for explicit specialization?
-      Diag(D.getIdentifierLoc(),
-           diag::err_explicit_instantiation_data_member_not_instantiated)
-        << Prev;
-      Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
-      // FIXME: Can we provide a note showing where this was declared?
-      return true;
+    if (!PrevTemplate) {
+      if (!Prev || !Prev->isStaticDataMember()) {
+        // We expect to see a data data member here.
+        Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
+            << Name;
+        for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+             P != PEnd; ++P)
+          Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
+        return true;
+      }
+
+      if (!Prev->getInstantiatedFromStaticDataMember()) {
+        // FIXME: Check for explicit specialization?
+        Diag(D.getIdentifierLoc(),
+             diag::err_explicit_instantiation_data_member_not_instantiated)
+            << Prev;
+        Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
+        // FIXME: Can we provide a note showing where this was declared?
+        return true;
+      }
+    } else {
+      // Explicitly instantiate a variable template.
+
+      // C++1y [dcl.spec.auto]p6:
+      //   ... A program that uses auto or decltype(auto) in a context not
+      //   explicitly allowed in this section is ill-formed.
+      //
+      // This includes auto-typed variable template instantiations.
+      if (R->isUndeducedType()) {
+        Diag(T->getTypeLoc().getLocStart(),
+             diag::err_auto_not_allowed_var_inst);
+        return true;
+      }
+
+      TemplateArgumentListInfo TemplateArgs;
+      if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+        // Translate the parser's template argument list into our AST format.
+        TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+        TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+        TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+        ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+                                           TemplateId->NumArgs);
+        translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+      }
+
+      DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
+                                          D.getIdentifierLoc(), TemplateArgs);
+      if (Res.isInvalid())
+        return true;
+
+      // Ignore access control bits, we don't need them for redeclaration
+      // checking.
+      Prev = cast<VarDecl>(Res.get());
     }
 
     // C++0x [temp.explicit]p2:
@@ -6750,7 +7248,13 @@ DeclResult Sema::ActOnExplicitInstantiat
     //   name shall be a simple-template-id.
     //
     // C++98 has the same restriction, just worded differently.
-    if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+    //
+    // C++1y If the explicit instantiation is for a variable, the
+    // unqualified-id in the declaration shall be a template-id.
+    if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()) &&
+        (!PrevTemplate ||
+         (D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
+          D.getCXXScopeSpec().isSet())))
       Diag(D.getIdentifierLoc(),
            diag::ext_explicit_instantiation_without_qualified_id)
         << Prev << D.getCXXScopeSpec().getRange();
@@ -6760,20 +7264,39 @@ DeclResult Sema::ActOnExplicitInstantiat
 
     // Verify that it is okay to explicitly instantiate here.
     MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
-    assert(MSInfo && "Missing static data member specialization info?");
+    TemplateSpecializationKind PrevTSK =
+        MSInfo ? MSInfo->getTemplateSpecializationKind()
+               : Prev->getTemplateSpecializationKind();
+    SourceLocation POI = MSInfo ? MSInfo->getPointOfInstantiation()
+                                : cast<VarTemplateSpecializationDecl>(Prev)
+                                      ->getPointOfInstantiation();
     bool HasNoEffect = false;
     if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
-                                        MSInfo->getTemplateSpecializationKind(),
-                                              MSInfo->getPointOfInstantiation(),
-                                               HasNoEffect))
+                                               PrevTSK, POI, HasNoEffect))
       return true;
-    if (HasNoEffect)
-      return (Decl*) 0;
 
-    // Instantiate static data member.
-    Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
-    if (TSK == TSK_ExplicitInstantiationDefinition)
-      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev);
+    if (!HasNoEffect) {
+      // Instantiate static data member or variable template.
+
+      Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+      if (PrevTemplate) {
+        // Merge attributes.
+        if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList())
+          ProcessDeclAttributeList(S, Prev, Attr);
+      }
+      if (TSK == TSK_ExplicitInstantiationDefinition)
+        InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
+    }
+
+    // Check the new variable specialization against the parsed input.
+    if (PrevTemplate && Prev && !Context.hasSameType(Prev->getType(), R)) {
+      Diag(T->getTypeLoc().getLocStart(),
+           diag::err_invalid_var_template_spec_type)
+          << 0 << PrevTemplate << R << Prev->getType();
+      Diag(PrevTemplate->getLocation(), diag::note_template_declared_here)
+          << 2 << PrevTemplate->getDeclName();
+      return true;
+    }
 
     // FIXME: Create an ExplicitInstantiation node?
     return (Decl*) 0;

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Aug  5 20:03:05 2013
@@ -2246,7 +2246,7 @@ FinishTemplateArgumentDeduction(Sema &S,
 }
 
 /// \brief Perform template argument deduction to determine whether
-/// the given template arguments match the given class template
+/// the given template arguments match the given variable template
 /// partial specialization per C++ [temp.class.spec.match].
 Sema::TemplateDeductionResult
 Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
@@ -2287,6 +2287,160 @@ Sema::DeduceTemplateArguments(ClassTempl
                                            Deduced, Info);
 }
 
+/// Complete template argument deduction for a variable template partial
+/// specialization.
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
+static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
+    Sema &S, VarTemplatePartialSpecializationDecl *Partial,
+    const TemplateArgumentList &TemplateArgs,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+    TemplateDeductionInfo &Info) {
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+  Sema::SFINAETrap Trap(S);
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  SmallVector<TemplateArgument, 4> Builder;
+  TemplateParameterList *PartialParams = Partial->getTemplateParameters();
+  for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
+    NamedDecl *Param = PartialParams->getParam(I);
+    if (Deduced[I].isNull()) {
+      Info.Param = makeTemplateParameter(Param);
+      return Sema::TDK_Incomplete;
+    }
+
+    // We have deduced this argument, so it still needs to be
+    // checked and converted.
+
+    // First, for a non-type template parameter type that is
+    // initialized by a declaration, we need the type of the
+    // corresponding non-type template parameter.
+    QualType NTTPType;
+    if (NonTypeTemplateParmDecl *NTTP =
+            dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+      NTTPType = NTTP->getType();
+      if (NTTPType->isDependentType()) {
+        TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                          Builder.data(), Builder.size());
+        NTTPType =
+            S.SubstType(NTTPType, MultiLevelTemplateArgumentList(TemplateArgs),
+                        NTTP->getLocation(), NTTP->getDeclName());
+        if (NTTPType.isNull()) {
+          Info.Param = makeTemplateParameter(Param);
+          // FIXME: These template arguments are temporary. Free them!
+          Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+                                                      Builder.size()));
+          return Sema::TDK_SubstitutionFailure;
+        }
+      }
+    }
+
+    if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial, NTTPType,
+                                       0, Info, false, Builder)) {
+      Info.Param = makeTemplateParameter(Param);
+      // FIXME: These template arguments are temporary. Free them!
+      Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+                                                  Builder.size()));
+      return Sema::TDK_SubstitutionFailure;
+    }
+  }
+
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
+      S.Context, Builder.data(), Builder.size());
+
+  Info.reset(DeducedArgumentList);
+
+  // Substitute the deduced template arguments into the template
+  // arguments of the class template partial specialization, and
+  // verify that the instantiated template arguments are both valid
+  // and are equivalent to the template arguments originally provided
+  // to the class template.
+  LocalInstantiationScope InstScope(S);
+  VarTemplateDecl *VarTemplate = Partial->getSpecializedTemplate();
+  const TemplateArgumentLoc *PartialTemplateArgs =
+      Partial->getTemplateArgsAsWritten();
+
+  // Note that we don't provide the langle and rangle locations.
+  TemplateArgumentListInfo InstArgs;
+
+  if (S.Subst(PartialTemplateArgs, Partial->getNumTemplateArgsAsWritten(),
+              InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+    unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
+    if (ParamIdx >= Partial->getTemplateParameters()->size())
+      ParamIdx = Partial->getTemplateParameters()->size() - 1;
+
+    Decl *Param = const_cast<NamedDecl *>(
+        Partial->getTemplateParameters()->getParam(ParamIdx));
+    Info.Param = makeTemplateParameter(Param);
+    Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
+    return Sema::TDK_SubstitutionFailure;
+  }
+  SmallVector<TemplateArgument, 4> ConvertedInstArgs;
+  if (S.CheckTemplateArgumentList(VarTemplate, Partial->getLocation(), InstArgs,
+                                  false, ConvertedInstArgs))
+    return Sema::TDK_SubstitutionFailure;
+
+  TemplateParameterList *TemplateParams = VarTemplate->getTemplateParameters();
+  for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
+    TemplateArgument InstArg = ConvertedInstArgs.data()[I];
+    if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
+      Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
+      Info.FirstArg = TemplateArgs[I];
+      Info.SecondArg = InstArg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+  }
+
+  if (Trap.hasErrorOccurred())
+    return Sema::TDK_SubstitutionFailure;
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given variable template
+/// partial specialization per C++ [temp.class.spec.match].
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+                              const TemplateArgumentList &TemplateArgs,
+                              TemplateDeductionInfo &Info) {
+  if (Partial->isInvalidDecl())
+    return TDK_Invalid;
+
+  // C++ [temp.class.spec.match]p2:
+  //   A partial specialization matches a given actual template
+  //   argument list if the template arguments of the partial
+  //   specialization can be deduced from the actual template argument
+  //   list (14.8.2).
+
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+  SFINAETrap Trap(*this);
+
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  Deduced.resize(Partial->getTemplateParameters()->size());
+  if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
+          *this, Partial->getTemplateParameters(), Partial->getTemplateArgs(),
+          TemplateArgs, Info, Deduced))
+    return Result;
+
+  SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
+  InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+                             DeducedArgs, Info);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  if (Trap.hasErrorOccurred())
+    return Sema::TDK_SubstitutionFailure;
+
+  return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
+                                           Deduced, Info);
+}
+
 /// \brief Determine whether the given type T is a simple-template-id type.
 static bool isSimpleTemplateIdType(QualType T) {
   if (const TemplateSpecializationType *Spec
@@ -4278,6 +4432,63 @@ Sema::getMoreSpecializedPartialSpecializ
                                             /*RefParamComparisons=*/0);
   if (Better1) {
     SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
+    InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, DeducedArgs,
+                               Info);
+    Better1 = !::FinishTemplateArgumentDeduction(
+        *this, PS2, PS1->getTemplateArgs(), Deduced, Info);
+  }
+
+  // Determine whether PS2 is at least as specialized as PS1
+  Deduced.clear();
+  Deduced.resize(PS1->getTemplateParameters()->size());
+  bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
+      *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
+      /*PartialOrdering=*/true,
+      /*RefParamComparisons=*/0);
+  if (Better2) {
+    SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+                                                 Deduced.end());
+    InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, DeducedArgs,
+                               Info);
+    Better2 = !::FinishTemplateArgumentDeduction(
+        *this, PS1, PS2->getTemplateArgs(), Deduced, Info);
+  }
+
+  if (Better1 == Better2)
+    return 0;
+
+  return Better1 ? PS1 : PS2;
+}
+
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
+VarTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+    VarTemplatePartialSpecializationDecl *PS1,
+    VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) {
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  TemplateDeductionInfo Info(Loc);
+
+  assert(PS1->getSpecializedTemplate() == PS1->getSpecializedTemplate() &&
+         "the partial specializations being compared should specialize"
+         " the same template.");
+  TemplateName Name(PS1->getSpecializedTemplate());
+  TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+  QualType PT1 = Context.getTemplateSpecializationType(
+      CanonTemplate, PS1->getTemplateArgs().data(),
+      PS1->getTemplateArgs().size());
+  QualType PT2 = Context.getTemplateSpecializationType(
+      CanonTemplate, PS2->getTemplateArgs().data(),
+      PS2->getTemplateArgs().size());
+
+  // Determine whether PS1 is at least as specialized as PS2
+  Deduced.resize(PS2->getTemplateParameters()->size());
+  bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
+      *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
+      /*PartialOrdering=*/true,
+      /*RefParamComparisons=*/0);
+  if (Better1) {
+    SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+                                                 Deduced.end());
     InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
                                DeducedArgs, Info);
     Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Aug  5 20:03:05 2013
@@ -61,7 +61,24 @@ Sema::getTemplateInstantiationArgs(Named
   DeclContext *Ctx = dyn_cast<DeclContext>(D);
   if (!Ctx) {
     Ctx = D->getDeclContext();
-    
+
+    // Add template arguments from a variable template instantiation.
+    if (VarTemplateSpecializationDecl *Spec =
+            dyn_cast<VarTemplateSpecializationDecl>(D)) {
+      // We're done when we hit an explicit specialization.
+      if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
+          !isa<VarTemplatePartialSpecializationDecl>(Spec))
+        return Result;
+
+      Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+
+      // If this variable template specialization was instantiated from a
+      // specialized member that is a variable template, we're done.
+      assert(Spec->getSpecializedTemplate() && "No variable template?");
+      if (Spec->getSpecializedTemplate()->isMemberSpecialization())
+        return Result;
+    }
+
     // If we have a template template parameter with translation unit context,
     // then we're performing substitution into a default template argument of
     // this template template parameter before we've constructed the template
@@ -284,6 +301,29 @@ InstantiatingTemplate(Sema &SemaRef, Sou
     Inst.PointOfInstantiation = PointOfInstantiation;
     Inst.Entity = PartialSpec;
     Inst.TemplateArgs = TemplateArgs.data();
+    Inst.NumTemplateArgs = TemplateArgs.size();
+    Inst.DeductionInfo = &DeductionInfo;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+    Sema &SemaRef, SourceLocation PointOfInstantiation,
+    VarTemplatePartialSpecializationDecl *PartialSpec,
+    ArrayRef<TemplateArgument> TemplateArgs,
+    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+    : SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext(
+                            SemaRef.InNonInstantiationSFINAEContext) {
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind =
+        ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = PartialSpec;
+    Inst.TemplateArgs = TemplateArgs.data();
     Inst.NumTemplateArgs = TemplateArgs.size();
     Inst.DeductionInfo = &DeductionInfo;
     Inst.InstantiationRange = InstantiationRange;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Aug  5 20:03:05 2013
@@ -318,7 +318,13 @@ TemplateDeclInstantiator::VisitTypeAlias
   return Inst;
 }
 
+// FIXME: Revise for static member templates.
 Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
+  return VisitVarDecl(D, /*ForVarTemplate=*/false);
+}
+
+Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, bool ForVarTemplate) {
+
   // If this is the variable for an anonymous struct or union,
   // instantiate the anonymous struct/union type first.
   if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
@@ -340,105 +346,22 @@ Decl *TemplateDeclInstantiator::VisitVar
     return 0;
   }
 
-  // Build the instantiated declaration
-  VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
-                                 D->getInnerLocStart(),
+  // Build the instantiated declaration.
+  VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, D->getInnerLocStart(),
                                  D->getLocation(), D->getIdentifier(),
-                                 DI->getType(), DI,
-                                 D->getStorageClass());
-  Var->setTSCSpec(D->getTSCSpec());
-  Var->setInitStyle(D->getInitStyle());
-  Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
-  Var->setConstexpr(D->isConstexpr());
-
-  // Substitute the nested name specifier, if any.
-  if (SubstQualifier(D, Var))
-    return 0;
-
-  // If we are instantiating a static data member defined
-  // out-of-line, the instantiation will have the same lexical
-  // context (which will be a namespace scope) as the template.
-  if (D->isOutOfLine())
-    Var->setLexicalDeclContext(D->getLexicalDeclContext());
-
-  Var->setAccess(D->getAccess());
-
-  if (!D->isStaticDataMember()) {
-    Var->setUsed(D->isUsed(false));
-    Var->setReferenced(D->isReferenced());
-  }
+                                 DI->getType(), DI, D->getStorageClass());
 
-  SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);
-
-  if (Var->hasAttrs())
-    SemaRef.CheckAlignasUnderalignment(Var);
-
-  // FIXME: In theory, we could have a previous declaration for variables that
-  // are not static data members.
-  // FIXME: having to fake up a LookupResult is dumb.
-  LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
-                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
-  if (D->isStaticDataMember())
-    SemaRef.LookupQualifiedName(Previous, Owner, false);
-  
   // In ARC, infer 'retaining' for variables of retainable type.
   if (SemaRef.getLangOpts().ObjCAutoRefCount && 
       SemaRef.inferObjCARCLifetime(Var))
     Var->setInvalidDecl();
 
-  SemaRef.CheckVariableDeclaration(Var, Previous);
-
-  if (D->isOutOfLine()) {
-    D->getLexicalDeclContext()->addDecl(Var);
-    Owner->makeDeclVisibleInContext(Var);
-  } else {
-    Owner->addDecl(Var);
-    if (Owner->isFunctionOrMethod())
-      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
-  }
-
-  // Link instantiations of static data members back to the template from
-  // which they were instantiated.
-  if (Var->isStaticDataMember())
-    SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
-                                                     TSK_ImplicitInstantiation);
-
-  if (Var->getAnyInitializer()) {
-    // We already have an initializer in the class.
-  } else if (D->getInit()) {
-    if (Var->isStaticDataMember() && !D->isOutOfLine())
-      SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated, D);
-    else
-      SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, D);
-
-    // Instantiate the initializer.
-    ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs,
-                                        D->getInitStyle() == VarDecl::CallInit);
-    if (!Init.isInvalid()) {
-      bool TypeMayContainAuto = true;
-      if (Init.get()) {
-        bool DirectInit = D->isDirectInit();
-        SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit,
-                                     TypeMayContainAuto);
-      } else
-        SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
-    } else {
-      // FIXME: Not too happy about invalidating the declaration
-      // because of a bogus initializer.
-      Var->setInvalidDecl();
-    }
-
-    SemaRef.PopExpressionEvaluationContext();
-  } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
-             !Var->isCXXForRangeDecl())
-    SemaRef.ActOnUninitializedDecl(Var, false);
-
-  // Diagnose unused local variables with dependent types, where the diagnostic
-  // will have been deferred.
-  if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed() &&
-      D->getType()->isDependentType())
-    SemaRef.DiagnoseUnusedDecl(Var);
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(D, Var))
+    return 0;
 
+  SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
+                                     StartingScope, ForVarTemplate);
   return Var;
 }
 
@@ -1026,6 +949,102 @@ TemplateDeclInstantiator::VisitClassTemp
   return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
 }
 
+Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
+  assert(D->getTemplatedDecl()->isStaticDataMember() &&
+         "Only static data member templates are allowed.");
+  // FIXME: Also only when instantiating a class?
+
+  // Create a local instantiation scope for this variable template, which
+  // will contain the instantiations of the template parameters.
+  LocalInstantiationScope Scope(SemaRef);
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return NULL;
+
+  VarDecl *Pattern = D->getTemplatedDecl();
+  VarTemplateDecl *PrevVarTemplate = 0;
+
+  if (Pattern->getPreviousDecl()) {
+    DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
+    if (!Found.empty())
+      PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
+  }
+
+  // FIXME: This, and ForVarTemplate, is a hack that is probably unnecessary.
+  // We should use a simplified version of VisitVarDecl.
+  VarDecl *VarInst = cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*ForVarTemplate=*/true));
+
+  DeclContext *DC = Owner;
+
+  /* FIXME: This should be handled in VisitVarDecl, as used to produce
+     VarInst above.
+  // Instantiate the qualifier.
+  NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc =
+        SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs);
+    if (!QualifierLoc)
+      return 0;
+  }
+
+  if (QualifierLoc)
+    VarInst->setQualifierInfo(QualifierLoc);
+  */
+
+  VarTemplateDecl *Inst = VarTemplateDecl::Create(
+      SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams,
+      VarInst, PrevVarTemplate);
+  VarInst->setDescribedVarTemplate(Inst);
+
+  Inst->setAccess(D->getAccess());
+  if (!PrevVarTemplate)
+    Inst->setInstantiatedFromMemberTemplate(D);
+
+  if (D->isOutOfLine()) {
+    Inst->setLexicalDeclContext(D->getLexicalDeclContext());
+    VarInst->setLexicalDeclContext(D->getLexicalDeclContext());
+  }
+
+  Owner->addDecl(Inst);
+
+  if (!PrevVarTemplate) {
+    // Queue up any out-of-line partial specializations of this member
+    // variable template; the client will force their instantiation once
+    // the enclosing class has been instantiated.
+    SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+    D->getPartialSpecializations(PartialSpecs);
+    for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+      if (PartialSpecs[I]->isOutOfLine())
+        OutOfLineVarPartialSpecs.push_back(
+            std::make_pair(Inst, PartialSpecs[I]));
+  }
+
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl(
+    VarTemplatePartialSpecializationDecl *D) {
+  assert(D->isStaticDataMember() &&
+         "Only static data member templates are allowed.");
+  // FIXME: Also only when instantiating a class?
+
+  VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
+
+  // Lookup the already-instantiated declaration and return that.
+  DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName());
+  assert(!Found.empty() && "Instantiation found nothing?");
+
+  VarTemplateDecl *InstVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
+  assert(InstVarTemplate && "Instantiation did not find a variable template?");
+
+  if (VarTemplatePartialSpecializationDecl *Result =
+          InstVarTemplate->findPartialSpecInstantiatedFromMember(D))
+    return Result;
+
+  return InstantiateVarTemplatePartialSpecialization(InstVarTemplate, D);
+}
+
 Decl *
 TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
   // Create a local instantiation scope for this function template, which
@@ -2256,6 +2275,87 @@ TemplateDeclInstantiator::VisitClassTemp
                    "inside templates");
 }
 
+Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
+    VarTemplateSpecializationDecl *D) {
+
+  TemplateArgumentListInfo VarTemplateArgsInfo;
+  VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
+  assert(VarTemplate &&
+         "A template specialization without specialized template?");
+
+  // Substitute the current template arguments.
+  const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo();
+  VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc());
+  VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc());
+
+  if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(),
+                    TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs))
+    return 0;
+
+  // Check that the template argument list is well-formed for this template.
+  SmallVector<TemplateArgument, 4> Converted;
+  bool ExpansionIntoFixedList = false;
+  if (SemaRef.CheckTemplateArgumentList(
+          VarTemplate, VarTemplate->getLocStart(),
+          const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false,
+          Converted, &ExpansionIntoFixedList))
+    return 0;
+
+  // Find the variable template specialization declaration that
+  // corresponds to these arguments.
+  void *InsertPos = 0;
+  if (VarTemplateSpecializationDecl *VarSpec = VarTemplate->findSpecialization(
+          Converted.data(), Converted.size(), InsertPos))
+    // If we already have a variable template specialization, return it.
+    return VarSpec;
+
+  return VisitVarTemplateSpecializationDecl(VarTemplate, D, InsertPos,
+                                            VarTemplateArgsInfo, Converted);
+}
+
+Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
+    VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos,
+    const TemplateArgumentListInfo &TemplateArgsInfo,
+    SmallVectorImpl<TemplateArgument> &Converted) {
+
+  // If this is the variable for an anonymous struct or union,
+  // instantiate the anonymous struct/union type first.
+  if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
+    if (RecordTy->getDecl()->isAnonymousStructOrUnion())
+      if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
+        return 0;
+
+  // Do substitution on the type of the declaration
+  TypeSourceInfo *DI =
+      SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
+                        D->getTypeSpecStartLoc(), D->getDeclName());
+  if (!DI)
+    return 0;
+
+  if (DI->getType()->isFunctionType()) {
+    SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
+        << D->isStaticDataMember() << DI->getType();
+    return 0;
+  }
+
+  // Build the instantiated declaration
+  VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create(
+      SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
+      VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted.data(),
+      Converted.size());
+  Var->setTemplateArgsInfo(TemplateArgsInfo);
+  VarTemplate->AddSpecialization(Var, InsertPos);
+
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(D, Var))
+    return 0;
+
+  SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
+                                     StartingScope);
+
+  return Var;
+}
+
 Decl *TemplateDeclInstantiator::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
   llvm_unreachable("@defs is not supported in Objective-C++");
 }
@@ -2442,6 +2542,134 @@ TemplateDeclInstantiator::InstantiateCla
   return InstPartialSpec;
 }
 
+/// \brief Instantiate the declaration of a variable template partial
+/// specialization.
+///
+/// \param VarTemplate the (instantiated) variable template that is partially
+/// specialized by the instantiation of \p PartialSpec.
+///
+/// \param PartialSpec the (uninstantiated) variable template partial
+/// specialization that we are instantiating.
+///
+/// \returns The instantiated partial specialization, if successful; otherwise,
+/// NULL to indicate an error.
+VarTemplatePartialSpecializationDecl *
+TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
+    VarTemplateDecl *VarTemplate,
+    VarTemplatePartialSpecializationDecl *PartialSpec) {
+  // Create a local instantiation scope for this variable template partial
+  // specialization, which will contain the instantiations of the template
+  // parameters.
+  LocalInstantiationScope Scope(SemaRef);
+
+  // Substitute into the template parameters of the variable template partial
+  // specialization.
+  TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return 0;
+
+  // Substitute into the template arguments of the variable template partial
+  // specialization.
+  TemplateArgumentListInfo InstTemplateArgs; // no angle locations
+  if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(),
+                    PartialSpec->getNumTemplateArgsAsWritten(),
+                    InstTemplateArgs, TemplateArgs))
+    return 0;
+
+  // Check that the template argument list is well-formed for this
+  // class template.
+  SmallVector<TemplateArgument, 4> Converted;
+  if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(),
+                                        InstTemplateArgs, false, Converted))
+    return 0;
+
+  // Figure out where to insert this variable template partial specialization
+  // in the member template's set of variable template partial specializations.
+  void *InsertPos = 0;
+  VarTemplateSpecializationDecl *PrevDecl =
+      VarTemplate->findPartialSpecialization(Converted.data(), Converted.size(),
+                                             InsertPos);
+
+  // Build the canonical type that describes the converted template
+  // arguments of the variable template partial specialization.
+  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
+      TemplateName(VarTemplate), Converted.data(), Converted.size());
+
+  // Build the fully-sugared type for this variable template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
+      TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs,
+      CanonType);
+
+  if (PrevDecl) {
+    // We've already seen a partial specialization with the same template
+    // parameters and template arguments. This can happen, for example, when
+    // substituting the outer template arguments ends up causing two
+    // variable template partial specializations of a member variable template
+    // to have identical forms, e.g.,
+    //
+    //   template<typename T, typename U>
+    //   struct Outer {
+    //     template<typename X, typename Y> pair<X,Y> p;
+    //     template<typename Y> pair<T, Y> p;
+    //     template<typename Y> pair<U, Y> p;
+    //   };
+    //
+    //   Outer<int, int> outer; // error: the partial specializations of Inner
+    //                          // have the same signature.
+    SemaRef.Diag(PartialSpec->getLocation(),
+                 diag::err_var_partial_spec_redeclared)
+        << WrittenTy->getType();
+    SemaRef.Diag(PrevDecl->getLocation(),
+                 diag::note_var_prev_partial_spec_here);
+    return 0;
+  }
+
+  // Do substitution on the type of the declaration
+  TypeSourceInfo *DI = SemaRef.SubstType(
+      PartialSpec->getTypeSourceInfo(), TemplateArgs,
+      PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName());
+  if (!DI)
+    return 0;
+
+  if (DI->getType()->isFunctionType()) {
+    SemaRef.Diag(PartialSpec->getLocation(),
+                 diag::err_variable_instantiates_to_function)
+        << PartialSpec->isStaticDataMember() << DI->getType();
+    return 0;
+  }
+
+  // Create the variable template partial specialization declaration.
+  VarTemplatePartialSpecializationDecl *InstPartialSpec =
+      VarTemplatePartialSpecializationDecl::Create(
+          SemaRef.Context, Owner, PartialSpec->getInnerLocStart(),
+          PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(),
+          DI, PartialSpec->getStorageClass(), Converted.data(),
+          Converted.size(), InstTemplateArgs,
+          VarTemplate->getNextPartialSpecSequenceNumber());
+
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(PartialSpec, InstPartialSpec))
+    return 0;
+
+  InstPartialSpec->setInstantiatedFromMember(PartialSpec);
+  InstPartialSpec->setTypeAsWritten(WrittenTy);
+
+  InstPartialSpec->setAccess(PartialSpec->getAccess());
+  // FIXME: How much of BuildVariableInstantiation() should go in here?
+
+  // Add this partial specialization to the set of variable template partial
+  // specializations. The instantiation of the initializer is not necessary.
+  VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+  return InstPartialSpec;
+}
+
 TypeSourceInfo*
 TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
                               SmallVectorImpl<ParmVarDecl *> &Params) {
@@ -3026,6 +3254,167 @@ void Sema::InstantiateFunctionDefinition
                             PendingLocalImplicitInstantiations);
 }
 
+VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
+    VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+    const TemplateArgumentList &TemplateArgList,
+    const TemplateArgumentListInfo &TemplateArgsInfo,
+    SmallVectorImpl<TemplateArgument> &Converted,
+    SourceLocation PointOfInstantiation, void *InsertPos,
+    LateInstantiatedAttrVec *LateAttrs,
+    LocalInstantiationScope *StartingScope) {
+  if (FromVar->isInvalidDecl())
+    return 0;
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar);
+  if (Inst)
+    return 0;
+
+  MultiLevelTemplateArgumentList TemplateArgLists;
+  TemplateArgLists.addOuterTemplateArguments(&TemplateArgList);
+
+  TemplateDeclInstantiator Instantiator(
+      *this, VarTemplate->getDeclContext(),
+      MultiLevelTemplateArgumentList(TemplateArgList));
+
+  // TODO: Set LateAttrs and StartingScope ...
+
+  return cast_or_null<VarTemplateSpecializationDecl>(
+      Instantiator.VisitVarTemplateSpecializationDecl(
+          VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted));
+}
+
+/// \brief Instantiates a variable template specialization by completing it
+/// with appropriate type information and initializer.
+VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
+    VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
+    const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+  // Do substitution on the type of the declaration
+  TypeSourceInfo *DI =
+      SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs,
+                PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName());
+  if (!DI)
+    return 0;
+
+  // Update the type of this variable template specialization.
+  VarSpec->setType(DI->getType());
+
+  // Instantiate the initializer.
+  InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
+
+  return VarSpec;
+}
+
+/// BuildVariableInstantiation - Used after a new variable has been created.
+/// Sets basic variable data and decides whether to postpone the
+/// variable instantiation.
+void Sema::BuildVariableInstantiation(
+    VarDecl *NewVar, VarDecl *OldVar,
+    const MultiLevelTemplateArgumentList &TemplateArgs,
+    LateInstantiatedAttrVec *LateAttrs,
+    LocalInstantiationScope *StartingScope,
+    bool ForVarTemplate) {
+
+  // If we are instantiating a static data member defined
+  // out-of-line, the instantiation will have the same lexical
+  // context (which will be a namespace scope) as the template.
+  if (OldVar->isOutOfLine())
+    NewVar->setLexicalDeclContext(OldVar->getLexicalDeclContext());
+  NewVar->setTSCSpec(OldVar->getTSCSpec());
+  NewVar->setInitStyle(OldVar->getInitStyle());
+  NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
+  NewVar->setConstexpr(OldVar->isConstexpr());
+  NewVar->setAccess(OldVar->getAccess());
+
+  if (!OldVar->isStaticDataMember()) {
+    NewVar->setUsed(OldVar->isUsed(false));
+    NewVar->setReferenced(OldVar->isReferenced());
+  }
+
+  InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope);
+
+  if (NewVar->hasAttrs())
+    CheckAlignasUnderalignment(NewVar);
+
+  // FIXME: In theory, we could have a previous declaration for variables that
+  // are not static data members.
+  // FIXME: having to fake up a LookupResult is dumb.
+  LookupResult Previous(*this, NewVar->getDeclName(), NewVar->getLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
+  if (!isa<VarTemplateSpecializationDecl>(NewVar))
+    LookupQualifiedName(Previous, NewVar->getDeclContext(), false);
+
+  CheckVariableDeclaration(NewVar, Previous);
+
+  if (OldVar->isOutOfLine()) {
+    OldVar->getLexicalDeclContext()->addDecl(NewVar);
+    if (!ForVarTemplate)
+      NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar);
+  } else {
+    if (!ForVarTemplate)
+      NewVar->getDeclContext()->addDecl(NewVar);
+    if (NewVar->getDeclContext()->isFunctionOrMethod())
+      CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar);
+  }
+
+  // Link instantiations of static data members back to the template from
+  // which they were instantiated.
+  if (NewVar->isStaticDataMember() && !ForVarTemplate)
+    NewVar->setInstantiationOfStaticDataMember(OldVar,
+                                               TSK_ImplicitInstantiation);
+
+  if (isa<VarTemplateSpecializationDecl>(NewVar)) {
+    // Do not instantiate the variable just yet.
+  } else
+    InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
+
+  // Diagnose unused local variables with dependent types, where the diagnostic
+  // will have been deferred.
+  if (!NewVar->isInvalidDecl() &&
+      NewVar->getDeclContext()->isFunctionOrMethod() && !NewVar->isUsed() &&
+      OldVar->getType()->isDependentType())
+    DiagnoseUnusedDecl(NewVar);
+}
+
+/// \brief Instantiate the initializer of a variable.
+void Sema::InstantiateVariableInitializer(
+    VarDecl *Var, VarDecl *OldVar,
+    const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+  if (Var->getAnyInitializer())
+    // We already have an initializer in the class.
+    return;
+
+  if (OldVar->getInit()) {
+    if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
+      PushExpressionEvaluationContext(Sema::ConstantEvaluated, OldVar);
+    else
+      PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, OldVar);
+
+    // Instantiate the initializer.
+    ExprResult Init =
+        SubstInitializer(OldVar->getInit(), TemplateArgs,
+                         OldVar->getInitStyle() == VarDecl::CallInit);
+    if (!Init.isInvalid()) {
+      bool TypeMayContainAuto = true;
+      if (Init.get()) {
+        bool DirectInit = OldVar->isDirectInit();
+        AddInitializerToDecl(Var, Init.take(), DirectInit, TypeMayContainAuto);
+      } else
+        ActOnUninitializedDecl(Var, TypeMayContainAuto);
+    } else {
+      // FIXME: Not too happy about invalidating the declaration
+      // because of a bogus initializer.
+      Var->setInvalidDecl();
+    }
+
+    PopExpressionEvaluationContext();
+  } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
+             !Var->isCXXForRangeDecl())
+    ActOnUninitializedDecl(Var, false);
+}
+
 /// \brief Instantiate the definition of the given variable from its
 /// template.
 ///
@@ -3047,26 +3436,76 @@ void Sema::InstantiateStaticDataMemberDe
                                                  VarDecl *Var,
                                                  bool Recursive,
                                                  bool DefinitionRequired) {
+  InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive,
+                                DefinitionRequired);
+}
+
+void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
+                                         VarDecl *Var, bool Recursive,
+                                         bool DefinitionRequired) {
+
   if (Var->isInvalidDecl())
     return;
 
-  // Find the out-of-line definition of this static data member.
+  VarTemplateSpecializationDecl *VarSpec =
+      dyn_cast<VarTemplateSpecializationDecl>(Var);
+  assert((VarSpec || Var->isStaticDataMember()) &&
+         "Not a static data member, nor a variable template specialization?");
+  VarDecl *PatternDecl = 0;
+
+  // If this is a variable template specialization, make sure that it is
+  // non-dependent, then find its instantiation pattern.
+  if (VarSpec) {
+    bool InstantiationDependent = false;
+    assert(!TemplateSpecializationType::anyDependentTemplateArguments(
+               VarSpec->getTemplateArgsInfo(), InstantiationDependent) &&
+           "Only instantiate variable template specializations that are "
+           "not type-dependent");
+
+    // Find the variable initialization that we'll be substituting.
+    assert(VarSpec->getSpecializedTemplate() &&
+           "Specialization without specialized template?");
+    llvm::PointerUnion<VarTemplateDecl *,
+                       VarTemplatePartialSpecializationDecl *> PatternPtr =
+        VarSpec->getSpecializedTemplateOrPartial();
+    if (PatternPtr.is<VarTemplatePartialSpecializationDecl *>())
+      PatternDecl = cast<VarDecl>(
+          PatternPtr.get<VarTemplatePartialSpecializationDecl *>());
+    else
+      PatternDecl = (PatternPtr.get<VarTemplateDecl *>())->getTemplatedDecl();
+    assert(PatternDecl && "instantiating a non-template");
+  }
+
+  // If this is a static data member, find its out-of-line definition.
   VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
-  assert(Def && "This data member was not instantiated from a template?");
-  assert(Def->isStaticDataMember() && "Not a static data member?");
-  Def = Def->getOutOfLineDefinition();
-
-  if (!Def) {
-    // We did not find an out-of-line definition of this static data member,
-    // so we won't perform any instantiation. Rather, we rely on the user to
-    // instantiate this definition (or provide a specialization for it) in
-    // another translation unit.
+  if (Var->isStaticDataMember()) {
+    assert(Def && "This data member was not instantiated from a template?");
+    assert(Def->isStaticDataMember() && "Not a static data member?");
+    Def = Def->getOutOfLineDefinition();
+  }
+
+  // If the instantiation pattern does not have an initializer, or if an
+  // out-of-line definition is not found, we won't perform any instantiation.
+  // Rather, we rely on the user to instantiate this definition (or provide
+  // a specialization for it) in another translation unit.
+  if ((VarSpec && !PatternDecl->getInit()) ||
+      (!VarSpec && Var->isStaticDataMember() && !Def)) {
     if (DefinitionRequired) {
-      Def = Var->getInstantiatedFromStaticDataMember();
-      Diag(PointOfInstantiation,
-           diag::err_explicit_instantiation_undefined_member)
-        << 2 << Var->getDeclName() << Var->getDeclContext();
-      Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+      if (!Var->isStaticDataMember()) {
+        Diag(PointOfInstantiation,
+             diag::err_explicit_instantiation_undefined_var_template)
+            << PatternDecl;
+        Diag(PatternDecl->getLocation(),
+             diag::note_explicit_instantiation_here);
+      } else {
+        Def = Var->getInstantiatedFromStaticDataMember();
+        Diag(PointOfInstantiation,
+             diag::err_explicit_instantiation_undefined_member)
+            << 3 << Var->getDeclName() << Var->getDeclContext();
+        Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+      }
+      if (VarSpec)
+        Var->setInvalidDecl();
     } else if (Var->getTemplateSpecializationKind()
                  == TSK_ExplicitInstantiationDefinition) {
       PendingInstantiations.push_back(
@@ -3086,6 +3525,11 @@ void Sema::InstantiateStaticDataMemberDe
   //   Except for inline functions, other explicit instantiation declarations
   //   have the effect of suppressing the implicit instantiation of the entity
   //   to which they refer.
+  //
+  // C++11 [temp.explicit]p10:
+  //   Except for inline functions, [...] explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity
+  //   to which they refer.
   if (TSK == TSK_ExplicitInstantiationDeclaration)
     return;
 
@@ -3098,17 +3542,24 @@ void Sema::InstantiateStaticDataMemberDe
       : Consumer(Consumer), Var(Var) { }
 
     ~PassToConsumerRAII() {
-      Consumer.HandleCXXStaticMemberVarInstantiation(Var);
+      if (Var->isStaticDataMember())
+        Consumer.HandleCXXStaticMemberVarInstantiation(Var);
+      else {
+        DeclGroupRef DG(Var);
+        Consumer.HandleTopLevelDecl(DG);
+      }
     }
   } PassToConsumerRAII(Consumer, Var);
 
-  // If we already have a definition, we're done.
-  if (VarDecl *Def = Var->getDefinition()) {
-    // We may be explicitly instantiating something we've already implicitly
-    // instantiated.
-    Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(),
-                                       PointOfInstantiation);
-    return;
+  if (!VarSpec) {
+    // If we already have a definition, we're done.
+    if (VarDecl *Def = Var->getDefinition()) {
+      // We may be explicitly instantiating something we've already implicitly
+      // instantiated.
+      Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(),
+                                         PointOfInstantiation);
+      return;
+    }
   }
 
   InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
@@ -3127,22 +3578,41 @@ void Sema::InstantiateStaticDataMemberDe
 
   // Enter the scope of this instantiation. We don't use
   // PushDeclContext because we don't have a scope.
-  ContextRAII previousContext(*this, Var->getDeclContext());
+  ContextRAII PreviousContext(*this, Var->getDeclContext());
   LocalInstantiationScope Local(*this);
-  
+
   VarDecl *OldVar = Var;
-  Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
-                                        getTemplateInstantiationArgs(Var)));
+  if (!VarSpec)
+    Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
+                                          getTemplateInstantiationArgs(Var)));
+  else
+    // Construct a VarTemplateSpecializationDecl to avoid name clashing with
+    // the primary template. (Note that unlike function declarations, variable
+    // declarations cannot be overloaded.)
+    // In fact, there is no need to construct a new declaration from scratch.
+    // Thus, simply complete its definition with an appropriately substituted
+    // type and initializer.
+    Var = CompleteVarTemplateSpecializationDecl(
+        VarSpec, PatternDecl, getTemplateInstantiationArgs(Var));
 
-  previousContext.pop();
+  PreviousContext.pop();
 
   if (Var) {
-    PassToConsumerRAII.Var = Var;
     MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
-    assert(MSInfo && "Missing member specialization information?");
-    Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
-                                       MSInfo->getPointOfInstantiation());
+    if (!VarSpec)
+      assert(MSInfo && "Missing member specialization information?");
+
+    PassToConsumerRAII.Var = Var;
+    if (MSInfo)
+      Var->setTemplateSpecializationKind(
+          MSInfo->getTemplateSpecializationKind(),
+          MSInfo->getPointOfInstantiation());
   }
+
+  // This variable may have local implicit instantiations that need to be
+  // instantiated within this scope.
+  PerformPendingInstantiations(/*LocalOnly=*/true);
+
   Local.Exit();
   
   if (Recursive) {
@@ -3155,14 +3625,12 @@ void Sema::InstantiateStaticDataMemberDe
 
     // Restore the set of pending vtables.
     assert(VTableUses.empty() &&
-           "VTableUses should be empty before it is discarded, "
-           "while instantiating static data member.");
+           "VTableUses should be empty before it is discarded.");
     VTableUses.swap(SavedVTableUses);
 
     // Restore the set of pending implicit instantiations.
     assert(PendingInstantiations.empty() &&
-           "PendingInstantiations should be empty before it is discarded, "
-           "while instantiating static data member.");
+           "PendingInstantiations should be empty before it is discarded.");
     PendingInstantiations.swap(SavedPendingInstantiations);
   }
 }
@@ -3593,6 +4061,20 @@ NamedDecl *Sema::FindInstantiatedDecl(So
     return cast<LabelDecl>(Inst);
   }
 
+  // For variable template specializations, update those that are still
+  // type-dependent.
+  if (VarTemplateSpecializationDecl *VarSpec =
+          dyn_cast<VarTemplateSpecializationDecl>(D)) {
+    bool InstantiationDependent = false;
+    const TemplateArgumentListInfo &VarTemplateArgs =
+        VarSpec->getTemplateArgsInfo();
+    if (TemplateSpecializationType::anyDependentTemplateArguments(
+            VarTemplateArgs, InstantiationDependent))
+      D = cast<NamedDecl>(
+          SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs));
+    return D;
+  }
+
   if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
     if (!Record->isDependentContext())
       return D;
@@ -3605,7 +4087,7 @@ NamedDecl *Sema::FindInstantiatedDecl(So
     else if (ClassTemplatePartialSpecializationDecl *PartialSpec
                = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
       ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
-    
+
     // Walk the current context to find either the record or an instantiation of
     // it.
     DeclContext *DC = CurContext;
@@ -3614,7 +4096,7 @@ NamedDecl *Sema::FindInstantiatedDecl(So
       // definition, we'll find our own context. We're done.
       if (DC->Equals(Record))
         return Record;
-      
+
       if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
         // Check whether we're in the process of instantiating a class template
         // specialization of the template we're mapping.
@@ -3624,13 +4106,12 @@ NamedDecl *Sema::FindInstantiatedDecl(So
           if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
             return InstRecord;
         }
-      
+
         // Check whether we're in the process of instantiating a member class.
         if (isInstantiationOf(Record, InstRecord))
           return InstRecord;
       }
-      
-      
+
       // Move to the outer template scope.
       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
         if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
@@ -3638,7 +4119,7 @@ NamedDecl *Sema::FindInstantiatedDecl(So
           continue;
         }
       }
-      
+
       DC = DC->getParent();
     }
 
@@ -3771,9 +4252,13 @@ void Sema::PerformPendingInstantiations(
       continue;
     }
 
-    // Instantiate static data member definitions.
+    // Instantiate variable definitions
     VarDecl *Var = cast<VarDecl>(Inst.first);
-    assert(Var->isStaticDataMember() && "Not a static data member?");
+
+    assert((Var->isStaticDataMember() ||
+            isa<VarTemplateSpecializationDecl>(Var)) &&
+           "Not a static data member, nor a variable template"
+           " specialization?");
 
     // Don't try to instantiate declarations if the most recent redeclaration
     // is invalid.
@@ -3796,14 +4281,15 @@ void Sema::PerformPendingInstantiations(
       break;
     }
 
-    PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(),
-                                        "instantiating static data member "
-                                        "definition");
-
+    PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+                                        "instantiating variable definition");
     bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
                               TSK_ExplicitInstantiationDefinition;
-    InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
-                                          DefinitionRequired);
+
+    // Instantiate static data member definitions or variable template
+    // specializations.
+    InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
+                                  DefinitionRequired);
   }
 }
 

Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Mon Aug  5 20:03:05 2013
@@ -158,6 +158,8 @@ bool serialization::isRedeclarableDeclKi
   case Decl::CXXRecord:
   case Decl::ClassTemplateSpecialization:
   case Decl::ClassTemplatePartialSpecialization:
+  case Decl::VarTemplateSpecialization:
+  case Decl::VarTemplatePartialSpecialization:
   case Decl::Function:
   case Decl::CXXMethod:
   case Decl::CXXConstructor:
@@ -166,6 +168,7 @@ bool serialization::isRedeclarableDeclKi
   case Decl::Var:
   case Decl::FunctionTemplate:
   case Decl::ClassTemplate:
+  case Decl::VarTemplate:
   case Decl::TypeAliasTemplate:
   case Decl::ObjCProtocol:
   case Decl::ObjCInterface:

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Aug  5 20:03:05 2013
@@ -239,6 +239,13 @@ namespace clang {
                                      ClassTemplatePartialSpecializationDecl *D);
     void VisitClassScopeFunctionSpecializationDecl(
                                        ClassScopeFunctionSpecializationDecl *D);
+    RedeclarableResult
+    VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);
+    void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
+      VisitVarTemplateSpecializationDeclImpl(D);
+    }
+    void VisitVarTemplatePartialSpecializationDecl(
+        VarTemplatePartialSpecializationDecl *D);
     void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
     void VisitValueDecl(ValueDecl *VD);
     void VisitEnumConstantDecl(EnumConstantDecl *ECD);
@@ -252,13 +259,15 @@ namespace clang {
     void VisitFieldDecl(FieldDecl *FD);
     void VisitMSPropertyDecl(MSPropertyDecl *FD);
     void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
-    void VisitVarDecl(VarDecl *VD);
+    RedeclarableResult VisitVarDeclImpl(VarDecl *D);
+    void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); }
     void VisitImplicitParamDecl(ImplicitParamDecl *PD);
     void VisitParmVarDecl(ParmVarDecl *PD);
     void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     void VisitTemplateDecl(TemplateDecl *D);
     RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
     void VisitClassTemplateDecl(ClassTemplateDecl *D);
+    void VisitVarTemplateDecl(VarTemplateDecl *D);
     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
     void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
     void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
@@ -917,7 +926,7 @@ void ASTDeclReader::VisitIndirectFieldDe
     FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx);
 }
 
-void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
+ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
   RedeclarableResult Redecl = VisitRedeclarable(VD);
   VisitDeclaratorDecl(VD);
 
@@ -950,6 +959,8 @@ void ASTDeclReader::VisitVarDecl(VarDecl
     SourceLocation POI = ReadSourceLocation(Record, Idx);
     Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
   }
+
+  return Redecl;
 }
 
 void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
@@ -1418,6 +1429,40 @@ void ASTDeclReader::VisitClassTemplateDe
   }
 }
 
+void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
+  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
+
+  if (ThisDeclID == Redecl.getFirstID()) {
+    // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
+    // the specializations.
+    SmallVector<serialization::DeclID, 2> SpecIDs;
+    SpecIDs.push_back(0);
+
+    // Specializations.
+    unsigned Size = Record[Idx++];
+    SpecIDs[0] += Size;
+    for (unsigned I = 0; I != Size; ++I)
+      SpecIDs.push_back(ReadDeclID(Record, Idx));
+
+    // Partial specializations.
+    Size = Record[Idx++];
+    SpecIDs[0] += Size;
+    for (unsigned I = 0; I != Size; ++I)
+      SpecIDs.push_back(ReadDeclID(Record, Idx));
+
+    VarTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+    if (SpecIDs[0]) {
+      typedef serialization::DeclID DeclID;
+
+      // FIXME: Append specializations!
+      CommonPtr->LazySpecializations =
+          new (Reader.getContext()) DeclID[SpecIDs.size()];
+      memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
+             SpecIDs.size() * sizeof(DeclID));
+    }
+  }
+}
+
 ASTDeclReader::RedeclarableResult
 ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
     ClassTemplateSpecializationDecl *D) {
@@ -1528,6 +1573,89 @@ void ASTDeclReader::VisitFunctionTemplat
   }
 }
 
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
+    VarTemplateSpecializationDecl *D) {
+  RedeclarableResult Redecl = VisitVarDeclImpl(D);
+
+  ASTContext &C = Reader.getContext();
+  if (Decl *InstD = ReadDecl(Record, Idx)) {
+    if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
+      D->SpecializedTemplate = VTD;
+    } else {
+      SmallVector<TemplateArgument, 8> TemplArgs;
+      Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+      TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(
+          C, TemplArgs.data(), TemplArgs.size());
+      VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS =
+          new (C)
+          VarTemplateSpecializationDecl::SpecializedPartialSpecialization();
+      PS->PartialSpecialization =
+          cast<VarTemplatePartialSpecializationDecl>(InstD);
+      PS->TemplateArgs = ArgList;
+      D->SpecializedTemplate = PS;
+    }
+  }
+
+  // Explicit info.
+  if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
+    VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo =
+        new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
+    ExplicitInfo->TypeAsWritten = TyInfo;
+    ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
+    ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
+    D->ExplicitInfo = ExplicitInfo;
+  }
+
+  SmallVector<TemplateArgument, 8> TemplArgs;
+  Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+  D->TemplateArgs =
+      TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
+  D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
+  D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
+
+  bool writtenAsCanonicalDecl = Record[Idx++];
+  if (writtenAsCanonicalDecl) {
+    VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(Record, Idx);
+    if (D->isCanonicalDecl()) { // It's kept in the folding set.
+      if (VarTemplatePartialSpecializationDecl *Partial =
+              dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
+        Partial->SequenceNumber =
+            CanonPattern->getNextPartialSpecSequenceNumber();
+        CanonPattern->getCommonPtr()->PartialSpecializations
+            .GetOrInsertNode(Partial);
+      } else {
+        CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
+      }
+    }
+  }
+
+  return Redecl;
+}
+
+void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
+    VarTemplatePartialSpecializationDecl *D) {
+  RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
+
+  ASTContext &C = Reader.getContext();
+  D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
+
+  unsigned NumArgs = Record[Idx++];
+  if (NumArgs) {
+    D->NumArgsAsWritten = NumArgs;
+    D->ArgsAsWritten = new (C) TemplateArgumentLoc[NumArgs];
+    for (unsigned i = 0; i != NumArgs; ++i)
+      D->ArgsAsWritten[i] = Reader.ReadTemplateArgumentLoc(F, Record, Idx);
+  }
+
+  // These are read/set from/to the first declaration.
+  if (ThisDeclID == Redecl.getFirstID()) {
+    D->InstantiatedFromMember.setPointer(
+        ReadDeclAs<VarTemplatePartialSpecializationDecl>(Record, Idx));
+    D->InstantiatedFromMember.setInt(Record[Idx++]);
+  }
+}
+
 void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
   VisitTypeDecl(D);
 
@@ -2178,6 +2306,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
   case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
     D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
     break;
+  case DECL_VAR_TEMPLATE:
+    D = VarTemplateDecl::CreateDeserialized(Context, ID);
+    break;
+  case DECL_VAR_TEMPLATE_SPECIALIZATION:
+    D = VarTemplateSpecializationDecl::CreateDeserialized(Context, ID);
+    break;
+  case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION:
+    D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
+    break;
   case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
     D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
     break;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Aug  5 20:03:05 2013
@@ -946,6 +946,9 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(DECL_CLASS_TEMPLATE);
   RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION);
   RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION);
+  RECORD(DECL_VAR_TEMPLATE);
+  RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION);
+  RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION);
   RECORD(DECL_FUNCTION_TEMPLATE);
   RECORD(DECL_TEMPLATE_TYPE_PARM);
   RECORD(DECL_NON_TYPE_TEMPLATE_PARM);
@@ -5227,6 +5230,19 @@ void ASTWriter::AddedCXXTemplateSpeciali
   // The specializations set is kept in the canonical template.
   assert(!WritingAST && "Already writing the AST!");
   TD = TD->getCanonicalDecl();
+  if (!(!D->isFromASTFile() && TD->isFromASTFile()))
+    return; // Not a source specialization added to a template from PCH.
+
+  UpdateRecord &Record = DeclUpdates[TD];
+  Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
+  Record.push_back(reinterpret_cast<uint64_t>(D));
+}
+
+void ASTWriter::AddedCXXTemplateSpecialization(
+    const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
+  // The specializations set is kept in the canonical template.
+  assert(!WritingAST && "Already writing the AST!");
+  TD = TD->getCanonicalDecl();
   if (!(!D->isFromASTFile() && TD->isFromASTFile()))
     return; // Not a source specialization added to a template from PCH.
 

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Mon Aug  5 20:03:05 2013
@@ -68,6 +68,9 @@ namespace clang {
                                             ClassTemplateSpecializationDecl *D);
     void VisitClassTemplatePartialSpecializationDecl(
                                      ClassTemplatePartialSpecializationDecl *D);
+    void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
+    void VisitVarTemplatePartialSpecializationDecl(
+        VarTemplatePartialSpecializationDecl *D);
     void VisitClassScopeFunctionSpecializationDecl(
                                        ClassScopeFunctionSpecializationDecl *D);
     void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
@@ -90,6 +93,7 @@ namespace clang {
     void VisitTemplateDecl(TemplateDecl *D);
     void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
     void VisitClassTemplateDecl(ClassTemplateDecl *D);
+    void VisitVarTemplateDecl(VarTemplateDecl *D);
     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
     void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
     void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
@@ -1184,6 +1188,87 @@ void ASTDeclWriter::VisitClassTemplatePa
   Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
 }
 
+void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) {
+  VisitRedeclarableTemplateDecl(D);
+
+  if (D->isFirstDeclaration()) {
+    typedef llvm::FoldingSetVector<VarTemplateSpecializationDecl> VTSDSetTy;
+    VTSDSetTy &VTSDSet = D->getSpecializations();
+    Record.push_back(VTSDSet.size());
+    for (VTSDSetTy::iterator I = VTSDSet.begin(), E = VTSDSet.end(); I != E;
+         ++I) {
+      assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
+      Writer.AddDeclRef(&*I, Record);
+    }
+
+    typedef llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
+    VTPSDSetTy;
+    VTPSDSetTy &VTPSDSet = D->getPartialSpecializations();
+    Record.push_back(VTPSDSet.size());
+    for (VTPSDSetTy::iterator I = VTPSDSet.begin(), E = VTPSDSet.end(); I != E;
+         ++I) {
+      assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
+      Writer.AddDeclRef(&*I, Record);
+    }
+  }
+  Code = serialization::DECL_VAR_TEMPLATE;
+}
+
+void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
+    VarTemplateSpecializationDecl *D) {
+  VisitVarDecl(D);
+
+  llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+  InstFrom = D->getSpecializedTemplateOrPartial();
+  if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) {
+    Writer.AddDeclRef(InstFromD, Record);
+  } else {
+    Writer.AddDeclRef(InstFrom.get<VarTemplatePartialSpecializationDecl *>(),
+                      Record);
+    Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record);
+  }
+
+  // Explicit info.
+  Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record);
+  if (D->getTypeAsWritten()) {
+    Writer.AddSourceLocation(D->getExternLoc(), Record);
+    Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record);
+  }
+
+  Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record);
+  Writer.AddSourceLocation(D->getPointOfInstantiation(), Record);
+  Record.push_back(D->getSpecializationKind());
+  Record.push_back(D->isCanonicalDecl());
+
+  if (D->isCanonicalDecl()) {
+    // When reading, we'll add it to the folding set of the following template.
+    Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record);
+  }
+
+  Code = serialization::DECL_VAR_TEMPLATE_SPECIALIZATION;
+}
+
+void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
+    VarTemplatePartialSpecializationDecl *D) {
+  VisitVarTemplateSpecializationDecl(D);
+
+  Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
+
+  Record.push_back(D->getNumTemplateArgsAsWritten());
+  for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i)
+    Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record);
+
+  Record.push_back(D->getSequenceNumber());
+
+  // These are read/set from/to the first declaration.
+  if (D->getPreviousDecl() == 0) {
+    Writer.AddDeclRef(D->getInstantiatedFromMember(), Record);
+    Record.push_back(D->isMemberSpecialization());
+  }
+
+  Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
+}
+
 void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
                                     ClassScopeFunctionSpecializationDecl *D) {
   VisitDecl(D);

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp Mon Aug  5 20:03:05 2013
@@ -23,4 +23,4 @@ X2& get_X2() {
   return X0<X2>::value; // expected-note{{instantiation}}
 }
   
-template<typename T> T x; // expected-error{{variable 'x' declared as a template}}
+template<typename T> T x; // expected-warning{{variable templates are a C++1y extension}}

Added: cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp?rev=187762&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp Mon Aug  5 20:03:05 2013
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 --std=c++1y -fsyntax-only -verify %s
+// RUN: cp %s %t
+// RUN: not %clang_cc1 --std=c++1y -x c++ -fixit %t -DFIXING
+// RUN: %clang_cc1 --std=c++1y -x c++ %t -DFIXING
+
+template<typename T> 
+T pi = T(3.1415926535897932385); // expected-note {{template is declared here}}
+
+template int pi<int>;
+
+#ifndef FIXING
+template float pi; // expected-error {{too few template arguments for template 'pi'}}
+template double pi_var0; // expected-error {{explicit instantiation of 'pi_var0' does not refer to a function template, variable template, member function, member class, or static data member}}
+#endif
+
+// Should recover as if definition
+template double pi_var = 5; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}}
+#ifndef FIXING
+template<typename T> 
+T pi0 = T(3.1415926535897932385); // expected-note {{previous definition is here}}
+
+template int pi0 = 10; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}} \
+                          expected-error{{redefinition of 'pi0' with a different type: 'int' vs 'T'}}
+#endif
+
+template<typename T> 
+T pi1 = T(3.1415926535897932385);
+
+// Should recover as if specialization
+template float pi1<float> = 1.0;  // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}}
+#ifndef FIXING
+namespace expected_global {
+  template<> double pi1<double> = 1.5;  // expected-error {{no variable template matches specialization}}
+  template int pi1<int> = 10;  // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} \
+                                  expected-error {{no variable template matches specialization}}
+}
+#endif

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp Mon Aug  5 20:03:05 2013
@@ -163,7 +163,8 @@ namespace PR9877 {
   template<> struct X<1>::Y { static const int Z = 1; };
 
   const int X<0>::Y::Z;
-  template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}}
+  template<> const int X<1>::Y::Z;  // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}} \
+                                    // expected-error{{forward declaration of variable template cannot have a nested name specifier}}
 }
 
 namespace PR9913 {

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Mon Aug  5 20:03:05 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s 
 class X { 
 public:
   operator bool();

Added: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp?rev=187762&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp Mon Aug  5 20:03:05 2013
@@ -0,0 +1,159 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -DPRECXX11
+// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s
+
+class A {
+  template<typename T> const T wrong;           // expected-error {{member 'wrong' declared as a template}}
+  template<typename T> const T wrong_init = 5;      // expected-error {{member 'wrong_init' declared as a template}}
+  template<typename T, typename T0> static const T right = T(100);
+  template<typename T> static const T right<T,int> = 5;
+  template<typename T> const int right<int,T>;  // expected-error {{member 'right' declared as a template}}
+  template<typename T> const float right<float,T> = 5;  // expected-error {{member 'right' declared as a template}}
+  template<> static const int right<int,int> = 7;       // expected-error {{explicit specialization of 'right' in class scope}}
+  template<> static const float right<float,int>;       // expected-error {{explicit specialization of 'right' in class scope}}
+  template static const int right<int,int>;     // expected-error {{template specialization requires 'template<>'}} \
+                                                // expected-error {{explicit specialization of 'right' in class scope}}
+};
+
+namespace out_of_line {
+  class B0 {
+    template<typename T, typename T0> static const T right = T(100);
+    template<typename T> static const T right<T,int> = T(5);
+  };
+  template<> const int B0::right<int,int> = 7;
+  template const int B0::right<int,int>;
+  template<> const int B0::right<int,float>;
+  template const int B0::right<int,float>;
+
+  class B1 {
+    template<typename T, typename T0> static const T right;
+    template<typename T> static const T right<T,int>;
+  };
+  template<typename T, typename T0> const T B1::right = T(100);
+  template<typename T> const T B1::right<T,int> = T(5);
+
+  class B2 {
+    template<typename T, typename T0> static const T right = T(100);  // expected-note {{previous definition is here}}
+    template<typename T> static const T right<T,int> = T(5);          // expected-note {{previous definition is here}}
+  };
+  template<typename T, typename T0> const T B2::right = T(100);   // expected-error {{redefinition of 'right'}}
+  template<typename T> const T B2::right<T,int> = T(5);           // expected-error {{redefinition of 'right'}}
+
+  class B3 {
+    template<typename T, typename T0> static const T right = T(100);
+    template<typename T> static const T right<T,int> = T(5);
+  };
+  template<typename T, typename T0> const T B3::right;  // expected-error {{forward declaration of variable template cannot have a nested name specifier}}
+  template<typename T> const T B3::right<T,int>;        // expected-error {{forward declaration of variable template partial specialization cannot have a nested name specifier}}
+
+  class B4 {
+    template<typename T, typename T0> static const T right;
+    template<typename T> static const T right<T,int>;
+    template<typename T, typename T0> static const T right_def = T(100);
+    template<typename T> static const T right_def<T,int>;   // expected-note {{explicit instantiation refers here}}
+  };
+  template<typename T, typename T0> const T B4::right;  // expected-error {{forward declaration of variable template cannot have a nested name specifier}}
+  template<typename T> const T B4::right<T,int>;        // expected-error {{forward declaration of variable template partial specialization cannot have a nested name specifier}} \
+                                                        // expected-note {{explicit instantiation refers here}}
+  template const int B4::right<int,int>;  // expected-error {{explicit instantiation of undefined static data member template 'right' of class}}
+  template const int B4::right_def<int,int>;  // expected-error {{explicit instantiation of undefined static data member template 'right_def' of class}}
+}
+
+namespace non_const_init {
+  class A {
+    template<typename T> static T wrong_inst = T(10); // expected-error {{non-const static data member must be initialized out of line}}
+    template<typename T> static T wrong_inst_fixed;
+  };
+  template int A::wrong_inst<int>;  // expected-note {{in instantiation of static data member 'non_const_init::A::wrong_inst<int>' requested here}}
+  template<typename T> T A::wrong_inst_fixed = T(10);
+  template int A::wrong_inst_fixed<int>;
+  
+  class B {
+    template<typename T> static T wrong_inst;
+    template<typename T> static T wrong_inst<T*> = T(100);  // expected-error {{non-const static data member must be initialized out of line}}
+    
+    template<typename T> static T wrong_inst_fixed;
+    template<typename T> static T wrong_inst_fixed<T*>;
+  };
+  template int B::wrong_inst<int*>;  // expected-note {{in instantiation of static data member 'non_const_init::B::wrong_inst<int *>' requested here}}
+  template<typename T> T B::wrong_inst_fixed = T(100);
+  template int B::wrong_inst_fixed<int>;
+  
+  class C {
+    template<typename T> static const T right_inst = T(10);
+    template<typename T> static const T right_inst<T*> = T(100);
+  };
+  template const int C::right_inst<int>;
+  template const int C::right_inst<int*>;
+  
+  namespace pointers {
+    
+    struct C0 {
+      template<typename U> static U Data;
+      template<typename U> static const U Data<U*> = U();   // Okay
+    };
+    template const int C0::Data<int*>;
+    
+    struct C1a {
+      template<typename U> static U Data;
+      template<typename U> static U* Data<U>;   // Okay, with out-of-line definition
+    };
+    template<typename T> T* C1a::Data<T> = new T();
+    template int* C1a::Data<int>;
+    
+    struct C1b {
+      template<typename U> static U Data;
+      template<typename U> static const U* Data<U>;   // Okay, with out-of-line definition
+    };
+    template<typename T> const T* C1b::Data<T> = (T*)(0);
+    template const int* C1b::Data<int>;
+
+    struct C2a {
+      template<typename U> static U Data;
+      template<typename U> static U* Data<U> = new U();   // expected-error {{non-const static data member must be initialized out of line}}
+    };
+    template int* C2a::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int>' requested here}}
+    
+    struct C2b {  // FIXME: ?!? Should this be an error? pointer-types are automatically non-const?
+      template<typename U> static U Data;
+      template<typename U> static const U* Data<U> = (U*)(0); // expected-error {{non-const static data member must be initialized out of line}}
+    };
+    template const int* C2b::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int>' requested here}}
+  }
+}
+
+struct matrix_constants {
+  // TODO: (?)
+};
+
+namespace in_class_template {
+  // FIXME: member data templates of class templates are not well supported yet.
+
+  template<typename T>
+  class D0 {
+    template<typename U> static U Data;
+    template<typename U> static const U Data<U*> = U();
+  };
+
+  template<typename T>
+  class D1 {
+    template<typename U> static U Data;
+    template<typename U> static U* Data<U*>;
+  };
+  template<typename T>
+  template<typename U> U* D1<T>::Data<U*> = (U*)(0);
+    
+  namespace to_be_fixed {
+    // FIXME: The following generate runtime exceptions!
+
+    //template<>
+    //template<typename U> U* D1<float>::Data<U*> = (U*)(0) + 1;
+    //template const int D0<float>::Data<int*>;
+    //template int* D1<float>::Data<int*>;
+  }
+}
+
+namespace in_nested_classes {
+  // TODO:
+}
+

Added: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp?rev=187762&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Mon Aug  5 20:03:05 2013
@@ -0,0 +1,415 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s
+// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s -DCXX11
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -DCXX11
+
+#ifdef CXX11
+  #define CONST constexpr
+#else
+  #define CONST const
+#endif
+
+template<typename T> 
+T pi = T(3.1415926535897932385); // expected-note {{template is declared here}}
+
+template<typename T> 
+CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}
+
+namespace use_in_top_level_funcs {
+
+  void good() {
+    int ipi = pi<int>;
+    int icpi = cpi<int>;
+    double dpi = pi<double>;
+    double dcpi = cpi<double>;
+  }
+
+  void no_deduce() {
+    // template arguments are not deduced for uses of variable templates.
+    int ipi = pi; // expected-error {{cannot refer to variable template 'pi' without a template argument list}}
+    int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}}
+  }
+  
+  template<typename T>
+  T circular_area(T r) {
+    return pi<T> * r * r;
+  }
+
+  template<typename T>
+  CONST T const_circular_area(T r) {
+    return cpi<T> * r * r;
+  }
+
+  double use_circular_area(double r) {
+    CONST float t = const_circular_area(2.0) - 12;
+#ifdef CXX11
+    static_assert(const_circular_area(2) == 12, "");
+    CONST int test = (t > 0) && (t < 1);
+    static_assert(test, "");
+#endif
+    return circular_area(r);
+  }
+}
+
+namespace shadow {
+  void foo() {
+    int ipi0 = pi<int>;
+    int pi;
+    int a = pi;
+    int ipi = pi<int>;  // expected-error {{expected '(' for function-style cast or type construction}} \
+                        // expected-error {{expected expression}}
+  }
+}
+
+namespace odr_tmpl {
+  namespace pv_cvt {
+    int v;   // expected-note {{previous definition is here}}
+    template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}}
+  }
+  namespace pvt_cv {
+    template<typename T> T v; // expected-note {{previous definition is here}}
+    int v;   // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}}
+  }
+  namespace pvt_cvt {
+    template<typename T> T v0; // expected-note {{previous definition is here}}
+    template<typename T> T v0; // expected-error {{redefinition of 'v0'}}
+
+    template<typename T> T v; // expected-note {{previous definition is here}}
+    template<typename T> int v; // expected-error {{redefinition of 'v'}}
+    
+    template<typename T> int v1; // expected-note {{previous template declaration is here}}
+    template<int I> int v1;      // expected-error {{template parameter has a different kind in template redeclaration}}
+  }
+  namespace pvt_use {
+    template<typename T> T v;
+    v = 10;  // expected-error {{C++ requires a type specifier for all declarations}}
+  }
+
+  namespace pvt_diff_params {
+    // FIXME: (?) Redefinitions should simply be not allowed, whether the
+    // template parameters match or not. However, this current behaviour also
+    // matches that of class templates...
+    template<typename T, typename> T v;   // expected-note 2{{previous template declaration is here}}
+    template<typename T> T v;   // expected-error {{too few template parameters in template redeclaration}}
+    template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}}
+  }
+
+  namespace pvt_extern {
+    template<typename T> T v = T();
+    template<typename T> extern T v;      // redeclaration is allowed \
+                                          // expected-note {{previous definition is here}}
+    template<typename T> extern int v;    // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}}
+
+#ifdef CXX11
+    template<typename T> extern auto v;   // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}}
+#endif
+  }
+
+#ifdef CXX11
+  namespace pvt_auto {
+    template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}}
+    template<typename T> auto v1 = T();  // expected-note {{previous definition is here}}
+    template<typename T> int v1;   // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}}
+    template<typename T> auto v2 = T();  // expected-note {{previous definition is here}}
+    template<typename T> T v2;   // expected-error {{redefinition of 'v2'}}
+    template<typename T> auto v3 = T();   // expected-note {{previous definition is here}}
+    template<typename T> extern T v3;     // expected-error {{redefinition of 'v3' with a different type: 'T' vs 'auto'}}
+    template<typename T> auto v4 = T();
+    template<typename T> extern auto v4;   // expected-error {{declaration of variable 'v4' with type 'auto' requires an initializer}}
+  }
+#endif
+  
+}  
+
+namespace explicit_instantiation {
+  template<typename T> 
+  T pi0a = T(3.1415926535897932385);  // expected-note {{variable template 'pi0a' declared here}}
+  template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}}
+
+  template<typename T> 
+  T pi0b = T(3.1415926535897932385);  // expected-note {{variable template 'pi0b' declared here}}
+  template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}}
+
+  template<typename T> 
+  T pi0c = T(3.1415926535897932385);  // expected-note {{variable template 'pi0c' declared here}}
+  template int pi0c<const int>;  // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}}
+
+  template<typename T> 
+  T pi0 = T(3.1415926535897932385);
+  template int pi0<int>;   // expected-note {{previous explicit instantiation is here}}
+  template int pi0<int>;   // expected-error {{duplicate explicit instantiation of 'pi0<int>'}}
+
+  template<typename T> 
+  CONST T pi1a = T(3.1415926535897932385);  // expected-note {{variable template 'pi1a' declared here}}
+  template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}}
+
+  template<typename T> 
+  CONST T pi1b = T(3.1415926535897932385);  // expected-note {{variable template 'pi1b' declared here}}
+  template int pi1b<const int>;  // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}}
+
+  template<typename T> 
+  CONST T pi1 = T(3.1415926535897932385);
+  template CONST int pi1<int>;   // expected-note {{previous explicit instantiation is here}}
+  template CONST int pi1<int>;   // expected-error {{duplicate explicit instantiation of 'pi1<int>'}}
+
+#ifdef CXX11
+  namespace auto_var {
+    template<typename T> auto var0 = T();
+    template auto var0<int>;    // expected-error {{'auto' variable template instantiation is not allowed}}
+    
+    template<typename T> auto var = T();
+    template int var<int>;
+  }
+#endif
+  
+  namespace extern_var {
+    // TODO:
+  }
+}
+
+namespace explicit_specialization {
+
+  namespace good {
+    template<typename T1, typename T2>
+    CONST int pi2 = 1;
+
+    template<typename T>
+    CONST int pi2<T,int> = 2;
+
+    template<typename T>
+    CONST int pi2<int,T> = 3;
+
+    template<> CONST int pi2<int,int> = 4;
+
+#ifdef CXX11   
+    void foo() {
+      static_assert(pi2<int,int> == 4, "");
+      static_assert(pi2<float,int> == 2, "");
+      static_assert(pi2<int,float> == 3, "");
+      static_assert(pi2<int,float> == pi2<int,double>, "");
+      static_assert(pi2<float,float> == 1, "");
+      static_assert(pi2<float,float> == pi2<float,double>, "");
+    }
+#endif
+  }
+
+  namespace ambiguous {
+
+    template<typename T1, typename T2>
+    CONST int pi2 = 1;
+
+    template<typename T>
+    CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}}
+
+    template<typename T>
+    CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}}
+    
+    void foo() {
+      int a = pi2<int,int>;  // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}}
+    }
+  }
+  
+  namespace type_changes {
+
+    template<typename T> 
+    T pi0 = T(3.1415926535897932385);
+
+    template<> float pi0<int> = 10;
+    template<> int pi0<const int> = 10;
+
+    template<typename T>
+    T pi1 = T(3.1415926535897932385);
+    template<> CONST int pi1<int> = 10;
+
+    template<typename T>
+    T pi2 = T(3.1415926535897932385);
+    template<> int pi2<const int> = 10;
+
+    template<typename T>
+    CONST T pi4 = T(3.1415926535897932385);
+    template<> int pi4<int> = 10;
+  }
+
+  namespace redefinition {
+    template<typename T>
+    T pi0 = T(3.1415926535897932385);
+
+    template<> int pi0<int> = 10;   // expected-note 3{{previous definition is here}}
+#ifdef CXX11
+// expected-note at -2 {{previous definition is here}}
+#endif
+    template<> int pi0<int> = 10;   // expected-error {{redefinition of 'pi0<int>'}}
+    template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}}
+    template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}}
+#ifdef CXX11
+    template<> auto pi0<int> = 10;  // expected-error {{redefinition of 'pi0<int>'}}
+#endif
+
+
+    template<typename T> 
+    CONST T pi1 = T(3.1415926535897932385);
+
+    template<> CONST int pi1<int> = 10;   // expected-note {{previous definition is here}}
+    template<> CONST int pi1<int> = 10;   // expected-error {{redefinition of 'pi1<int>'}}
+  }
+  
+  namespace before_instantiation {
+    template<typename T> 
+    T pi0 = T(3.1415926535897932385);   // expected-note {{variable template 'pi0' declared here}}
+
+    template<> int pi0<int> = 10;
+    template int pi0<int>;
+    template float pi0<int>;    // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}}
+
+    template<typename T1, typename T2>
+    CONST int pi2 = 1;
+
+    template<typename T> CONST int pi2<T,int> = 2;
+    template CONST int pi2<int,int>;
+  }
+  namespace after_instantiation {
+    template<typename T> 
+    T pi0 = T(3.1415926535897932385);
+
+    template int pi0<int>;   // expected-note 2{{explicit instantiation first required here}}
+    template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}}
+    template<> float pi0<int>;    // expected-error {{explicit specialization of 'pi0' after instantiation}}
+
+    template<typename T1, typename T2>
+    CONST int pi2 = 1;
+
+    template CONST int pi2<int,int>;
+    template<typename T> CONST int pi2<T,int> = 2;
+  }
+
+#ifdef CXX11
+  namespace auto_var {
+    template<typename T, typename> auto var0 = T();
+    template<typename T> auto var0<T,int> = T();
+    template<> auto var0<int,int> = 7;
+
+    template<typename T, typename> auto var = T();
+    template<typename T> T var<T,int> = T(5);
+    template<> int var<int,int> = 7;
+
+    void foo() {
+      int i0 = var0<int,int>;
+      int b = var<int,int>;
+    }
+  }
+#endif
+  
+  namespace extern_var {
+    // TODO:
+  }
+  
+  namespace diff_type {
+    // TODO:
+    template<typename T> T var = T();
+    template<typename T> T* var<T> = new T();
+#ifdef CXX11
+    template<typename T> auto var<T*> = T();  // expected-note {{previous definition is here}}
+    template<typename T> T var<T*> = T();     // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}}
+#endif
+  }
+}
+
+namespace use_in_structs {
+  // TODO:
+}
+
+namespace attributes {
+  // TODO:
+}
+
+#ifdef CXX11
+namespace arrays {
+  template<typename T>
+  T* arr = new T[10]{T(10), T(23)};
+
+  float f = 10.5;
+  template<> float* arr<float> = &f;
+  
+  void bar() {
+    int *iarr = arr<int>;
+    iarr[0] = 1;
+    iarr[2] = 3;
+    iarr[6] = -2;
+
+    float ff = *arr<float>;
+    float nof = arr<float>[3];  // No bounds-check in C++
+  }
+}
+#endif
+
+namespace nested {
+  
+  namespace n0a {
+    template<typename T> 
+    T pi0a = T(3.1415926535897932385);
+  }
+  
+  using namespace n0a;
+  int i0a = pi0a<int>;
+  
+  template float pi0a<float>;
+  float f0a = pi0a<float>;
+  
+  template<> double pi0a<double> = 5.2;
+  double d0a = pi0a<double>;
+
+  namespace n0b {
+    template<typename T> 
+    T pi0b = T(3.1415926535897932385);
+  }
+  
+  int i0b = n0b::pi0b<int>;
+  
+  template float n0b::pi0b<float>;
+  float f0b = n0b::pi0b<float>;
+  
+  template<> double n0b::pi0b<double> = 5.2;
+  double d0b = n0b::pi0b<double>;
+  
+  namespace n1 {
+    template<typename T> 
+    T pi1a = T(3.1415926535897932385);
+#ifdef CXX11
+// expected-note at -2 {{explicit instantiation refers here}}
+#endif
+
+    template<typename T> 
+    T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}
+#ifdef CXX11
+// expected-note at -2 {{explicit instantiation refers here}}
+#endif
+  }
+  
+  namespace use_n1a {
+    using namespace n1;
+    int i1 = pi1a<int>;
+
+    template float pi1a<float>;
+#ifdef CXX11
+// expected-error at -2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}}
+#endif
+    float f1 = pi1a<float>;
+    
+    template<> double pi1a<double> = 5.2;  // expected-error {{no variable template matches specialization}}
+    double d1 = pi1a<double>;
+  }
+  
+  namespace use_n1b {
+    int i1 = n1::pi1b<int>;
+    
+    template float n1::pi1b<float>;
+#ifdef CXX11
+// expected-error at -2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}}
+#endif
+    float f1 = n1::pi1b<float>;
+    
+    template<> double n1::pi1b<double> = 5.2;  // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \
+                                               // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}}
+    double d1 = n1::pi1b<double>;
+  }
+}
+

Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Mon Aug  5 20:03:05 2013
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-c++11-compat -verify %s -DCXX1YCOMPAT
+
+#ifndef CXX1YCOMPAT
 
 namespace std {
   struct type_info;
@@ -378,3 +381,77 @@ namespace rdar11736429 {
     X x; // expected-warning{{union member 'x' with a non-trivial constructor is incompatible with C++98}}
   };
 }
+#endif
+
+template<typename T> T var = T(10);
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template<typename T> T* var<T*> = new T();
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template<> int var<int> = 10;
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template int var<int>;
+float fvar = var<float>;
+
+class A {  
+  template<typename T> static T var = T(10);
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+  
+  template<typename T> static T* var<T*> = new T(); 
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+};
+
+struct B {  template<typename T> static T v; };
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template<typename T> T B::v = T();
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template<typename T> T* B::v<T*> = new T();
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template<> int B::v<int> = 10;
+#ifdef CXX1YCOMPAT
+// expected-warning at -2 {{variable templates are incompatible with C++ standards before C++1y}}
+#else
+// expected-warning at -4 {{variable templates are a C++1y extension}}
+#endif
+
+template int B::v<int>;
+float fsvar = B::v<float>;
+

Modified: cfe/trunk/test/SemaCXX/for-range-examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/for-range-examples.cpp (original)
+++ cfe/trunk/test/SemaCXX/for-range-examples.cpp Mon Aug  5 20:03:05 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 
 
 namespace value_range_detail {
   template<typename T>

Modified: cfe/trunk/test/SemaCXX/unknown-type-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-type-name.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/unknown-type-name.cpp (original)
+++ cfe/trunk/test/SemaCXX/unknown-type-name.cpp Mon Aug  5 20:03:05 2013
@@ -93,14 +93,14 @@ template<typename T> int A<T>::h(T::type
 template<typename T> int h(T::type, int); // expected-error{{missing 'typename'}}
 template<typename T> int h(T::type x, char); // expected-error{{missing 'typename'}}
 
-template<typename T> int junk1(T::junk); // expected-error{{declared as a template}}
+template<typename T> int junk1(T::junk); // expected-warning{{variable templates are a C++1y extension}}
 template<typename T> int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
 template<typename T> int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} expected-warning{{C++11}}
 template<typename T> int junk4(T::junk j); // expected-error{{missing 'typename'}}
 
 // FIXME: We can tell this was intended to be a function because it does not
 //        have a dependent nested name specifier.
-template<typename T> int i(T::type, int()); // expected-error{{variable 'i' declared as a template}}
+template<typename T> int i(T::type, int()); // expected-warning{{variable templates are a C++1y extension}}
 
 // FIXME: We know which type specifier should have been specified here. Provide
 //        a fix-it to add 'typename A<T>::type'

Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Mon Aug  5 20:03:05 2013
@@ -50,7 +50,9 @@ void f() {
   template<typename T> class X; // expected-error{{expression}}
 }
 
-template<typename T> class X1 var; // expected-error{{declared as a template}}
+template<typename T> class X1 var; // expected-warning{{variable templates are a C++1y extension}} \
+                                   // expected-error {{variable has incomplete type 'class X1'}} \
+                                   // expected-note {{forward declaration of 'X1'}}
 
 namespace M {
 }

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Aug  5 20:03:05 2013
@@ -4582,7 +4582,9 @@ CXCursor clang_getCursorDefinition(CXCur
     return clang_getNullCursor();
   }
 
-  case Decl::Var: {
+  case Decl::Var:
+  case Decl::VarTemplateSpecialization:
+  case Decl::VarTemplatePartialSpecialization: {
     // Ask the variable if it has a definition.
     if (const VarDecl *Def = cast<VarDecl>(D)->getDefinition())
       return MakeCXCursor(Def, TU);
@@ -4604,6 +4606,13 @@ CXCursor clang_getCursorDefinition(CXCur
     return clang_getNullCursor();
   }
 
+  case Decl::VarTemplate: {
+    if (VarDecl *Def =
+            cast<VarTemplateDecl>(D)->getTemplatedDecl()->getDefinition())
+      return MakeCXCursor(cast<VarDecl>(Def)->getDescribedVarTemplate(), TU);
+    return clang_getNullCursor();
+  }
+
   case Decl::Using:
     return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), 
                                        D->getLocation(), TU);

Modified: cfe/trunk/tools/libclang/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/RecursiveASTVisitor.h?rev=187762&r1=187761&r2=187762&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/RecursiveASTVisitor.h (original)
+++ cfe/trunk/tools/libclang/RecursiveASTVisitor.h Mon Aug  5 20:03:05 2013
@@ -395,6 +395,7 @@ private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
   bool TraverseClassInstantiations(ClassTemplateDecl *D);
+  bool TraverseVariableInstantiations(VarTemplateDecl *D);
   bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
   bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
                                           unsigned Count);
@@ -1418,6 +1419,57 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
     // it was instantiated, and thus should not be traversed.
   })
 
+// A helper method for traversing the implicit instantiations of a
+// class template.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
+    VarTemplateDecl *D) {
+  VarTemplateDecl::spec_iterator end = D->spec_end();
+  for (VarTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+    VarTemplateSpecializationDecl *SD = *it;
+
+    switch (SD->getSpecializationKind()) {
+    // Visit the implicit instantiations with the requested pattern.
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      TRY_TO(TraverseDecl(SD));
+      break;
+
+    // We don't need to do anything on an explicit instantiation
+    // or explicit specialization because there will be an explicit
+    // node for it elsewhere.
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+    case TSK_ExplicitSpecialization:
+      break;
+    }
+  }
+
+  return true;
+}
+
+DEF_TRAVERSE_DECL(
+    VarTemplateDecl,
+    {
+  VarDecl *TempDecl = D->getTemplatedDecl();
+  TRY_TO(TraverseDecl(TempDecl));
+  TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+  // By default, we do not traverse the instantiations of
+  // variable templates since they do not appear in the user code. The
+  // following code optionally traverses them.
+  //
+  // We only traverse the variable instantiations when we see the canonical
+  // declaration of the template, to ensure we only visit them once.
+  if (getDerived().shouldVisitTemplateInstantiations() &&
+      D == D->getCanonicalDecl())
+    TRY_TO(TraverseVariableInstantiations(D));
+
+      // Note that getInstantiatedFromMemberTemplate() is just a link
+      // from a template instantiation back to the template from which
+      // it was instantiated, and thus should not be traversed.
+})
+
 // A helper method for traversing the instantiations of a
 // function while skipping its specializations.
 template<typename Derived>
@@ -1744,6 +1796,43 @@ DEF_TRAVERSE_DECL(VarDecl, {
     TRY_TO(TraverseVarHelper(D));
   })
 
+DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
+  // For implicit instantiations, we don't want to
+  // recurse at all, since the instatiated class isn't written in
+  // the source code anywhere.
+  if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+
+  if (!getDerived().shouldVisitTemplateInstantiations() &&
+      D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+    // Returning from here skips traversing the
+    // declaration context of the VarTemplateSpecializationDecl
+    // (embedded in the DEF_TRAVERSE_DECL() macro).
+    return true;
+})
+
+DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl,
+                  {
+  // The partial specialization.
+  if (TemplateParameterList *TPL = D->getTemplateParameters()) {
+    for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+         I != E; ++I) {
+      TRY_TO(TraverseDecl(*I));
+    }
+  }
+  // The args that remains unspecialized.
+  TRY_TO(TraverseTemplateArgumentLocsHelper(D->getTemplateArgsAsWritten(),
+                                            D->getNumTemplateArgsAsWritten()));
+
+  // Don't need the VarTemplatePartialSpecializationHelper, even
+  // though that's our parent class -- we already visit all the
+  // template args here.
+  TRY_TO(TraverseVarHelper(D));
+
+                    // Instantiations will have been visited with the primary
+                    // template.
+})
+
 DEF_TRAVERSE_DECL(ImplicitParamDecl, {
     TRY_TO(TraverseVarHelper(D));
   })





More information about the cfe-commits mailing list