Re: [RFC][IPA-VRP] Re-factor tree-vrp to factor out common code

2016-07-23 Thread kugan

Hi Richard,


As we had value_range_type in tree-ssanames.h why not put value_range there?


For IPA_VRP, we now need value_range used in ipa-prop.h (in ipa-vrp
patch). Based on this, attached patch now adds struct value_range to
tree-ssanames.h and fixes the header files. Please note that I also had
to add other headers in few places due to the dependency. Are you OK
with this ?
Here is alternate patch where we keep struct value_range and enum 
value_range_type to tree-vrp.h. May be it is a better approach? Please 
let me know what is your preference.


Thanks,
Kugan
>From 37129f66a59c435afc301ecce1ba9340fdfc9eb2 Mon Sep 17 00:00:00 2001
From: Kugan Vivekanandarajah 
Date: Tue, 21 Jun 2016 12:42:44 +1000
Subject: [PATCH 4/7] Refactor vrp

---
 gcc/Makefile.in|  1 +
 gcc/asan.c |  1 +
 gcc/builtins.c |  1 +
 gcc/cgraph.c   |  1 +
 gcc/cgraphunit.c   |  1 +
 gcc/fold-const.c   |  1 +
 gcc/gengtype.c |  2 +-
 gcc/gimple-builder.c   |  1 +
 gcc/gimple-laddress.c  |  1 +
 gcc/hsa-gen.c  |  1 +
 gcc/internal-fn.c  |  1 +
 gcc/ipa-cp.c   |  1 +
 gcc/ipa-devirt.c   |  1 +
 gcc/ipa-inline-transform.c |  1 +
 gcc/ipa-inline.c   |  1 +
 gcc/ipa-profile.c  |  1 +
 gcc/ipa-utils.c|  1 +
 gcc/ipa.c  |  1 +
 gcc/lto/lto-partition.c|  1 +
 gcc/lto/lto.c  |  1 +
 gcc/ssa.h  |  1 +
 gcc/targhooks.c|  1 +
 gcc/toplev.c   |  1 +
 gcc/tree-ssa-address.c |  1 +
 gcc/tree-ssanames.h|  5 -
 gcc/tree-vrp.c | 50 +++---
 gcc/tree-vrp.h | 54 ++
 27 files changed, 90 insertions(+), 44 deletions(-)
 create mode 100644 gcc/tree-vrp.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 776f6d7..36ceb76 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2424,6 +2424,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/tree-phinodes.c \
   $(srcdir)/tree-ssa-alias.h \
   $(srcdir)/tree-ssanames.h \
+  $(srcdir)/tree-vrp.h \
   $(srcdir)/ipa-prop.h \
   $(srcdir)/trans-mem.c \
   $(srcdir)/lto-streamer.h \
diff --git a/gcc/asan.c b/gcc/asan.c
index 71095fb..6451c85 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "tm_p.h"
 #include "stringpool.h"
+#include "tree-vrp.h"
 #include "tree-ssanames.h"
 #include "optabs.h"
 #include "emit-rtl.h"
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 5d234a5..a5c36f4 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "predict.h"
 #include "tm_p.h"
 #include "stringpool.h"
+#include "tree-vrp.h"
 #include "tree-ssanames.h"
 #include "expmed.h"
 #include "optabs.h"
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index e256dd0..3a5473a 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "value-prof.h"
 #include "ipa-utils.h"
 #include "symbol-summary.h"
+#include "tree-vrp.h"
 #include "ipa-prop.h"
 #include "ipa-inline.h"
 #include "cfgloop.h"
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 4bfcad7..4fcc368 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -190,6 +190,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "toplev.h"
 #include "debug.h"
 #include "symbol-summary.h"
+#include "tree-vrp.h"
 #include "ipa-prop.h"
 #include "gimple-pretty-print.h"
 #include "plugin.h"
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3b9500d..2068f8a 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -75,6 +75,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "md5.h"
 #include "case-cfn-macros.h"
 #include "stringpool.h"
+#include "tree-vrp.h"
 #include "tree-ssanames.h"
 #include "selftest.h"
 
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 5479b8f..97fe7ee 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1712,7 +1712,7 @@ open_base_files (void)
   "explow.h", "calls.h", "cilk.h", "emit-rtl.h", "varasm.h", "stmt.h",
   "expr.h", "alloc-pool.h", "cselib.h", "insn-addr.h", "optabs.h",
   "libfuncs.h", "debug.h", "internal-fn.h", "gimple-fold.h", "tree-eh.h",
-  "gimple-iterator.h", "gimple-ssa.h", "tree-cfg.h",
+  "gimple-iterator.h", "gimple-ssa.h", "tree-cfg.h", "tree-vrp.h",
   "tree-phinodes.h", "ssa-iterators.h", "stringpool.h", "tree-ssanames.h",
   "tree-ssa-loop.h", "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h",
   "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h", 
diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c
index f124554..4fb21e4 100644
--- a/gcc/gimple-builder.c
+++ b/gcc/gimple-builder.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree

[PATCH] Minor changes in tree-vrp.c

2016-07-23 Thread Patrick Palka
1. When dumping assert details, print loc->expr instead of the bare SSA
name.  loc->expr is not always equal to the SSA name.  For example we
sometimes insert an ASSERT_EXPR like

  x_7 = ASSERT_EXPR  8>;

The diff of the new dump output looks like:

Assertions to be inserted for x_4(D)
if (_4 <= 8)

BB #3
EDGE 2->3 2 [39.0%]  (FALSE_VALUE,EXECUTABLE)
 -  PREDICATE: x_4(D) gt_expr 8
 +  PREDICATE: (unsigned int) x_4(D) + 4294967295 gt_expr 8

2. In extract_code_and_val_from_cond_with_ops verify that name is equal to
either cond_op0 or cond_op1.  If name is not equal to one of these
operands then its caller register_edge_assert_for will malfunction and
the wrong assertion will get inserted.

Is this OK to commit after bootstrap + regtesting?

gcc/ChangeLog:

* tree-vrp.c (dump_asserts_for): Print loc->expr instead of
name.
(extract_code_and_val_from_cond_with_ops): Verify that name is
either cond_op0 or cond_op1.
---
 gcc/tree-vrp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index a3068ec..5072370 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -4827,7 +4827,7 @@ dump_asserts_for (FILE *file, tree name)
  dump_edge_info (file, loc->e, dump_flags, 0);
}
   fprintf (file, "\n\tPREDICATE: ");
