OSDN Git Service

PR c++/11094, DR 408
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 2010 15:55:20 +0000 (15:55 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 2010 15:55:20 +0000 (15:55 +0000)
* cp-tree.h (VAR_HAD_UNKNOWN_BOUND, SET_VAR_HAD_UNKNOWN_BOUND): New.
* decl2.c (finish_static_data_member_decl): Set it.
* decl.c (duplicate_decls): Propagate it.
* pt.c (tsubst_decl): Don't substitute the domain of an array
VAR_DECL if it's set.
(regenerate_decl_from_template): Substitute it here.
(type_dependent_expression_p): Return true if it's set.
* semantics.c (finish_decltype_type): Instantiate such a variable.
* typeck.c (cxx_sizeof_expr): Likewise.
(strip_array_domain): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158075 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/dr408.C [new file with mode: 0644]

index c044294..4ea2565 100644 (file)
@@ -1,5 +1,17 @@
 2010-04-07  Jason Merrill  <jason@redhat.com>
 
+       PR c++/11094, DR 408
+       * cp-tree.h (VAR_HAD_UNKNOWN_BOUND, SET_VAR_HAD_UNKNOWN_BOUND): New.
+       * decl2.c (finish_static_data_member_decl): Set it.
+       * decl.c (duplicate_decls): Propagate it.
+       * pt.c (tsubst_decl): Don't substitute the domain of an array
+       VAR_DECL if it's set.
+       (regenerate_decl_from_template): Substitute it here.
+       (type_dependent_expression_p): Return true if it's set.
+       * semantics.c (finish_decltype_type): Instantiate such a variable.
+       * typeck.c (cxx_sizeof_expr): Likewise.
+       (strip_array_domain): New.
+
        * name-lookup.c (current_decl_namespace): Non-static.
        (pop_nested_namespace): Sanity check.
        * cp-tree.h: Declare current_decl_namespace.
index f71317b..941c49a 100644 (file)
@@ -1758,7 +1758,7 @@ struct GTY(()) lang_decl_base {
   unsigned threadprivate_or_deleted_p : 1; /* var or fn */
   unsigned anticipated_p : 1;             /* fn or type */
   unsigned friend_attr : 1;               /* fn or type */
-  unsigned template_conv_p : 1;                   /* template only? */
+  unsigned template_conv_p : 1;                   /* var or template */
   unsigned odr_used : 1;                  /* var or fn */
   unsigned u2sel : 1;
   /* 1 spare bit */
@@ -2088,6 +2088,15 @@ struct GTY(()) lang_decl {
 #define DECL_TEMPLATE_CONV_FN_P(NODE) \
   (DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE))->u.base.template_conv_p)
 
+/* Nonzero if NODE, a static data member, was declared in its class as an
+   array of unknown bound.  */
+#define VAR_HAD_UNKNOWN_BOUND(NODE)                    \
+  (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))          \
+   ? DECL_LANG_SPECIFIC (NODE)->u.base.template_conv_p \
+   : false)
+#define SET_VAR_HAD_UNKNOWN_BOUND(NODE) \
+  (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.template_conv_p = true)
+
 /* Set the overloaded operator code for NODE to CODE.  */
 #define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
   (LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
@@ -5393,6 +5402,7 @@ extern tree composite_pointer_type                (tree, tree, tree, tree,
                                                 composite_pointer_operation, 
                                                 tsubst_flags_t);
 extern tree merge_types                                (tree, tree);
+extern tree strip_array_domain                 (tree);
 extern tree check_return_expr                  (tree, bool *);
 extern tree cp_build_binary_op                  (location_t,
                                                 enum tree_code, tree, tree,
index bfbe3ca..7a82ed6 100644 (file)
@@ -1929,6 +1929,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          if (DECL_VIRTUAL_P (newdecl))
            DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
        }
+      /* Only variables have this field.  */
+      else if (TREE_CODE (newdecl) == VAR_DECL
+              && VAR_HAD_UNKNOWN_BOUND (olddecl))
+       SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
index 90adc68..d811c9e 100644 (file)
@@ -785,6 +785,10 @@ finish_static_data_member_decl (tree decl,
   DECL_INITIAL (decl) = init;
   DECL_IN_AGGR_P (decl) = 1;
 
+  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+      && TYPE_DOMAIN (TREE_TYPE (decl)) == NULL_TREE)
+    SET_VAR_HAD_UNKNOWN_BOUND (decl);
+
   cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
 }
 
index 1c0e13e..367608f 100644 (file)
@@ -9496,6 +9496,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              type = DECL_ORIGINAL_TYPE (t);
            else
              type = TREE_TYPE (t);
+           if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
+             type = strip_array_domain (type);
            type = tsubst (type, args, complain, in_decl);
          }
        if (TREE_CODE (r) == VAR_DECL)
