================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1484-1532
@@ -1482,2 +1483,51 @@
 
+// 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;
+}
+
+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
----------------
Richard Smith wrote:
> Once this patch lands, it'd be good to go back over this and clean up this 
> duplication: traversal for variable templates, class templates, and function 
> templates all use exactly the same code (other than some trivial differences 
> in class names).
Right. I've added a FIXME to this effect.

================
Comment at: lib/AST/ASTImporter.cpp:106
@@ -106,2 +106,2 @@
 
     bool ImportDefinition(RecordDecl *From, RecordDecl *To, 
----------------
Richard Smith wrote:
> Updates to ASTImporter.cpp aren't generally necessary: it's already *very* 
> incomplete (it doesn't support function templates, for instance) and would 
> require substantial work to make it complete.
So... Is this an invitation to drop these changes, or to keep them around at 
least for future-proofness reasons?

================
Comment at: lib/AST/Decl.cpp:1563
@@ +1562,3 @@
+        QualType T, TypeSourceInfo *TInfo, StorageClass SC,
+        VarDecl *PrevDecl)
+  : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() {
----------------
Richard Smith wrote:
> You're not using PrevDecl here; remove it?
Ow. Good catch. 

================
Comment at: include/clang/AST/Decl.h:1205
@@ -1188,1 +1204,3 @@
+    : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, 0) {
+    // Function parameters cannot be variable templates. Hence, PrevDecl=0.
     assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
----------------
Richard Smith wrote:
> More to the point, function parameters cannot be redeclarations. There's no 
> fundamental reason to only use PrevDecl for variable templates.
Right. I've removed PrevDecl from VarDecl.

================
Comment at: lib/AST/DeclTemplate.cpp:1208-1209
@@ +1207,4 @@
+{ 
+  // FIXME: Is this needed for variable templates?
+  //AdoptTemplateParameterList(Params, this);
+}
----------------
Richard Smith wrote:
> Maybe adopt them into DC (though they should presumably be there already).
I think they should be in DC by now. I leave this commented out for now, and 
remove it once I'm sure that there are no unforeseen corner case. 

================
Comment at: lib/Sema/SemaExpr.cpp:11571
@@ -11536,1 +11570,3 @@
+  
+  if (/*Var->isUsed(false) ||*/ !IsPotentiallyEvaluatedContext(SemaRef))
     return;
----------------
Richard Smith wrote:
> Did you mean to leave this in the patch?
Yes. But I don't find it necessary anymore.

================
Comment at: lib/Sema/SemaTemplateDeduction.cpp:4489-4550
@@ +4488,64 @@
+VarTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+                                  VarTemplatePartialSpecializationDecl *PS1,
+                                  VarTemplatePartialSpecializationDecl *PS2,
+                                              SourceLocation Loc) {
+
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  TemplateDeductionInfo Info(Loc);
+
+  //QualType PT1 = PS1->getInjectedSpecializationType();
+  //QualType PT2 = PS2->getInjectedSpecializationType();
+  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,
+                                                 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;
+}
+
----------------
Richard Smith wrote:
> Instead of duplicating it, can you template the existing 
> getMoreSpecializedPartialSpecialization on the type of 
> PartialSpecializationDecl?
Marked as TODO.

================
Comment at: lib/Serialization/ASTWriterDecl.cpp:1217-1271
@@ +1216,57 @@
+
+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;
+}
+
----------------
Richard Smith wrote:
> It looks like the corresponding code in ASTDeclReader is missing?
Right. I had missed that. Thanks.

================
Comment at: lib/Sema/SemaTemplateInstantiateDecl.cpp:3439-3445
@@ +3438,9 @@
+  
+  /*
+  // 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);
+  */
+}
----------------
Richard Smith wrote:
> Why commented out?
I had meant to remove it. This block of code is only used in 
TemplateDeclInstantiator::VisitVarDecl()

================
Comment at: lib/Sema/SemaTemplate.cpp:2591
@@ +2590,3 @@
+        return true;
+      DI = SubstType(Templated->getTypeSourceInfo(),
+                                
MultiLevelTemplateArgumentList(TemplateArgList),
----------------
Richard Smith wrote:
> Richard Smith wrote:
> > Indentation.
> What happens when the type of the variable depends on the initializer:
> 
>     template<typename T> auto var1 = T();
>     template<int...N> int var2[] = { N... };
Added a FIXME for now.


================
Comment at: lib/Sema/SemaTemplate.cpp:7330
@@ -6758,1 +7329,3 @@
+            (D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
+                D.getCXXScopeSpec().isSet())))
       Diag(D.getIdentifierLoc(),
----------------
Richard Smith wrote:
> Why check the scope specifier here? It looks like this won't reject:
> 
>     template<typename T> T var = T();
>     template int var;
> 
> Do we handle that elsewhere?
> 
> Please also update the preceding quotation based on N3690 (the new wording 
> includes some relevant text about variable templates.)
It parses "template int var" as an explicit instantiation and complains about 
"too few arguments".

================
Comment at: lib/Sema/SemaTemplateInstantiateDecl.cpp:1114-1115
@@ +1113,4 @@
+  DeclContext *DC = Owner;
+  /*
+  // If this is the variable for an anonymous struct or union,
+  // instantiate the anonymous struct/union type first.
----------------
Richard Smith wrote:
> Add a FIXME here to revisit this.
Removed.


http://llvm-reviews.chandlerc.com/D1067
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to