aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-07-22 17:18:37 +0000
committerDouglas Gregor <dgregor@apple.com>2009-07-22 17:18:37 +0000
commitdfe3f2d8ba49f03d01f42570e640d9a6755e6c08 (patch)
tree835a53a7b1cfa1edc7f881dc7b9553c4a6a6258c
parent9533a7fdb8397421f3be52e879442460a87389f6 (diff)
Implement parsing and semantic analysis for out-of-line definitions of static
data members of class templates. We don't instantiate the definitions yet, however. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76756 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/Sema.h1
-rw-r--r--lib/Sema/SemaDecl.cpp39
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp26
-rw-r--r--test/Parser/cxx-template-decl.cpp3
5 files changed, 67 insertions, 5 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3553a0386b..4cd1dca9a6 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -722,6 +722,9 @@ def note_template_param_prev_default_arg : Note<
def err_template_param_default_arg_missing : Error<
"template parameter missing a default argument">;
+def err_template_variable : Error<"variable %0 declared as a template">;
+def err_template_variable_noparams : Error<
+ "extraneous 'template<>' in declaration of variable %0">;
// C++ Template Argument Lists
def err_template_arg_list_different_arity : Error<
"%select{too few|too many}0 template arguments for "
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 22e4323ec1..7f652f2c1a 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -443,6 +443,7 @@ public:
bool &Redeclaration);
NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, NamedDecl* PrevDecl,
+ MultiTemplateParamsArg TemplateParamLists,
bool &Redeclaration);
void CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
bool &Redeclaration);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 283033bd7c..beceeef54d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1520,7 +1520,9 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
move(TemplateParamLists),
IsFunctionDefinition, Redeclaration);
} else {
- New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
+ New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl,
+ move(TemplateParamLists),
+ Redeclaration);
}
if (New == 0)
@@ -1772,6 +1774,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
NamedDecl*
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R,NamedDecl* PrevDecl,
+ MultiTemplateParamsArg TemplateParamLists,
bool &Redeclaration) {
DeclarationName Name = GetNameForDeclarator(D);
@@ -1840,7 +1843,36 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
-
+ // Check that we can declare a template here.
+ if (TemplateParamLists.size() &&
+ CheckTemplateDeclScope(S, TemplateParamLists))
+ return 0;
+
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ D.getCXXScopeSpec(),
+ (TemplateParameterList**)TemplateParamLists.release(),
+ TemplateParamLists.size())) {
+ if (TemplateParams->size() > 0) {
+ // There is no such thing as a variable template.
+ Diag(D.getIdentifierLoc(), diag::err_template_variable)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+ return 0;
+ } else {
+ // There is an extraneous 'template<>' for this variable. Complain
+ // about it, but allow the declaration of the variable.
+ Diag(TemplateParams->getTemplateLoc(), diag::err_template_variable)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+ }
+ }
+
// The variable can not
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
II, R, SC,
@@ -2209,8 +2241,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else {
// FIXME: Handle function template specializations
}
- }
-
+ }
// C++ [dcl.fct.spec]p5:
// The virtual specifier shall only be used in declarations of
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
new file mode 100644
index 0000000000..41d5f1baae
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ static T value;
+};
+
+template<typename T>
+T X0<T>::value = 0;
+
+struct X1 {
+ X1(int);
+};
+
+struct X2 { };
+
+int& get_int() { return X0<int>::value; }
+X1& get_X1() { return X0<X1>::value; }
+
+double*& get_double_ptr() { return X0<int*>::value; } // expected-error{{initialized}}
+
+X2& get_X2() {
+ return X0<X2>::value; // FIXME: instantiation should fail!
+}
+
+template<typename T> T x; // expected-error{{variable 'x' declared as a template}} \ No newline at end of file
diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp
index 6955018790..b7117cd8d6 100644
--- a/test/Parser/cxx-template-decl.cpp
+++ b/test/Parser/cxx-template-decl.cpp
@@ -5,7 +5,8 @@ export class foo { }; // expected-error {{expected template}}
template x; // expected-error {{C++ requires a type specifier for all declarations}}
export template x; // expected-error {{expected '<' after 'template'}} \
// expected-note {{exported templates are unsupported}} \
-// expected-error {{C++ requires a type specifier for all declarations}}
+// expected-error {{C++ requires a type specifier for all declarations}} \
+// expected-error {{declared as a template}}
// See Sema::ParsedFreeStandingDeclSpec about the double diagnostic. This is
// because ParseNonTypeTemplateParameter starts parsing a DeclSpec.
template < ; // expected-error {{parse error}} expected-error {{declaration does not declare anything}}