This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH 1/3] Fix various latent issues revealed by P0732 work.
On Fri, 9 Nov 2018 at 11:32, Kyrill Tkachov <kyrylo.tkachov@foss.arm.com> wrote:
>
>
> On 09/11/18 10:28, Matthew Malcomson wrote:
> > (Third attempt to put this on the mailing list now -- today is not a good day for my email skills :-[)
> >
> > Hi there,
> >
> > This patch has caused a few g++ and libstdc++ regression test failures on arm,
> >
> > I've included the g++ failures below.
> >
> > Do you mind looking into this?
> > Cheers,
> >
> > Matthew
> >
> >
> > dg-cmp-results.sh: Verbosity is 2, Variant is ""
> >
> > Older log file: just-before-problemcase-g++.sum
> > Test Run By matthew on Thu Nov 8 16:45:40 2018
> > Target is arm-none-eabi
> > Host is x86_64-pc-linux-gnu
> >
> > Newer log file: g++-after-problem.sum
> > Test Run By matthew on Thu Nov 8 21:36:14 2018
> > Target is arm-none-eabi
> > Host is x86_64-pc-linux-gnu
> >
> > PASS->FAIL: g++.dg/cpp0x/constexpr-static12.C -std=c++14 scan-assembler-not _ZNSt10unique_ptrC1Ei
> > PASS->FAIL: g++.dg/cpp0x/constexpr-static12.C -std=c++17 scan-assembler-not _ZNSt10unique_ptrC1Ei
> > PASS->FAIL: g++.dg/cpp0x/constexpr-static3.C -std=gnu++14 scan-assembler-not static_initialization
> > PASS->FAIL: g++.dg/cpp0x/constexpr-static3.C -std=gnu++17 scan-assembler-not static_initialization
> > PASS->FAIL: g++.dg/cpp0x/constexpr-static.C -std=gnu++14 scan-assembler-not static_initialization
> > PASS->FAIL: g++.dg/cpp0x/constexpr-static.C -std=gnu++17 scan-assembler-not static_initialization
> > PASS->FAIL: g++.dg/cpp0x/implicit13.C -std=c++14 scan-assembler-not _ZN1BC1Ev
> > PASS->FAIL: g++.dg/cpp0x/implicit13.C -std=c++17 scan-assembler-not _ZN1BC1Ev
> > NA->FAIL: g++.dg/cpp0x/pr83734.C -std=gnu++14 (internal compiler error)
> > PASS->FAIL: g++.dg/cpp0x/pr83734.C -std=gnu++14 (test for excess errors)
> > NA->FAIL: g++.dg/cpp0x/pr83734.C -std=gnu++17 (internal compiler error)
> > PASS->FAIL: g++.dg/cpp0x/pr83734.C -std=gnu++17 (test for excess errors)
> > PASS->FAIL: g++.dg/cpp1y/constexpr-empty3.C -std=c++14 scan-assembler-not static_init
> > PASS->FAIL: g++.dg/cpp1y/constexpr-empty3.C -std=c++17 scan-assembler-not static_init
> >
> >
>
> I believe these are tracked in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87935 FWIW.
>
Yes, that was my intention.
> Kyrill
>
> > On 05/11/18 02:06, Jason Merrill wrote:
> > The initialized_type hunk fixes handling of void AGGR_INIT_EXPRs that call a
> > non-constructor; an AGGR_INIT_EXPR can have void type if its initialization
> > semantics are more complicated than just expanding the call.
> >
> > The cxx_eval_vec_init_1 hunk corrects AGGR_INIT_EXPRs that were
> > nonsensically built to initialize an object of void type. And the
> > build_aggr_init_expr hunk makes sure we don't do that again.
> >
> > The ocp_convert and cxx_eval_outermost_constant_expr hunks deal with making
> > sure that a constant CONSTRUCTOR has the right type.
> >
> > Tested x86_64-pc-linux-gnu, applying to trunk.
> >
> > * cvt.c (ocp_convert): Don't wrap a CONSTRUCTOR in a NOP_EXPR.
> > * constexpr.c (initialized_type): Fix AGGR_INIT_EXPR handling.
> > (cxx_eval_vec_init_1): Correct type of AGGR_INIT_EXPR.
> > (cxx_eval_outermost_constant_expr): Make sure a CONSTRUCTOR has the
> > right type. Don't wrap a CONSTRUCTOR if one was passed in.
> > * tree.c (build_aggr_init_expr): Check for void.
> > ---
> > gcc/cp/constexpr.c | 22 +++++++++++++---------
> > gcc/cp/cvt.c | 10 +++++++++-
> > gcc/cp/tree.c | 2 ++
> > gcc/cp/ChangeLog | 7 +++++++
> > 4 files changed, 31 insertions(+), 10 deletions(-)
> >
> > diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> > index 7692b1727da..4fb1ba527e3 100644
> > --- a/gcc/cp/constexpr.c
> > +++ b/gcc/cp/constexpr.c
> > @@ -2778,8 +2778,10 @@ initialized_type (tree t)
> > {
> > if (TYPE_P (t))
> > return t;
> > - tree type = cv_unqualified (TREE_TYPE (t));
> > - if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
> > + tree type = TREE_TYPE (t);
> > + if (!VOID_TYPE_P (type))
> > + /* No need to look deeper. */;
> > + else if (TREE_CODE (t) == CALL_EXPR)
> > {
> > /* A constructor call has void type, so we need to look deeper. */
> > tree fn = get_function_named_in_call (t);
> > @@ -2787,7 +2789,9 @@ initialized_type (tree t)
> > && DECL_CXX_CONSTRUCTOR_P (fn))
> > type = DECL_CONTEXT (fn);
> > }
> > - return type;
> > + else if (TREE_CODE (t) == AGGR_INIT_EXPR)
> > + type = TREE_TYPE (AGGR_INIT_EXPR_SLOT (t));
> > + return cv_unqualified (type);
> > }
> > /* We're about to initialize element INDEX of an array or class from VALUE.
> > @@ -3000,7 +3004,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
> > &argvec, elttype, LOOKUP_NORMAL,
> > complain);
> > release_tree_vector (argvec);
> > - init = build_aggr_init_expr (TREE_TYPE (init), init);
> > + init = build_aggr_init_expr (elttype, init);
> > pre_init = true;
> > }
> > @@ -5089,7 +5093,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> > r = build_nop (TREE_TYPE (r), r);
> > TREE_CONSTANT (r) = false;
> > }
> > - else if (non_constant_p || r == t)
> > + else if (non_constant_p)
> > return t;
> > if (should_unshare)
> > @@ -5097,18 +5101,18 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> > if (TREE_CODE (r) == CONSTRUCTOR && CLASS_TYPE_P (TREE_TYPE (r)))
> > {
> > + r = adjust_temp_type (type, r);
> > if (TREE_CODE (t) == TARGET_EXPR
> > && TARGET_EXPR_INITIAL (t) == r)
> > return t;
> > - else
> > + else if (TREE_CODE (t) != CONSTRUCTOR)
> > {
> > r = get_target_expr (r);
> > TREE_CONSTANT (r) = true;
> > - return r;
> > }
> > }
> > - else
> > - return r;
> > +
> > + return r;
> > }
> > /* Returns true if T is a valid subexpression of a constant expression,
> > diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
> > index 315b0d6a65a..b04e9a70652 100644
> > --- a/gcc/cp/cvt.c
> > +++ b/gcc/cp/cvt.c
> > @@ -725,7 +725,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
> > /* We need a new temporary; don't take this shortcut. */;
> > else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
> > {
> > - if (same_type_p (type, TREE_TYPE (e)))
> > + tree etype = TREE_TYPE (e);
> > + if (same_type_p (type, etype))
> > /* The call to fold will not always remove the NOP_EXPR as
> > might be expected, since if one of the types is a typedef;
> > the comparison in fold is just equality of pointers, not a
> > @@ -743,9 +744,16 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
> > {
> > /* Don't build a NOP_EXPR of class type. Instead, change the
> > type of the temporary. */
> > + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype));
> > TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
> > return e;
> > }
> > + else if (TREE_CODE (e) == CONSTRUCTOR)
> > + {
> > + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype));
> > + TREE_TYPE (e) = type;
> > + return e;
> > + }
> > else
> > {
> > /* We shouldn't be treating objects of ADDRESSABLE type as
> > diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> > index 74018e97bb7..51af9f2015e 100644
> > --- a/gcc/cp/tree.c
> > +++ b/gcc/cp/tree.c
> > @@ -576,6 +576,8 @@ build_aggr_init_expr (tree type, tree init)
> > tree rval;
> > int is_ctor;
> > + gcc_assert (!VOID_TYPE_P (type));
> > +
> > /* Don't build AGGR_INIT_EXPR in a template. */
> > if (processing_template_decl)
> > return init;
> > diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
> > index 7e9c0e2642a..4f40627a226 100644
> > --- a/gcc/cp/ChangeLog
> > +++ b/gcc/cp/ChangeLog
> > @@ -1,5 +1,12 @@
> > 2018-11-04 Jason Merrill <jason@redhat.com><mailto:jason@redhat.com>
> > + * cvt.c (ocp_convert): Don't wrap a CONSTRUCTOR in a NOP_EXPR.
> > + * constexpr.c (initialized_type): Fix AGGR_INIT_EXPR handling.
> > + (cxx_eval_vec_init_1): Correct type of AGGR_INIT_EXPR.
> > + (cxx_eval_outermost_constant_expr): Make sure a CONSTRUCTOR has the
> > + right type. Don't wrap a CONSTRUCTOR if one was passed in.
> > + * tree.c (build_aggr_init_expr): Check for void.
> > +
> > PR c++/60503 - wrong lambda attribute syntax.
> > * parser.c (cp_parser_lambda_declarator_opt): Fix attribute
> > handling.
> >
> > base-commit: 703d2f69fad4772dc4aedb5327b5e3d88e8e1843
> >
> >
> > On 05/11/18 02:06, Jason Merrill wrote:
> >
> > The initialized_type hunk fixes handling of void AGGR_INIT_EXPRs that call a
> > non-constructor; an AGGR_INIT_EXPR can have void type if its initialization
> > semantics are more complicated than just expanding the call.
> >
> > The cxx_eval_vec_init_1 hunk corrects AGGR_INIT_EXPRs that were
> > nonsensically built to initialize an object of void type. And the
> > build_aggr_init_expr hunk makes sure we don't do that again.
> >
> > The ocp_convert and cxx_eval_outermost_constant_expr hunks deal with making
> > sure that a constant CONSTRUCTOR has the right type.
> >
> > Tested x86_64-pc-linux-gnu, applying to trunk.
> >
> > * cvt.c (ocp_convert): Don't wrap a CONSTRUCTOR in a NOP_EXPR.
> > * constexpr.c (initialized_type): Fix AGGR_INIT_EXPR handling.
> > (cxx_eval_vec_init_1): Correct type of AGGR_INIT_EXPR.
> > (cxx_eval_outermost_constant_expr): Make sure a CONSTRUCTOR has the
> > right type. Don't wrap a CONSTRUCTOR if one was passed in.
> > * tree.c (build_aggr_init_expr): Check for void.
> > ---
> > gcc/cp/constexpr.c | 22 +++++++++++++---------
> > gcc/cp/cvt.c | 10 +++++++++-
> > gcc/cp/tree.c | 2 ++
> > gcc/cp/ChangeLog | 7 +++++++
> > 4 files changed, 31 insertions(+), 10 deletions(-)
> >
> > diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> > index 7692b1727da..4fb1ba527e3 100644
> > --- a/gcc/cp/constexpr.c
> > +++ b/gcc/cp/constexpr.c
> > @@ -2778,8 +2778,10 @@ initialized_type (tree t)
> > {
> > if (TYPE_P (t))
> > return t;
> > - tree type = cv_unqualified (TREE_TYPE (t));
> > - if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
> > + tree type = TREE_TYPE (t);
> > + if (!VOID_TYPE_P (type))
> > + /* No need to look deeper. */;
> > + else if (TREE_CODE (t) == CALL_EXPR)
> > {
> > /* A constructor call has void type, so we need to look deeper. */
> > tree fn = get_function_named_in_call (t);
> > @@ -2787,7 +2789,9 @@ initialized_type (tree t)
> > && DECL_CXX_CONSTRUCTOR_P (fn))
> > type = DECL_CONTEXT (fn);
> > }
> > - return type;
> > + else if (TREE_CODE (t) == AGGR_INIT_EXPR)
> > + type = TREE_TYPE (AGGR_INIT_EXPR_SLOT (t));
> > + return cv_unqualified (type);
> > }
> >
> > /* We're about to initialize element INDEX of an array or class from VALUE.
> > @@ -3000,7 +3004,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
> > &argvec, elttype, LOOKUP_NORMAL,
> > complain);
> > release_tree_vector (argvec);
> > - init = build_aggr_init_expr (TREE_TYPE (init), init);
> > + init = build_aggr_init_expr (elttype, init);
> > pre_init = true;
> > }
> >
> > @@ -5089,7 +5093,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> > r = build_nop (TREE_TYPE (r), r);
> > TREE_CONSTANT (r) = false;
> > }
> > - else if (non_constant_p || r == t)
> > + else if (non_constant_p)
> > return t;
> >
> > if (should_unshare)
> > @@ -5097,18 +5101,18 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> >
> > if (TREE_CODE (r) == CONSTRUCTOR && CLASS_TYPE_P (TREE_TYPE (r)))
> > {
> > + r = adjust_temp_type (type, r);
> > if (TREE_CODE (t) == TARGET_EXPR
> > && TARGET_EXPR_INITIAL (t) == r)
> > return t;
> > - else
> > + else if (TREE_CODE (t) != CONSTRUCTOR)
> > {
> > r = get_target_expr (r);
> > TREE_CONSTANT (r) = true;
> > - return r;
> > }
> > }
> > - else
> > - return r;
> > +
> > + return r;
> > }
> >
> > /* Returns true if T is a valid subexpression of a constant expression,
> > diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
> > index 315b0d6a65a..b04e9a70652 100644
> > --- a/gcc/cp/cvt.c
> > +++ b/gcc/cp/cvt.c
> > @@ -725,7 +725,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
> > /* We need a new temporary; don't take this shortcut. */;
> > else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
> > {
> > - if (same_type_p (type, TREE_TYPE (e)))
> > + tree etype = TREE_TYPE (e);
> > + if (same_type_p (type, etype))
> > /* The call to fold will not always remove the NOP_EXPR as
> > might be expected, since if one of the types is a typedef;
> > the comparison in fold is just equality of pointers, not a
> > @@ -743,9 +744,16 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
> > {
> > /* Don't build a NOP_EXPR of class type. Instead, change the
> > type of the temporary. */
> > + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype));
> > TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
> > return e;
> > }
> > + else if (TREE_CODE (e) == CONSTRUCTOR)
> > + {
> > + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype));
> > + TREE_TYPE (e) = type;
> > + return e;
> > + }
> > else
> > {
> > /* We shouldn't be treating objects of ADDRESSABLE type as
> > diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> > index 74018e97bb7..51af9f2015e 100644
> > --- a/gcc/cp/tree.c
> > +++ b/gcc/cp/tree.c
> > @@ -576,6 +576,8 @@ build_aggr_init_expr (tree type, tree init)
> > tree rval;
> > int is_ctor;
> >
> > + gcc_assert (!VOID_TYPE_P (type));
> > +
> > /* Don't build AGGR_INIT_EXPR in a template. */
> > if (processing_template_decl)
> > return init;
> > diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
> > index 7e9c0e2642a..4f40627a226 100644
> > --- a/gcc/cp/ChangeLog
> > +++ b/gcc/cp/ChangeLog
> > @@ -1,5 +1,12 @@
> > 2018-11-04 Jason Merrill <jason@redhat.com><mailto:jason@redhat.com>
> >
> > + * cvt.c (ocp_convert): Don't wrap a CONSTRUCTOR in a NOP_EXPR.
> > + * constexpr.c (initialized_type): Fix AGGR_INIT_EXPR handling.
> > + (cxx_eval_vec_init_1): Correct type of AGGR_INIT_EXPR.
> > + (cxx_eval_outermost_constant_expr): Make sure a CONSTRUCTOR has the
> > + right type. Don't wrap a CONSTRUCTOR if one was passed in.
> > + * tree.c (build_aggr_init_expr): Check for void.
> > +
> > PR c++/60503 - wrong lambda attribute syntax.
> > * parser.c (cp_parser_lambda_declarator_opt): Fix attribute
> > handling.
> >
> > base-commit: 703d2f69fad4772dc4aedb5327b5e3d88e8e1843
> >
>