[PATCH] PR c++/36408

Dodji Seketeli dodji@redhat.com
Fri Nov 27 22:04:00 GMT 2009


Hello,

Here is a second try at this PR as I got sidetracked by some amusements
since last time :-)

So we are not emitting any error message on:
~=~
template<int>
void foo()
{
  int i = ({ }); //<-- we should error or warn here.
}

int main()
{
  foo<0>();
}
~=~

At template instantiation time (in DECL_EXPR case in tsubst_expr) the initializer
of the DECL_EXPR 'i' gets tsubsted into NULL. As a result, 'i' is
value-initialized, so it ends up being set to zero.

We should not end up in there to begin with.

The patch below folds the empty list of expression statements (which
the empty statement expression is lowered into) into void_zero_node at parsing
time, so that convert_for_assignment eventually emits the right error at
instantiation time when the initializer of 'i' is checked.

Tested against trunk on x86_64-unknown-linux-gnu.


        Dodji

commit e839f36c30bf53c7beb9f2ad923f9a8c14e50419
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Fri Nov 27 21:01:29 2009 +0100

    Fix PR c++/36408
    
    gcc/cp/ChangeLog:
    
    	PR c++/36408
    	* cp-tree.h (empty_expr_stmt_p): Declare ...
    	* semantics.c (empty_expr_stmt_p): ... this.
    	* pt.c (fold_non_dependent_expr): Use it.
    
    gcc/testsuite/ChangeLog:
    	PR c++/36408
    	* g++.dg/template/stmtexpr2.C: New test.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c6de2b4..2d8f409 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5074,6 +5074,7 @@ extern tree begin_stmt_expr			(void);
 extern tree finish_stmt_expr_expr		(tree, tree);
 extern tree finish_stmt_expr			(tree, bool);
 extern tree stmt_expr_value_expr		(tree);
+bool empty_expr_stmt_p				(tree);
 extern tree perform_koenig_lookup		(tree, VEC(tree,gc) *);
 extern tree finish_call_expr			(tree, VEC(tree,gc) **, bool,
 						 bool, tsubst_flags_t);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index dfe7791..b53295e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4636,6 +4636,8 @@ fold_non_dependent_expr (tree expr)
 				    /*in_decl=*/NULL_TREE,
 				    /*function_p=*/false,
 				    /*integral_constant_expression_p=*/true);
+      if (empty_expr_stmt_p (expr))
+	expr = void_zero_node;
       processing_template_decl = saved_processing_template_decl;
     }
   return expr;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 34b5d57..fdea195 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1847,6 +1847,31 @@ stmt_expr_value_expr (tree stmt_expr)
   return t;
 }
 
+/* Return TRUE iff EXPR_STMT is an empty expression statement.  */
+
+bool
+empty_expr_stmt_p (tree expr_stmt)
+{
+  tree body = NULL_TREE;
+
+  if (expr_stmt)
+    {
+      if (TREE_CODE (expr_stmt) == EXPR_STMT)
+	body = EXPR_STMT_EXPR (expr_stmt);
+      else if (TREE_CODE (expr_stmt) == STATEMENT_LIST)
+	body = expr_stmt;
+    }
+
+    if (body)
+      {
+	if (TREE_CODE (body) == STATEMENT_LIST)
+	  return tsi_end_p (tsi_start (body));
+	else
+	  return empty_expr_stmt_p (body);
+      }
+  return false;
+}
+
 /* Perform Koenig lookup.  FN is the postfix-expression representing
    the function (or functions) to call; ARGS are the arguments to the
    call.  Returns the functions to be considered by overload
diff --git a/gcc/testsuite/g++.dg/template/stmtexpr2.C b/gcc/testsuite/g++.dg/template/stmtexpr2.C
new file mode 100644
index 0000000..ef29b43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/stmtexpr2.C
@@ -0,0 +1,26 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin: PR c++/36408
+// { dg-options "" }
+// { dg-do compile }
+
+template<int>
+void
+foo()
+{
+  int i = ({ }); // { dg-error "void value not ignored" }
+}
+
+template<int>
+void
+bar()
+{
+  int i = ({ ({}); }); // { dg-error "void value not ignored" }
+}
+
+int
+main ()
+{
+  foo<0> ();
+  bar<0> ();
+}
+



More information about the Gcc-patches mailing list