OSDN Git Service

PR c++/28341
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Aug 2006 23:53:10 +0000 (23:53 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Aug 2006 23:53:10 +0000 (23:53 +0000)
* tree.c (cast_valid_in_integral_constant_expression_p): New
function.
* cp-tree.h (tsubst_copy_and_build): Adjust prototype.
* pt.c (tsubst_expr): Add integral_constant_expression_p
parameter.
(fold_non_dependent_expr): Adjust callers of
tsubst_{expr,copy_and_build}.
(tsubst_friend_function): Likewise.
(tsubst_template_arg): Likewise.
(tsubst_default_argument): Likewise.
(tsubst_decl): Likewise.
(tsubst): Likewise.
(tsubst_omp_clasuses): Likewise.
(regenerate_decl_fromp_template): Likewise.
(instantiate_decl): Likewise.
(tsubst_initializer_list): Likewise.
(tsubst_enum): Likewise.
(tsubst_expr): Use RECUR throughout.
(tsubst_copy_and_build): Change definition of RECUR.  Do not allow
invalid casts in integral constant expressions.
* parser.c (cp_parser_postfix_expression): Use
cast_valid_in_integral_constant_expression_p.
(cp_parser_cast_expression): Likewise.
(cp_parser_functional_cast): Likewise.

PR c++/28346
* pt.c (tsubst_qualified_id): Do not strip references from
OFFSET_REFs.

2006-08-20  Mark Mitchell  <mark@codesourcery.com>

PR c++/28341
* g++.dg/template/ref3.C: New test.
* g++.dg/template/nontype13.C: New test.

PR c++/28346
* g++.dg/template/ptrmem17.C: New test.

2006-08-20  Mark Mitchell  <mark@codesourcery.com>

* objcp-lang.c (objcp_tsubst_copy_and_build): Adjust call to
tsubst_copy_and_build.

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

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

index 8f767b0..6fd125a 100644 (file)
@@ -1,3 +1,35 @@
+2006-08-20  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/28341
+       * tree.c (cast_valid_in_integral_constant_expression_p): New
+       function.
+       * cp-tree.h (tsubst_copy_and_build): Adjust prototype.
+       * pt.c (tsubst_expr): Add integral_constant_expression_p
+       parameter.
+       (fold_non_dependent_expr): Adjust callers of
+       tsubst_{expr,copy_and_build}.
+       (tsubst_friend_function): Likewise.
+       (tsubst_template_arg): Likewise.
+       (tsubst_default_argument): Likewise.
+       (tsubst_decl): Likewise.
+       (tsubst): Likewise.
+       (tsubst_omp_clasuses): Likewise.
+       (regenerate_decl_fromp_template): Likewise.
+       (instantiate_decl): Likewise.
+       (tsubst_initializer_list): Likewise.
+       (tsubst_enum): Likewise.
+       (tsubst_expr): Use RECUR throughout.
+       (tsubst_copy_and_build): Change definition of RECUR.  Do not allow
+       invalid casts in integral constant expressions.
+       * parser.c (cp_parser_postfix_expression): Use
+       cast_valid_in_integral_constant_expression_p.
+       (cp_parser_cast_expression): Likewise.
+       (cp_parser_functional_cast): Likewise.
+
+       PR c++/28346
+       * pt.c (tsubst_qualified_id): Do not strip references from
+       OFFSET_REFs. 
+
 2006-08-17  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/28606
index 040dd90..79018a4 100644 (file)
@@ -4117,7 +4117,7 @@ extern void print_candidates                      (tree);
 extern void instantiate_pending_templates      (int);
 extern tree tsubst_default_argument            (tree, tree, tree);
 extern tree tsubst_copy_and_build              (tree, tree, tsubst_flags_t,
-                                                tree, bool);
+                                                tree, bool, bool);
 extern tree most_general_template              (tree);
 extern tree get_mostly_instantiated_function_type (tree);
 extern int problematic_instantiation_changed   (void);
@@ -4391,6 +4391,7 @@ extern tree fold_if_not_in_template               (tree);
 extern tree rvalue                             (tree);
 extern tree convert_bitfield_to_declared_type   (tree);
 extern tree cp_save_expr                       (tree);
+extern bool cast_valid_in_integral_constant_expression_p (tree);
 
 /* in typeck.c */
 extern int string_conv_p                       (tree, tree, int);
