On Wed, Aug 07, 2019 at 12:23:25PM -0400, Jason Merrill wrote:
> On Wed, Aug 7, 2019, 9:11 AM Marek Polacek <[email protected]> wrote:
>
> > On Tue, Aug 06, 2019 at 09:25:45PM -0400, Jason Merrill wrote:
> > > Let's downgrade the errors in earlier standard modes to pedwarn. Ok with
> > > that change.
> >
> > Works for me, here's what I'll apply once it passes testing.
> >
> > I removed the diagnostic in potential_constant_expression_1/ASM_EXPR so
> > that
> > we don't generate duplicate pedwarns for the same thing. Hope that's OK.
> >
> > 2019-08-07 Marek Polacek <[email protected]>
> >
> > PR c++/91346 - Implement P1668R1, allow unevaluated asm in
> > constexpr.
> > * constexpr.c (cxx_eval_constant_expression): Handle ASM_EXPR.
> > (potential_constant_expression_1) <case ASM_EXPR>: Allow.
> > * cp-tree.h (finish_asm_stmt): Adjust.
> > * parser.c (cp_parser_asm_definition): Grab the locaion of "asm"
> > and
> > use it. Change an error to a pedwarn. Allow asm in C++2a, warn
> > otherwise.
> > * pt.c (tsubst_expr): Pass a location down to finish_asm_stmt.
> > * semantics.c (finish_asm_stmt): New location_t parameter. Use it.
> >
> > * g++.dg/cpp2a/inline-asm1.C: New test.
> > * g++.dg/cpp2a/inline-asm2.C: New test.
> > * g++.dg/cpp1y/constexpr-neg1.C: Adjust dg-error.
> >
> > diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
> > index 36a66337433..e86b0789b84 100644
> > --- gcc/cp/constexpr.c
> > +++ gcc/cp/constexpr.c
> > @@ -5289,6 +5289,18 @@ cxx_eval_constant_expression (const constexpr_ctx
> > *ctx, tree t,
> > r = void_node;
> > break;
> >
> > + case ASM_EXPR:
> > + if (!ctx->quiet)
> > + {
> > + error_at (cp_expr_loc_or_input_loc (t),
> > + "inline assembly is not a constant expression");
> > + inform (cp_expr_loc_or_input_loc (t),
> > + "only unevaluated inline assembly is allowed in a "
> > + "%<constexpr%> function in C++2a");
> > + }
> > + *non_constant_p = true;
> > + return t;
> > +
> > default:
> > if (STATEMENT_CODE_P (TREE_CODE (t)))
> > {
> > @@ -6469,13 +6481,18 @@ potential_constant_expression_1 (tree t, bool
> > want_rval, bool strict, bool now,
> > /* GCC internal stuff. */
> > case VA_ARG_EXPR:
> > case TRANSACTION_EXPR:
> > - case ASM_EXPR:
> > case AT_ENCODE_EXPR:
> > fail:
> > if (flags & tf_error)
> > error_at (loc, "expression %qE is not a constant expression", t);
> > return false;
> >
> > + case ASM_EXPR:
> > + /* In C++2a, unevaluated inline assembly is permitted in constexpr
> > + functions. If it's used in earlier standard modes, we pedwarn in
> > + cp_parser_asm_definition. */
> > + return true;
> >
>
> Actually, do we need this change? If it's (possibly) unevaluated, we
> shouldn't get here.
We can get here when using asm() in ({ }) like this (ugh):
constexpr int
foo (bool b)
{
if (b)
{
constexpr int i = ({ asm(""); 42; });
return i;
}
else
return 42;
}
static_assert(foo(false) == 42, "");
With the current state of potential_constant_expression_1, we generate
inline-asm3.C: In function ‘constexpr int foo(bool)’:
inline-asm3.C:10:27: error: inline assembly is not a constant expression
10 | constexpr int i = ({ asm(""); 42; });
| ^~~
inline-asm3.C:10:27: note: only unevaluated inline assembly is allowed in a
‘constexpr’ function in C++2a
which I thought was better than what we emit with the hunk revered:
inline-asm3.C: In function ‘constexpr int foo(bool)’:
inline-asm3.C:10:27: error: expression ‘<statement>’ is not a constant
expression
10 | constexpr int i = ({ asm(""); 42; });
| ^~~
But I'm happy to revert that hunk if you want.
Marek