-  print_generic_expr (file, name, 0);
+  print_generic_expr (file, loc->expr, 0);
   fprintf (file, " %s ", get_tree_code_name (loc->comp_code));
   print_generic_expr (file, loc->val, 0);
   fprintf (file, "\n\n");
@@ -5009,13 +5009,15 @@ extract_code_and_val_from_cond_with_ops (tree name, 
enum tree_code cond_code,
   comp_code = swap_tree_comparison (cond_code);
   val = cond_op0;
 }
-  else
+  else if (name == cond_op0)
 {
   /* The comparison is of the form NAME COMP VAL, so the
 comparison code remains unchanged.  */
   comp_code = cond_code;
   val = cond_op1;
 }
+  else
+gcc_unreachable ();
 
   /* Invert the comparison code as necessary.  */
   if (invert)
-- 
2.9.2.413.g76d2a70



[PR49366] emit loc exprs for C++ non-virtual pmf template value parms

2016-07-23 Thread Alexandre Oliva
We used to emit, in debug information, the values bound to pointer to
member function template parameters only when they were NULL or
virtual member functions, because those can be represented with
DW_AT_const_value.

In order to represent the symbolic pointer to member function
constants for non-virtual member functions, we'd need to be able to
emit relocations for part of DW_AT_const_value, which we don't.  The
more viable alternative is to use DW_AT_location to represent such
values, as slated for inclusion in DWARFv5, according to
http://www.dwarfstd.org/ShowIssue.php?issue=130412.1>.

With this patch, when we can't emit a DW_AT_const_value, we emit each
"member" of the pointer to member function "record" as a
DW_OP_stack_value DW_OP_piece, as long as the referenced member
function is output in the same translation unit, otherwise we'd get
relocations to external symbols, something to avoid in debug sections.

Regstrapped on x86_64-linux-gnu and i686-pc-linux-gnu, and manually
cross-tested with both endiannesses (just to be sure ;-) with a
mips64-elf target.  Ok to install?

for  gcc/ChangeLog

PR debug/49366
* dwarf2out.c (loc_list_from_tree_1): Expand some CONSTRUCTORs
in DW_OP_pieces, just enough to handle pointers to member
functions.
(gen_remaining_tmpl_value_param_die_attribute): Use a location
expression on DWARFv5 if a constant value doesn't work.

for  gcc/testsuite/ChangeLog

