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

Larisse Voufo lvoufo at google.com
Mon Aug 5 08:37:26 PDT 2013



================
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<
----------------
Richard Smith wrote:
> It looks like you don't use this diagnostic; remove.
Right. This must have been lost with previous revisions.

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1902-1903
@@ +1901,4 @@
+
+DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl,
+                  {
+  // The partial specialization.
----------------
Richard Smith wrote:
> Join these lines.
Yeah. I need to be a bit more attentive with clang-format.

================
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">;
   
----------------
Richard Smith wrote:
> This has two spaces in a row if %0 is 0.
Fixed in one of the lasts patches after this...

================
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;
+
----------------
Richard Smith wrote:
> 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?
Probably. We have some class-scope partial specialization right now. However, it looks like I have not well mapped the behavior from nested templates. So, I guess I'll know for sure after that is done.

================
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 *>();
+}
+
----------------
Richard Smith wrote:
> It looks like this has no callers; remove it.
I have replaced it with getTemplateOrSpecializationInfo(). However, I'd like to make sure that static data member templates are working well before I remove it completely...

================
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) +
----------------
Richard Smith wrote:
> Why is this commented out?
I was in the process of replacing it with TemplateOrInstantiation. Removed.

================
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)
----------------
Richard Smith wrote:
> Remove commented out code.
Same logic as earlier. I am not 100% confident that it is not needed yet. I will eventually removed it when/if I get static data member templates to work properly. I added a FIXME for now. 

================
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();
+
----------------
Richard Smith wrote:
> 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.)
Ok.

================
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;
     }
 
----------------
Richard Smith wrote:
> This check seems like it belongs in Sema.
Ok.

================
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);
----------------
Richard Smith wrote:
> This should be handled elsewhere: perhaps in ParseOptionalCXXScopeSpecifier's handling of annot_template_id.
Ok. Noted.

================
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())
----------------
Richard Smith wrote:
> Is it really valid for a type to be defined in a variable template declaration? That seems like a big can of worms.
I'm not sure. But perhaps this is another question to add onto my "notes".

I interpret this as allowing things like 
  template<typename T> class { } var = ...;
since "class { }" is anonymous and this is okay:
  class {} var;

But that can lead to things like 
  template<typename T> class {T foo;} var = ...;

Which can be "tricky" to manage...

Should we just reject all such cases, or at least just allow the first one, where the anonymous type is non-dependent?






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



More information about the cfe-commits mailing list