index 78e6eb6..d015ae1 100644 (file)
@@ -4004,9 +4004,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
 
        /* Only type conversions to integral or enumeration types
           can be used in constant-expressions.  */
-       if (parser->integral_constant_expression_p
-           && !dependent_type_p (type)
-           && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+       if (!cast_valid_in_integral_constant_expression_p (type)
            && (cp_parser_non_integral_constant_expression
                (parser,
                 "a cast to a type other than an integral or "
@@ -5490,9 +5488,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
 
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
-         if (parser->integral_constant_expression_p
-             && !dependent_type_p (type)
-             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+         if (!cast_valid_in_integral_constant_expression_p (type)
              && (cp_parser_non_integral_constant_expression
                  (parser,
                   "a cast to a type other than an integral or "
@@ -15695,13 +15691,11 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
      conversions to integral or enumeration type can be used".  */
   if (TREE_CODE (type) == TYPE_DECL)
     type = TREE_TYPE (type);
-  if (cast != error_mark_node && !dependent_type_p (type)
-      && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-    {
-      if (cp_parser_non_integral_constant_expression
-         (parser, "a call to a constructor"))
-       return error_mark_node;
-    }
+  if (cast != error_mark_node
+      && !cast_valid_in_integral_constant_expression_p (type)
+      && (cp_parser_non_integral_constant_expression
+         (parser, "a call to a constructor")))
+    return error_mark_node;
   return cast;
 }
 
index c9e28c8..4a58ef3 100644 (file)
@@ -159,7 +159,7 @@ static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
 static int eq_local_specializations (const void *, const void *);
 static bool dependent_type_p_r (tree);
 static tree tsubst (tree, tree, tsubst_flags_t, tree);
-static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree, bool);
 static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
 
 /* Make the current scope suitable for access checking when we are
@@ -3400,7 +3400,8 @@ fold_non_dependent_expr (tree expr)
                                    /*args=*/NULL_TREE,
                                    tf_error,
                                    /*in_decl=*/NULL_TREE,
-                                   /*function_p=*/false);
+                                   /*function_p=*/false,
+                                   /*integral_constant_expression_p=*/true);
       processing_template_decl = saved_processing_template_decl;
     }
   return expr;
@@ -5225,7 +5226,8 @@ tsubst_friend_function (tree decl, tree args)
         current cless with same name.  */
       push_nested_namespace (ns);
       fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
-                        tf_warning_or_error, NULL_TREE);
+                        tf_warning_or_error, NULL_TREE,
+                        /*integral_constant_expression_p=*/false);
       pop_nested_namespace (ns);
       arglist = tsubst (DECL_TI_ARGS (decl), args,
                        tf_warning_or_error, NULL_TREE);
@@ -6035,7 +6037,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     r = tsubst (t, args, complain, in_decl);
   else
     {
-      r = tsubst_expr (t, args, complain, in_decl);
+      r = tsubst_expr (t, args, complain, in_decl,
+                      /*integral_constant_expression_p=*/true);
       r = fold_non_dependent_expr (r);
     }
   return r;
@@ -6260,7 +6263,8 @@ tsubst_default_argument (tree fn, tree type, tree arg)
      stack.  */
   ++function_depth;
   arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
-                    tf_warning_or_error, NULL_TREE);
+                    tf_warning_or_error, NULL_TREE,
+                    /*integral_constant_expression_p=*/false);
   --function_depth;
   pop_deferring_access_checks();
 
@@ -6721,10 +6725,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        TREE_TYPE (r) = type;
        cp_apply_type_quals_to_decl (cp_type_quals (type), r);
 
+       /* DECL_INITIAL gives the number of bits in a bit-field.  */
+       DECL_INITIAL (r)
+         = tsubst_expr (DECL_INITIAL (t), args,
+                        complain, in_decl,
+                        /*integral_constant_expression_p=*/true);
        /* We don't have to set DECL_CONTEXT here; it is set by
           finish_member_declaration.  */
-       DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
-                                       complain, in_decl);
        TREE_CHAIN (r) = NULL_TREE;
        if (VOID_TYPE_P (type))
          error ("instantiation of %q+D as type %qT", r, type);