PR debug/49366
* g++.dg/debug/dwarf2/template-params-12.H: New.
* g++.dg/debug/dwarf2/template-params-12f.C: New.
* g++.dg/debug/dwarf2/template-params-12g.C: New.
* g++.dg/debug/dwarf2/template-params-12n.C: New.
* g++.dg/debug/dwarf2/template-params-12s.C: New.
* g++.dg/debug/dwarf2/template-params-12u.C: New.
* g++.dg/debug/dwarf2/template-params-12v.C: New.
* g++.dg/debug/dwarf2/template-params-12w.C: New.
---
 gcc/dwarf2out.c| 93 +-
 .../g++.dg/debug/dwarf2/template-params-12.H   | 17 
 .../g++.dg/debug/dwarf2/template-params-12f.C  |  7 ++
 .../g++.dg/debug/dwarf2/template-params-12g.C  |  7 ++
 .../g++.dg/debug/dwarf2/template-params-12n.C  | 10 +++
 .../g++.dg/debug/dwarf2/template-params-12s.C  |  8 ++
 .../g++.dg/debug/dwarf2/template-params-12u.C  |  7 ++
 .../g++.dg/debug/dwarf2/template-params-12v.C  |  6 ++
 .../g++.dg/debug/dwarf2/template-params-12w.C  |  6 ++
 9 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12.H
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12f.C
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12g.C
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12n.C
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12s.C
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12u.C
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12v.C
 create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/template-params-12w.C

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e3cb586..c658220 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -16142,6 +16142,89 @@ loc_list_from_tree_1 (tree loc, int want_address,
 case COMPLEX_CST:
   if ((ret = cst_pool_loc_descr (loc)))
have_address = 1;
+  else if (TREE_CODE (loc) == CONSTRUCTOR)
+   {
+ tree type = TREE_TYPE (loc);
+ unsigned HOST_WIDE_INT size = int_size_in_bytes (type);
+ unsigned HOST_WIDE_INT offset = 0;
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
+
+ if (TREE_CODE (type) == RECORD_TYPE)
+   {
+ /* This is very limited, but it's enough to output
+pointers to member functions, as long as the
+referenced function is defined in the current
+translation unit.  */
+ FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (loc), cnt, ce)
+   {
+ tree val = ce->value;
+
+ tree field = ce->index;
+
+ if (val)
+   STRIP_NOPS (val);
+
+ if (!field || DECL_BIT_FIELD (field))
+   {
+ expansion_failed (loc, NULL_RTX,
+   "bitfield in record type constructor");
+ size = offset = (unsigned HOST_WIDE_INT)-1;
+ ret = NULL;
+ break;
+   }
+
+ HOST_WIDE_INT fieldsize = tree_to_shwi (DECL_SIZE_UNIT 
(field));
+ unsigned HOST_WIDE_INT pos = int_byte_position (field);
+ gcc_assert (pos + fieldsize <= size);
+ if (pos < offset)
+   {
+ expansion_failed (loc, NULL_RTX,
+

Re: [C PATCH] Don't mark C99 inline functions as always_inline (PR c/71969)

2016-07-23 Thread Richard Biener
On July 22, 2016 5:09:07 PM GMT+02:00, Jakub Jelinek  wrote:
>Hi!
>
>As Richard reported on IRC, we are marking C99 inline (without extern)
>functions as effectively always_inline, even when the intent has been
>to do
>this only for the GNU extern inline functions (i.e. -fgnu89-inline
>extern
>inline or extern inline __attribute__((gnu_inline))).
>
>Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok
>for
>trunk?  The alias-11.c change is needed because the inliner decides not
>to
>inline new_cfi, and as it uses since -std=c11 default C99 inline
>semantics
>without extern, the body isn't emitted.

LGTM,
Richard.

>2016-07-22  Jakub Jelinek  
>
>   PR c/71969
>   * c-decl.c (finish_function): Only set DECL_DISREGARD_INLINE_LIMITS
>   on GNU extern inline functions.
>
>   * gcc.dg/alias-11.c (add_cfi, new_cfi): Change __inline__ to
>   static __inline__.
>   * gcc.dg/pr71969-1.c: New test.
>   * gcc.dg/pr71969-2.c: New test.
>   * gcc.dg/pr71969-3.c: New test.
>
>--- gcc/c/c-decl.c.jj  2016-07-21 08:59:53.0 +0200
>+++ gcc/c/c-decl.c 2016-07-22 13:46:40.766019603 +0200
>@@ -9262,7 +9262,9 @@ finish_function (void)
> 
>   /* For GNU C extern inline functions disregard inline limits.  */
>   if (DECL_EXTERNAL (fndecl)
>-  && DECL_DECLARED_INLINE_P (fndecl))
>+  && DECL_DECLARED_INLINE_P (fndecl)
>+  && (flag_gnu89_inline
>+|| lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (fndecl
> DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
> 
>   /* Genericize before inlining.  Delay genericizing nested functions
>--- gcc/testsuite/gcc.dg/alias-11.c.jj 2008-09-05 12:54:36.0
>+0200
>+++ gcc/testsuite/gcc.dg/alias-11.c2016-07-22 17:01:49.930290850 +0200
>@@ -24,7 +24,7 @@ dw_cfi_node *cie_cfi_head;
> unsigned fde_table_in_use;
> dw_fde_node *fde_table;
> 
>-__inline__ void
>+static __inline__ void
> add_cfi (dw_cfi_node **list_head, dw_cfi_node *cfi)
> {
>   dw_cfi_node **p;
>@@ -35,7 +35,7 @@ add_cfi (dw_cfi_node **list_head, dw_cfi
>   *p = cfi;
> }
> 
>-__inline__ struct dw_cfi_struct *
>+static __inline__ struct dw_cfi_struct *
> new_cfi (void)
> {
>   dw_cfi_node *cfi = (dw_cfi_node *) malloc (sizeof (dw_cfi_node));
>--- gcc/testsuite/gcc.dg/pr71969-1.c.jj2016-07-22 14:18:44.336452571
>+0200
>+++ gcc/testsuite/gcc.dg/pr71969-1.c   2016-07-22 14:25:23.877557343
>+0200
>@@ -0,0 +1,37 @@
>+/* PR c/71969 */
>+/* { dg-do compile } */
>+/* { dg-options "-std=gnu99 -fno-gnu89-inline -O2
>-fdump-tree-einline-details" } */
>+
>+volatile int v;
>+#define S v++;
>+#define S10 S S S S S S S S S S
>+#define S100 S10 S10 S10 S10 S10 S10 S10 S10 S10 S10
>+
>+extern inline void
>+foo (void) { S100 }
>+
>+inline void
>+bar (void) { S100 }
>+
>+static inline void
>+baz (void) { S100 }
>+
>+int
>+main ()
>+{
>+  foo ();
>+  foo ();
>+  foo ();
>+  foo ();
>+  bar ();
>+  bar ();
>+  bar ();
>+  bar ();
>+  baz ();
>+  baz ();
>+  baz ();
>+  baz ();
>+  return 0;
>+}
>+
>+/* { dg-final { scan-tree-dump-times "will not early inline" 12
>"einline" } } */
>--- gcc/testsuite/gcc.dg/pr71969-2.c.jj2016-07-22 14:27:35.781941234
>+0200
>+++ gcc/testsuite/gcc.dg/pr71969-2.c   2016-07-22 14:29:18.873678141
>+0200
>@@ -0,0 +1,23 @@
>+/* PR c/71969 */
>+/* { dg-do compile } */
>+/* { dg-options "-std=gnu99 -fno-gnu89-inline -O2
>-fdump-tree-einline-details" } */
>+
>+volatile int v;
>+#define S v++;
>+#define S10 S S S S S S S S S S
>+#define S100 S10 S10 S10 S10 S10 S10 S10 S10 S10 S10
>+
>+extern inline __attribute__((gnu_inline)) void
>+foo (void) { S100 }
>+
>+int
>+main ()
>+{
>+  foo ();
>+  foo ();
>+  foo ();
>+  foo ();
>+  return 0;
>+}
>+
>+/* { dg-final { scan-tree-dump-times "Inlining foo into main" 4
>"einline" } } */
>--- gcc/testsuite/gcc.dg/pr71969-3.c.jj2016-07-22 14:29:33.300501382
>+0200
>+++ gcc/testsuite/gcc.dg/pr71969-3.c   2016-07-22 14:30:18.360949296
>+0200
>@@ -0,0 +1,38 @@
>+/* PR c/71969 */
>+/* { dg-do compile } */
>+/* { dg-options "-std=gnu99 -fgnu89-inline -O2
>-fdump-tree-einline-details" } */
>+
>+volatile int v;
>+#define S v++;
>+#define S10 S S S S S S S S S S
>+#define S100 S10 S10 S10 S10 S10 S10 S10 S10 S10 S10
>+
>+extern inline void
>+foo (void) { S100 }
>+
>+inline void
>+bar (void) { S100 }
>+
>+static inline void
>+baz (void) { S100 }
>+
>+int
>+main ()
>+{
>+  foo ();
>+  foo ();
>+  foo ();
>+  foo ();
>+  bar ();
>+  bar ();
>+  bar ();
>+  bar ();
>+  baz ();
>+  baz ();
>+  baz ();
>+  baz ();
>+  return 0;
>+}
>+
>+/* { dg-final { scan-tree-dump-times "will not early inline" 8
>"einline" } } */
>+/* { dg-final { scan-tree-dump-times "Inlining foo into main" 4
>"einline" } } */
>
>   Jakub




Re: [PATCH] accept flexible arrays in struct in unions (c++/71912 - [6/7 regression])

2016-07-23 Thread Martin Sebor

On 07/22/2016 01:14 PM, Martin Sebor wrote:

r231665 committed in the 6.0 cycle tightened up the checking of
flexible array members in C++ with the goal of rejecting code
that could lead to hard to find bugs, while at the same time
accepting (with a warning) benign extensions also accepted in
C mode.

c++/71912 is a complaint that G++ rejects one such extension:
defining structs with flexible array members in a union.  When
reviewing the code that causes it to be rejected I realized
that it was, in fact, meant to be accepted and is rejected due
to a bug.

The attached patch fixes that bug and implements more robust
checking for this class of problems.  As in C mode, it accepts
"benign" instances of this idiom (with a pedantic warning) while
still rejecting the erroneous cases.

There are outstanding problems with flexible array members in
C++, such as c++/68489 - arrays of flexible array members are
silently accepted.  In a follow-on patch I will address at
least a part of the problem.  I submit this one separately
since it's considered a regression and as such might be
a candidate for backporting to the 6.x branch.

Is this patch okay for trunk?  For 6.x?


I had looked at the wrong set of test results before posting
the first patch and missed a bunch of test suite failures due
to a bug that let the find_flexarray function descend into
static data members when looking for flexible array members,
causing infinite recursion.

The attached patch fixes that, adds a new test to exercise
the previously untested static data members, and annotates
an invalid regression test with a gd-error directive.

Martin
PR c++/71912 - [6/7 regression] flexible array in struct in union rejected

gcc/cp/ChangeLog:
2016-07-23  Martin Sebor  

	PR c++/71912
	* class.c (struct flexmems_t):  Add members.
	(find_flexarrays): Add arguments.  Correct handling of anonymous
	structs.
	(diagnose_flexarrays): Adjust to issue warnings in addition to errors.
	(check_flexarrays): Add argument.

gcc/testsuite/ChangeLog:
2016-07-23  Martin Sebor  

	PR c++/71912
	* g++.dg/ext/flexary19.C: New test.
	* g++.dg/ext/flexary18.C: New test.
	* g++.dg/ext/flexary4.C: Correct the handling of anonymous structs.
	* g++.dg/torture/pr64312.C: Add a dg-error directive to an ill-formed
	regression test.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b2db7f8..c2c4219 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -149,9 +149,9 @@ static bool accessible_nvdtor_p (tree);
 
 /* Used by find_flexarrays and related.  */
 struct flexmems_t;
-static void find_flexarrays (tree, flexmems_t *);
 static void diagnose_flexarrays (tree, const flexmems_t *);
-static void check_flexarrays (tree, flexmems_t * = NULL);
+static void find_flexarrays (tree, flexmems_t *, bool = false, tree = NULL_TREE);
+static void check_flexarrays (tree, flexmems_t * = NULL, bool = false);
 static void check_bases (tree, int *, int *);
 static void check_bases_and_members (tree);
 static tree create_vtable_ptr (tree, tree *);
@@ -6688,25 +6688,45 @@ field_nonempty_p (const_tree fld)
   return false;
 }
 
-/* Used by find_flexarrays and related.  */
-struct flexmems_t {
+/* Used by find_flexarrays and related functions.  */
+
+struct flexmems_t
+{
   /* The first flexible array member or non-zero array member found
- in order of layout.  */
+ in the order of layout.  */
   tree array;
   /* First non-static non-empty data member in the class or its bases.  */
   tree first;
-  /* First non-static non-empty data member following either the flexible
- array member, if found, or the zero-length array member.  */
-  tree after;
+  /* A pair of the first non-static non-empty data members following
+ either the flexible array member, if found, or the zero-length
+ array member otherwise.  AFTER[1] refers to the first such data
+ member of a union that the struct containing the flexible array
+ member or zero-length array is a member, or NULL when no such
+ union exists.  AFTER[0] refers to the first such data member
+ that is not a member of such a union.  */
+  tree after[2];
+
+  /* The type in which an anonymous struct or union containing ARRAY
+ is defined or null if no such anonymous struct or union exists.  */
+  tree anonctx;
 };
 
 /* Find either the first flexible array member or the first zero-length
array, in that order or preference, among members of class T (but not
-   its base classes), and set members of FMEM accordingly.  */
+   its base classes), and set members of FMEM accordingly.
+   BASE_P is true if T is a base class of another class.
+   PUN is set to the outermost union of which T is a member if one such
+   union exists, otherwise to NULL.  */
 
 static void
-find_flexarrays (tree t, flexmems_t *fmem)
+find_flexarrays (tree t, flexmems_t *fmem, bool base_p,
+		 tree pun /* = NULL_TREE */)
 {
+  /* Set the "pointer" to the outermost enclosing union if not set
+ yet and maintain it for the remainder of the recursion. 

[PATCH] Invalidate argument slots for const/pure calls

2016-07-23 Thread John David Anglin
The attached patch fixes PR middle-end/71712.  We need to invalidate the 
argument slots in
const/pure calls as they are owned by the callee.  The caller can't assume they 
are preserved
across the call.  Fix is similar to that for PR71532.

Tested on hppa-unknown-linux-gnu.

Okay for trunk?

Dave
--
John David Anglin   dave.ang...@bell.net

2016-08-23  John David Anglin  

PR middle-end/71732
* cselib.c (cselib_process_insn): Invalidate argument slots for
const/pure calls.

Index: cselib.c
===
--- cselib.c(revision 238612)
+++ cselib.c(working copy)
@@ -2659,6 +2659,13 @@
   if (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
  || !(RTL_CONST_OR_PURE_CALL_P (insn)))
cselib_invalidate_mem (callmem);
+  else
+   /* For const/pure calls, invalidate any argument slots because
+  they are owned by the callee.  */
+   for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1))
+ if (GET_CODE (XEXP (x, 0)) == USE
+ && MEM_P (XEXP (XEXP (x, 0), 0)))
+   cselib_invalidate_mem (XEXP (XEXP (x, 0), 0));
 }
 
   cselib_record_sets (insn);


Re: [PATCH] RFC: On-demand locations within string-literals

2016-07-23 Thread Martin Sebor

On 07/08/2016 03:49 PM, David Malcolm wrote:

This patch implements precise tracking of source locations for the
individual chars within string literals, so that we can e.g. underline
specific ranges in -Wformat diagnostics.

...

Successfully bootstrapped®rtested on x86_64-pc-linux-gnu.

Thoughts?


I applied the patch to my -Wformat-length branch and managed to
get it to work in the sprintf-length pass in the middle end, but
I'm not sure I did it right (I suspect not, or at least not the
way it should be done).  I couldn't find other places where the
bits it depends on are used (I copied bits and pieces of the code
I used from the C front end until it all fell into place ).  It
would be great if there was a tutorial on how to plug it in where
it isn't used yet (as in the middle end).  For example, how do
I determine what CLK_XXX constant I should pass to the
cpp_create_reader() function in the middle end?

I ran my tests with the patch and while it handled a good number
of test cases it eventually crashed.  A test case for the ICE is
attached though it needs my -Wformat-length patch to trigger it.
You may be able to tell what's wrong from the debugger context
(included in the test case).  If not, you may be able to
reproduce it by applying my latest patch and hacking the three
argument overload of location_from_offset() the way I did (in
the xyz.i comment).  Or I can send you my latest patch with all
this in place.

Beyond that, the range normally works fine, except when macros
are involved like they are in my tests.  You can see the effect
in the range.out file.  (This works without your patch but it
could very well be because I didn't set it up right.)

That's all I have for now.

Martin

# 1 "/src/gcc-49905/gcc/testsuite/gcc.dg/format/c99-sprintf-length-1.c"

char buffer [8];
extern char *ptr;

void f (__builtin_va_list va)
{
  __builtin_sprintf (buffer + sizeof buffer, "%c", 0);
}

/*
(gdb) r
Starting program: /build/gcc-49905/gcc/cc1 -fpreprocessed xyz.i -quiet 
-dumpbase xyz.i -mtune=generic -march=x86-64 -auxbase xyz -Wformat=1 
-Wformat-length=1 -o xyz.s

Breakpoint 1, location_from_offset (loc=2147483652, offset=1, length=2)
at /src/gcc-49905/gcc/gimple-ssa-sprintf.c:369
369 = cpp_create_reader (CLK_GNUC11, ident_hash, line_table);
(gdb) l
364 static location_t
365 location_from_offset (location_t loc, int offset, int length)
366 {
367 #if 1
368   static struct cpp_reader* parse_in
369 = cpp_create_reader (CLK_GNUC11, ident_hash, line_table);
370 
371   static string_concat_db *g_string_concat_db
372 = new (ggc_alloc  ()) string_concat_db ();
373 
(gdb) l
374   source_range range;
375   if (get_source_range_for_substring (parse_in, g_string_concat_db, loc,
376   offset, offset + length, &range))
377 return make_location (range.m_start, range.m_start, range.m_finish);
378   return loc;
379 #else
(gdb) c
/src/gcc-49905/gcc/testsuite/gcc.dg/format/c99-sprintf-length-1.c: In function 
’:
/src/gcc-49905/gcc/testsuite/gcc.dg/format/c99-sprintf-length-1.c:5:6: internal 
compiler error: in get_substring_ranges_for_loc, at input.c:1310
and avoid exercising any of the others.  The buffer and objsize macros
  ^
0x1921136 get_substring_ranges_for_loc
/src/gcc-49905/gcc/input.c:1310
0x19212cc get_source_range_for_substring(cpp_reader*, string_concat_db*, 
unsigned int, int, int, source_range*)
/src/gcc-49905/gcc/input.c:1354
0x17eb1ae location_from_offset
/src/gcc-49905/gcc/gimple-ssa-sprintf.c:375
0x17ed220 compute_format_length
/src/gcc-49905/gcc/gimple-ssa-sprintf.c:1343
0x17edf4c 
pass_sprintf_length::compute_format_length(pass_sprintf_length::call_info 
const&, format_result*)
/src/gcc-49905/gcc/gimple-ssa-sprintf.c:1880
0x17ee780 pass_sprintf_length::handle_gimple_call(gimple_stmt_iterator)
/src/gcc-49905/gcc/gimple-ssa-sprintf.c:2122
0x17ee8cf pass_sprintf_length::execute(function*)
/src/gcc-49905/gcc/gimple-ssa-sprintf.c:2153
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See  for instructions.
[Inferior 1 (process 23446) exited with code 04]


 */
$ cat xyz.c && /build/gcc-49905/gcc/xgcc -B/build/gcc-49905/gcc -Wformat 
-Wformat-length=1 -S xyz.c
char d[2];

#define P(n, f) __builtin_vsprintf (d + sizeof d - n, f, va)

void f (__builtin_va_list va)
{
   __builtin_vsprintf (d + sizeof d - 2, "%#3x", va);
  P (2, "%#3x");
}
xyz.c: In function ‘f’:
xyz.c:7:42: warning: ‘%#3x’ directive writing between 3 and 10 bytes into a 
region of size 2 [-Wformat-length=]
__builtin_vsprintf (d + sizeof d - 2, "%#3x", va);
  ^~
xyz.c:7:42: note: using the range [‘1u’, ‘2147483648u’] for directive argument
xyz.c:7:4: note: format output between 4 and 11 bytes into a dest

Re: [PATCH] RFC: On-demand locations within string-literals

2016-07-23 Thread David Malcolm
On Sat, 2016-07-23 at 15:35 -0600, Martin Sebor wrote:
> On 07/08/2016 03:49 PM, David Malcolm wrote:
> > This patch implements precise tracking of source locations for the
> > individual chars within string literals, so that we can e.g.
> > underline
> > specific ranges in -Wformat diagnostics.
> ...
> > Successfully bootstrapped®rtested on x86_64-pc-linux-gnu.
> > 
> > Thoughts?
> 
> I applied the patch to my -Wformat-length branch and managed to
> get it to work in the sprintf-length pass in the middle end, but
> I'm not sure I did it right (I suspect not, or at least not the
> way it should be done).  I couldn't find other places where the
> bits it depends on are used (I copied bits and pieces of the code
> I used from the C front end until it all fell into place ).  It
> would be great if there was a tutorial on how to plug it in where
> it isn't used yet (as in the middle end).  For example, how do
> I determine what CLK_XXX constant I should pass to the
> cpp_create_reader() function in the middle end?

Thanks for trying it out.  I've been reworking the patch, and I have a
much more robust version that I think is close to being ready, with an
easier interface, some bug fixes, and, ahem, EBCDIC support...  and
more usefully to the average user, gracefully handling of other
encodings.

I'd hoped to post the new version on Monday (along with code that wires
it up into c-common/c-format.c).

Though reading your post, I realize now that my interface is in c
-common.h, and that's not going to be usable for you from the middle
end.  Presumably I'm going to need to rework things to be usable from a
gimple-*.c file.  Is it acceptable to somehow wire this up to a
langhook, so that locations for sprintf-style strings are only
available for c-family, with a graceful fallback on other frontends?

Alternatively, I can post the c-common.h interface for review, and we
can get that good enough for trunk, and then we can work on
generalizing it so it's usable from the middle-end for your new pass.

> I ran my tests with the patch and while it handled a good number
> of test cases it eventually crashed.  A test case for the ICE is
> attached though it needs my -Wformat-length patch to trigger it.
> You may be able to tell what's wrong from the debugger context
> (included in the test case).  If not, you may be able to
> reproduce it by applying my latest patch and hacking the three
> argument overload of location_from_offset() the way I did (in
> the xyz.i comment).  Or I can send you my latest patch with all
> this in place.

My patch has changed a lot, so I don't know how useful debugging is
going to be.  I'd be interested in seeing your latest patch.

> Beyond that, the range normally works fine, except when macros
> are involved like they are in my tests.  You can see the effect
> in the range.out file.  (This works without your patch but it
> could very well be because I didn't set it up right.)

Sadly I can't figure out what's going wrong - but the code's changed a
lot at my end since then.  Sorry.

> That's all I have for now.

Martin
> 

Thanks for posting this, it's very helpful.
Dave

> 


Re: [PATCH] Teach VRP to register assertions along default switch labels (PR 18046)

2016-07-23 Thread kugan



On 23/07/16 05:26, Patrick Palka wrote:

This patch teaches VRP to register along a default switch label
assertions that corresponds to the anti range of each case label.


Hi Patrick,

In case of a larger switch statement with case values that cannot be 
combined, you could end up with very large number of ASSERT_EXPRs in the 
default basic block. I am not sure if this would have any impact on 
compile time/memory usage? If that is the case you might want to punt at 
some length?


Thanks,
Kugan


C++ PATCH for c++/71576 (bitfield and rvalue reference)

2016-07-23 Thread Jason Merrill
The code for recognizing problems with binding a glvalue to a
reference was using real_lvalue_p, which returns 0 for xvalues, so the
code that used that to handle bitfields wasn't handling a bitfield
member of an xvalue.  Fixed by using lvalue_kind instead.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit be097879a53ff700b0b220671e52ab671ab4ddce
Author: Jason Merrill 
Date:   Fri Jul 22 13:51:50 2016 -0400

PR c++/71576 - bitfield and rvalue reference

* call.c (convert_like_real): Use is_bitfield_expr_with_lowered_type.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 061e708..835b02a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6771,7 +6771,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, 
int argnum,
  expr, ref_type);
return error_mark_node;
  }
-   if (lvalue & clk_bitfield)
+   if (is_bitfield_expr_with_lowered_type (expr))
  {
expr = convert_bitfield_to_declared_type (expr);
expr = fold_convert (type, expr);
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield3.C 
b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield3.C
new file mode 100644
index 000..9d2d872
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield3.C
@@ -0,0 +1,14 @@
+// PR c++/71576
+// { dg-do compile { target c++11 } }
+
+template < typename T > T && foo ();
+
+struct A 
+{
+  int i:5;
+};
+
+void foo ()
+{
+  int &&j = foo < A > ().i;
+}


C++ PATCH For c++/71350 (error-recursion ICE with initializer-list)

2016-07-23 Thread Jason Merrill
In this testcase we hit an error and then a warning while trying to
print the name of the function, because the warning wasn't properly
respecting complain.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 559a9aac40a5eb421948cd939637e4fe1c919843
Author: Jason Merrill 
Date:   Fri Jul 22 15:11:55 2016 -0400

PR c++/71350 - error recursion with initializer-list

* decl.c (reshape_init_r): Check complain for missing braces warning.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e5e1121..08fa95d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5894,8 +5894,10 @@ reshape_init_r (tree type, reshape_iter *d, bool 
first_initializer_p,
}
}
 
-  warning (OPT_Wmissing_braces, "missing braces around initializer for 
%qT",
-  type);
+  if (complain & tf_warning)
+   warning (OPT_Wmissing_braces,
+"missing braces around initializer for %qT",
+type);
 }
 
   /* Dispatch to specialized routines.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype66.C 
b/gcc/testsuite/g++.dg/cpp0x/decltype66.C
new file mode 100644
index 000..76ff1e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype66.C
@@ -0,0 +1,19 @@
+// PR c++/71350
+// { dg-do compile { target c++11 } }
+
+template
+struct Array
+{
+T data[N];
+};
+
+template
+struct Foo
+{
+int operator[](const Array& i) const { return 0; }
+auto bar() -> decltype((*this)[{1,2}] * 0) {
+  return *this;// { dg-error "cannot convert" }
+}
+};
+
+template struct Foo;


C++ PATCH for c++/71738 (ICE with multi-template friend)

2016-07-23 Thread Jason Merrill
Here lookup_template_class is tsubsting a TEMPLATE_DECL and then
crashing when it gets a TEMPLATE_DECL back, when a TEMPLATE_DECL is
what it wants to end up with anyway.  This is silly.

The testcase is also silly, since members have access to their
enclosing class and so the friend declaration has no effect.  Less
silly variants of the testcase still don't work.  But fixing this ICE
doesn't need to wait for the more general fix for multi-level template
friends.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 990c17ca879abf64c248d4f68fdb20937d515dbe
Author: Jason Merrill 
Date:   Fri Jul 22 15:37:49 2016 -0400

PR c++/71738 - nested template friend

* pt.c (lookup_template_class_1): Handle getting template from tsubst.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3ee53d1..a44bead 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8601,7 +8601,9 @@ lookup_template_class_1 (tree d1, tree arglist, tree 
in_decl, tree context,
 for parameters in the TYPE_DECL of the alias template
 done earlier.  So be careful while getting the template
 of FOUND.  */
