OSDN Git Service

PR c++/13969
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Feb 2004 18:35:18 +0000 (18:35 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Feb 2004 18:35:18 +0000 (18:35 +0000)
* g++.dg/template/static6.C: New test.

PR c++/13969
* cp-tree.h (fold_non_dependent_expr): New function.
* parser.c (cp_parser_fold_non_dependent_expr): Remove.
(cp_parser_template_argument): Use fold_non_dependent_expr.
(cp_parser_direct_declarator): Likewise.
* pt.c (fold_non_dependent_expr): New function.
(convert_nontype_argument): Use it.
(tsubst_qualified_id): Simplify.
(tsubst_copy_and_build): Likewise.

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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/static6.C [new file with mode: 0644]

index 4ef866f..ec034bc 100644 (file)
@@ -1,5 +1,17 @@
 2004-02-04  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/13969
+       * cp-tree.h (fold_non_dependent_expr): New function.
+       * parser.c (cp_parser_fold_non_dependent_expr): Remove.
+       (cp_parser_template_argument): Use fold_non_dependent_expr.
+       (cp_parser_direct_declarator): Likewise.
+       * pt.c (fold_non_dependent_expr): New function.
+       (convert_nontype_argument): Use it.
+       (tsubst_qualified_id): Simplify.
+       (tsubst_copy_and_build): Likewise.
+
+2004-02-04  Mark Mitchell  <mark@codesourcery.com>
+
        * decl.c (cxx_push_function_context): Do not set
        current_function_is_thunk.
        * method.c (use_thunk): Set CALL_FROM_THUNK on the call to the
index 5e64578..64b9549 100644 (file)
@@ -3927,6 +3927,7 @@ extern tree template_for_substitution           (tree);
 extern tree build_non_dependent_expr            (tree);
 extern tree build_non_dependent_args            (tree);
 extern bool reregister_specialization           (tree, tree, tree);
+extern tree fold_non_dependent_expr             (tree);
 
 /* in repo.c */
 extern void repo_template_used (tree);
index 4905b94..4ee1aa6 100644 (file)
@@ -1669,8 +1669,6 @@ static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
-static tree cp_parser_fold_non_dependent_expr
-  (tree);
 static bool cp_parser_friend_p
   (tree);
 static cp_token *cp_parser_require
@@ -8411,7 +8409,7 @@ cp_parser_template_argument (cp_parser* parser)
   argument = cp_parser_constant_expression (parser, 
                                            /*allow_non_constant_p=*/false,
                                            /*non_constant_p=*/NULL);
-  argument = cp_parser_fold_non_dependent_expr (argument);
+  argument = fold_non_dependent_expr (argument);
   if (!maybe_type_id)
     return argument;
   if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -10417,7 +10415,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                                                 /*allow_non_constant=*/true,
                                                 &non_constant_p);
              if (!non_constant_p)
-               bounds = cp_parser_fold_non_dependent_expr (bounds);
+               bounds = fold_non_dependent_expr (bounds);
            }
          else
            bounds = NULL_TREE;
@@ -14734,37 +14732,6 @@ cp_parser_declares_only_class_p (cp_parser *parser)
          || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
-/* Simplify EXPR if it is a non-dependent expression.  Returns the
-   (possibly simplified) expression.  */
-
-static tree
-cp_parser_fold_non_dependent_expr (tree expr)
-{
-  /* If we're in a template, but EXPR isn't value dependent, simplify
-     it.  We're supposed to treat:
-     
-       template <typename T> void f(T[1 + 1]);
-       template <typename T> void f(T[2]);
-                  
-     as two declarations of the same function, for example.  */
-  if (processing_template_decl
-      && !type_dependent_expression_p (expr)
-      && !value_dependent_expression_p (expr))
-    {
-      HOST_WIDE_INT saved_processing_template_decl;
-
-      saved_processing_template_decl = processing_template_decl;
-      processing_template_decl = 0;
-      expr = tsubst_copy_and_build (expr,
-                                   /*args=*/NULL_TREE,
-                                   tf_error,
-                                   /*in_decl=*/NULL_TREE,
-                                   /*function_p=*/false);
-      processing_template_decl = saved_processing_template_decl;
-    }
-  return expr;
-}
-
 /* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
    Returns TRUE iff `friend' appears among the DECL_SPECIFIERS.  */
 
index 7040138..b7d794e 100644 (file)
@@ -3099,20 +3099,60 @@ redeclare_class_template (tree type, tree parms)
     }
 }
 