@@ -6852,7 +6859,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            if (DECL_HAS_VALUE_EXPR_P (t))
              {
                tree ve = DECL_VALUE_EXPR (t);
-               ve = tsubst_expr (ve, args, complain, in_decl);
+               ve = tsubst_expr (ve, args, complain, in_decl,
+                                 /*constant_expression_p=*/false);
                SET_DECL_VALUE_EXPR (r, ve);
              }
          }
@@ -7658,7 +7666,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case ARRAY_REF:
       {
        tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
-       tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
+       tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl,
+                              /*integral_constant_expression_p=*/false);
        if (e1 == error_mark_node || e2 == error_mark_node)
          return error_mark_node;
 
@@ -7680,8 +7689,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree type;
 
-       type = finish_typeof (tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
-                                          complain, in_decl));
+       type = finish_typeof (tsubst_expr 
+                             (TYPEOF_TYPE_EXPR (t), args,
+                              complain, in_decl,
+                              /*integral_constant_expression_p=*/false));
        return cp_build_qualified_type_real (type,
                                             cp_type_quals (t)
                                             | cp_type_quals (type),
@@ -7867,7 +7878,11 @@ tsubst_qualified_id (tree qualified_id, tree args,
               /*template_arg_p=*/false));
     }
 
-  if (TREE_CODE (expr) != SCOPE_REF)
+  /* Expressions do not generally have reference type.  */
+  if (TREE_CODE (expr) != SCOPE_REF
+      /* However, if we're about to form a pointer-to-member, we just
+        want the referenced member referenced.  */
+      && TREE_CODE (expr) != OFFSET_REF)
     expr = convert_from_reference (expr);
 
   return expr;
@@ -8276,7 +8291,8 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
          OMP_CLAUSE_OPERAND (nc, 0)
-           = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
+           = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, 
+                          in_decl, /*integral_constant_expression_p=*/false);
          break;
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
@@ -8305,7 +8321,8 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
 
   if (TREE_CODE (t) != TREE_LIST)
     return tsubst_copy_and_build (t, args, complain, in_decl,
-                                 /*function_p=*/false);
+                                 /*function_p=*/false,
+                                 /*integral_constant_expression_p=*/false);
 
   if (t == void_list_node)
     return t;
@@ -8327,8 +8344,13 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
    processing.  */
 
 static tree
-tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
+            bool integral_constant_expression_p)
 {
+#define RECUR(NODE)                            \
+  tsubst_expr ((NODE), args, complain, in_decl,        \
+              integral_constant_expression_p)
+
   tree stmt, tmp;
 
   if (t == NULL_TREE || t == error_mark_node)
@@ -8345,7 +8367,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree_stmt_iterator i;
        for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
-         tsubst_expr (tsi_stmt (i), args, complain, in_decl);
+         RECUR (tsi_stmt (i));
        break;
       }
 
@@ -8355,12 +8377,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       break;
 
     case RETURN_EXPR:
-      finish_return_stmt (tsubst_expr (TREE_OPERAND (t, 0),
-                                      args, complain, in_decl));
+      finish_return_stmt (RECUR (TREE_OPERAND (t, 0)));
       break;
 
     case EXPR_STMT:
-      tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
+      tmp = RECUR (EXPR_STMT_EXPR (t));
       if (EXPR_STMT_STMT_EXPR_RESULT (t))
        finish_stmt_expr_expr (tmp, cur_stmt_expr);
       else
@@ -8368,8 +8389,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       break;
 
     case USING_STMT:
-      do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t),
-                                      args, complain, in_decl));
+      do_using_directive (RECUR (USING_STMT_NAMESPACE (t)));
       break;
 
     case DECL_EXPR:
@@ -8386,7 +8406,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            tree name = DECL_NAME (decl);
            tree decl;
 
-           scope = tsubst_expr (scope, args, complain, in_decl);
+           scope = RECUR (scope);
            decl = lookup_qualified_name (scope, name,
                                          /*is_type_p=*/false,
                                          /*complain=*/false);
@@ -8425,7 +8445,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                        init = cp_fname_init (name, &TREE_TYPE (decl));
                      }
                    else
-                     init = tsubst_expr (init, args, complain, in_decl);
+                     init = RECUR (init);
                    finish_decl (decl, init, NULL_TREE);
                  }
              }
