These patches address regressions revealed by my work to run the testsuite in C++14 mode.

The first patch addresses multiple failures caused by force_paren_expr wrapping simple expressions so that decltype(auto) will treat them differently. The static_cast to reference trick was breaking bitfields, so I've switched to setting a flag on the COMPONENT_REF instead. And then I stopped doing the wrapping in unevaluated context to address problems with addressof.

The second patch fixes an ICE on auto11.C due to confusion between 'auto' and 'T'.

The third patch fixes many missed errors in auto9.C.

The fourth patch harmonizes the default VLA warning level in C++14 mode with C++98/11: now we mostly won't get warnings about VLAs with -std=gnu++1y, but we will with -std=c++1y or with -Wvla. It also fixes the text of a pedwarn in build_new to be more helpful.

The last patch applies to C++11 mode as well; running vt-34051 with -pedantic-errors was producing a spurious extra semicolon pedwarn.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 478642f744b15bfc6e9170e760a94a3ff073df42
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Mar 6 11:36:49 2014 -0500

    	* cp-tree.h (REF_PARENTHESIZED_P): New.
    	* semantics.c (force_paren_expr): Set it.
    	* pt.c (do_auto_deduction): Check it.
    	(tsubst) [COMPONENT_REF]: Copy it.
    	* typeck.c (maybe_warn_about_useless_cast): Don't strip dereference.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8ec7d6a..45e4d82 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -100,6 +100,7 @@ c-common.h, not after.
       TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
       FNDECL_USED_AUTO (in FUNCTION_DECL)
       DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
+      REF_PARENTHESIZED_P (in COMPONENT_REF, SCOPE_REF)
    3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
       ICS_BAD_FLAG (in _CONV)
       FN_TRY_BLOCK_P (in TRY_BLOCK)
@@ -3031,6 +3032,12 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 #define PAREN_STRING_LITERAL_P(NODE) \
   TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE))
 
+/* Indicates whether a COMPONENT_REF has been parenthesized.  Currently
+   only set some of the time in C++14 mode.  */
+
+#define REF_PARENTHESIZED_P(NODE) \
+  TREE_LANG_FLAG_2 (COMPONENT_REF_CHECK (NODE))
+
 /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a
    constructor call, rather than an ordinary function call.  */
 #define AGGR_INIT_VIA_CTOR_P(NODE) \
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6476d8a..d4d54b8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14915,6 +14915,7 @@ tsubst_copy_and_build (tree t,
 	tree object;
 	tree object_type;
 	tree member;
+	tree r;
 
 	object = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
 						     args, complain, in_decl);
@@ -14999,11 +15000,19 @@ tsubst_copy_and_build (tree t,
 	    RETURN (error_mark_node);
 	  }
 	else if (TREE_CODE (member) == FIELD_DECL)
-	  RETURN (finish_non_static_data_member (member, object, NULL_TREE));
+	  {
+	    r = finish_non_static_data_member (member, object, NULL_TREE);
+	    if (TREE_CODE (r) == COMPONENT_REF)
+	      REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
+	    RETURN (r);
+	  }
 
-	RETURN (finish_class_member_access_expr (object, member,
-						/*template_p=*/false,
-						complain));
+	r = finish_class_member_access_expr (object, member,
+					     /*template_p=*/false,
+					     complain);
+	if (TREE_CODE (r) == COMPONENT_REF)
+	  REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
+	RETURN (r);
       }
 
     case THROW_EXPR:
@@ -21619,7 +21628,8 @@ do_auto_deduction (tree type, tree init, tree auto_node)
   targs = make_tree_vec (1);
   if (AUTO_IS_DECLTYPE (auto_node))
     {
-      bool id = (DECL_P (init) || TREE_CODE (init) == COMPONENT_REF);
+      bool id = (DECL_P (init) || (TREE_CODE (init) == COMPONENT_REF
+				   && !REF_PARENTHESIZED_P (init)));
       TREE_VEC_ELT (targs, 0)
 	= finish_decltype_type (init, id, tf_warning_or_error);
       if (type != auto_node)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b9c1271..fcd8409 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1605,11 +1605,18 @@ force_paren_expr (tree expr)
   if (cxx_dialect < cxx1y)
     return expr;
 
+  /* If we're in unevaluated context, we can't be deducing a
+     return/initializer type, so we don't need to mess with this.  */
+  if (cp_unevaluated_operand)
+    return expr;
+
   if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
       && TREE_CODE (expr) != SCOPE_REF)
     return expr;
 
