PR c++/70167 - array prvalue treated as lvalue
authorJason Merrill <jason@redhat.com>
Tue, 9 May 2017 13:48:58 +0000 (09:48 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 9 May 2017 13:48:58 +0000 (09:48 -0400)
* cp-tree.h (CONSTRUCTOR_C99_COMPOUND_LITERAL): New.
(enum fcl_t): New.
* semantics.c (finish_compound_literal): Add fcl_context parameter.
Only make a static variable for C99 syntax.
* parser.c (cp_parser_postfix_expression): Pass it.
* pt.c (tsubst_copy_and_build): Likewise.
* call.c (extend_ref_init_temps): Set
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.

From-SVN: r247793

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp0x/initlist-array6.C [new file with mode: 0644]

index c4b850f5186002cab8073c6688fdc5e1ae100b40..a5990e2a6c25de8ed91ade8f3d1abe134523f98a 100644 (file)
@@ -1,3 +1,15 @@
+2017-05-09  Jason Merrill  <jason@redhat.com>
+
+       PR c++/70167 - array prvalue treated as lvalue
+       * cp-tree.h (CONSTRUCTOR_C99_COMPOUND_LITERAL): New.
+       (enum fcl_t): New.
+       * semantics.c (finish_compound_literal): Add fcl_context parameter.
+       Only make a static variable for C99 syntax.
+       * parser.c (cp_parser_postfix_expression): Pass it.
+       * pt.c (tsubst_copy_and_build): Likewise.
+       * call.c (extend_ref_init_temps): Set
+       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
+
 2017-05-09  Nathan Sidwell  <nathan@acm.org>
 
        * cp-lang.c (get_global_decls, cxx_pushdecl): New.
index d9accd16401a365bd6ca6b848e1901aea131aa15..dee236e703d228d88b491c748ae2d2b88ad4c557 100644 (file)
@@ -10516,6 +10516,9 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups)
              FOR_EACH_VEC_SAFE_ELT (elts, i, p)
                p->value = extend_ref_init_temps (decl, p->value, cleanups);
            }
+         recompute_constructor_flags (ctor);
+         if (decl_maybe_constant_var_p (decl) && TREE_CONSTANT (ctor))
+           DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
        }
     }
 
index b64fa6dafbc7d476e367da8069d2c7cf0251d16e..100f85c126508e15798fa2a3f76452fcfa085dba 100644 (file)
@@ -369,6 +369,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL)
       CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
       DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
+      CONSTUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
    4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
          CALL_EXPR, or FIELD_DECL).
       IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
@@ -3898,6 +3899,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define CONSTRUCTOR_MUTABLE_POISON(NODE) \
   (TREE_LANG_FLAG_2 (CONSTRUCTOR_CHECK (NODE)))
 
+/* True if this typed CONSTRUCTOR represents C99 compound-literal syntax rather
+   than C++11 functional cast syntax.  */
+#define CONSTRUCTOR_C99_COMPOUND_LITERAL(NODE) \
+  (TREE_LANG_FLAG_3 (CONSTRUCTOR_CHECK (NODE)))
+
 #define DIRECT_LIST_INIT_P(NODE) \
    (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE))
 
@@ -6483,7 +6489,10 @@ extern tree finish_this_expr                     (void);
 extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t);
 extern cp_expr finish_unary_op_expr            (location_t, enum tree_code, cp_expr,
                                                 tsubst_flags_t);
-extern tree finish_compound_literal            (tree, tree, tsubst_flags_t);
+/* Whether this call to finish_compound_literal represents a C++11 functional
+   cast or a C99 compound literal.  */
+enum fcl_t { fcl_functional, fcl_c99 };
+extern tree finish_compound_literal            (tree, tree, tsubst_flags_t, fcl_t = fcl_functional);
 extern tree finish_fname                       (tree);
 extern void finish_translation_unit            (void);
 extern tree finish_template_type_parm          (tree, tree);