- found = TREE_CODE (found) == TYPE_DECL
+ found = TREE_CODE (found) == TEMPLATE_DECL
+   ? found
+   : TREE_CODE (found) == TYPE_DECL
? TYPE_TI_TEMPLATE (TREE_TYPE (found))
: CLASSTYPE_TI_TEMPLATE (found);
}
diff --git a/gcc/testsuite/g++.dg/template/friend63.C 
b/gcc/testsuite/g++.dg/template/friend63.C
new file mode 100644
index 000..f3a292c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend63.C
@@ -0,0 +1,29 @@
+// PR c++/71738
+
+template < class > struct S
+{
+  template < class > struct A
+  { 
+template < class > struct B
+{
+  template 
+  void operator=(Z) { S::i = 0; }
+};
+  };
+
+  // Note that this friend declaration is useless, since nested classes are
+  // already friends of their enclosing class.
+  template < class X >
+  template < class Y >
+  template < class Z >
+  friend void A < X >::B < Y >::operator= (Z);
+
+private:
+  static int i;
+};
+
+int main()
+{
+  S::A::B b;
+  b = 0;
+}


C++ PATCH for c++/70778 (ICE with member template template parameter)

2016-07-23 Thread Jason Merrill
Here when we partially instantiated the declaration of the AddToFront
partial specialization, which meant substituting into
"Holder", we weren't replacing KeyType in the template
parameter list of Holder, leading to confusion when we encounter it
later and try to substitute in 0.