@@ -8438,43 +8458,43 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
     case FOR_STMT:
       stmt = begin_for_stmt ();
-      tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
+                         RECUR (FOR_INIT_STMT (t));
       finish_for_init_stmt (stmt);
-      tmp = tsubst_expr (FOR_COND (t), args, complain, in_decl);
+      tmp = RECUR (FOR_COND (t));
       finish_for_cond (tmp, stmt);
-      tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
+      tmp = RECUR (FOR_EXPR (t));
       finish_for_expr (tmp, stmt);
-      tsubst_expr (FOR_BODY (t), args, complain, in_decl);
+      RECUR (FOR_BODY (t));
       finish_for_stmt (stmt);
       break;
 
     case WHILE_STMT:
       stmt = begin_while_stmt ();
-      tmp = tsubst_expr (WHILE_COND (t), args, complain, in_decl);
+      tmp = RECUR (WHILE_COND (t));
       finish_while_stmt_cond (tmp, stmt);
-      tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
+      RECUR (WHILE_BODY (t));
       finish_while_stmt (stmt);
       break;
 
     case DO_STMT:
       stmt = begin_do_stmt ();
-      tsubst_expr (DO_BODY (t), args, complain, in_decl);
+      RECUR (DO_BODY (t));
       finish_do_body (stmt);
-      tmp = tsubst_expr (DO_COND (t), args, complain, in_decl);
+      tmp = RECUR (DO_COND (t));
       finish_do_stmt (tmp, stmt);
       break;
 
     case IF_STMT:
       stmt = begin_if_stmt ();
-      tmp = tsubst_expr (IF_COND (t), args, complain, in_decl);
+      tmp = RECUR (IF_COND (t));
       finish_if_stmt_cond (tmp, stmt);
-      tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl);
+      RECUR (THEN_CLAUSE (t));
       finish_then_clause (stmt);
 
       if (ELSE_CLAUSE (t))
        {
          begin_else_clause (stmt);
-         tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl);
+         RECUR (ELSE_CLAUSE (t));
          finish_else_clause (stmt);
        }
 
@@ -8488,7 +8508,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        stmt = begin_compound_stmt (BIND_EXPR_TRY_BLOCK (t)
                                    ? BCS_TRY_BLOCK : 0);
 
-      tsubst_expr (BIND_EXPR_BODY (t), args, complain, in_decl);
+      RECUR (BIND_EXPR_BODY (t));
 
       if (BIND_EXPR_BODY_BLOCK (t))
        finish_function_body (stmt);
@@ -8506,16 +8526,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
     case SWITCH_STMT:
       stmt = begin_switch_stmt ();
-      tmp = tsubst_expr (SWITCH_STMT_COND (t), args, complain, in_decl);
+      tmp = RECUR (SWITCH_STMT_COND (t));
       finish_switch_cond (tmp, stmt);
-      tsubst_expr (SWITCH_STMT_BODY (t), args, complain, in_decl);
+      RECUR (SWITCH_STMT_BODY (t));
       finish_switch_stmt (stmt);
       break;
 
     case CASE_LABEL_EXPR:
-      finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
-                        tsubst_expr (CASE_HIGH (t), args, complain,
-                                     in_decl));
+      finish_case_label (RECUR (CASE_LOW (t)),
+                        RECUR (CASE_HIGH (t)));
       break;
 
     case LABEL_EXPR:
@@ -8528,7 +8547,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        /* Computed goto's must be tsubst'd into.  On the other hand,
           non-computed gotos must not be; the identifier in question
           will have no binding.  */
-       tmp = tsubst_expr (tmp, args, complain, in_decl);
+       tmp = RECUR (tmp);
       else
        tmp = DECL_NAME (tmp);
       finish_goto_stmt (tmp);
@@ -8537,7 +8556,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case ASM_EXPR:
       tmp = finish_asm_stmt
        (ASM_VOLATILE_P (t),
-        tsubst_expr (ASM_STRING (t), args, complain, in_decl),
+        RECUR (ASM_STRING (t)),
         tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
         tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
         tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl));
