[Patch X86_64]: Fix multiplication cost for -march=znver1.

2016-03-05 Thread Kumar, Venkataramanan
Hi Maintainers,

The below patch changes multiplication cost for -march=znver1 target.  
GCC Bootstrap tested with  BOOT_CFLAGS="-O2 -g -march=znver1".

(---Snip---)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d8a2909..b5dde5e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1350,11 +1350,11 @@ struct processor_costs znver1_cost = {
   COSTS_N_INSNS (1),   /* cost of a lea instruction.  */
   COSTS_N_INSNS (1),   /* variable shift costs.  */
   COSTS_N_INSNS (1),   /* constant shift costs.  */
-  {COSTS_N_INSNS (4),  /* cost of starting multiply for QI.  */
-   COSTS_N_INSNS (4),  /*   HI.  */
-   COSTS_N_INSNS (4),  /*   SI.  */
-   COSTS_N_INSNS (6),  /*   DI.  */
-   COSTS_N_INSNS (6)}, /*other.  */
+  {COSTS_N_INSNS (3),  /* cost of starting multiply for QI.  */
+   COSTS_N_INSNS (3),  /*   HI.  */
+   COSTS_N_INSNS (3),  /*   SI.  */
+   COSTS_N_INSNS (4),  /*   DI.  */
+   COSTS_N_INSNS (4)}, /*other.  */
   0,   /* cost of multiply per each bit
set.  */
   {COSTS_N_INSNS (19), /* cost of a divide/mod for QI.  */
(---Snip---)

2016-03-05  Venkataramanan Kumar  

 * config/i386/i386.c (znver1_cost): Fix Multiply cost.

Ok for trunk?

Regards,
Venkat.


RE: [Patch X86_64] : Fix type attribute for sseimul reservations in znver1.md

2016-03-05 Thread Kumar, Venkataramanan
Hi Uros,

> -Original Message-
> From: Uros Bizjak [mailto:ubiz...@gmail.com]
> Sent: Friday, March 04, 2016 1:10 AM
> To: Kumar, Venkataramanan
> Cc: gcc-patches@gcc.gnu.org
> Subject: Re: [Patch X86_64] : Fix type attribute for sseimul reservations in
> znver1.md
> 
> On Thu, Mar 3, 2016 at 7:05 PM, Kumar, Venkataramanan
>  wrote:
> > Hi Maintainers,
> >
> > The below patch corrects the type attribute  for "sseimul" type
> reservations in znver1.md.
> >
> > (snip)
> > diff --git a/gcc/config/i386/znver1.md b/gcc/config/i386/znver1.md
> > index 3db3bed..feeccd7 100644
> > --- a/gcc/config/i386/znver1.md
> > +++ b/gcc/config/i386/znver1.md
> > @@ -913,28 +913,28 @@
> >  (define_insn_reservation "znver1_sseimul" 3
> >  (and (eq_attr "cpu" "znver1")
> >   (and (eq_attr "mode" "TI")
> > -  (and (eq_attr "type" "ssemul")
> > +  (and (eq_attr "type" "sseimul")
> > (eq_attr "memory" "none"
> >  "znver1-direct,znver1-fp0*3")
> >
> >  (define_insn_reservation "znver1_sseimul_avx256" 4
> >  (and (eq_attr "cpu" "znver1")
> >   (and (eq_attr "mode" "OI")
> > -  (and (eq_attr "type" "ssemul")
> > +  (and (eq_attr "type" "sseimul")
> > (eq_attr "memory" "none"
> >  "znver1-double,znver1-fp0*4")
> >
> >  (define_insn_reservation "znver1_sseimul_load" 7
> >  (and (eq_attr "cpu" "znver1")
> >   (and (eq_attr "mode" "TI")
> > -  (and (eq_attr "type" "ssemul")
> > +  (and (eq_attr "type" "sseimul")
> > (eq_attr "memory" "load"
> >  "znver1-direct,znver1-load,znver1-fp0*3")
> >
> >  (define_insn_reservation "znver1_sseimul_avx256_load" 8
> >  (and (eq_attr "cpu" "znver1")
> >   (and (eq_attr "mode" "OI")
> > -  (and (eq_attr "type" "ssemul")
> > +  (and (eq_attr "type" "sseimul")
> > (eq_attr "memory" "load"
> >  "znver1-double,znver1-load,znver1-fp0*4")
> >
> > @@ -942,13 +942,13 @@
> >  (and (eq_attr "cpu" "znver1")
> >   (and (eq_attr "mode" "DI")
> >(and (eq_attr "memory" "none")
> > -   (eq_attr "type" "ssemul"
> > +   (eq_attr "type" "sseimul"
> >  "znver1-direct,znver1-fp0*4")
> > (Snip)
> >
> > Changelog
> >
> > 2016-03-03  Venkataramanan Kumar
> 
> >
> >Fix sseimul type attribute.
> >* config/i386/znver1.md
> >(znver1_sseimul, znver1_sseimul_avx256, znver1_sseimul_load,
> >znver1_sseimul_avx256_load,  znver1_sseimul_di,
> >znver1_sseimul_load_di) : Fix the type attribute.
> >
> > Ok for trunk if bootstrap and testing passes?
> 
> OK.
> 
> BTW: This patch is trivial, according to [1]. The criteria is simply:
> 
> Obvious fixes can be committed without prior approval. Just check in
> the fix and copy it to gcc-patches. A good test to determine whether a
> fix is obvious: will the person who objects to my work the most be
> able to find a fault with my fix? If the fix is later found to be
> faulty, it can always be rolled back. We don't want to get overly
> restrictive about checkin policies.
> 
> [1] https://gcc.gnu.org/svnwrite.html
> 

Thank you I up-streamed in trunk. 
One small change I also did  is reduced the latency by 1 for DI mode in those 
pattern. 
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=234007

regards,
Venkat.

> Thanks,
> Uros.


Re: [Patch X86_64]: Fix multiplication cost for -march=znver1.

2016-03-05 Thread Uros Bizjak
On Sat, Mar 5, 2016 at 1:13 PM, Kumar, Venkataramanan
 wrote:
> Hi Maintainers,
>
> The below patch changes multiplication cost for -march=znver1 target.
> GCC Bootstrap tested with  BOOT_CFLAGS="-O2 -g -march=znver1".
>
> (---Snip---)
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index d8a2909..b5dde5e 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -1350,11 +1350,11 @@ struct processor_costs znver1_cost = {
>COSTS_N_INSNS (1),   /* cost of a lea instruction.  */
>COSTS_N_INSNS (1),   /* variable shift costs.  */
>COSTS_N_INSNS (1),   /* constant shift costs.  */
> -  {COSTS_N_INSNS (4),  /* cost of starting multiply for QI.  
> */
> -   COSTS_N_INSNS (4),  /*   HI.  
> */
> -   COSTS_N_INSNS (4),  /*   SI.  
> */
> -   COSTS_N_INSNS (6),  /*   DI.  
> */
> -   COSTS_N_INSNS (6)}, /*other.  
> */
> +  {COSTS_N_INSNS (3),  /* cost of starting multiply for QI.  
> */
> +   COSTS_N_INSNS (3),  /*   HI.  
> */
> +   COSTS_N_INSNS (3),  /*   SI.  
> */
> +   COSTS_N_INSNS (4),  /*   DI.  
> */
> +   COSTS_N_INSNS (4)}, /*other.  
> */
>0,   /* cost of multiply per each bit
> set.  */
>{COSTS_N_INSNS (19), /* cost of a divide/mod for QI.  */
> (---Snip---)
>
> 2016-03-05  Venkataramanan Kumar  
>
>  * config/i386/i386.c (znver1_cost): Fix Multiply cost.
>
> Ok for trunk?

OK as a trivial change.

Uros.


RE: [Patch X86_64]: Fix multiplication cost for -march=znver1.

2016-03-05 Thread Kumar, Venkataramanan
Hi Uros,

> -Original Message-
> From: Uros Bizjak [mailto:ubiz...@gmail.com]
> Sent: Saturday, March 05, 2016 9:06 PM
> To: Kumar, Venkataramanan
> Cc: gcc-patches@gcc.gnu.org; Richard Beiner (richard.guent...@gmail.com)
> Subject: Re: [Patch X86_64]: Fix multiplication cost for -march=znver1.
> 
> On Sat, Mar 5, 2016 at 1:13 PM, Kumar, Venkataramanan
>  wrote:
> > Hi Maintainers,
> >
> > The below patch changes multiplication cost for -march=znver1 target.
> > GCC Bootstrap tested with  BOOT_CFLAGS="-O2 -g -march=znver1".
> >
> > (---Snip---)
> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index
> > d8a2909..b5dde5e 100644
> > --- a/gcc/config/i386/i386.c
> > +++ b/gcc/config/i386/i386.c
> > @@ -1350,11 +1350,11 @@ struct processor_costs znver1_cost = {
> >COSTS_N_INSNS (1),   /* cost of a lea instruction.  */
> >COSTS_N_INSNS (1),   /* variable shift costs.  */
> >COSTS_N_INSNS (1),   /* constant shift costs.  */
> > -  {COSTS_N_INSNS (4),  /* cost of starting multiply for 
> > QI.  */
> > -   COSTS_N_INSNS (4),  /*   
> > HI.  */
> > -   COSTS_N_INSNS (4),  /*   
> > SI.  */
> > -   COSTS_N_INSNS (6),  /*   
> > DI.  */
> > -   COSTS_N_INSNS (6)}, /*
> > other.  */
> > +  {COSTS_N_INSNS (3),  /* cost of starting multiply for 
> > QI.  */
> > +   COSTS_N_INSNS (3),  /*   
> > HI.  */
> > +   COSTS_N_INSNS (3),  /*   
> > SI.  */
> > +   COSTS_N_INSNS (4),  /*   
> > DI.  */
> > +   COSTS_N_INSNS (4)}, /*
> > other.  */
> >0,   /* cost of multiply per each bit
> > set.  */
> >{COSTS_N_INSNS (19), /* cost of a divide/mod for QI.  */
> > (---Snip---)
> >
> > 2016-03-05  Venkataramanan Kumar
> 
> >
> >  * config/i386/i386.c (znver1_cost): Fix Multiply cost.
> >
> > Ok for trunk?
> 
> OK as a trivial change.

Thank you. I up-streamed the patch.
Ref: https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=234008

> 
> Uros.


[committed, libffi] Match upstream soname

2016-03-05 Thread Richard Henderson

When I went to apply my symbol versioning patch to upstream,
I discovered that upstream had already bumped their soname to
6.4.0, beyond the bump that I'd applied to gcc to 5.0.0.

So I bumped upstream to 7.0.0, including the symbol versioning,
and this adjusts gcc to match.


r~
2016-03-02  Richard Henderson  

* libtool-version: Increase to 7:0:0.
* libffi.map.in: Increase version numbers to 7.0.


diff --git a/libffi/libffi.map.in b/libffi/libffi.map.in
index ca50967..8bd27ef 100644
--- a/libffi/libffi.map.in
+++ b/libffi/libffi.map.in
@@ -3,7 +3,7 @@
 #include 
 #include 
 
-LIBFFI_BASE_5 {
+LIBFFI_BASE_7.0 {
   global:
/* Exported data variables.  */
ffi_type_void;
@@ -46,17 +46,17 @@ LIBFFI_BASE_5 {
 };
 
 #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-LIBFFI_COMPLEX_5 {
+LIBFFI_COMPLEX_7.0 {
   global:
/* Exported data variables.  */
ffi_type_complex_float;
ffi_type_complex_double;
ffi_type_complex_longdouble;
-} LIBFFI_BASE_5;
+} LIBFFI_BASE_7.0;
 #endif
 
 #if FFI_CLOSURES
-LIBFFI_CLOSURE_5 {
+LIBFFI_CLOSURE_7.0 {
   global:
ffi_closure_alloc;
ffi_closure_free;
@@ -66,13 +66,13 @@ LIBFFI_CLOSURE_5 {
ffi_prep_raw_closure_loc;
ffi_prep_java_raw_closure;
ffi_prep_java_raw_closure_loc;
-} LIBFFI_BASE_5;
+} LIBFFI_BASE_7.0;
 #endif
 
 #if FFI_GO_CLOSURES
-LIBFFI_GO_CLOSURE_5 {
+LIBFFI_GO_CLOSURE_7.0 {
   global:
ffi_call_go;
ffi_prep_go_closure;
-} LIBFFI_CLOSURE_5;
+} LIBFFI_CLOSURE_7.0;
 #endif
diff --git a/libffi/libtool-version b/libffi/libtool-version
index 0a841ca..dfb8b11 100644
--- a/libffi/libtool-version
+++ b/libffi/libtool-version
@@ -3,4 +3,4 @@
 # a separate file so that version updates don't involve re-running
 # automake.
 # CURRENT:REVISION:AGE
-5:0:0
+7:0:0


[PATCH] Fix pr70061

2016-03-05 Thread Richard Henderson

The problem is that we are emitting copy sequences to edges without caring
for deferred popping of arguments.  Thus when we began emitting code for the
first block, which in this case starts with a label, we had 32 bytes of
pending stack adjustment, which emit_label flushed.  The ICE is due to the
label not being the first insn in the BB.

There are two equivalent ways to fix this: we can either save/restore
inhibit_defer_pop around these sequences, or we can manually flush any
pending stack adjustment.

This does the latter.  Ok?


r~
* tree-outofssa.c (emit_partition_copy): Flush pending stack adjust.
(insert_value_copy_on_edge): Likewise.

* gcc.c-torture/compile/pr70061.c: New test.


diff --git a/gcc/testsuite/gcc.c-torture/compile/pr70061.c 
b/gcc/testsuite/gcc.c-torture/compile/pr70061.c
new file mode 100644
index 000..a7ebcfc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr70061.c
@@ -0,0 +1,10 @@
+typedef int v8si __attribute__ ((vector_size (32)));
+
+int
+foo(v8si c, v8si d)
+{
+l0:
+  if (c[2])
+d ^= c;
+  return d[3];
+}
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 25286a2..4125529 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-ter.h"
 #include "tree-ssa-coalesce.h"
 #include "tree-outof-ssa.h"
+#include "dojump.h"
 
 /* FIXME: A lot of code here deals with expanding to RTL.  All that code
should be in cfgexpand.c.  */
@@ -220,6 +221,7 @@ emit_partition_copy (rtx dest, rtx src, int unsignedsrcp, 
tree sizeexp)
 }
   else
 emit_move_insn (dest, src);
+  do_pending_stack_adjust ();
 
   rtx_insn *seq = get_insns ();
   end_sequence ();
@@ -312,6 +314,8 @@ insert_value_copy_on_edge (edge e, int dest, tree src, 
source_location locus)
 
   if (x != dest_rtx)
 emit_move_insn (dest_rtx, x);
+  do_pending_stack_adjust ();
+
   seq = get_insns ();
   end_sequence ();
 


[PATCH, fortran, v3] Use Levenshtein spelling suggestions in Fortran FE

2016-03-05 Thread Bernhard Reutner-Fischer
Changes for v2 -> v3:

- rebased

Changes for v1 -> v2:

- subroutines using interfaces
- keyword arguments (named parameters)

Rewrite C++ autovec in plain C.
Factor out levenshtein distance handling into a commonly used
gfc_closest_fuzzy_match().

gcc/fortran/ChangeLog

2015-12-27  Bernhard Reutner-Fischer  

* gfortran.h (gfc_lookup_function_fuzzy): New declaration.
(gfc_closest_fuzzy_match): New declaration.
(vec_push): New definition.
* misc.c (gfc_closest_fuzzy_match): New definition.
* resolve.c: Include spellcheck.h.
(lookup_function_fuzzy_find_candidates): New static function.
(lookup_uop_fuzzy_find_candidates): Likewise.
(lookup_uop_fuzzy): Likewise.
(resolve_operator) : Call lookup_uop_fuzzy.
(gfc_lookup_function_fuzzy): New definition.
(resolve_unknown_f): Call gfc_lookup_function_fuzzy.
* interface.c (check_interface0): Likewise.
(lookup_arg_fuzzy_find_candidates): New static function.
(lookup_arg_fuzzy ): Likewise.
(compare_actual_formal): Call lookup_arg_fuzzy.
* symbol.c: Include spellcheck.h.
(lookup_symbol_fuzzy_find_candidates): New static function.
(lookup_symbol_fuzzy): Likewise.
(gfc_set_default_type): Call lookup_symbol_fuzzy.
(lookup_component_fuzzy_find_candidates): New static function.
(lookup_component_fuzzy): Likewise.
(gfc_find_component): Call lookup_component_fuzzy.

gcc/testsuite/ChangeLog

2015-12-27  Bernhard Reutner-Fischer  

* gfortran.dg/spellcheck-operator.f90: New testcase.
* gfortran.dg/spellcheck-procedure_1.f90: New testcase.
* gfortran.dg/spellcheck-procedure_2.f90: New testcase.
* gfortran.dg/spellcheck-structure.f90: New testcase.
* gfortran.dg/spellcheck-parameter.f90: New testcase.

---

David Malcolm's nice Levenshtein distance spelling check helpers
were used in some parts of other frontends. This proposed patch adds
some spelling corrections to the fortran frontend.

Suggestions are printed if we can find a suitable name, currently
perusing a very simple cutoff factor:
/* If more than half of the letters were misspelled, the suggestion is
   likely to be meaningless.  */
cutoff = MAX (strlen (typo), strlen (best_guess)) / 2;
which effectively skips names with less than 4 characters.
For e.g. structures, one could try to be much smarter in an attempt to
also provide suggestions for single-letter members/components.

This patch covers (at least partly):
- user-defined operators
- structures (types and their components)
- functions
- symbols (variables)
- subroutines using interfaces
- keyword arguments (named parameters)

If anybody has a testcase where a spelling-suggestion would make sense
then please pass it along so we maybe can add support for GCC-7.

Signed-off-by: Bernhard Reutner-Fischer 
---
 gcc/fortran/gfortran.h |  12 +++
 gcc/fortran/interface.c|  72 +--
 gcc/fortran/misc.c |  39 
 gcc/fortran/resolve.c  | 100 -
 gcc/fortran/symbol.c   |  84 -
 gcc/testsuite/gfortran.dg/spellcheck-operator.f90  |  30 +++
 gcc/testsuite/gfortran.dg/spellcheck-parameter.f90 |  15 
 .../gfortran.dg/spellcheck-procedure_1.f90 |  41 +
 .../gfortran.dg/spellcheck-procedure_2.f90 |  35 
 gcc/testsuite/gfortran.dg/spellcheck-structure.f90 |  35 
 10 files changed, 446 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-operator.f90
 create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-parameter.f90
 create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-procedure_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-procedure_2.f90
 create mode 100644 gcc/testsuite/gfortran.dg/spellcheck-structure.f90

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 33fffd8..5c0c403 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2669,6 +2669,17 @@ void gfc_done_2 (void);
 
 int get_c_kind (const char *, CInteropKind_t *);
 
+const char *gfc_closest_fuzzy_match (const char *, char **);
+static inline void
+vec_push (char **&optr, size_t &osz, const char *elt)
+{
+  /* {auto,}vec.safe_push () replacement.  Don't ask..  */
+  // if (strlen (elt) < 4) return; premature optimization: eliminated by cutoff
+  optr = XRESIZEVEC (char *, optr, osz + 2);
+  optr[osz] = CONST_CAST (char *, elt);
+  optr[++osz] = NULL;
+}
+
 /* options.c */
 unsigned int gfc_option_lang_mask (void);
 void gfc_init_options_struct (struct gcc_options *);
@@ -3088,6 +3099,7 @@ bool gfc_type_is_extensible (gfc_symbol *);
 bool gfc_resolve_intrinsic (gfc_symbol *, locus *);
 bool gfc_explicit_interface_required (gfc_symbol *, char *, int);
 extern int gfc_do_concurrent_flag;
+

Re: [PATCH] Fix PR c++/66786 (ICE with nested lambdas in variable template)

2016-03-05 Thread Jason Merrill

On 02/08/2016 12:19 AM, Patrick Palka wrote:

Here, we are calling template_class_depth on a FIELD_DECL corresponding
to a lambda that is used inside variable template.  template_class_depth
however does not see that this FIELD_DECL is used inside a variable
template binding because its chain of DECL_CONTEXTs does not include the
corresponding VAR_DECL.  So template_class_depth returns the wrong
template nesting level which causes its callers to malfunction.  In
particular we strip a template argument level in
tsubst_copy [FIELD_DECL] when we shouldn't have.

This patch makes template_class_depth look at a lambda type's
LAMBDA_TYPE_EXTRA_SCOPE field instead of its TYPE_CONTEXT, so that it
can iterate into an enclosing variable template, if applicable.

Tested on x86_64-pc-linux gnu, no new regressions.  Also tested against
Boost.  Is this OK to commit?


This is breaking several lambda testcases with -fconcepts on; 
LAMBDA_TYPE_EXTRA_SCOPE can also be a FIELD_DECL or PARM_DECL.  Let's 
just check DECL_P.


Jason



C++ PATCH for another c++/67364 testcase (constexpr wrong evaluation)

2016-03-05 Thread Jason Merrill
Lewis reported another testcase which hits the "accessing uninitialized 
member" error, and can lead to wrong values.


Tested x86_64-pc-linux-gnu, applying to trunk.
commit 1bfb2997968d18b337cbd144a698b7be3bf6b28e
Author: Jason Merrill 
Date:   Sat Mar 5 14:44:31 2016 -0500

	PR c++/67364
	* constexpr.c (cxx_eval_store_expression): Replace
	CONSTRUCTOR_ELTS in nested CONSTRUCTORs, too.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c9f9c47..f23e7c9 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2939,39 +2939,34 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
   /* Don't share a CONSTRUCTOR that might be changed later.  */
   init = unshare_expr (init);
   if (target == object)
+/* The hash table might have moved since the get earlier.  */
+valp = ctx->values->get (object);
+
+  if (TREE_CODE (init) == CONSTRUCTOR)
 {
-  /* The hash table might have moved since the get earlier.  */
-  valp = ctx->values->get (object);
-  if (TREE_CODE (init) == CONSTRUCTOR)
-	{
-	  /* An outer ctx->ctor might be pointing to *valp, so replace
-	 its contents.  */
-	  CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
-	  TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
-	  TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
-	}
-  else
-	*valp = init;
+  /* An outer ctx->ctor might be pointing to *valp, so replace
+	 its contents.  */
+  CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
+  TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
+  TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
 }
   else
-{
-  *valp = init;
+*valp = init;
 
-  /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
-	 CONSTRUCTORs.  */
-  tree elt;
-  unsigned i;
-  bool c = TREE_CONSTANT (init);
-  bool s = TREE_SIDE_EFFECTS (init);
-  if (!c || s)
-	FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
-	  {
-	if (!c)
-	  TREE_CONSTANT (elt) = false;
-	if (s)
-	  TREE_SIDE_EFFECTS (elt) = true;
-	  }
-}
+  /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
+ CONSTRUCTORs, if any.  */
+  tree elt;
+  unsigned i;
+  bool c = TREE_CONSTANT (init);
+  bool s = TREE_SIDE_EFFECTS (init);
+  if (!c || s)
+FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
+  {
+	if (!c)
+	  TREE_CONSTANT (elt) = false;
+	if (s)
+	  TREE_SIDE_EFFECTS (elt) = true;
+  }
   release_tree_vector (ctors);
 
   if (*non_constant_p)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C
new file mode 100644
index 000..547dec4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C
@@ -0,0 +1,30 @@
+// PR c++/67364
+// { dg-do compile { target c++11 } }
+
+template 
+struct tuple {
+  Xn storage_;
+
+  constexpr tuple(Xn const& xn)
+: storage_(xn)
+  { }
+
+  template 
+  constexpr tuple(tuple const& other)
+: storage_(other.storage_)
+  { }
+
+  template 
+  constexpr tuple(tuple& other)
+: tuple(const_cast(other))
+  { }
+};
+
+template 
+struct wrapper { T value; };
+
+template 
+constexpr wrapper wrap(T t) { return {t}; }
+
+constexpr wrapper> t = wrap(tuple{2});
+static_assert(t.value.storage_ == 2, "");