Tested x86_64-pc-linux-gnu, applying to trunk.


C++ PATCH for c++/70709 (hang with zero-length array member)

2016-07-23 Thread Jason Merrill
Since a zero-length array is represented with a TYPE_MAX_VALUE of
unsigned -1, iterating up from 0 takes a long time.  So let's avoid
that.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 237edb92e3aa09ad1eae62ed633bf161a8590bd7
Author: Jason Merrill 
Date:   Fri Jul 22 17:00:06 2016 -0400

PR c++/70709 - zero-length array member

* class.c (walk_subobject_offsets): Handle 0-length array.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b2db7f8..b537b7e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4175,7 +4175,8 @@ walk_subobject_offsets (tree type,
   /* Avoid recursing into objects that are not interesting.  */
   if (!CLASS_TYPE_P (element_type)
  || !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type)
- || !domain)
+ || !domain
+ || integer_minus_onep (TYPE_MAX_VALUE (domain)))
return 0;
 
   /* Step through each of the elements in the array.  */
diff --git a/gcc/testsuite/g++.dg/ext/array3.C 
b/gcc/testsuite/g++.dg/ext/array3.C
new file mode 100644
index 000..e8940db
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/array3.C
@@ -0,0 +1,19 @@
+// PR c++/70709
+// { dg-options "" }
+
+struct A
+{
+  A (int);
+};
+
+struct B
+{
+  B () {} 
+  A a[0];
+};
+
+struct C
+{
+  C () {} 
+  B a[0];
+};