@@ -8553,11 +8572,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       if (CLEANUP_P (t))
        {
          stmt = begin_try_block ();
-         tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
+         RECUR (TRY_STMTS (t));
          finish_cleanup_try_block (stmt);
-         finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
-                                      complain, in_decl),
-                         stmt);
+         finish_cleanup (RECUR (TRY_HANDLERS (t)), stmt);
        }
       else
        {
@@ -8568,14 +8585,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          else
            stmt = begin_try_block ();
 
-         tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
+         RECUR (TRY_STMTS (t));
 
          if (FN_TRY_BLOCK_P (t))
            finish_function_try_block (stmt);
          else
            finish_try_block (stmt);
 
-         tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
+         RECUR (TRY_HANDLERS (t));
          if (FN_TRY_BLOCK_P (t))
            finish_function_handler_sequence (stmt, compound_stmt);
          else
@@ -8598,7 +8615,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          }
        stmt = begin_handler ();
        finish_handler_parms (decl, stmt);
-       tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
+       RECUR (HANDLER_BODY (t));
        finish_handler (stmt);
       }
       break;
@@ -8611,7 +8628,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
                                args, complain, in_decl);
       stmt = begin_omp_parallel ();
-      tsubst_expr (OMP_PARALLEL_BODY (t), args, complain, in_decl);
+      RECUR (OMP_PARALLEL_BODY (t));
       OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt))
        = OMP_PARALLEL_COMBINED (t);
       break;
@@ -8624,19 +8641,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                                      args, complain, in_decl);
        init = OMP_FOR_INIT (t);
        gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
-       decl = tsubst_expr (TREE_OPERAND (init, 0), args, complain, in_decl);
-       init = tsubst_expr (TREE_OPERAND (init, 1), args, complain, in_decl);
-       cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl);
-       incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl);
+       decl = RECUR (TREE_OPERAND (init, 0));
+       init = RECUR (TREE_OPERAND (init, 1));
+       cond = RECUR (OMP_FOR_COND (t));
+       incr = RECUR (OMP_FOR_INCR (t));
 
        stmt = begin_omp_structured_block ();
 
        pre_body = push_stmt_list ();
-       tsubst_expr (OMP_FOR_PRE_BODY (t), args, complain, in_decl);
+       RECUR (OMP_FOR_PRE_BODY (t));
        pre_body = pop_stmt_list (pre_body);
 
        body = push_stmt_list ();
-       tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl);
+       RECUR (OMP_FOR_BODY (t));
        body = pop_stmt_list (body);
 
        t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
@@ -8652,7 +8669,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_SINGLE:
       tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
       stmt = push_stmt_list ();
-      tsubst_expr (OMP_BODY (t), args, complain, in_decl);
+      RECUR (OMP_BODY (t));
       stmt = pop_stmt_list (stmt);
 
       t = copy_node (t);
@@ -8666,7 +8683,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_MASTER:
     case OMP_ORDERED:
       stmt = push_stmt_list ();
-      tsubst_expr (OMP_BODY (t), args, complain, in_decl);
+      RECUR (OMP_BODY (t));
       stmt = pop_stmt_list (stmt);
 
       t = copy_node (t);
@@ -8677,8 +8694,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_ATOMIC:
       {
        tree op0, op1;
-       op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);
-       op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
+       op0 = RECUR (TREE_OPERAND (t, 0));
+       op1 = RECUR (TREE_OPERAND (t, 1));
        finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
       }
       break;
@@ -8687,10 +8704,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
 
       return tsubst_copy_and_build (t, args, complain, in_decl,
-                                   /*function_p=*/false);
+                                   /*function_p=*/false,
+                                   integral_constant_expression_p);
     }
 
   return NULL_TREE;
+#undef RECUR
 }
 
 /* T is a postfix-expression that is not being used in a function
@@ -8706,7 +8725,8 @@ tsubst_non_call_postfix_expression (tree t, tree args,
                             /*done=*/false, /*address_p=*/false);
   else
     t = tsubst_copy_and_build (t, args, complain, in_decl,
-                              /*function_p=*/false);
+                              /*function_p=*/false,
+                              /*integral_constant_expression_p=*/false);
 
   return t;
 }