+/* Simplify EXPR if it is a non-dependent expression.  Returns the
+   (possibly simplified) expression.  */
+
+tree
+fold_non_dependent_expr (tree expr)
+{
+  /* If we're in a template, but EXPR isn't value dependent, simplify
+     it.  We're supposed to treat:
+     
+       template <typename T> void f(T[1 + 1]);
+       template <typename T> void f(T[2]);
+                  
+     as two declarations of the same function, for example.  */
+  if (processing_template_decl
+      && !type_dependent_expression_p (expr)
+      && !value_dependent_expression_p (expr))
+    {
+      HOST_WIDE_INT saved_processing_template_decl;
+
+      saved_processing_template_decl = processing_template_decl;
+      processing_template_decl = 0;
+      expr = tsubst_copy_and_build (expr,
+                                   /*args=*/NULL_TREE,
+                                   tf_error,
+                                   /*in_decl=*/NULL_TREE,
+                                   /*function_p=*/false);
+      processing_template_decl = saved_processing_template_decl;
+    }
+  return expr;
+}
+
 /* Attempt to convert the non-type template parameter EXPR to the
    indicated TYPE.  If the conversion is successful, return the
    converted value.  If the conversion is unsuccessful, return
    NULL_TREE if we issued an error message, or error_mark_node if we
    did not.  We issue error messages for out-and-out bad template
    parameters, but not simply because the conversion failed, since we
-   might be just trying to do argument deduction.  By the time this
-   function is called, neither TYPE nor EXPR may make use of template
-   parameters.  */
+   might be just trying to do argument deduction.  Both TYPE and EXPR
+   must be non-dependent.  */
 
 static tree
 convert_nontype_argument (tree type, tree expr)
 {
-  tree expr_type = TREE_TYPE (expr);
+  tree expr_type;
+
+  /* If we are in a template, EXPR may be non-dependent, but still
+     have a syntactic, rather than semantic, form.  For example, EXPR
+     might be a SCOPE_REF, rather than the VAR_DECL to which the
+     SCOPE_REF refers.  Preserving the qualifying scope is necessary
+     so that access checking can be performed when the template is
+     instantiated -- but here we need the resolved form so that we can
+     convert the argument.  */
+  expr = fold_non_dependent_expr (expr);
+  expr_type = TREE_TYPE (expr);
 
   /* A template-argument for a non-type, non-template
      template-parameter shall be one of:
@@ -3136,12 +3176,31 @@ convert_nontype_argument (tree type, tree expr)
      --a pointer to member expressed as described in _expr.unary.op_.  */
 
   /* An integral constant-expression can include const variables or
-     enumerators.  Simplify things by folding them to their values,
+.     enumerators.  Simplify things by folding them to their values,
      unless we're about to bind the declaration to a reference
      parameter.  */
-  if (INTEGRAL_TYPE_P (expr_type)
-      && TREE_CODE (type) != REFERENCE_TYPE)
-    expr = decl_constant_value (expr);
+  if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
+    while (true) 
+      {
+       tree const_expr = decl_constant_value (expr);
+       /* In a template, the initializer for a VAR_DECL may not be
+          marked as TREE_CONSTANT, in which case decl_constant_value
+          will not return the initializer.  Handle that special case
+          here.  */
+       if (expr == const_expr
+           && TREE_CODE (expr) == VAR_DECL
+           && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr)
+           && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr))
+           /* DECL_INITIAL can be NULL if we are processing a
+              variable initialized to an expression involving itself.
+              We know it is initialized to a constant -- but not what
+              constant, yet.  */
+           && DECL_INITIAL (expr))
+         const_expr = DECL_INITIAL (expr);
+       if (expr == const_expr)
+         break;
+       expr = fold_non_dependent_expr (const_expr);
+      }
 
   if (is_overloaded_fn (expr))
     /* OK for now.  We'll check that it has external linkage later.
@@ -7279,11 +7338,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
   
   /* Remember that there was a reference to this entity.  */
   if (DECL_P (expr))
-    {
-      mark_used (expr);
-      if (!args && TREE_CODE (expr) == VAR_DECL)
-       expr = DECL_INITIAL (expr);
-    }
+    mark_used (expr);
 
   if (is_template)
     expr = lookup_template_function (expr, template_args);
@@ -8485,11 +8540,6 @@ tsubst_copy_and_build (tree t,
     case VAR_DECL:
       if (args)
        t = tsubst_copy (t, args, complain, in_decl);
-      else
-       /* If there are no ARGS, then we are evaluating a
-          non-dependent expression.  If the expression is
-          non-dependent, the variable must be a constant.  */
-       t = DECL_INITIAL (t);
       return convert_from_reference (t);
 
     case VA_ARG_EXPR:
index 28dc9cf..def7ad6 100644 (file)
@@ -1,3 +1,8 @@
+2004-02-04  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/13969
+       * g++.dg/template/static6.C: New test.
+
 2004-02-04  Ian Lance Taylor  <ian@wasabisystems.com>
 
        * gcc.dg/arm-mmx-1.c: Don't look for ldmfd if -mthumb.
diff --git a/gcc/testsuite/g++.dg/template/static6.C b/gcc/testsuite/g++.dg/template/static6.C
new file mode 100644 (file)
index 0000000..30ecae9
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/13969
+
+struct B { 
+  static const int N=10; 
+}; 
+template <int> struct X {}; 
+template <typename> struct S { 
+  static const int N = B::N; 
+  X<N> x; 
+}; 
+template class S<float>;