-  if (type_dependent_expression_p (expr))
+  if (TREE_CODE (expr) == COMPONENT_REF)
+    REF_PARENTHESIZED_P (expr) = true;
+  else if (type_dependent_expression_p (expr))
     expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr);
   else
     {
@@ -1619,7 +1626,7 @@ force_paren_expr (tree expr)
 	  tree type = unlowered_expr_type (expr);
 	  bool rval = !!(kind & clk_rvalueref);
 	  type = cp_build_reference_type (type, rval);
-	  expr = build_static_cast (type, expr, tf_warning_or_error);
+	  expr = build_static_cast (type, expr, tf_error);
 	}
     }
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index c91612c..d8374d9 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6291,7 +6291,10 @@ maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain)
   if (warn_useless_cast
       && complain & tf_warning)
     {
-      if (REFERENCE_REF_P (expr))
+      /* In C++14 mode, this interacts badly with force_paren_expr.  And it
+	 isn't necessary in any mode, because the code below handles
+	 glvalues properly.  For 4.9, just skip it in C++14 mode.  */
+      if (cxx_dialect < cxx1y && REFERENCE_REF_P (expr))
 	expr = TREE_OPERAND (expr, 0);
 
       if ((TREE_CODE (type) == REFERENCE_TYPE
commit daaf775af5b39c2216a0a7230ec011f38470e913
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Mar 7 10:32:10 2014 -0500

    	* typeck.c (comp_template_parms_position): 'auto' and
    	'decltype(auto)' are different from real template parms.

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d8374d9..559f19b5 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1150,6 +1150,11 @@ comp_template_parms_position (tree t1, tree t2)
 	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
+  /* In C++14 we can end up comparing 'auto' to a normal template
+     parameter.  Don't confuse them.  */
+  if (cxx_dialect >= cxx1y && (is_auto (t1) || is_auto (t2)))
+    return TYPE_IDENTIFIER (t1) == TYPE_IDENTIFIER (t2);
+
   return true;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto11.C b/gcc/testsuite/g++.dg/cpp0x/auto11.C
index 05f5f5c..dcdb28c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto11.C
@@ -8,5 +8,5 @@ template<int> struct A
 
 void foo()
 {
-  A<0>().operator auto();	// { dg-error "auto.*conversion" }
+  A<0>().operator auto();	// { dg-error "auto" }
 }
commit 86d7f9d36ebf053ad016dcd4dd7339ceb247a14e
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Mar 7 11:09:49 2014 -0500

    	* parser.c (cp_parser_type_id_1): Only allow 'auto' in C++1y if
    	we're in a trailing return type.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 71a2a9e..5725283 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17992,7 +17992,9 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
     abstract_declarator = NULL;
 
   if (type_specifier_seq.type
-      && cxx_dialect < cxx1y
+      /* None of the valid uses of 'auto' in C++14 involve the type-id
+	 nonterminal, but it is valid in a trailing-return-type.  */
+      && !(cxx_dialect >= cxx1y && is_trailing_return)
       && type_uses_auto (type_specifier_seq.type))
     {
       /* A type-id with type 'auto' is only ok if the abstract declarator
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59110.C b/gcc/testsuite/g++.dg/cpp1y/pr59110.C
index dbbfa9b..5c9c208 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr59110.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59110.C
@@ -1,4 +1,4 @@
 // PR c++/59110
 // { dg-options "-std=c++1y" }
 
-int i = *(auto*)0; // { dg-error "cannot convert" }
+int i = *(auto*)0; // { dg-error "" }
commit c8958aa5909143fcb673bc9f3cc2e570de99c1ea
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Mar 6 11:36:13 2014 -0500

    	* decl.c (create_array_type_for_decl): Only warn about invalid
    	C++1y VLA if flag_iso or warn_vla>0.
    	(grokdeclarator): Likewise.
    	* pt.c (tsubst): Likewise.
    	* semantics.c (finish_decltype_type): Likewise.
    	* typeck.c (cxx_sizeof_or_alignof_type): Likewise.
    	(cp_build_addr_expr_1): Likewise.
    	* init.c (build_new_1): Improve diagnostics.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index cd2cc9c..92fd65f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8528,7 +8528,8 @@ create_array_type_for_decl (tree name, tree type, tree size)
       return error_mark_node;
     }
 
-  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)
+      && (flag_iso || warn_vla > 0))
     pedwarn (input_location, OPT_Wvla, "array of array of runtime bound");
 
   /* Figure out the index type for the array.  */
@@ -9760,7 +9761,8 @@ grokdeclarator (const cp_declarator *declarator,
                    : G_("cannot declare pointer to qualified function type %qT"),
 		   type);
 
-	  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+	  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)
+	      && (flag_iso || warn_vla > 0))
 	    pedwarn (input_location, OPT_Wvla,
 		     declarator->kind == cdk_reference
 		     ? G_("reference to array of runtime bound")
@@ -10108,7 +10110,8 @@ grokdeclarator (const cp_declarator *declarator,
 	  type = error_mark_node;
 	}
 
-      if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+      if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)
+	  && (flag_iso || warn_vla > 0))
 	pedwarn (input_location, OPT_Wvla,
 		 "typedef naming array of runtime bound");
 
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3ae2b5c..7f5d045 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2285,6 +2285,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      is therefore reusable.  */
   tree data_addr;
   tree init_preeval_expr = NULL_TREE;
+  tree orig_type = type;
 
   if (nelts)
     {
@@ -2330,7 +2331,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	  if (complain & tf_error)
 	    {
 	      error_at (EXPR_LOC_OR_LOC (inner_nelts, input_location),
-			"array size in operator new must be constant");
+			"array size in new-expression must be constant");
 	      cxx_constant_value(inner_nelts);
 	    }
 	  nelts = error_mark_node;
@@ -2344,7 +2345,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 
   if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error))
     {
-      error ("variably modified type not allowed in operator new");
+      error ("variably modified type not allowed in new-expression");
       return error_mark_node;
     }
 