@@ -8719,10 +8739,13 @@ tsubst_copy_and_build (tree t,
                       tree args,
                       tsubst_flags_t complain,
                       tree in_decl,
-                      bool function_p)
+                      bool function_p,
+                      bool integral_constant_expression_p)
 {
-#define RECUR(NODE) \
-  tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
+#define RECUR(NODE)                                            \
+  tsubst_copy_and_build (NODE, args, complain, in_decl,        \
+                        /*function_p=*/false,                  \
+                        integral_constant_expression_p)
 
   tree op1;
 
@@ -8757,7 +8780,7 @@ tsubst_copy_and_build (tree t,
 
        decl = finish_id_expression (t, decl, NULL_TREE,
                                     &idk,
-                                    /*integral_constant_expression_p=*/false,
+                                    integral_constant_expression_p,
                                     /*allow_non_integral_constant_expression_p=*/false,
                                     &non_integral_constant_expression_p,
                                     /*template_p=*/false,
@@ -8820,29 +8843,41 @@ tsubst_copy_and_build (tree t,
         RECUR (TREE_OPERAND (t, 0)));
 
     case CAST_EXPR:
-      return build_functional_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case REINTERPRET_CAST_EXPR:
-      return build_reinterpret_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case CONST_CAST_EXPR:
-      return build_const_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case DYNAMIC_CAST_EXPR:
-      return build_dynamic_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case STATIC_CAST_EXPR:
-      return build_static_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
+      {
+       tree type;
+       tree op;
+
+       type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+       if (integral_constant_expression_p
+           && !cast_valid_in_integral_constant_expression_p (type))
+         {
+           error ("a cast to a type other than an integral or "
+                  "enumeration type cannot appear in a constant-expression");
+           return error_mark_node; 
+         }
+
+       op = RECUR (TREE_OPERAND (t, 0));
+
+       switch (TREE_CODE (t))
+         {
+         case CAST_EXPR:
+           return build_functional_cast (type, op);
+         case REINTERPRET_CAST_EXPR:
+           return build_reinterpret_cast (type, op);
+         case CONST_CAST_EXPR:
+           return build_const_cast (type, op);
+         case DYNAMIC_CAST_EXPR:
+           return build_dynamic_cast (type, op);
+         case STATIC_CAST_EXPR:
+           return build_static_cast (type, op);
+         default:
+           gcc_unreachable ();
+         }
+      }
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
@@ -8933,7 +8968,9 @@ tsubst_copy_and_build (tree t,
       else
        {
          ++skip_evaluation;
-         op1 = RECUR (op1);
+         op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+                                      /*function_p=*/false,
+                                      /*integral_constant_expression_p=*/false);
          --skip_evaluation;
        }
       if (TYPE_P (op1))
@@ -9018,7 +9055,9 @@ tsubst_copy_and_build (tree t,
 
            function = tsubst_copy_and_build (function, args, complain,
                                              in_decl,
-                                             !qualified_p);
+                                             !qualified_p,
+                                             integral_constant_expression_p);
+
            if (BASELINK_P (function))
              qualified_p = true;
          }
@@ -9267,7 +9306,8 @@ tsubst_copy_and_build (tree t,
        tree stmt_expr = begin_stmt_expr ();
 
        cur_stmt_expr = stmt_expr;
-       tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+       tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
+                    integral_constant_expression_p);
        stmt_expr = finish_stmt_expr (stmt_expr, false);
        cur_stmt_expr = old_stmt_expr;
 
@@ -11751,7 +11791,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
   else if (TREE_CODE (decl) == VAR_DECL)
     DECL_INITIAL (decl) =
       tsubst_expr (DECL_INITIAL (code_pattern), args,
-                  tf_error, DECL_TI_TEMPLATE (decl));
+                  tf_error, DECL_TI_TEMPLATE (decl),
+                  /*integral_constant_expression_p=*/false);
   else
     gcc_unreachable ();
 
@@ -12000,7 +12041,8 @@ instantiate_decl (tree d, int defer_ok,
          push_nested_class (DECL_CONTEXT (d));
          init = tsubst_expr (DECL_INITIAL (code_pattern),
                              args,
-                             tf_warning_or_error, NULL_TREE);
+                             tf_warning_or_error, NULL_TREE,
+                             /*integral_constant_expression_p=*/false);
          cp_finish_decl (d, init, /*init_const_expr_p=*/false,
                          /*asmspec_tree=*/NULL_TREE,
                          LOOKUP_ONLYCONVERTING);
@@ -12131,7 +12173,8 @@ instantiate_decl (tree d, int defer_ok,
 
       /* Substitute into the body of the function.  */
       tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
-                  tf_warning_or_error, tmpl);
+                  tf_warning_or_error, tmpl,
+                  /*integral_constant_expression_p=*/false);
 
       /* We don't need the local specializations any more.  */
       htab_delete (local_specializations);
