[PATCH] Variable templates w/ partial support for static data members

Richard Smith richard at metafoo.co.uk
Sun Aug 4 23:29:22 PDT 2013



================
Comment at: include/clang/AST/ASTContext.h:275
@@ +274,3 @@
+public:
+  /// \brief A type synonymn for the TemplateOrInstantiation mapping.
+  typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
----------------
Typo "synonym"

================
Comment at: include/clang/AST/Decl.h:954
@@ -959,1 +953,3 @@
+    Kind K = getKind();
+    if ((K == ParmVar) || (K == ImplicitParam))
       return false;
----------------
No parens around these.

================
Comment at: include/clang/AST/DeclTemplate.h:2402-2403
@@ +2401,4 @@
+  /// variable template or variable template partial specialization from which
+  /// it
+  /// was instantiated.
+  llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
----------------
Extra newline in this comment.

================
Comment at: include/clang/AST/DeclTemplate.h:2436-2443
@@ +2435,10 @@
+  /// \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 return the
+  /// deduced template arguments for the variable template partial
+  /// specialization
+  /// itself.
+  const TemplateArgumentList &getTemplateInstantiationArgs() const {
----------------
Likewise.

================
Comment at: include/clang/AST/DeclTemplate.h:2620-2621
@@ +2619,4 @@
+  /// \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
----------------
And here.

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1535-1537
@@ +1534,5 @@
+  // templates.
+DEF_TRAVERSE_DECL(
+    VarTemplateDecl,
+    {
+  VarDecl *TempDecl = D->getTemplatedDecl();
----------------
Join these lines.

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1902-1903
@@ +1901,4 @@
+
+DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl,
+                  {
+  // The partial specialization.
----------------
Join these lines.

================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:3066-3068
@@ -3051,2 +3065,5 @@
   "class template or class template partial specialization">;
+def err_var_template_qualified_declarator_no_match : Error<
+  "nested name specifier '%0' for declaration does not refer into a variable, "
+  "variable template or variable template partial specialization">;
 def err_specialize_member_of_template : Error<
----------------
It looks like you don't use this diagnostic; remove.

================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:3110
@@ -3084,1 +3109,3 @@
+def err_var_spec_no_template : Error<
+  "no variable template matches %select{|partial}0 specialization">;
   
----------------
This has two spaces in a row if %0 is 0.

================
Comment at: include/clang/Sema/Template.h:381-386
@@ -380,1 +380,8 @@
 
+    /// \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.
+    SmallVector<
+        std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
+    OutOfLineVarPartialSpecs;
+
----------------
You don't appear to use these for anything yet; I assume support for class-scope partial specialization of variable templates will follow in a separate patch?

================
Comment at: lib/AST/ASTContext.cpp:7995-7996
@@ +7994,4 @@
+         llvm::capacity_in_bytes(TemplateOrInstantiation)
+         //   + llvm::capacity_in_bytes(InstantiatedFromStaticDataMember)
+         +
+         llvm::capacity_in_bytes(InstantiatedFromUsingDecl) +
----------------
Why is this commented out?

================
Comment at: lib/AST/Decl.cpp:1987
@@ -1962,3 +1986,3 @@
   if (isStaticDataMember())
-    return getASTContext().getInstantiatedFromStaticDataMember(this);
-
+    // return getASTContext().getInstantiatedFromStaticDataMember(this);
+    return getASTContext().getTemplateOrSpecializationInfo(this)
----------------
Remove commented out code.

================
Comment at: lib/AST/ASTContext.cpp:1044-1049
@@ -1044,7 +1044,7 @@
 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 *>();
+}
+
----------------
It looks like this has no callers; remove it.

================
Comment at: lib/Parse/ParseCXXInlineMethods.cpp:59-62
@@ +58,6 @@
+    NamedDecl *VD = FnD;
+    if (VarTemplateDecl *VT = VD ? dyn_cast<VarTemplateDecl>(VD) : 0)
+      // Re-direct this decl to refer to the templated decl so that we can
+      // initialize it.
+      VD = VT->getTemplatedDecl();
+
----------------
This can't happen: FnD is always a function declaration here. (We only handle initializers here in order to deal with a "= 0" pure-specifier.)

================
Comment at: lib/Parse/ParseDecl.cpp:1805-1816
@@ -1805,12 +1804,14 @@
 
-  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.
+    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;
     }
 
----------------
This check seems like it belongs in Sema.

================
Comment at: lib/Parse/ParseExprCXX.cpp:564-569
@@ -563,2 +563,8 @@
   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();
+    SS = TemplateId->SS;
+  }
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
----------------
This should be handled elsewhere: perhaps in ParseOptionalCXXScopeSpecifier's handling of annot_template_id.

================
Comment at: lib/Sema/SemaDecl.cpp:4962
@@ +4961,3 @@
+        if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+          // This is an explicit specialization.
+
----------------
... partial or explicit specialization.

================
Comment at: lib/Sema/SemaDecl.cpp:4945
@@ +4944,3 @@
+    if (TemplateParams) {
+      if (!TemplateParams->size() &&
+          D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
----------------
    if (TemplateParams->empty() &&

================
Comment at: lib/Sema/SemaDecl.cpp:5018-5019
@@ +5017,4 @@
+            // If the name of the template was qualified, we must be defining
+            // the
+            // template out-of-line.
+            if (!D.getCXXScopeSpec().isInvalid() && !Invalid &&
----------------
Redundant newline.

================
Comment at: lib/Sema/SemaTemplate.cpp:216
@@ -213,3 +215,3 @@
   }
-
+  // assert(false && "...");
   TemplateResult = TemplateTy::make(Template);
----------------
Remove.

================
Comment at: lib/Sema/SemaTemplate.cpp:2583
@@ +2582,3 @@
+  // a placeholder for an incomplete declarative context; which must be
+  // complete by instantiation time. Thus, do search through the partial
+  // specializations yet.
----------------
*do not

================
Comment at: lib/Sema/SemaTemplateDeduction.cpp:2404
@@ +2403,3 @@
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given class template
+/// partial specialization per C++ [temp.class.spec.match].
----------------
... given variable template

================
Comment at: lib/Sema/SemaTemplateInstantiateDecl.cpp:2313-2315
@@ +2312,5 @@
+
+  // 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())
----------------
Is it really valid for a type to be defined in a variable template declaration? That seems like a big can of worms.


http://llvm-reviews.chandlerc.com/D1067



More information about the cfe-commits mailing list