C++ PATCH for c++/55922 and 63151 (list-value-initialization of base)

2016-07-23 Thread Jason Merrill
Using build_value_init in a base initialization is wrong, because it
calls the complete object constructor and misses protected access.  So
let's handle list-value-initialization in expand_aggr_init_1.

Tested x86_64-pc-linux-gnu, applying to trunk.


Re: C++ PATCH for c++/55922 and 63151 (list-value-initialization of base)

2016-07-23 Thread Jason Merrill
On Sat, Jul 23, 2016 at 10:55 PM, Jason Merrill  wrote:
> Using build_value_init in a base initialization is wrong, because it
> calls the complete object constructor and misses protected access.  So
> let's handle list-value-initialization in expand_aggr_init_1.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
commit db083599cde3a758e04c151b7fd86346ae598a4b
Author: Jason Merrill 
Date:   Fri Jul 22 00:48:45 2016 -0400

PR c++/55922 - list-value-initialization of base

PR c++/63151
* init.c (expand_aggr_init_1): Handle list-initialization from {}.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6047639..6362263 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1817,6 +1817,19 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, 
tree init, int flags,
   return;
 }
 
+  /* List-initialization from {} becomes value-initialization for non-aggregate
+ classes with default constructors.  Handle this here so protected access
+ works.  */
+  if (init && TREE_CODE (init) == TREE_LIST)
+{
+  tree elt = TREE_VALUE (init);
+  if (DIRECT_LIST_INIT_P (elt)
+ && CONSTRUCTOR_ELTS (elt) == 0
+ && CLASSTYPE_NON_AGGREGATE (type)
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+   init = void_type_node;
+}
+
   /* If an explicit -- but empty -- initializer list was present,
  that's value-initialization.  */
   if (init == void_type_node)
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-base2.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-base2.C
new file mode 100644
index 000..68ccad9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-base2.C
@@ -0,0 +1,21 @@
+// PR c++/55922
+// { dg-do run { target c++11 } }
+
+bool called = false;
+
+struct Base {
+  Base() { if (called) throw 1; called = true; }
+};
+
+struct B1 : virtual Base {
+  B1() { }
+};
+
+struct C : B1, virtual Base {
+  C() : B1{}
+  { }
+};
+
+int main() {
+  C c;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-base3.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-base3.C
new file mode 100644
index 000..9febac3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-base3.C
@@ -0,0 +1,17 @@
+// PR c++/71774
+// { dg-do compile { target c++11 } }
+
+class Meow
+{
+  protected:
+Meow() =default;
+virtual void f() {}
+};
+
+class Purr : public Meow
+{
+  public:
+Purr()
+  : Meow{}
+{}  
+};


Re: C++ PATCH for c++/70778 (ICE with member template template parameter)

2016-07-23 Thread Jason Merrill
On Sat, Jul 23, 2016 at 10:50 PM, Jason Merrill  wrote:
> Here when we partially instantiated the declaration of the AddToFront
> partial specialization, which meant substituting into
> "Holder", we weren't replacing KeyType in the template
> parameter list of Holder, leading to confusion when we encounter it
> later and try to substitute in 0.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
commit fa7e4de043897f89467887f84e705cdd3a0cfb79
Author: Jason Merrill 
Date:   Fri Jul 22 16:42:52 2016 -0400

PR c++/70778 - member template template parameter

* pt.c (tsubst): Also substitute into the template of a
BOUND_TEMPLATE_TEMPLATE_PARM.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a44bead..65fa982 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13232,13 +13232,20 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
 
if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
  {
-   tree argvec = tsubst (TYPE_TI_ARGS (t), args,
+   tree tinfo = TYPE_TEMPLATE_INFO (t);
+   /* We might need to substitute into the types of non-type
+  template parameters.  */
+   tree tmpl = tsubst (TI_TEMPLATE (tinfo), args,
+   complain, in_decl);
+   if (tmpl == error_mark_node)
+ return error_mark_node;
+   tree argvec = tsubst (TI_ARGS (tinfo), args,
  complain, in_decl);
if (argvec == error_mark_node)
  return error_mark_node;
 
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
- = build_template_info (TYPE_TI_TEMPLATE (t), argvec);
+ = build_template_info (tmpl, argvec);
  }
  }
break;
diff --git a/gcc/testsuite/g++.dg/template/ttp29.C 
b/gcc/testsuite/g++.dg/template/ttp29.C
new file mode 100644
index 000..7d4e03a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp29.C
@@ -0,0 +1,21 @@
+// PR c++/70778
+
+template 
+struct Stuff
+{
+  template 
+  struct AddToFront;
+
+  template  class Holder, KeyType Indexs>
+  struct AddToFront >
+  {
+  };
+};
+
+template 
+struct Holder {};
+
+int main()
+{
+  Stuff::AddToFront<0, Holder<24> > t;
+}


C++ PATCH for c++/66617 (base list-initialization)

2016-07-23 Thread Jason Merrill
List-initialization of bases with virtual bases was also broken,
because we weren't considering the VTT argument when looking for the
initializer-list argument or passing it through to a constructor.
Fixed by using num_artificial_parms_for.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 4814781775222dba33106197435e1c20514df720
Author: Jason Merrill 
Date:   Fri Jul 22 18:05:03 2016 -0400

PR c++/66617 - virtual base list-initialization

* call.c (add_list_candidates): Handle VTT parm.
(build_new_method_call_1): Likewise.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 2f373a3..802c325 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3577,15 +3577,13 @@ merge_conversion_sequences (conversion *user_seq, 
conversion *std_seq)
 
 static void
 add_list_candidates (tree fns, tree first_arg,
-tree init_list, tree totype,
+const vec *args, tree totype,
 tree explicit_targs, bool template_only,
 tree conversion_path, tree access_path,
 int flags,
 struct z_candidate **candidates,
 tsubst_flags_t complain)
 {
-  vec *args;
-
   gcc_assert (*candidates == NULL);
 
   /* We're looking for a ctor for list-initialization.  */
@@ -3594,6 +3592,9 @@ add_list_candidates (tree fns, tree first_arg,
  avoid the copy constructor call for copy-list-initialization.  */
   flags |= LOOKUP_NO_NARROWING;
 
+  unsigned nart = num_artificial_parms_for (get_first_fn (fns)) - 1;
+  tree init_list = (*args)[nart];
+
   /* Always use the default constructor if the list is empty (DR 990).  */
   if (CONSTRUCTOR_NELTS (init_list) == 0
   && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
@@ -3603,7 +3604,6 @@ add_list_candidates (tree fns, tree first_arg,
   else if (TYPE_HAS_LIST_CTOR (totype))
 {
   flags |= LOOKUP_LIST_ONLY;
-  args = make_tree_vector_single (init_list);
   add_candidates (fns, first_arg, args, NULL_TREE,
  explicit_targs, template_only, conversion_path,
  access_path, flags, candidates, complain);
@@ -3611,14 +3611,20 @@ add_list_candidates (tree fns, tree first_arg,
return;
 }
 
-  args = ctor_to_vec (init_list);
+  /* Expand the CONSTRUCTOR into a new argument vec.  */
+  vec *new_args;
+  vec_alloc (new_args, nart + CONSTRUCTOR_NELTS (init_list));
+  for (unsigned i = 0; i < nart; ++i)
+new_args->quick_push ((*args)[i]);
+  for (unsigned i = 0; i < CONSTRUCTOR_NELTS (init_list); ++i)
+new_args->quick_push (CONSTRUCTOR_ELT (init_list, i)->value);
 
   /* We aren't looking for list-ctors anymore.  */
   flags &= ~LOOKUP_LIST_ONLY;
   /* We allow more user-defined conversions within an init-list.  */
   flags &= ~LOOKUP_NO_CONVERSION;
 
-  add_candidates (fns, first_arg, args, NULL_TREE,
+  add_candidates (fns, first_arg, new_args, NULL_TREE,
  explicit_targs, template_only, conversion_path,
  access_path, flags, candidates, complain);
 }
@@ -3698,16 +3704,16 @@ build_user_type_conversion_1 (tree totype, tree expr, 
int flags,
   gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
  && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
 
+  args = make_tree_vector_single (expr);
   if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
  /* List-initialization.  */
- add_list_candidates (ctors, first_arg, expr, totype, NULL_TREE,
+ add_list_candidates (ctors, first_arg, args, totype, NULL_TREE,
   false, TYPE_BINFO (totype), TYPE_BINFO (totype),
   ctorflags, &candidates, complain);
}
   else
{
- args = make_tree_vector_single (expr);
  add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
  TYPE_BINFO (totype), TYPE_BINFO (totype),
  ctorflags, &candidates, complain);
@@ -8350,15 +8356,20 @@ build_new_method_call_1 (tree instance, tree fns, 
vec **args,
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
 
+  /* The number of arguments artificial parms in ARGS; we subtract one because
+ there's no 'this' in ARGS.  */
+  unsigned skip = num_artificial_parms_for (fn) - 1;
+
   /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
  initializer, not T({ }).  */
-  if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !vec_safe_is_empty (*args)
-  && DIRECT_LIST_INIT_P ((**args)[0]))
+  if (DECL_CONSTRUCTOR_P (fn)
+  && vec_safe_length (user_args) > skip
+  && DIRECT_LIST_INIT_P ((*user_args)[skip]))
 {
-  tree init_list = (**args)[0];
+  tree init_list = (*user_args)[skip];
   tree init = NULL_TREE;
 
-  gcc_assert ((*args)->length () == 1
+  gcc_assert (user_args->length () == skip + 1
  && !(flags & LOOKUP_ONLYCONVERTING));