This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR c++/7050


This patch fixes PR 7050, an ICE on invalid code regression in 3.2.
(According to the gnats bug report, it worked in 2.95.4.)

The issue was that an expression like (a ? b : throw) would result in
the compiler trying to store the result of the throw expression to the
result of the conditional expression. (The conditional expression
takes on b's type in this case.) Avoid this by refusing to store a
void-valued expression.

Tested (bootstrap and make -k check) on i686-pc-linux-gnu with 3.2
from CVS.

This bug is also present in 3.3 and the mainline. Let me know if
separate patches are needed. (This patch works for 3.3, but I haven't
had time to look at mainline yet.)


2003-02-27  Andrew Lewycky  <andrew at mxc dot ca>

	PR c++/7050
	* expr.c (store_expr): Don't attempt to store void-typed trees,
	just evaluate them for side effects.
	* cp/expr.c (cxx_expand_expr): Return const0_rtx for throw
	expressions.

2003-02-27  Andrew Lewycky  <andrew at mxc dot ca>

	PR c++/7050
	* g++.dg/expr/cond-throw1.C: New test.


Index: gcc/expr.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/expr.c,v
retrieving revision 1.423.2.19.4.8
diff -c -3 -p -r1.423.2.19.4.8 expr.c
*** gcc/expr.c	3 Feb 2003 18:01:37 -0000	1.423.2.19.4.8
--- gcc/expr.c	27 Feb 2003 14:20:45 -0000
*************** store_expr (exp, target, want_value)
*** 3917,3922 ****
--- 3917,3931 ----
    int dont_return_target = 0;
    int dont_store_target = 0;
  
+   if (VOID_TYPE_P (TREE_TYPE (exp)))
+     {
+       /* C++ can generate ?: expressions with a throw expression in
one
+ 	 branch and an rvalue in the other. Here, we resolve attempts to
+ 	 store the throw expression's nonexistant result. */
+       if (want_value) abort ();
+       expand_expr (exp, const0_rtx, VOIDmode, 0);
+       return NULL_RTX;
+     }
    if (TREE_CODE (exp) == COMPOUND_EXPR)
      {
        /* Perform first part of compound expression, then assign from
second
Index: gcc/cp/expr.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/expr.c,v
retrieving revision 1.63
diff -c -3 -p -r1.63 expr.c
*** gcc/cp/expr.c	23 Jan 2002 14:25:56 -0000	1.63
--- gcc/cp/expr.c	27 Feb 2003 14:20:53 -0000
*************** cplus_expand_expr (exp, target, tmode, m
*** 111,117 ****
        
      case THROW_EXPR:
        expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
!       return NULL;
  
      case MUST_NOT_THROW_EXPR:
        expand_eh_region_start ();
--- 111,117 ----
        
      case THROW_EXPR:
        expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
!       return const0_rtx;
  
      case MUST_NOT_THROW_EXPR:
        expand_eh_region_start ();



extern "C" void abort(void);

#define CI(stmt) try { stmt; abort(); } catch (int) { }

struct has_destructor
{
    ~has_destructor() { }
};

struct no_destructor
{
};

int PI(int& i) { return i++; }

int main(int argc, char *argv[])
{
    (argc+1 ? has_destructor() : throw 0);
    CI((argc+1 ? throw 0 : has_destructor()));
    CI((0 ? has_destructor() : throw 0));
    CI((1 ? throw 0 : has_destructor()));
    (0 ? throw 0 : has_destructor());
    (1 ? has_destructor() : throw 0);

    (argc+1 ? no_destructor() : throw 0);
    CI((argc+1 ? throw 0 : no_destructor()));
    CI((0 ? no_destructor() : throw 0));
    CI((1 ? throw 0 : no_destructor()));
    (0 ? throw 0 : no_destructor());
    (1 ? no_destructor() : throw 0);

    int i = 1;
    CI(throw PI(i));
    if (i != 2) abort();

    (1 ? 0 : throw PI(i));
    if (i != 2) abort();

    CI(0 ? 0 : throw PI(i));
    if (i != 3) abort();

    CI(0 ? has_destructor() : throw PI(i));
    if (i != 4) abort();
    (argc+1 ? has_destructor() : throw PI(i));
    if (i != 4) abort();

    i = 1;
    CI(throw i++);
    if (i != 2) abort();

    (1 ? 0 : throw i++);
    if (i != 2) abort();

    CI(0 ? 0 : throw i++);
    if (i != 3) abort();

    CI(0 ? has_destructor() : throw i++);
    if (i != 4) abort();
    (argc+1 ? has_destructor() : throw i++);
    if (i != 4) abort();
}


-- 
Andrew Lewycky <andrew at mxc dot ca>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]