@@ -16456,10 +16458,15 @@ regenerate_decl_from_template (tree decl, tree tmpl)
        DECL_DECLARED_INLINE_P (decl) = 1;
     }
   else if (TREE_CODE (decl) == VAR_DECL)
-    DECL_INITIAL (decl) =
-      tsubst_expr (DECL_INITIAL (code_pattern), args,
-                  tf_error, DECL_TI_TEMPLATE (decl),
-                  /*integral_constant_expression_p=*/false);
+    {
+      DECL_INITIAL (decl) =
+       tsubst_expr (DECL_INITIAL (code_pattern), args,
+                    tf_error, DECL_TI_TEMPLATE (decl),
+                    /*integral_constant_expression_p=*/false);
+      if (VAR_HAD_UNKNOWN_BOUND (decl))
+       TREE_TYPE (decl) = tsubst (TREE_TYPE (code_pattern), args,
+                                  tf_error, DECL_TI_TEMPLATE (decl));
+    }
   else
     gcc_unreachable ();
 
@@ -17730,6 +17737,15 @@ type_dependent_expression_p (tree expression)
       return false;
     }
 
+  /* A static data member of the current instantiation with incomplete
+     array type is type-dependent, as the definition and specializations
+     can have different bounds.  */
+  if (TREE_CODE (expression) == VAR_DECL
+      && DECL_CLASS_SCOPE_P (expression)
+      && dependent_type_p (DECL_CONTEXT (expression))
+      && VAR_HAD_UNKNOWN_BOUND (expression))
+    return true;
+
   if (TREE_TYPE (expression) == unknown_type_node)
     {
       if (TREE_CODE (expression) == ADDR_EXPR)
index 5cf4b69..d425402 100644 (file)
@@ -4836,6 +4836,14 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
   /* The type denoted by decltype(e) is defined as follows:  */
 
   expr = resolve_nondeduced_context (expr);
+
+  /* To get the size of a static data member declared as an array of
+     unknown bound, we need to instantiate it.  */
+  if (TREE_CODE (expr) == VAR_DECL
+      && VAR_HAD_UNKNOWN_BOUND (expr)
+      && DECL_TEMPLATE_INSTANTIATION (expr))
+    instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false);
+
   if (id_expression_or_member_access_p)
     {
       /* If e is an id-expression or a class member access (5.2.5
index 4b91912..f623717 100644 (file)
@@ -878,6 +878,19 @@ merge_types (tree t1, tree t2)
     return cp_build_type_attribute_variant (t1, attributes);
 }
 
+/* Return the ARRAY_TYPE type without its domain.  */
+
+tree
+strip_array_domain (tree type)
+{
+  tree t2;
+  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+  if (TYPE_DOMAIN (type) == NULL_TREE)
+    return type;
+  t2 = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
+  return cp_build_type_attribute_variant (t2, TYPE_ATTRIBUTES (type));
+}
+
 /* Wrapper around cp_common_type that is used by c-common.c and other
    front end optimizations that remove promotions.  
 
@@ -1596,6 +1609,13 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
       return e;
     }
 
+  /* To get the size of a static data member declared as an array of
+     unknown bound, we need to instantiate it.  */
+  if (TREE_CODE (e) == VAR_DECL
+      && VAR_HAD_UNKNOWN_BOUND (e)
+      && DECL_TEMPLATE_INSTANTIATION (e))
+    instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
+
   if (TREE_CODE (e) == COMPONENT_REF
       && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
       && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
index 4156ad4..32c64b3 100644 (file)
@@ -1,5 +1,7 @@
 2010-04-07  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/template/dr408.C: New.
+
        * g++.dg/lookup/ns4.C: New.
 
        PR c++/38392
diff --git a/gcc/testsuite/g++.dg/template/dr408.C b/gcc/testsuite/g++.dg/template/dr408.C
new file mode 100644 (file)
index 0000000..d118ce4
--- /dev/null
@@ -0,0 +1,45 @@
+// DR 408
+// { dg-do link }
+
+// Test that a size given in the out-of-class definition isn't used until
+// instantiation time.
+template<typename T>
+struct X
+{
+  static char s[];
+  int c;
+};
+
+template<typename T>
+char X<T>::s[sizeof(X<T>)];
+
+#define sassert(EXP) int ar[(EXP)?1:-1]
+sassert(sizeof (X<char>::s) == sizeof (int));
+
+// Test that a specialization can have a different size.
+
+template <int> void g();
+template <> void g<2>() { }
+
+template <typename T>
+struct S {
+  static int i[];
+  void f();
+};
+
+template <typename T>
+int S<T>::i[] = { 1 };
+
+template <typename T>
+void S<T>::f() {
+  g<sizeof (i) / sizeof (int)>();
+}
+
+template <>
+int S<int>::i[] = { 1, 2 };
+
+int main()
+{
+  S<int> s;
+  s.f();
+}