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...
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187762 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index e04685c..9f832e5 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -55,11 +55,11 @@
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);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0b276d0..80fab62 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1797,24 +1797,69 @@
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 @@
// 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)
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 8df15ba..e62be69 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -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 @@
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);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 9704b98..d4a83fb 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -465,8 +465,8 @@
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 @@
// '::' 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;
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index d8ad259..fa23bd1 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -242,32 +242,31 @@
// 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.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 036278f..8f89481 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1437,8 +1437,9 @@
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 @@
// annotation token to a type annotation token now.
AnnotateTemplateIdTokenAsType();
return false;
- }
+ } else if (TemplateId->Kind == TNK_Var_template)
+ return false;
}
if (SS.isEmpty())