@@ -2357,8 +2358,17 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       && !TREE_CONSTANT (maybe_constant_value (outer_nelts)))
     {
       if (complain & tf_warning_or_error)
-	pedwarn(EXPR_LOC_OR_LOC (outer_nelts, input_location), OPT_Wvla,
-		"ISO C++ does not support variable-length array types");
+	{
+	  const char *msg;
+	  if (typedef_variant_p (orig_type))
+	    msg = ("non-constant array new length must be specified "
+		   "directly, not by typedef");
+	  else
+	    msg = ("non-constant array new length must be specified "
+		   "without parentheses around the type-id");
+	  pedwarn (EXPR_LOC_OR_LOC (outer_nelts, input_location),
+		   OPT_Wvla, msg);
+	}
       else
 	return error_mark_node;
     }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8126905..6476d8a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11954,7 +11954,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
 	if (cxx_dialect >= cxx1y
 	    && !(TREE_CODE (t) == REFERENCE_TYPE && REFERENCE_VLA_OK (t))
-	    && array_of_runtime_bound_p (type))
+	    && array_of_runtime_bound_p (type)
+	    && (flag_iso || warn_vla > 0))
 	  {
 	    if (complain & tf_warning_or_error)
 	      pedwarn
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d2c453f..b9c1271 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7031,7 +7031,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
 	}
     }
 