index ab56f120083ba607dbe5ef0f0c32515a45af36e1..19514525d2f1aae8d6af70d37fce68fb3fe5b582 100644 (file)
@@ -6770,7 +6770,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                /* Form the representation of the compound-literal.  */
                postfix_expression
                  = finish_compound_literal (type, initializer,
-                                            tf_warning_or_error);
+                                            tf_warning_or_error, fcl_c99);
                postfix_expression.set_location (initializer.get_location ());
                break;
              }
@@ -26834,7 +26834,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
        type = TREE_TYPE (type);
 
       cast = finish_compound_literal (type, expression_list,
-                                     tf_warning_or_error);
+                                     tf_warning_or_error, fcl_functional);
       /* Create a location of the form:
            type_name{i, f}
            ^~~~~~~~~~~~~~~
index b42b1fc10fb72b640dbf3243116cb34bfdfa367d..a4a0d83503a7d204f43e38cc5ce783d7647f5048 100644 (file)
@@ -17709,7 +17709,12 @@ tsubst_copy_and_build (tree t,
        CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t);
 
        if (TREE_HAS_CONSTRUCTOR (t))
-         RETURN (finish_compound_literal (type, r, complain));
+         {
+           fcl_t cl = fcl_functional;
+           if (CONSTRUCTOR_C99_COMPOUND_LITERAL (t))
+             cl = fcl_c99;
+           RETURN (finish_compound_literal (type, r, complain, cl));
+         }
 
        TREE_TYPE (r) = type;
        RETURN (r);
index b15763d08c2f2934df6033ead3bc00b69b925d1a..238dfff4743551ee0435e5bf7479a722e2fa02b7 100644 (file)
@@ -2647,12 +2647,14 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
   return result;
 }
 
-/* Finish a compound-literal expression.  TYPE is the type to which
-   the CONSTRUCTOR in COMPOUND_LITERAL is being cast.  */
+/* Finish a compound-literal expression or C++11 functional cast with aggregate
+   initializer.  TYPE is the type to which the CONSTRUCTOR in COMPOUND_LITERAL
+   is being cast.  */
 
 tree
 finish_compound_literal (tree type, tree compound_literal,
-                        tsubst_flags_t complain)
+                        tsubst_flags_t complain,
+                        fcl_t fcl_context)
 {
   if (type == error_mark_node)
     return error_mark_node;
@@ -2661,7 +2663,7 @@ finish_compound_literal (tree type, tree compound_literal,
     {
       compound_literal
        = finish_compound_literal (TREE_TYPE (type), compound_literal,
-                                  complain);
+                                  complain, fcl_context);
       return cp_build_c_cast (type, compound_literal, complain);
     }
 
@@ -2682,6 +2684,8 @@ finish_compound_literal (tree type, tree compound_literal,
       TREE_TYPE (compound_literal) = type;
       /* Mark the expression as a compound literal.  */
       TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+      if (fcl_context == fcl_c99)
+       CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
       return compound_literal;
     }
 
@@ -2717,10 +2721,17 @@ finish_compound_literal (tree type, tree compound_literal,
   compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL,
                                        complain);
   if (TREE_CODE (compound_literal) == CONSTRUCTOR)
-    TREE_HAS_CONSTRUCTOR (compound_literal) = true;
+    {
+      TREE_HAS_CONSTRUCTOR (compound_literal) = true;
+      if (fcl_context == fcl_c99)
+       CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
+    }
 
   /* Put static/constant array temporaries in static variables.  */
+  /* FIXME all C99 compound literals should be variables rather than C++
+     temporaries, unless they are used as an aggregate initializer.  */
   if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
+      && fcl_context == fcl_c99
       && TREE_CODE (type) == ARRAY_TYPE
       && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
       && initializer_constant_valid_p (compound_literal, type))
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array6.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array6.C
new file mode 100644 (file)
index 0000000..fdfde0a
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/70167
+// { dg-do compile { target c++11 } }
+
+template<class T, unsigned S> void f(T(&&)[S]) { }
+
+using arr = const int[2];
+
+int main()
+{
+  f(arr{1, 2});
+}