@@ -12285,7 +12328,8 @@ tsubst_initializer_list (tree t, tree argvec)
        in_base_initializer = 1;
 
       init = tsubst_expr (TREE_VALUE (t), argvec, tf_warning_or_error,
-                         NULL_TREE);
+                         NULL_TREE, 
+                         /*integral_constant_expression_p=*/false);
       in_base_initializer = 0;
 
       if (decl)
@@ -12329,7 +12373,8 @@ tsubst_enum (tree tag, tree newtag, tree args)
       /* Note that in a template enum, the TREE_VALUE is the
         CONST_DECL, not the corresponding INTEGER_CST.  */
       value = tsubst_expr (DECL_INITIAL (decl),
-                          args, tf_warning_or_error, NULL_TREE);
+                          args, tf_warning_or_error, NULL_TREE,
+                          /*integral_constant_expression_p=*/true);
 
       /* Give this enumeration constant the correct access.  */
       set_current_access_from_decl (decl);
index 53d37be..90839b7 100644 (file)
@@ -2376,6 +2376,17 @@ fold_if_not_in_template (tree expr)
   return fold (expr);
 }
 
+/* Returns true if a cast to TYPE may appear in an integral constant
+   expression.  */
+
+bool
+cast_valid_in_integral_constant_expression_p (tree type)
+{
+  return (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+         || dependent_type_p (type)
+         || type == error_mark_node);
+}
+
 \f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
index c161476..38b9ffe 100644 (file)
@@ -1,3 +1,8 @@
+2006-08-20  Mark Mitchell  <mark@codesourcery.com>
+
+       * objcp-lang.c (objcp_tsubst_copy_and_build): Adjust call to
+       tsubst_copy_and_build.
+
 2006-07-28  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        * Make-lang.in: Use $(HEADER_H) instead of header.h in dependencies.
index 3508185..19a8654 100644 (file)
@@ -110,8 +110,10 @@ tree
 objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, 
                             tree in_decl, bool function_p ATTRIBUTE_UNUSED)
 {
-#define RECURSE(NODE) \
-  tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
+#define RECURSE(NODE)                                                  \
+  tsubst_copy_and_build (NODE, args, complain, in_decl,                \
+                        /*function_p=*/false,                          \
+                        /*integral_constant_expression_p=*/false)
 
   /* The following two can only occur in Objective-C++.  */
 
index abaa9b7..bc920d0 100644 (file)
@@ -1,3 +1,12 @@
+2006-08-20  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/28341
+       * g++.dg/template/ref3.C: New test.
+       * g++.dg/template/nontype13.C: New test.
+
+       PR c++/28346
+       * g++.dg/template/ptrmem17.C: New test.
+
 2006-08-20  Danny Smith  <dannysmith@users.sourceforge.net>
 
        PR target/28648 c:
index 5ff697a..9b76d1a 100644 (file)
@@ -11,7 +11,7 @@ struct Dummy
   template<bool B>
   void tester()
   {
-    bar<evil>()(); // { dg-error "argument" }
+    bar<evil>()(); // { dg-error "constant" }
   }
   template<bool B>
   struct bar
diff --git a/gcc/testsuite/g++.dg/template/ptrmem17.C b/gcc/testsuite/g++.dg/template/ptrmem17.C
new file mode 100644 (file)
index 0000000..154f17a
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/28346
+
+template<int> struct A
+{
+  int& i;
+  A();
+  ~A() { &A::i; } // { dg-error "reference" }
+};
+
+A<0> a; // { dg-error "instantiated" }
diff --git a/gcc/testsuite/g++.dg/template/ref3.C b/gcc/testsuite/g++.dg/template/ref3.C
new file mode 100644 (file)
index 0000000..4390f71
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/28341
+
+template<const int&> struct A {};
+
+template<typename T> struct B
+{
+  A<(T)0> b; // { dg-error "constant" }
+  A<T(0)> a; // { dg-error "constant" }
+};
+
+B<const int&> b;