Implement parsing and semantic analysis for out-of-line definitions of static
authorDouglas Gregor <dgregor@apple.com>
Wed, 22 Jul 2009 17:18:37 +0000 (17:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 22 Jul 2009 17:18:37 +0000 (17:18 +0000)
data members of class templates. We don't instantiate the definitions yet,
however.

llvm-svn: 76756

clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp [new file with mode: 0644]
clang/test/Parser/cxx-template-decl.cpp

index 3553a03..4cd1dca 100644 (file)
@@ -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 "
index 22e4323..7f652f2 100644 (file)
@@ -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);
index 283033b..beceeef 100644 (file)
@@ -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/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
new file mode 100644 (file)
index 0000000..41d5f1b
--- /dev/null
@@ -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
index 6955018..b7117cd 100644 (file)
@@ -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}}