diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 14101e61c9f..e68cf959468 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2009-11-28 Richard Guenther + + PR tree-optimization/42183 + * tree-nrv.c (tree_nrv): Bail out if the RESULT_DECL has its + address taken. Merge the addressable state of the NRV + variable and the result instead of copying it. + 2009-11-28 Jakub Jelinek * matrix-reorg.c (analyze_matrix_allocation_site): Remove unused diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 16f2741054d..1c3e6f91fc3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-11-28 Richard Guenther + + PR tree-optimization/42183 + * g++.dg/torture/pr42183.C: New testcase. + 2009-11-28 Kai Tietz * gcc.dg/lto/20081210-1_0.c (uintptr_t): Use for diff --git a/gcc/testsuite/g++.dg/torture/pr42183.C b/gcc/testsuite/g++.dg/torture/pr42183.C new file mode 100644 index 00000000000..375b37f0c66 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr42183.C @@ -0,0 +1,51 @@ +// { dg-do compile } + +class IntSize { +public: + IntSize(int width, int height) : m_width(width), m_height(height) { } + int m_width, m_height; +}; +class IntPoint { +public: + IntPoint(int x, int y) : m_x(x), m_y(y) { } + int m_x, m_y; +}; +class IntRect { +public: + IntRect(int x, int y, int width, int height) + : m_location(IntPoint(x, y)), m_size(IntSize(width, height)) { } + void intersect(const IntRect&); + IntPoint m_location; + IntSize m_size; +}; +inline IntRect intersection(const IntRect& a, const IntRect& b) { + IntRect c = a; + c.intersect(b); + return c; +} +class RenderObject { +public: + int contentWidth() const { } + int contentHeight() const { } + virtual int xPos() const { } + virtual int yPos() const { } + virtual int paddingTop() const; + virtual int paddingLeft() const; + virtual int borderTop() const { } + virtual int borderLeft() const { } +}; +class RenderMenuList : public RenderObject { + virtual IntRect controlClipRect(int tx, int ty) const; + RenderObject* m_innerBlock; +}; +IntRect RenderMenuList::controlClipRect(int tx, int ty) const { + IntRect outerBox(tx + borderLeft() + paddingLeft(), + ty + borderTop() + paddingTop(), + contentWidth(), contentHeight()); + IntRect innerBox(tx + m_innerBlock->xPos() + m_innerBlock->paddingLeft(), + ty + m_innerBlock->yPos() + m_innerBlock->paddingTop(), + m_innerBlock->contentWidth(), + m_innerBlock->contentHeight()); + return intersection(outerBox, innerBox); +} + diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c index defa8def89c..a825a7a0c3f 100644 --- a/gcc/tree-nrv.c +++ b/gcc/tree-nrv.c @@ -129,6 +129,12 @@ tree_nrv (void) if (DECL_NAME (result)) return 0; + /* If the result has its address taken then it might be modified + by means not detected in the following loop. Bail out in this + case. */ + if (TREE_ADDRESSABLE (result)) + return 0; + /* Look through each block for assignments to the RESULT_DECL. */ FOR_EACH_BB (bb) { @@ -178,7 +184,7 @@ tree_nrv (void) || TREE_ADDRESSABLE (found) || DECL_ALIGN (found) > DECL_ALIGN (result) || !useless_type_conversion_p (result_type, - TREE_TYPE (found))) + TREE_TYPE (found))) return 0; } else if (gimple_has_lhs (stmt)) @@ -218,7 +224,7 @@ tree_nrv (void) DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found); } - TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (found); + TREE_ADDRESSABLE (result) |= TREE_ADDRESSABLE (found); /* Now walk through the function changing all references to VAR to be RESULT. */