aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-09-22 06:29:20 -0700
committerIan Lance Taylor <iant@golang.org>2022-09-22 06:29:20 -0700
commit795cffe109e28b248a54b8ee583cbae48368c2a7 (patch)
tree0c12b075c51c0d5097f26953835ae540d9f2f501 /gcc/c
parent9f62ed218fa656607740b386c0caa03e65dcd283 (diff)
parentf35be1268c996d993ab0b4ff329734d467474445 (diff)
downloadgcc-795cffe109e28b248a54b8ee583cbae48368c2a7.zip
gcc-795cffe109e28b248a54b8ee583cbae48368c2a7.tar.gz
gcc-795cffe109e28b248a54b8ee583cbae48368c2a7.tar.bz2
Merge from trunk revision f35be1268c996d993ab0b4ff329734d467474445.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog154
-rw-r--r--gcc/c/c-convert.cc25
-rw-r--r--gcc/c/c-decl.cc44
-rw-r--r--gcc/c/c-parser.cc289
-rw-r--r--gcc/c/c-tree.h6
-rw-r--r--gcc/c/c-typeck.cc196
-rw-r--r--gcc/c/gimple-parser.cc5
7 files changed, 566 insertions, 153 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 3aa672b..b7fe1a4 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,157 @@
+2022-09-19 Marek Polacek <polacek@redhat.com>
+
+ PR c/106947
+ * c-typeck.cc (maybe_warn_for_null_address): Don't emit stray
+ notes.
+
+2022-09-15 Richard Biener <rguenther@suse.de>
+
+ * c-decl.cc (build_void_list_node): Remove.
+
+2022-09-14 Julian Brown <julian@codesourcery.com>
+
+ * c-typeck.cc (c_finish_omp_clauses): Remove whole mapping node group
+ on error.
+
+2022-09-07 Joseph Myers <joseph@codesourcery.com>
+
+ * c-parser.cc (c_parser_static_assert_declaration_no_semi)
+ (c_parser_alignas_specifier, c_parser_alignof_expression): Allow
+ for C2x spellings of keywords.
+ (c_parser_postfix_expression): Handle RID_TRUE and RID_FALSE.
+
+2022-09-06 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.cc (c_parser_omp_clause_doacross_sink): Don't verify val
+ in omp_cur_iteration - 1 has integer_type_node type.
+
+2022-09-03 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.cc (c_parser_omp_clause_name): Handle doacross.
+ (c_parser_omp_clause_depend_sink): Renamed to ...
+ (c_parser_omp_clause_doacross_sink): ... this. Add depend_p argument.
+ Handle parsing of doacross(sink:omp_cur_iteration-1). Use
+ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE instead of
+ OMP_CLAUSE_DEPEND_SINK_NEGATIVE, build OMP_CLAUSE_DOACROSS instead
+ of OMP_CLAUSE_DEPEND and set OMP_CLAUSE_DOACROSS_DEPEND flag on it.
+ (c_parser_omp_clause_depend): Use OMP_CLAUSE_DOACROSS_SINK and
+ OMP_CLAUSE_DOACROSS_SOURCE instead of OMP_CLAUSE_DEPEND_SINK and
+ OMP_CLAUSE_DEPEND_SOURCE, build OMP_CLAUSE_DOACROSS for depend(source)
+ and set OMP_CLAUSE_DOACROSS_DEPEND on it.
+ (c_parser_omp_clause_doacross): New function.
+ (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_DOACROSS.
+ (c_parser_omp_depobj): Use OMP_CLAUSE_DEPEND_INVALID instead of
+ OMP_CLAUSE_DEPEND_SOURCE.
+ (c_parser_omp_for_loop): Don't diagnose here linear clause together
+ with ordered with argument.
+ (c_parser_omp_simd): Don't diagnose ordered clause with argument on
+ for simd.
+ (OMP_ORDERED_DEPEND_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DOACROSS.
+ (c_parser_omp_ordered): Handle also doacross and adjust for it
+ diagnostic wording.
+ * c-typeck.cc (c_finish_omp_clauses): Handle OMP_CLAUSE_DOACROSS.
+ Don't handle OMP_CLAUSE_DEPEND_SOURCE and OMP_CLAUSE_DEPEND_SINK.
+
+2022-09-02 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/90885
+ * c-parser.cc (c_parser_string_literal): Clear ret.m_decimal.
+ (c_parser_expr_no_commas): Likewise.
+ (c_parser_conditional_expression): Likewise.
+ (c_parser_binary_expression): Clear m_decimal when popping the
+ stack.
+ (c_parser_unary_expression): Clear ret.m_decimal.
+ (c_parser_has_attribute_expression): Likewise for result.
+ (c_parser_predefined_identifier): Likewise for expr.
+ (c_parser_postfix_expression): Likewise for expr.
+ Set expr.m_decimal when handling a CPP_NUMBER that was a decimal
+ token.
+ * c-tree.h (c_expr::m_decimal): New bitfield.
+ * c-typeck.cc (parser_build_binary_op): Clear result.m_decimal.
+ (parser_build_binary_op): Call check_for_xor_used_as_pow.
+
+2022-09-01 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.cc (grokparms): Handle () in a function declaration the
+ same as (void) for C2X.
+
+2022-08-31 Joseph Myers <joseph@codesourcery.com>
+
+ * c-parser.cc (c_parser_label): Pass attributes to do_case.
+ * c-typeck.cc (do_case): Add argument ATTRS. Pass it to
+ c_add_case_label.
+
+2022-08-26 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.cc (convert_arguments): Handle BUILT_IN_ISSIGNALING.
+
+2022-08-25 Marek Polacek <polacek@redhat.com>
+
+ * c-convert.cc (c_convert) <case POINTER_TYPE>: Handle NULLPTR_TYPE.
+ Give a better diagnostic when converting to nullptr_t.
+ * c-decl.cc (c_init_decl_processing): Perform C-specific nullptr
+ initialization.
+ * c-parser.cc (c_parse_init): Maybe OR D_C2X into mask.
+ (c_parser_postfix_expression): Handle RID_NULLPTR.
+ * c-typeck.cc (null_pointer_constant_p): Return true when expr is
+ nullptr_node.
+ (build_unary_op) <case TRUTH_NOT_EXPR>: Handle NULLPTR_TYPE.
+ (build_conditional_expr): Handle the case when the second/third operand
+ is NULLPTR_TYPE and third/second operand is POINTER_TYPE.
+ (convert_for_assignment): Handle converting an expression of type
+ nullptr_t to pointer/bool.
+ (build_binary_op) <case TRUTH_XOR_EXPR>: Handle NULLPTR_TYPE.
+ <case EQ_EXPR>: Handle comparing operands of type nullptr_t.
+
+2022-08-25 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.cc (start_decl): Do not diagnose initialization of
+ variable-sized objects here.
+ * c-parser.cc (c_parser_braced_init): Add argument DECL. All
+ callers changed.
+ (c_parser_initializer): Diagnose initialization of variable-sized
+ objects other than with braced initializer.
+ (c_parser_braced_init): Use pedwarn_c11 for empty initializer
+ braces and update diagnostic text. Diagnose initialization of
+ variable-sized objects with nonempty braces.
+ * c-typeck.cc (digest_init): Update diagnostic for initialization
+ of variable-sized objects.
+ (really_start_incremental_init, set_designator)
+ (process_init_element): Update comments.
+ (pop_init_level): Allow scalar empty initializers.
+
+2022-08-17 Tobias Burnus <tobias@codesourcery.com>
+ Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR c++/104493
+ * c-decl.cc (c_decl_attributes, finish_decl): Call omp_mappable_type
+ instead of removed langhook.
+ * c-typeck.cc (c_finish_omp_clauses): Likewise.
+
+2022-08-11 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/102633
+ * c-parser.cc (c_parser_initializer): Add new tree parameter. Use it.
+ Call suppress_warning.
+ (c_parser_declaration_or_fndef): Pass d down to c_parser_initializer.
+ (c_parser_omp_declare_reduction): Pass omp_priv down to
+ c_parser_initializer.
+
+2022-08-08 Tom Honermann <tom@honermann.net>
+
+ * c-parser.cc (c_parser_string_literal): Use char8_t as the type
+ of CPP_UTF8STRING when char8_t support is enabled.
+ * c-typeck.cc (digest_init): Allow initialization of an array
+ of character type by a string literal with type array of
+ char8_t.
+
+2022-08-01 David Malcolm <dmalcolm@redhat.com>
+
+ * c-typeck.cc (build_c_cast): Quote names of address spaces in
+ diagnostics.
+ (convert_for_assignment): Add a note to address space mismatch
+ diagnostics, specifying the expected and actual types.
+
2022-07-10 Lewis Hyatt <lhyatt@gmail.com>
PR preprocessor/97498
diff --git a/gcc/c/c-convert.cc b/gcc/c/c-convert.cc
index 18083d5..6e74913 100644
--- a/gcc/c/c-convert.cc
+++ b/gcc/c/c-convert.cc
@@ -133,6 +133,20 @@ c_convert (tree type, tree expr, bool init_const)
(loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
case POINTER_TYPE:
+ /* The type nullptr_t may be converted to a pointer type. The result is
+ a null pointer value. */
+ if (NULLPTR_TYPE_P (TREE_TYPE (e)))
+ {
+ /* To make sure that (void *)nullptr is not a null pointer constant,
+ build_c_cast will create an additional NOP_EXPR around the result
+ of this conversion. */
+ if (TREE_SIDE_EFFECTS (e))
+ ret = build2 (COMPOUND_EXPR, type, e, build_int_cst (type, 0));
+ else
+ ret = build_int_cst (type, 0);
+ goto maybe_fold;
+ }
+ gcc_fallthrough ();
case REFERENCE_TYPE:
ret = convert_to_pointer (type, e);
goto maybe_fold;
@@ -180,7 +194,16 @@ c_convert (tree type, tree expr, bool init_const)
return ret;
}
- error ("conversion to non-scalar type requested");
+ /* If we are converting to nullptr_t, don't say "non-scalar type" because
+ the nullptr_t type is a scalar type. Only nullptr_t shall be converted
+ to nullptr_t. */
+ if (code == NULLPTR_TYPE)
+ {
+ error ("conversion from %qT to %qT", TREE_TYPE (e), type);
+ inform (input_location, "only %qT can be converted to %qT", type, type);
+ }
+ else
+ error ("conversion to non-scalar type requested");
return error_mark_node;
}
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index ae8990c..b09c639 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4531,6 +4531,12 @@ c_init_decl_processing (void)
pushdecl (build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier ("_Bool"),
boolean_type_node));
+ /* C-specific nullptr initialization. */
+ record_builtin_type (RID_MAX, "nullptr_t", nullptr_type_node);
+ /* The size and alignment of nullptr_t is the same as for a pointer to
+ character type. */
+ SET_TYPE_ALIGN (nullptr_type_node, GET_MODE_ALIGNMENT (ptr_mode));
+
input_location = save_loc;
make_fname_decl = c_make_fname_decl;
@@ -5074,8 +5080,7 @@ c_decl_attributes (tree *node, tree attributes, int flags)
&& ((VAR_P (*node) && is_global_var (*node))
|| TREE_CODE (*node) == FUNCTION_DECL))
{
- if (VAR_P (*node)
- && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node)))
+ if (VAR_P (*node) && !omp_mappable_type (TREE_TYPE (*node)))
attributes = tree_cons (get_identifier ("omp declare target implicit"),
NULL_TREE, attributes);
else
@@ -5181,29 +5186,15 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
initialized = false;
else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
- /* A complete type is ok if size is fixed. */
-
- if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl)))
- || C_DECL_VARIABLE_SIZE (decl))
- {
- error ("variable-sized object may not be initialized");
- initialized = false;
- }
+ /* A complete type is ok if size is fixed. If the size is
+ variable, an empty initializer is OK and nonempty
+ initializers will be diagnosed in the parser. */
}
else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
{
error ("variable %qD has initializer but incomplete type", decl);
initialized = false;
}
- else if (C_DECL_VARIABLE_SIZE (decl))
- {
- /* Although C99 is unclear about whether incomplete arrays
- of VLAs themselves count as VLAs, it does not make
- sense to permit them to be initialized given that
- ordinary VLAs may not be initialized. */
- error ("variable-sized object may not be initialized");
- initialized = false;
- }
}
if (initialized)
@@ -5701,7 +5692,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
DECL_ATTRIBUTES (decl)
= remove_attribute ("omp declare target implicit",
DECL_ATTRIBUTES (decl));
- if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (decl)))
+ if (!omp_mappable_type (TREE_TYPE (decl)))
error ("%q+D in declare target directive does not have mappable type",
decl);
else if (!lookup_attribute ("omp declare target",
@@ -7877,7 +7868,7 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
error ("%<[*]%> not allowed in other than function prototype scope");
}
- if (arg_types == NULL_TREE && !funcdef_flag
+ if (arg_types == NULL_TREE && !funcdef_flag && !flag_isoc2x
&& !in_system_header_at (input_location))
warning (OPT_Wstrict_prototypes,
"function declaration isn%'t a prototype");
@@ -7905,9 +7896,8 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
tree parm, type, typelt;
unsigned int parmno;
- /* In C2X, convert () in a function definition to (void). */
+ /* In C2X, convert () to (void). */
if (flag_isoc2x
- && funcdef_flag
&& !arg_types
&& !arg_info->parms)
arg_types = arg_info->types = void_list_node;
@@ -10686,14 +10676,6 @@ record_builtin_type (enum rid rid_index, const char *name, tree type)
debug_hooks->type_decl (decl, false);
}
-/* Build the void_list_node (void_type_node having been created). */
-tree
-build_void_list_node (void)
-{
- tree t = build_tree_list (NULL_TREE, void_type_node);
- return t;
-}
-
/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR. */
struct c_parm *
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 92049d1..bce79d3 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -119,6 +119,8 @@ c_parse_init (void)
mask |= D_CXXONLY;
if (!flag_isoc99)
mask |= D_C99;
+ if (!flag_isoc2x)
+ mask |= D_C2X;
if (flag_no_asm)
{
mask |= D_ASM | D_EXT;
@@ -1521,9 +1523,9 @@ static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
static tree c_parser_simple_asm_expr (c_parser *);
static tree c_parser_gnu_attributes (c_parser *);
-static struct c_expr c_parser_initializer (c_parser *);
+static struct c_expr c_parser_initializer (c_parser *, tree);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
- struct obstack *);
+ struct obstack *, tree);
static void c_parser_initelt (c_parser *, struct obstack *);
static void c_parser_initval (c_parser *, struct c_expr *,
struct obstack *);
@@ -2286,7 +2288,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
int flag_sanitize_save = flag_sanitize;
if (TREE_CODE (d) == PARM_DECL)
flag_sanitize = 0;
- init = c_parser_initializer (parser);
+ init = c_parser_initializer (parser, d);
flag_sanitize = flag_sanitize_save;
finish_init ();
}
@@ -2628,13 +2630,14 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
tree string = NULL_TREE;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
+ tree spelling = c_parser_peek_token (parser)->value;
assert_loc = c_parser_peek_token (parser)->location;
if (flag_isoc99)
pedwarn_c99 (assert_loc, OPT_Wpedantic,
- "ISO C99 does not support %<_Static_assert%>");
+ "ISO C99 does not support %qE", spelling);
else
pedwarn_c99 (assert_loc, OPT_Wpedantic,
- "ISO C90 does not support %<_Static_assert%>");
+ "ISO C90 does not support %qE", spelling);
c_parser_consume_token (parser);
matching_parens parens;
if (!parens.require_open (parser))
@@ -2665,7 +2668,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
new C2X feature of _Static_assert. */
pedwarn_c11 (assert_loc, OPT_Wpedantic,
"ISO C11 does not support omitting the string in "
- "%<_Static_assert%>");
+ "%qE", spelling);
parens.require_close (parser);
if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
@@ -3772,13 +3775,14 @@ c_parser_alignas_specifier (c_parser * parser)
tree ret = error_mark_node;
location_t loc = c_parser_peek_token (parser)->location;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
+ tree spelling = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
if (flag_isoc99)
pedwarn_c99 (loc, OPT_Wpedantic,
- "ISO C99 does not support %<_Alignas%>");
+ "ISO C99 does not support %qE", spelling);
else
pedwarn_c99 (loc, OPT_Wpedantic,
- "ISO C90 does not support %<_Alignas%>");
+ "ISO C90 does not support %qE", spelling);
matching_parens parens;
if (!parens.require_open (parser))
return ret;
@@ -5211,19 +5215,34 @@ c_parser_type_name (c_parser *parser, bool alignas_ok)
Any expression without commas is accepted in the syntax for the
constant-expressions, with non-constant expressions rejected later.
+ DECL is the declaration we're parsing this initializer for.
+
This function is only used for top-level initializers; for nested
ones, see c_parser_initval. */
static struct c_expr
-c_parser_initializer (c_parser *parser)
+c_parser_initializer (c_parser *parser, tree decl)
{
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- return c_parser_braced_init (parser, NULL_TREE, false, NULL);
+ return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
else
{
struct c_expr ret;
location_t loc = c_parser_peek_token (parser)->location;
+ if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
+ error_at (loc,
+ "variable-sized object may not be initialized except "
+ "with an empty initializer");
ret = c_parser_expr_no_commas (parser, NULL);
+ /* This is handled mostly by gimplify.cc, but we have to deal with
+ not warning about int x = x; as it is a GCC extension to turn off
+ this warning but only if warn_init_self is zero. */
+ if (VAR_P (decl)
+ && !DECL_EXTERNAL (decl)
+ && !TREE_STATIC (decl)
+ && ret.value == decl
+ && !warn_init_self)
+ suppress_warning (decl, OPT_Winit_self);
if (TREE_CODE (ret.value) != STRING_CST
&& TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
ret = convert_lvalue_to_rvalue (loc, ret, true, true);
@@ -5240,11 +5259,12 @@ location_t last_init_list_comma;
compound literal, and NULL_TREE for other initializers and for
nested braced lists. NESTED_P is true for nested braced lists,
false for the list of a compound literal or the list that is the
- top-level initializer in a declaration. */
+ top-level initializer in a declaration. DECL is the declaration for
+ the top-level initializer for a declaration, otherwise NULL_TREE. */
static struct c_expr
c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
- struct obstack *outer_obstack)
+ struct obstack *outer_obstack, tree decl)
{
struct c_expr ret;
struct obstack braced_init_obstack;
@@ -5262,10 +5282,15 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
really_start_incremental_init (type);
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
- pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces");
+ pedwarn_c11 (brace_loc, OPT_Wpedantic,
+ "ISO C forbids empty initializer braces before C2X");
}
else
{
+ if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
+ error_at (brace_loc,
+ "variable-sized object may not be initialized except "
+ "with an empty initializer");
/* Parse a non-empty initializer list, possibly with a trailing
comma. */
while (true)
@@ -5439,6 +5464,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
= objc_build_message_expr (rec, args);
mexpr.original_code = ERROR_MARK;
mexpr.original_type = NULL;
+ mexpr.m_decimal = 0;
/* Now parse and process the remainder of the
initializer, starting with this message
expression as a primary-expression. */
@@ -5521,7 +5547,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
init = c_parser_braced_init (parser, NULL_TREE, true,
- braced_init_obstack);
+ braced_init_obstack, NULL_TREE);
else
{
init = c_parser_expr_no_commas (parser, after);
@@ -5889,14 +5915,14 @@ c_parser_label (c_parser *parser, tree std_attrs)
if (c_parser_next_token_is (parser, CPP_COLON))
{
c_parser_consume_token (parser);
- label = do_case (loc1, exp1, NULL_TREE);
+ label = do_case (loc1, exp1, NULL_TREE, std_attrs);
}
else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
{
c_parser_consume_token (parser);
exp2 = c_parser_expr_no_commas (parser, NULL).value;
if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- label = do_case (loc1, exp1, exp2);
+ label = do_case (loc1, exp1, exp2, std_attrs);
}
else
c_parser_error (parser, "expected %<:%> or %<...%>");
@@ -5905,7 +5931,7 @@ c_parser_label (c_parser *parser, tree std_attrs)
{
c_parser_consume_token (parser);
if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- label = do_case (loc1, NULL_TREE, NULL_TREE);
+ label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
}
else
{
@@ -7447,7 +7473,14 @@ c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
default:
case CPP_STRING:
case CPP_UTF8STRING:
- value = build_string (1, "");
+ if (type == CPP_UTF8STRING && flag_char8_t)
+ {
+ value = build_string (TYPE_PRECISION (char8_type_node)
+ / TYPE_PRECISION (char_type_node),
+ ""); /* char8_t is 8 bits */
+ }
+ else
+ value = build_string (1, "");
break;
case CPP_STRING16:
value = build_string (TYPE_PRECISION (char16_type_node)
@@ -7472,9 +7505,14 @@ c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
{
default:
case CPP_STRING:
- case CPP_UTF8STRING:
TREE_TYPE (value) = char_array_type_node;
break;
+ case CPP_UTF8STRING:
+ if (flag_char8_t)
+ TREE_TYPE (value) = char8_array_type_node;
+ else
+ TREE_TYPE (value) = char_array_type_node;
+ break;
case CPP_STRING16:
TREE_TYPE (value) = char16_array_type_node;
break;
@@ -7496,6 +7534,7 @@ c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
ret.original_code = STRING_CST;
ret.original_type = NULL_TREE;
set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc));
+ ret.m_decimal = 0;
parser->seen_string_literal = true;
return ret;
}
@@ -7575,6 +7614,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
code, exp_location, rhs.value,
rhs.original_type);
+ ret.m_decimal = 0;
set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
if (code == NOP_EXPR)
ret.original_code = MODIFY_EXPR;
@@ -7712,6 +7752,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
: NULL);
}
set_c_expr_source_range (&ret, start, exp2.get_finish ());
+ ret.m_decimal = 0;
return ret;
}
@@ -7901,6 +7942,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
TREE_OPERAND (t, 0) = stack[0].expr.value; \
TREE_OPERAND (t, 1) = stack[1].expr.value; \
stack[0].expr.value = t; \
+ stack[0].expr.m_decimal = 0; \
} \
else \
stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
@@ -8105,6 +8147,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
set_c_expr_source_range (&ret, cast_loc, expr.get_finish ());
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
+ ret.m_decimal = 0;
return ret;
}
else
@@ -8187,6 +8230,7 @@ c_parser_unary_expression (c_parser *parser)
ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
ret.src_range.m_start = op_loc;
ret.src_range.m_finish = finish;
+ ret.m_decimal = 0;
return ret;
}
case CPP_PLUS:
@@ -8359,10 +8403,12 @@ c_parser_alignof_expression (c_parser *parser)
location_t end_loc;
tree alignof_spelling = c_parser_peek_token (parser)->value;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
- bool is_c11_alignof = strcmp (IDENTIFIER_POINTER (alignof_spelling),
- "_Alignof") == 0;
+ bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
+ "_Alignof") == 0
+ || strcmp (IDENTIFIER_POINTER (alignof_spelling),
+ "alignof") == 0);
/* A diagnostic is not required for the use of this identifier in
- the implementation namespace; only diagnose it for the C11
+ the implementation namespace; only diagnose it for the C11 or C2X
spelling because of existing code using the other spellings. */
if (is_c11_alignof)
{
@@ -8420,6 +8466,7 @@ c_parser_alignof_expression (c_parser *parser)
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
set_c_expr_source_range (&ret, start_loc, end_loc);
+ ret.m_decimal = 0;
return ret;
}
else
@@ -8439,6 +8486,7 @@ c_parser_alignof_expression (c_parser *parser)
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
set_c_expr_source_range (&ret, start_loc, end_loc);
+ ret.m_decimal = 0;
return ret;
}
}
@@ -8560,6 +8608,7 @@ c_parser_has_attribute_expression (c_parser *parser)
result.value = boolean_false_node;
set_c_expr_source_range (&result, start, finish);
+ result.m_decimal = 0;
return result;
}
@@ -8925,6 +8974,7 @@ c_parser_predefined_identifier (c_parser *parser)
expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
c_parser_peek_token (parser)->value);
set_c_expr_source_range (&expr, loc, loc);
+ expr.m_decimal = 0;
c_parser_consume_token (parser);
return expr;
}
@@ -9003,12 +9053,14 @@ c_parser_postfix_expression (c_parser *parser)
source_range tok_range = c_parser_peek_token (parser)->get_range ();
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
+ expr.m_decimal = 0;
switch (c_parser_peek_token (parser)->type)
{
case CPP_NUMBER:
expr.value = c_parser_peek_token (parser)->value;
set_c_expr_source_range (&expr, tok_range);
loc = c_parser_peek_token (parser)->location;
+ expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
c_parser_consume_token (parser);
if (TREE_CODE (expr.value) == FIXED_CST
&& !targetm.fixed_point_supported_p ())
@@ -10220,6 +10272,24 @@ c_parser_postfix_expression (c_parser *parser)
"%<depend%> clause");
expr.set_error ();
break;
+ /* C23 'nullptr' literal. */
+ case RID_NULLPTR:
+ c_parser_consume_token (parser);
+ expr.value = nullptr_node;
+ set_c_expr_source_range (&expr, tok_range);
+ pedwarn_c11 (loc, OPT_Wpedantic,
+ "ISO C does not support %qs before C2X", "nullptr");
+ break;
+ case RID_TRUE:
+ c_parser_consume_token (parser);
+ expr.value = boolean_true_node;
+ set_c_expr_source_range (&expr, tok_range);
+ break;
+ case RID_FALSE:
+ c_parser_consume_token (parser);
+ expr.value = boolean_false_node;
+ set_c_expr_source_range (&expr, tok_range);
+ break;
default:
c_parser_error (parser, "expected expression");
expr.set_error ();
@@ -10284,7 +10354,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
error_at (type_loc, "compound literal has variable size");
type = error_mark_node;
}
- init = c_parser_braced_init (parser, type, false, NULL);
+ init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE);
finish_init ();
maybe_warn_string_init (type_loc, type, init);
@@ -10317,6 +10387,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
expr.value = build_compound_literal (start_loc, type, init.value, non_const,
alignas_align);
set_c_expr_source_range (&expr, init.src_range);
+ expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
if (type != error_mark_node
@@ -10531,6 +10602,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
+ expr.m_decimal = 0;
break;
case CPP_OPEN_PAREN:
/* Function call. */
@@ -10579,6 +10651,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
= c_build_function_call_vec (expr_loc, arg_loc, expr.value,
exprlist, origtypes);
set_c_expr_source_range (&expr, start, finish);
+ expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) == INTEGER_CST
@@ -10629,6 +10702,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
expr.original_type = DECL_BIT_FIELD_TYPE (field);
}
+ expr.m_decimal = 0;
break;
case CPP_DEREF:
/* Structure element reference. */
@@ -10670,6 +10744,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
expr.original_type = DECL_BIT_FIELD_TYPE (field);
}
+ expr.m_decimal = 0;
break;
case CPP_PLUS_PLUS:
/* Postincrement. */
@@ -10740,6 +10815,7 @@ c_parser_expression (c_parser *parser)
expr.value = build_compound_expr (loc, expr.value, next.value);
expr.original_code = COMPOUND_EXPR;
expr.original_type = next.original_type;
+ expr.m_decimal = 0;
}
return expr;
}
@@ -12771,6 +12847,8 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
else if (!strcmp ("dist_schedule", p))
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+ else if (!strcmp ("doacross", p))
+ result = PRAGMA_OMP_CLAUSE_DOACROSS;
break;
case 'e':
if (!strcmp ("enter", p))
@@ -13188,6 +13266,7 @@ c_parser_omp_variable_list (c_parser *parser,
t_expr.original_code = ERROR_MARK;
t_expr.original_type = NULL;
set_c_expr_source_range (&t_expr, op_loc, op_loc);
+ t_expr.m_decimal = 0;
t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
true, false);
t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
@@ -15919,8 +15998,8 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list)
*/
static tree
-c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
- tree list)
+c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
+ tree list, bool depend_p)
{
tree vec = NULL;
if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -15930,6 +16009,30 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
return list;
}
+ if (!depend_p)
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "omp_cur_iteration") == 0
+ && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
+ && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER
+ && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN)
+ {
+ tree val = c_parser_peek_nth_token (parser, 3)->value;
+ if (integer_onep (val))
+ {
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_CHAIN (u) = list;
+ return u;
+ }
+ }
+ }
+
+
+
while (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_token (parser)->id_kind == C_ID_ID)
{
@@ -15975,7 +16078,7 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
{
vec = tree_cons (addend, t, vec);
if (neg)
- OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
}
if (c_parser_next_token_is_not (parser, CPP_COMMA)
@@ -15989,8 +16092,9 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
if (vec == NULL_TREE)
return list;
- tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK;
+ tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
OMP_CLAUSE_DECL (u) = nreverse (vec);
OMP_CLAUSE_CHAIN (u) = list;
return u;
@@ -16182,6 +16286,7 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
+ enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
tree nl, c, iterators = NULL_TREE;
matching_parens parens;
@@ -16213,9 +16318,9 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
else if (strcmp ("depobj", p) == 0)
kind = OMP_CLAUSE_DEPEND_DEPOBJ;
else if (strcmp ("sink", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SINK;
+ dkind = OMP_CLAUSE_DOACROSS_SINK;
else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
+ dkind = OMP_CLAUSE_DOACROSS_SOURCE;
else
goto invalid_kind;
break;
@@ -16225,18 +16330,20 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
c_parser_consume_token (parser);
if (iterators
- && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+ && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
+ || dkind == OMP_CLAUSE_DOACROSS_SINK))
{
pop_scope ();
error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
- kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
iterators = NULL_TREE;
}
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
{
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
+ OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
OMP_CLAUSE_DECL (c) = NULL_TREE;
OMP_CLAUSE_CHAIN (c) = list;
parens.skip_until_found_close (parser);
@@ -16246,8 +16353,8 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
goto resync_fail;
- if (kind == OMP_CLAUSE_DEPEND_SINK)
- nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list);
+ if (dkind == OMP_CLAUSE_DOACROSS_SINK)
+ nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true);
else
{
nl = c_parser_omp_variable_list (parser, clause_loc,
@@ -16283,6 +16390,65 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
return list;
}
+/* OpenMP 5.2:
+ doacross ( source : )
+ doacross ( source : omp_cur_iteration )
+
+ doacross ( sink : vec )
+ doacross ( sink : omp_cur_iteration - logical_iteration ) */
+
+static tree
+c_parser_omp_clause_doacross (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
+ tree nl;
+ const char *p;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ goto invalid_kind;
+
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp ("sink", p) == 0)
+ kind = OMP_CLAUSE_DOACROSS_SINK;
+ else if (strcmp ("source", p) == 0)
+ kind = OMP_CLAUSE_DOACROSS_SOURCE;
+ else
+ goto invalid_kind;
+
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto resync_fail;
+
+ if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
+ {
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "omp_cur_iteration") == 0)
+ c_parser_consume_token (parser);
+ nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
+ OMP_CLAUSE_DECL (nl) = NULL_TREE;
+ OMP_CLAUSE_CHAIN (nl) = list;
+ }
+ else
+ nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false);
+
+ parens.skip_until_found_close (parser);
+ return nl;
+
+ invalid_kind:
+ c_parser_error (parser, "invalid doacross kind");
+ resync_fail:
+ parens.skip_until_found_close (parser);
+ return list;
+}
+
/* OpenMP 4.0:
map ( map-kind: variable-list )
map ( variable-list )
@@ -17200,6 +17366,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_depend (parser, clauses);
c_name = "depend";
break;
+ case PRAGMA_OMP_CLAUSE_DOACROSS:
+ clauses = c_parser_omp_clause_doacross (parser, clauses);
+ c_name = "doacross";
+ break;
case PRAGMA_OMP_CLAUSE_MAP:
clauses = c_parser_omp_clause_map (parser, clauses);
c_name = "map";
@@ -19144,7 +19314,7 @@ c_parser_omp_depobj (c_parser *parser)
parens.skip_until_found_close (parser);
tree clause = NULL_TREE;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
location_t c_loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_NAME))
{
@@ -19183,7 +19353,7 @@ c_parser_omp_depobj (c_parser *parser)
else if (!strcmp ("inoutset", p2))
kind = OMP_CLAUSE_DEPEND_INOUTSET;
}
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (kind == OMP_CLAUSE_DEPEND_INVALID)
{
clause = error_mark_node;
error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
@@ -19195,7 +19365,7 @@ c_parser_omp_depobj (c_parser *parser)
clause = error_mark_node;
}
}
- if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
{
clause = error_mark_node;
error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
@@ -19394,19 +19564,6 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
= build_int_cst (NULL_TREE, collapse);
ordered = collapse;
}
- if (ordered)
- {
- for (tree *pc = &clauses; *pc; )
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
- {
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<linear%> clause may not be specified together "
- "with %<ordered%> clause with a parameter");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- }
- else
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
count = ordered ? ordered : collapse;
@@ -19844,15 +20001,6 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
{
omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
- tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
- OMP_CLAUSE_ORDERED);
- if (c && OMP_CLAUSE_ORDERED_EXPR (c))
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> clause with parameter may not be specified "
- "on %qs construct", p_name);
- OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
- }
}
block = c_begin_compound_stmt (true);
@@ -20091,14 +20239,18 @@ c_parser_omp_masked (location_t loc, c_parser *parser,
# pragma omp ordered ordered-clauses new-line
structured-block
- # pragma omp ordered depend-clauses new-line */
+ # pragma omp ordered depend-clauses new-line
+
+ OpenMP 5.2
+ # pragma omp ordered doacross-clauses new-line */
#define OMP_ORDERED_CLAUSE_MASK \
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
static bool
c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
@@ -20118,7 +20270,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (!strcmp ("depend", p))
+ if (!strcmp ("depend", p) || !strcmp ("doacross", p))
{
if (!flag_openmp) /* flag_openmp_simd */
{
@@ -20128,8 +20280,8 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
if (context == pragma_stmt)
{
error_at (loc,
- "%<#pragma omp ordered%> with %<depend%> clause may "
- "only be used in compound statements");
+ "%<#pragma omp ordered%> with %qs clause may "
+ "only be used in compound statements", p);
c_parser_skip_to_pragma_eol (parser, false);
return true;
}
@@ -22576,7 +22728,7 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
location_t loc = c_parser_peek_token (parser)->location;
rich_location richloc (line_table, loc);
start_init (omp_priv, NULL_TREE, 0, &richloc);
- struct c_expr init = c_parser_initializer (parser);
+ struct c_expr init = c_parser_initializer (parser, omp_priv);
finish_init ();
finish_decl (omp_priv, loc, init.value,
init.original_type, NULL_TREE);
@@ -23425,6 +23577,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword)
TRANSACTION_EXPR_RELAXED (ret.value) = 1;
SET_EXPR_LOCATION (ret.value, loc);
ret.original_code = TRANSACTION_EXPR;
+ ret.m_decimal = 0;
if (!parens.require_close (parser))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e655afd..46a3e8e 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -147,6 +147,9 @@ struct c_expr
etc), so we stash a copy here. */
source_range src_range;
+ /* True if this was directly from a decimal constant token. */
+ bool m_decimal : 1;
+
/* Access to the first and last locations within the source spelling
of this expression. */
location_t get_start () const { return src_range.m_start; }
@@ -161,12 +164,13 @@ struct c_expr
}
/* Set the value to error_mark_node whilst ensuring that src_range
- is initialized. */
+ and m_decimal are initialized. */
void set_error ()
{
value = error_mark_node;
src_range.m_start = UNKNOWN_LOCATION;
src_range.m_finish = UNKNOWN_LOCATION;
+ m_decimal = 0;
}
};
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index fd0a7f8..b4ef090 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -133,6 +133,13 @@ null_pointer_constant_p (const_tree expr)
/* This should really operate on c_expr structures, but they aren't
yet available everywhere required. */
tree type = TREE_TYPE (expr);
+
+ /* An integer constant expression with the value 0, such an expression
+ cast to type void*, or the predefined constant nullptr, are a null
+ pointer constant. */
+ if (expr == nullptr_node)
+ return true;
+
return (TREE_CODE (expr) == INTEGER_CST
&& !TREE_OVERFLOW (expr)
&& integer_zerop (expr)
@@ -2987,6 +2994,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
+ ret.m_decimal = 0;
pop_maybe_used (false);
}
else
@@ -3010,6 +3018,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
c_last_sizeof_loc = loc;
ret.original_code = SIZEOF_EXPR;
ret.original_type = NULL;
+ ret.m_decimal = 0;
if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr)))
{
/* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */
@@ -3040,6 +3049,7 @@ c_expr_sizeof_type (location_t loc, struct c_type_name *t)
c_last_sizeof_loc = loc;
ret.original_code = SIZEOF_EXPR;
ret.original_type = NULL;
+ ret.m_decimal = 0;
if (type == error_mark_node)
{
ret.value = error_mark_node;
@@ -3546,6 +3556,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
case BUILT_IN_ISINF_SIGN:
case BUILT_IN_ISNAN:
case BUILT_IN_ISNORMAL:
+ case BUILT_IN_ISSIGNALING:
case BUILT_IN_FPCLASSIFY:
type_generic_remove_excess_precision = true;
break;
@@ -3774,6 +3785,7 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
result.original_code = code;
result.original_type = NULL;
+ result.m_decimal = 0;
if (reject_gcc_builtin (arg.value))
{
@@ -3821,6 +3833,7 @@ parser_build_binary_op (location_t location, enum tree_code code,
struct c_expr arg1, struct c_expr arg2)
{
struct c_expr result;
+ result.m_decimal = 0;
enum tree_code code1 = arg1.original_code;
enum tree_code code2 = arg2.original_code;
@@ -3835,6 +3848,7 @@ parser_build_binary_op (location_t location, enum tree_code code,
arg1.value, arg2.value, true);
result.original_code = code;
result.original_type = NULL;
+ result.m_decimal = 0;
if (TREE_CODE (result.value) == ERROR_MARK)
{
@@ -3978,6 +3992,14 @@ parser_build_binary_op (location_t location, enum tree_code code,
"comparison between %qT and %qT",
type1, type2);
+ if (warn_xor_used_as_pow
+ && code == BIT_XOR_EXPR
+ && arg1.m_decimal
+ && arg2.m_decimal)
+ check_for_xor_used_as_pow (arg1.get_location (), arg1.value,
+ location,
+ arg2.value);
+
return result;
}
@@ -4575,7 +4597,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
case TRUTH_NOT_EXPR:
if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
- && typecode != COMPLEX_TYPE)
+ && typecode != COMPLEX_TYPE && typecode != NULLPTR_TYPE)
{
error_at (location,
"wrong type argument to unary exclamation mark");
@@ -5515,6 +5537,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
}
result_type = type2;
}
+ /* 6.5.15: "if one is a null pointer constant (other than a pointer) or has
+ type nullptr_t and the other is a pointer, the result type is the pointer
+ type." */
+ else if (code1 == NULLPTR_TYPE && code2 == POINTER_TYPE)
+ result_type = type2;
+ else if (code1 == POINTER_TYPE && code2 == NULLPTR_TYPE)
+ result_type = type1;
if (!result_type)
{
@@ -6032,18 +6061,18 @@ build_c_cast (location_t loc, tree type, tree expr)
if (!addr_space_superset (as_to, as_from, &as_common))
{
if (ADDR_SPACE_GENERIC_P (as_from))
- warning_at (loc, 0, "cast to %s address space pointer "
+ warning_at (loc, 0, "cast to %qs address space pointer "
"from disjoint generic address space pointer",
c_addr_space_name (as_to));
else if (ADDR_SPACE_GENERIC_P (as_to))
warning_at (loc, 0, "cast to generic address space pointer "
- "from disjoint %s address space pointer",
+ "from disjoint %qs address space pointer",
c_addr_space_name (as_from));
else
- warning_at (loc, 0, "cast to %s address space pointer "
- "from disjoint %s address space pointer",
+ warning_at (loc, 0, "cast to %qs address space pointer "
+ "from disjoint %qs address space pointer",
c_addr_space_name (as_to),
c_addr_space_name (as_from));
}
@@ -7252,6 +7281,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (!null_pointer_constant_p (rhs)
&& asr != asl && !targetm.addr_space.subset_p (asr, asl))
{
+ auto_diagnostic_group d;
+ bool diagnosed = true;
switch (errtype)
{
case ic_argpass:
@@ -7259,7 +7290,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
const char msg[] = G_("passing argument %d of %qE from "
"pointer to non-enclosed address space");
if (warnopt)
- warning_at (expr_loc, warnopt, msg, parmnum, rname);
+ diagnosed
+ = warning_at (expr_loc, warnopt, msg, parmnum, rname);
else
error_at (expr_loc, msg, parmnum, rname);
break;
@@ -7269,7 +7301,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
const char msg[] = G_("assignment from pointer to "
"non-enclosed address space");
if (warnopt)
- warning_at (location, warnopt, msg);
+ diagnosed = warning_at (location, warnopt, msg);
else
error_at (location, msg);
break;
@@ -7280,7 +7312,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
const char msg[] = G_("initialization from pointer to "
"non-enclosed address space");
if (warnopt)
- warning_at (location, warnopt, msg);
+ diagnosed = warning_at (location, warnopt, msg);
else
error_at (location, msg);
break;
@@ -7290,7 +7322,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
const char msg[] = G_("return from pointer to "
"non-enclosed address space");
if (warnopt)
- warning_at (location, warnopt, msg);
+ diagnosed = warning_at (location, warnopt, msg);
else
error_at (location, msg);
break;
@@ -7298,6 +7330,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
default:
gcc_unreachable ();
}
+ if (diagnosed)
+ {
+ if (errtype == ic_argpass)
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ else
+ inform (location, "expected %qT but pointer is of type %qT",
+ type, rhstype);
+ }
return error_mark_node;
}
@@ -7602,12 +7642,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
error_at (location, msg);
return error_mark_node;
}
- else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
+ else if (codel == POINTER_TYPE
+ && (coder == INTEGER_TYPE || coder == NULLPTR_TYPE))
{
- /* An explicit constant 0 can convert to a pointer,
- or one that results from arithmetic, even including
- a cast to integer type. */
- if (!null_pointer_constant)
+ /* An explicit constant 0 or type nullptr_t can convert to a pointer,
+ or one that results from arithmetic, even including a cast to
+ integer type. */
+ if (!null_pointer_constant && coder != NULLPTR_TYPE)
switch (errtype)
{
case ic_argpass:
@@ -7680,7 +7721,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
return convert (type, rhs);
}
- else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
+ else if (codel == BOOLEAN_TYPE
+ /* The type nullptr_t may be converted to bool. The
+ result is false. */
+ && (coder == POINTER_TYPE || coder == NULLPTR_TYPE))
{
tree ret;
bool save = in_late_binary_op;
@@ -8033,6 +8077,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
expr.original_type = NULL;
+ expr.m_decimal = 0;
maybe_warn_string_init (init_loc, type, expr);
if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
@@ -8045,7 +8090,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
if (char_array)
{
- if (typ2 != char_type_node)
+ if (typ2 != char_type_node && typ2 != char8_type_node)
incompat_string_cst = true;
}
else if (!comptypes (typ1, typ2))
@@ -8280,7 +8325,9 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
- error_init (init_loc, "variable-sized object may not be initialized");
+ error_init (init_loc,
+ "variable-sized object may not be initialized except "
+ "with an empty initializer");
return error_mark_node;
}
@@ -8630,8 +8677,9 @@ really_start_incremental_init (tree type)
constructor_max_index = integer_minus_one_node;
/* constructor_max_index needs to be an INTEGER_CST. Attempts
- to initialize VLAs will cause a proper error; avoid tree
- checking errors as well by setting a safe value. */
+ to initialize VLAs with a nonempty initializer will cause a
+ proper error; avoid tree checking errors as well by setting a
+ safe value. */
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
constructor_max_index = integer_minus_one_node;
@@ -8894,6 +8942,7 @@ pop_init_level (location_t loc, int implicit,
ret.value = NULL_TREE;
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
+ ret.m_decimal = 0;
if (implicit == 0)
{
@@ -9013,12 +9062,14 @@ pop_init_level (location_t loc, int implicit,
&& !gnu_vector_type_p (constructor_type))
{
/* A nonincremental scalar initializer--just return
- the element, after verifying there is just one. */
+ the element, after verifying there is just one.
+ Empty scalar initializers are supported in C2X. */
if (vec_safe_is_empty (constructor_elements))
{
- if (!constructor_erroneous && constructor_type != error_mark_node)
- error_init (loc, "empty scalar initializer");
- ret.value = error_mark_node;
+ if (constructor_erroneous || constructor_type == error_mark_node)
+ ret.value = error_mark_node;
+ else
+ ret.value = build_zero_cst (constructor_type);
}
else if (vec_safe_length (constructor_elements) != 1)
{
@@ -9103,7 +9154,7 @@ set_designator (location_t loc, bool array,
return true;
/* Likewise for an initializer for a variable-size type. Those are
- diagnosed in digest_init. */
+ diagnosed in the parser, except for empty initializer braces. */
if (COMPLETE_TYPE_P (constructor_type)
&& TREE_CODE (TYPE_SIZE (constructor_type)) != INTEGER_CST)
return true;
@@ -10264,7 +10315,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
return;
/* Ignore elements of an initializer for a variable-size type.
- Those are diagnosed in digest_init. */
+ Those are diagnosed in the parser (empty initializer braces are OK). */
if (COMPLETE_TYPE_P (constructor_type)
&& !poly_int_tree_p (TYPE_SIZE (constructor_type)))
return;
@@ -11137,10 +11188,10 @@ c_start_switch (location_t switch_loc,
return add_stmt (cs->switch_stmt);
}
-/* Process a case label at location LOC. */
+/* Process a case label at location LOC, with attributes ATTRS. */
tree
-do_case (location_t loc, tree low_value, tree high_value)
+do_case (location_t loc, tree low_value, tree high_value, tree attrs)
{
tree label = NULL_TREE;
@@ -11176,7 +11227,7 @@ do_case (location_t loc, tree low_value, tree high_value)
label = c_add_case_label (loc, c_switch_stack->cases,
SWITCH_STMT_COND (c_switch_stack->switch_stmt),
- low_value, high_value);
+ low_value, high_value, attrs);
if (label == error_mark_node)
label = NULL_TREE;
return label;
@@ -11694,18 +11745,19 @@ maybe_warn_for_null_address (location_t loc, tree op, tree_code code)
|| from_macro_expansion_at (loc))
return;
+ bool w;
if (code == EQ_EXPR)
- warning_at (loc, OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qE will never be NULL",
- op);
+ w = warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
else
- warning_at (loc, OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qE will never be NULL",
- op);
+ w = warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
- if (DECL_P (op))
+ if (w && DECL_P (op))
inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
}
@@ -12096,10 +12148,10 @@ build_binary_op (location_t location, enum tree_code code,
case TRUTH_XOR_EXPR:
if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
|| code0 == REAL_TYPE || code0 == COMPLEX_TYPE
- || code0 == FIXED_POINT_TYPE)
+ || code0 == FIXED_POINT_TYPE || code0 == NULLPTR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
|| code1 == REAL_TYPE || code1 == COMPLEX_TYPE
- || code1 == FIXED_POINT_TYPE))
+ || code1 == FIXED_POINT_TYPE || code1 == NULLPTR_TYPE))
{
/* Result of these operations is always an int,
but that does not mean the operands should be
@@ -12407,6 +12459,27 @@ build_binary_op (location_t location, enum tree_code code,
result_type = type1;
pedwarn (location, 0, "comparison between pointer and integer");
}
+ /* 6.5.9: One of the following shall hold:
+ -- both operands have type nullptr_t; */
+ else if (code0 == NULLPTR_TYPE && code1 == NULLPTR_TYPE)
+ {
+ result_type = nullptr_type_node;
+ /* No need to convert the operands to result_type later. */
+ converted = 1;
+ }
+ /* -- one operand has type nullptr_t and the other is a null pointer
+ constant. We will have to convert the former to the type of the
+ latter, because during gimplification we can't have mismatching
+ comparison operand type. We convert from nullptr_t to the other
+ type, since only nullptr_t can be converted to nullptr_t. Also,
+ even a constant 0 is a null pointer constant, so we may have to
+ create a pointer type from its type. */
+ else if (code0 == NULLPTR_TYPE && null_pointer_constant_p (orig_op1))
+ result_type = (INTEGRAL_TYPE_P (type1)
+ ? build_pointer_type (type1) : type1);
+ else if (code1 == NULLPTR_TYPE && null_pointer_constant_p (orig_op0))
+ result_type = (INTEGRAL_TYPE_P (type0)
+ ? build_pointer_type (type0) : type0);
if ((TREE_CODE (TREE_TYPE (orig_op0)) == BOOLEAN_TYPE
|| truth_value_p (TREE_CODE (orig_op0)))
^ (TREE_CODE (TREE_TYPE (orig_op1)) == BOOLEAN_TYPE
@@ -14173,12 +14246,19 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
+ tree *grp_start_p = NULL, grp_sentinel = NULL_TREE;
+
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
bool need_complete = false;
bool need_implicitly_determined = false;
+ /* We've reached the end of a list of expanded nodes. Reset the group
+ start pointer. */
+ if (c == grp_sentinel)
+ grp_start_p = NULL;
+
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
@@ -14778,15 +14858,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
break;
- case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
- {
- gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
- == OMP_CLAUSE_DEPEND_SOURCE);
- break;
- }
- if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ break;
+ if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
{
gcc_assert (TREE_CODE (t) == TREE_LIST);
for (; t; t = TREE_CHAIN (t))
@@ -14814,7 +14890,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
break;
}
- /* FALLTHRU */
+ gcc_unreachable ();
+ case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_AFFINITY:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST
@@ -14939,12 +15016,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST)
{
+ grp_start_p = pc;
+ grp_sentinel = OMP_CLAUSE_CHAIN (c);
+
if (handle_omp_array_sections (c, ort))
remove = true;
else
{
t = OMP_CLAUSE_DECL (c);
- if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
+ if (!omp_mappable_type (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"array section does not have mappable type "
@@ -15081,7 +15161,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
- else if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
+ else if (!omp_mappable_type (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE does not have a mappable type in %qs clause",
@@ -15162,7 +15242,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|| (OMP_CLAUSE_MAP_KIND (c)
== GOMP_MAP_FORCE_DEVICEPTR)))
&& t == OMP_CLAUSE_DECL (c)
- && !lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
+ && !omp_mappable_type (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD does not have a mappable type in %qs clause", t,
@@ -15279,7 +15359,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
cname);
remove = true;
}
- else if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
+ else if (!omp_mappable_type (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD does not have a mappable type in %qs clause", t,
@@ -15582,7 +15662,19 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
if (remove)
- *pc = OMP_CLAUSE_CHAIN (c);
+ {
+ if (grp_start_p)
+ {
+ /* If we found a clause to remove, we want to remove the whole
+ expanded group, otherwise gimplify
+ (omp_resolve_clause_dependencies) can get confused. */
+ *grp_start_p = grp_sentinel;
+ pc = grp_start_p;
+ grp_start_p = NULL;
+ }
+ else
+ *pc = OMP_CLAUSE_CHAIN (c);
+ }
else
pc = &OMP_CLAUSE_CHAIN (c);
}
diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc
index b909eac..5a2da2c 100644
--- a/gcc/c/gimple-parser.cc
+++ b/gcc/c/gimple-parser.cc
@@ -1332,6 +1332,7 @@ c_parser_gimple_call_internal (gimple_parser &parser)
exprlist.address ());
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
+ expr.m_decimal = 0;
}
}
return expr;
@@ -1751,6 +1752,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
finish = c_parser_tokens_buf (parser, 0)->location;
expr.value = build_array_ref (op_loc, expr.value, idx);
set_c_expr_source_range (&expr, start, finish);
+ expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
@@ -1774,6 +1776,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
expr.value = build_call_array_loc
(expr_loc, TREE_TYPE (TREE_TYPE (expr.value)),
expr.value, exprlist.length (), exprlist.address ());
+ expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
break;
@@ -1802,6 +1805,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
expr.value = build_component_ref (op_loc, expr.value, ident,
comp_loc, UNKNOWN_LOCATION);
set_c_expr_source_range (&expr, start, finish);
+ expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
expr.original_type = NULL;
@@ -1851,6 +1855,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
ident, comp_loc,
expr.get_location ());
set_c_expr_source_range (&expr, start, finish);
+ expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
expr.original_type = NULL;