-  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)
+      && (flag_iso || warn_vla > 0))
     {
       if (complain & tf_warning_or_error)
 	pedwarn (input_location, OPT_Wvla,
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ae2e503..c91612c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1552,7 +1552,8 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
       return value;
     }
 
-  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)
+      && (flag_iso || warn_vla > 0))
     {
       if (complain & tf_warning_or_error)
 	pedwarn (input_location, OPT_Wvla,
@@ -5471,7 +5472,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
 
   if (argtype != error_mark_node)
     {
-      if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (argtype))
+      if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (argtype)
+	  && (flag_iso || warn_vla > 0))
 	{
 	  if (complain & tf_warning_or_error)
 	    pedwarn (input_location, OPT_Wvla,
diff --git a/gcc/testsuite/g++.dg/ext/vla1.C b/gcc/testsuite/g++.dg/ext/vla1.C
index f372535..55ae5c8 100644
--- a/gcc/testsuite/g++.dg/ext/vla1.C
+++ b/gcc/testsuite/g++.dg/ext/vla1.C
@@ -9,7 +9,7 @@ class A { A (int); };
 
 A::A (int i)
 {
-  int ar[1][i];    // { dg-error "variable length array" }
+  int ar[1][i];    // { dg-error "array" }
 
   ar[0][0] = 0;
 }
diff --git a/gcc/testsuite/g++.dg/ext/vla5.C b/gcc/testsuite/g++.dg/ext/vla5.C
index 2457e34..ca58309 100644
--- a/gcc/testsuite/g++.dg/ext/vla5.C
+++ b/gcc/testsuite/g++.dg/ext/vla5.C
@@ -6,5 +6,5 @@
 void
 test (int a)
 {
-  new (char[a]); // { dg-warning "variable-length array" }
+  new (char[a]); // { dg-warning "parentheses" }
 }
diff --git a/gcc/testsuite/g++.dg/ext/vla8.C b/gcc/testsuite/g++.dg/ext/vla8.C
index 1c6000f..9e2d6bd 100644
--- a/gcc/testsuite/g++.dg/ext/vla8.C
+++ b/gcc/testsuite/g++.dg/ext/vla8.C
@@ -8,7 +8,7 @@ struct AvlTreeIter
 
   AvlTreeIter()
   {
-    new (void* [Num()]); // { dg-warning "variable-length array" }
+    new (void* [Num()]); // { dg-warning "parentheses" }
   }
 };
 
diff --git a/gcc/testsuite/g++.dg/init/new35.C b/gcc/testsuite/g++.dg/init/new35.C
index c5f79aa..7d07cf5 100644
--- a/gcc/testsuite/g++.dg/init/new35.C
+++ b/gcc/testsuite/g++.dg/init/new35.C
@@ -5,7 +5,7 @@ int
 main (int argc, char **argv)
 {
   typedef char A[argc];
-  new A; // { dg-warning "variable-length array types|not a constant" }
+  new A; // { dg-warning "array" }
   new A[0]; // { dg-error "must be constant|not a constant" }
   new A[5]; // { dg-error "must be constant|not a constant" }
   new (A[0]); // { dg-error "must be constant|not a constant" }
diff --git a/gcc/testsuite/g++.dg/init/new37.C b/gcc/testsuite/g++.dg/init/new37.C
index 82ca18b..eab7854 100644
--- a/gcc/testsuite/g++.dg/init/new37.C
+++ b/gcc/testsuite/g++.dg/init/new37.C
@@ -3,7 +3,7 @@
 void
 nonconst(int n)
 {
-  new (long[n][n]); // { dg-error "variable length|array size|not a constant" }
+  new (long[n][n]); // { dg-error "variable length|array size|not a constant|runtime bound" }
   new long[n][n]; // { dg-error "variable length|array size|not a constant" }
 }
 
commit fdf7f71e757340ea3eca836b5fa42e4faee36e13
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Mar 7 09:55:58 2014 -0500

    	* parser.c (cp_parser_using_declaration): Consume the semicolon
    	after bare parameter pack error.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8bc1126..71a2a9e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16016,7 +16016,10 @@ cp_parser_using_declaration (cp_parser* parser,
 	    USING_DECL_TYPENAME_P (decl) = 1;
 
 	  if (check_for_bare_parameter_packs (decl))
-            return false;
+	    {
+	      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+	      return false;
+	    }
 	  else
 	    /* Add it to the list of members in this class.  */
 	    finish_member_declaration (decl);
@@ -16031,7 +16034,10 @@ cp_parser_using_declaration (cp_parser* parser,
 					 decl, NLE_NULL,
 					 token->location);
 	  else if (check_for_bare_parameter_packs (decl))
-	    return false;
+	    {
+	      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+	      return false;
+	    }
 	  else if (!at_namespace_scope_p ())
 	    do_local_using_decl (decl, qscope, identifier);
 	  else

Reply via email to