mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 15:21:24 +08:00
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. From-SVN: r274169
This commit is contained in:
parent
699ce759c2
commit
529bc4103b
gcc
cp
testsuite
@ -1,3 +1,15 @@
|
||||
2019-08-07 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2019-08-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* parser.c (cp_parser_omp_clause_name): Parse use_device_addr clause.
|
||||
|
@ -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;
|
||||
|
||||
case OBJ_TYPE_REF:
|
||||
if (cxx_dialect >= cxx2a)
|
||||
/* In C++2a virtual calls can be constexpr, don't give up yet. */
|
||||
|
@ -7052,8 +7052,8 @@ enum {
|
||||
extern tree begin_compound_stmt (unsigned int);
|
||||
|
||||
extern void finish_compound_stmt (tree);
|
||||
extern tree finish_asm_stmt (int, tree, tree, tree, tree,
|
||||
tree, bool);
|
||||
extern tree finish_asm_stmt (location_t, int, tree, tree,
|
||||
tree, tree, tree, bool);
|
||||
extern tree finish_label_stmt (tree);
|
||||
extern void finish_label_decl (tree);
|
||||
extern cp_expr finish_parenthesized_expr (cp_expr);
|
||||
|
@ -19817,16 +19817,18 @@ cp_parser_asm_definition (cp_parser* parser)
|
||||
bool invalid_inputs_p = false;
|
||||
bool invalid_outputs_p = false;
|
||||
required_token missing = RT_NONE;
|
||||
location_t asm_loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
|
||||
/* Look for the `asm' keyword. */
|
||||
cp_parser_require_keyword (parser, RID_ASM, RT_ASM);
|
||||
|
||||
/* In C++2a, unevaluated inline assembly is permitted in constexpr
|
||||
functions. */
|
||||
if (parser->in_function_body
|
||||
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
|
||||
{
|
||||
error ("%<asm%> in %<constexpr%> function");
|
||||
cp_function_chain->invalid_constexpr = true;
|
||||
}
|
||||
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl)
|
||||
&& (cxx_dialect < cxx2a))
|
||||
pedwarn (asm_loc, 0, "%<asm%> in %<constexpr%> function only available "
|
||||
"with %<-std=c++2a%> or %<-std=gnu++2a%>");
|
||||
|
||||
/* Handle the asm-qualifier-list. */
|
||||
location_t volatile_loc = UNKNOWN_LOCATION;
|
||||
@ -20032,7 +20034,7 @@ cp_parser_asm_definition (cp_parser* parser)
|
||||
/* Create the ASM_EXPR. */
|
||||
if (parser->in_function_body)
|
||||
{
|
||||
asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
|
||||
asm_stmt = finish_asm_stmt (asm_loc, volatile_p, string, outputs,
|
||||
inputs, clobbers, labels, inline_p);
|
||||
/* If the extended syntax was not used, mark the ASM_EXPR. */
|
||||
if (!extended_p)
|
||||
|
@ -17396,8 +17396,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
|
||||
complain, in_decl);
|
||||
tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
|
||||
complain, in_decl);
|
||||
tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
|
||||
clobbers, labels, ASM_INLINE_P (t));
|
||||
tmp = finish_asm_stmt (EXPR_LOCATION (t), ASM_VOLATILE_P (t), string,
|
||||
outputs, inputs, clobbers, labels,
|
||||
ASM_INLINE_P (t));
|
||||
tree asm_expr = tmp;
|
||||
if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
|
||||
asm_expr = TREE_OPERAND (asm_expr, 0);
|
||||
|
@ -1484,8 +1484,9 @@ finish_compound_stmt (tree stmt)
|
||||
considered volatile, and whether it is asm inline. */
|
||||
|
||||
tree
|
||||
finish_asm_stmt (int volatile_p, tree string, tree output_operands,
|
||||
tree input_operands, tree clobbers, tree labels, bool inline_p)
|
||||
finish_asm_stmt (location_t loc, int volatile_p, tree string,
|
||||
tree output_operands, tree input_operands, tree clobbers,
|
||||
tree labels, bool inline_p)
|
||||
{
|
||||
tree r;
|
||||
tree t;
|
||||
@ -1532,7 +1533,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
|
||||
effectively const. */
|
||||
|| (CLASS_TYPE_P (TREE_TYPE (operand))
|
||||
&& C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
|
||||
cxx_readonly_error (input_location, operand, lv_asm);
|
||||
cxx_readonly_error (loc, operand, lv_asm);
|
||||
|
||||
tree *op = &operand;
|
||||
while (TREE_CODE (*op) == COMPOUND_EXPR)
|
||||
@ -1585,8 +1586,9 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
|
||||
resolve the overloading. */
|
||||
if (TREE_TYPE (operand) == unknown_type_node)
|
||||
{
|
||||
error ("type of %<asm%> operand %qE could not be determined",
|
||||
TREE_VALUE (t));
|
||||
error_at (loc,
|
||||
"type of %<asm%> operand %qE could not be determined",
|
||||
TREE_VALUE (t));
|
||||
operand = error_mark_node;
|
||||
}
|
||||
|
||||
@ -1634,7 +1636,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
|
||||
}
|
||||
}
|
||||
|
||||
r = build_stmt (input_location, ASM_EXPR, string,
|
||||
r = build_stmt (loc, ASM_EXPR, string,
|
||||
output_operands, input_operands,
|
||||
clobbers, labels);
|
||||
ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
|
||||
|
@ -1,3 +1,10 @@
|
||||
2019-08-07 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/91346 - Implement P1668R1, allow unevaluated asm in constexpr.
|
||||
* 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.
|
||||
|
||||
2019-08-07 Janne Blomqvist <jb@gcc.gnu.org>
|
||||
|
||||
PR fortran/53796
|
||||
|
@ -7,7 +7,7 @@ constexpr int f(int i) {
|
||||
thread_local int l = i; // { dg-error "thread_local" }
|
||||
goto foo; // { dg-error "goto" }
|
||||
foo:
|
||||
asm("foo"); // { dg-error "asm" }
|
||||
asm("foo"); // { dg-error "asm" "" { target c++17_down } }
|
||||
int k; // { dg-error "uninitialized" }
|
||||
A a; // { dg-error "non-literal" }
|
||||
return i;
|
||||
|
13
gcc/testsuite/g++.dg/cpp2a/inline-asm1.C
Normal file
13
gcc/testsuite/g++.dg/cpp2a/inline-asm1.C
Normal file
@ -0,0 +1,13 @@
|
||||
// P1668R1: Permit unevaluated inline asm in constexpr functions
|
||||
// PR c++/91346
|
||||
// { dg-do compile { target c++14 } }
|
||||
// { dg-options "" }
|
||||
|
||||
constexpr int
|
||||
foo (int a, int b)
|
||||
{
|
||||
if (__builtin_is_constant_evaluated ())
|
||||
return a + b;
|
||||
asm (""); // { dg-warning ".asm. in .constexpr. function only available with" "" { target c++17_down } }
|
||||
return a;
|
||||
}
|
17
gcc/testsuite/g++.dg/cpp2a/inline-asm2.C
Normal file
17
gcc/testsuite/g++.dg/cpp2a/inline-asm2.C
Normal file
@ -0,0 +1,17 @@
|
||||
// P1668R1: Permit unevaluated inline asm in constexpr functions
|
||||
// PR c++/91346
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
constexpr int
|
||||
foo (bool b)
|
||||
{
|
||||
if (b)
|
||||
return 42;
|
||||
asm (""); // { dg-error "inline assembly is not a constant expression" }
|
||||
// { dg-message "only unevaluated inline assembly" "" { target *-*-* } .-1 }
|
||||
return -1;
|
||||
}
|
||||
|
||||
constexpr int i = foo (true);
|
||||
static_assert(i == 42, "");
|
||||
constexpr int j = foo (false); // { dg-message "in .constexpr. expansion of" }
|
Loading…
x
Reference in New Issue
Block a user