diff mbox

C++ PATCH for c++/47956 (missing diagnostic for non-const static)

Message ID 4DDF2218.7050704@redhat.com
State New
Headers show

Commit Message

Jason Merrill May 27, 2011, 4:01 a.m. UTC
struct A { static auto i = 42; };

is ill-formed because i is non-const, but we weren't noticing that 
because we were checking it before replacing the auto.  Fixed by moving 
the check into cp_finish_decl.

It also seems we were incorrectly setting DECL_INITIALIZED_IN_CLASS for 
some template static data members; I had to fix that to avoid testsuite 
regressions.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 5719ff482f5048956429380ed6938e88c56d0962
Author: Jason Merrill <jason@redhat.com>
Date:   Thu May 26 14:44:27 2011 -0400

    	PR c++/47956
    	* decl.c (check_static_variable_definition): Now static.
    	(cp_finish_decl): Call it here.
    	(grokdeclarator): Not here.
    	* pt.c (instantiate_class_template_1): Or here.
    	* cp-tree.h: Don't declare it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ada01fb..a01253e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4895,7 +4895,6 @@  extern void finish_stmt				(void);
 extern tree static_fn_type			(tree);
 extern void revert_static_member_fn		(tree);
 extern void fixup_anonymous_aggr		(tree);
-extern int check_static_variable_definition	(tree, tree);
 extern tree compute_array_index_type		(tree, tree, tsubst_flags_t);
 extern tree check_default_argument		(tree, tree);
 typedef int (*walk_namespaces_fn)		(tree, void *);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a956dbb..a524880 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -74,6 +74,7 @@  static void push_local_name (tree);
 static tree grok_reference_init (tree, tree, tree, tree *);
 static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
 			 int, int, tree);
+static int check_static_variable_definition (tree, tree);
 static void record_unknown_type (tree, const char *);
 static tree builtin_function_1 (tree, tree, bool);
 static tree build_library_fn_1 (tree, enum tree_code, tree);
@@ -5909,6 +5910,7 @@  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
   if (current_class_type
       && CP_DECL_CONTEXT (decl) == current_class_type
       && TYPE_BEING_DEFINED (current_class_type)
+      && !CLASSTYPE_TEMPLATE_INSTANTIATION (current_class_type)
       && (DECL_INITIAL (decl) || init))
     DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
 
@@ -5939,6 +5941,11 @@  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
   if (!ensure_literal_type_for_constexpr_object (decl))
     DECL_DECLARED_CONSTEXPR_P (decl) = 0;
 
+  if (TREE_CODE (decl) == VAR_DECL
+      && DECL_CLASS_SCOPE_P (decl)
+      && DECL_INITIALIZED_IN_CLASS_P (decl))
+    check_static_variable_definition (decl, type);
+
   if (init && TREE_CODE (decl) == FUNCTION_DECL)
     {
       tree clone;
@@ -7640,9 +7647,12 @@  build_ptrmem_type (tree class_type, tree member_type)
    messages.  Return 1 if the definition is particularly bad, or 0
    otherwise.  */
 
-int
+static int
 check_static_variable_definition (tree decl, tree type)
 {
+  /* Can't check yet if we don't know the type.  */
+  if (dependent_type_p (type))
+    return 0;
   /* If DECL is declared constexpr, we'll do the appropriate checks
      in check_initializer.  */
   if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
@@ -10025,21 +10035,6 @@  grokdeclarator (const cp_declarator *declarator,
 			staticp = 1;
 		      }
 		  }
-
-		if (uses_template_parms (type))
-		  /* We'll check at instantiation time.  */
-		  ;
-		else if (constexpr_p)
-		  /* constexpr has the same requirements.  */
-		  ;
-		else if (check_static_variable_definition (unqualified_id,
-							   type))
-		  /* If we just return the declaration, crashes
-		     will sometimes occur.  We therefore return
-		     void_type_node, as if this was a friend
-		     declaration, to cause callers to completely
-		     ignore this declaration.  */
-		  return error_mark_node;
 	      }
 
 	    if (staticp)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ab48c8f..3b26700 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8414,8 +8414,6 @@  instantiate_class_template_1 (tree type)
 			 /*init_const_expr_p=*/false,
 			 /*asmspec_tree=*/NULL_TREE,
 			 /*flags=*/0);
-		      if (DECL_INITIALIZED_IN_CLASS_P (r))
-			check_static_variable_definition (r, TREE_TYPE (r));
 		    }
 		  else if (TREE_CODE (r) == FIELD_DECL)
 		    {
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto7.C b/gcc/testsuite/g++.dg/cpp0x/auto7.C
index 9ef5a80..e7ab723 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto7.C
@@ -7,7 +7,7 @@  auto j;			// { dg-error "has no initializer" }
 
 template<int> struct A
 {
-  static auto k = 7;
+  static auto k = 7;	// { dg-error "non-const" }
   static auto l;	// { dg-error "has no initializer" }
   auto m;		// { dg-error "has no initializer" }
 };
diff --git a/gcc/testsuite/g++.dg/template/crash50.C b/gcc/testsuite/g++.dg/template/crash50.C
index 0060561..286685a 100644
--- a/gcc/testsuite/g++.dg/template/crash50.C
+++ b/gcc/testsuite/g++.dg/template/crash50.C
@@ -3,5 +3,5 @@ 
 
 struct A
 {
-  template<int> void* foo(; // { dg-error "primary-expression|initialization|static" }
+  template<int> void* foo(; // { dg-error "primary-expression|initialization|static|template" }
 };
diff --git a/gcc/testsuite/g++.dg/template/static9.C b/gcc/testsuite/g++.dg/template/static9.C
index 8845647..ab70101 100644
--- a/gcc/testsuite/g++.dg/template/static9.C
+++ b/gcc/testsuite/g++.dg/template/static9.C
@@ -3,7 +3,6 @@ 
 template<typename T> struct A
 {
   static const T i = 0; // { dg-error "declared void" "void" }
-			// { dg-error "invalid|non-literal" "invalid" { target *-*-* } 5 }
 };
 
 A<void> a; // { dg-message "instantiated" }
diff --git a/gcc/testsuite/g++.old-deja/g++.ext/memconst.C b/gcc/testsuite/g++.old-deja/g++.ext/memconst.C
index 7dd2df7..d934763 100644
--- a/gcc/testsuite/g++.old-deja/g++.ext/memconst.C
+++ b/gcc/testsuite/g++.old-deja/g++.ext/memconst.C
@@ -21,5 +21,5 @@  public:
 void
 foo::bar ()
 {
-    qwerty QWERTY ((unsigned short*)dummy_key); // { dg-error "" } 
+    qwerty QWERTY ((unsigned short*)dummy_key);
 }