[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