aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog42
-rw-r--r--gcc/c/c-decl.cc23
-rw-r--r--gcc/c/c-parser.cc157
-rw-r--r--gcc/c/c-tree.h3
-rw-r--r--gcc/c/c-typeck.cc229
5 files changed, 376 insertions, 78 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 464e5a1..2e5c896 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,45 @@
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well.
+ * c-typeck.cc (convert_lvalue_to_rvalue): New overload and
+ wrapper.
+ (build_atomic_assign, build_modify_expr): Use it.
+ (build_asm_expr, handle_omp-array_sections_1): Simplify with
+ it.
+ (build_unary_op): Handle hardbools.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/108931
+ * c-typeck.cc (composite_type_cond): Renamed from
+ composite_type with argument for condition
+ (composite_type): New function.
+ (composite_type_internal): Implement new logic.
+ (build_conditional_expr): Pass condition.
+ (common_pointer_type): Adapt.
+ (pointer_diff): Adapt.
+ (build_binary_op): Adapt.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/121217
+ * c-typeck.cc (tagged_types_tu_compatible_p): Add check.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from
+ clauses.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_variable_list): Use location of the
+ map expression as the clause location.
+ (c_parser_omp_clause_map): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply
+ iterators to generated clauses.
+
2025-08-02 Martin Uecker <uecker@tugraz.at>
* c-decl.cc (get_parm_array_spec): Remove.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 7850365..8e8bac6 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4825,6 +4825,29 @@ c_init_decl_processing (void)
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
+
+ if (warn_keyword_macro)
+ {
+ for (unsigned int i = 0; i < num_c_common_reswords; ++i)
+ /* For C register keywords which don't start with underscore
+ or start with just single underscore. Don't complain about
+ ObjC or Transactional Memory keywords. */
+ if (c_common_reswords[i].word[0] == '_'
+ && c_common_reswords[i].word[1] == '_')
+ continue;
+ else if (c_common_reswords[i].disable
+ & (D_TRANSMEM | D_OBJC | D_CXX_OBJC))
+ continue;
+ else
+ {
+ tree id = get_identifier (c_common_reswords[i].word);
+ if (C_IS_RESERVED_WORD (id)
+ && C_RID_CODE (id) != RID_CXX_COMPAT_WARN)
+ cpp_lookup (parse_in,
+ (const unsigned char *) IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+ }
+ }
}
/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 4a13fc0..814accf 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -16659,7 +16659,7 @@ c_parser_omp_variable_list (c_parser *parser,
|| CONVERT_EXPR_P (decl))
decl = TREE_OPERAND (decl, 0);
- tree u = build_omp_clause (clause_loc, kind);
+ tree u = build_omp_clause (loc, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
@@ -20072,7 +20072,7 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
map ( [map-type-modifier[,] ...] map-kind: variable-list )
map-type-modifier:
- always | close */
+ always | close | present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
@@ -20087,15 +20087,35 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
int pos = 1;
int map_kind_pos = 0;
- while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ int iterator_length = 0;
+ for (;;)
{
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
+ c_token *tok = c_parser_peek_nth_token_raw (parser, pos);
+ if (tok->type != CPP_NAME)
+ break;
+
+ const char *p = IDENTIFIER_POINTER (tok->value);
+ c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
+ {
+ unsigned n = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ {
+ iterator_length = n - pos + 1;
+ pos = n;
+ next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ }
+ }
+
+ if (next_tok->type == CPP_COLON)
{
map_kind_pos = pos;
break;
}
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ if (next_tok->type == CPP_COMMA)
pos++;
else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
== CPP_OPEN_PAREN)
@@ -20117,6 +20137,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
int present_modifier = 0;
int mapper_modifier = 0;
tree mapper_name = NULL_TREE;
+ tree iterators = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
@@ -20150,6 +20171,17 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
close_modifier++;
c_parser_consume_token (parser);
}
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
else if (strcmp ("mapper", p) == 0)
{
c_parser_consume_token (parser);
@@ -20223,8 +20255,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
else
{
c_parser_error (parser, "%<map%> clause with map-type modifier other "
- "than %<always%>, %<close%>, %<mapper%> or "
- "%<present%>");
+ "than %<always%>, %<close%>, %<iterator%>, "
+ "%<mapper%> or %<present%>");
parens.skip_until_found_close (parser);
return list;
}
@@ -20273,9 +20305,19 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
tree last_new = NULL_TREE;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
{
OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_ITERATORS (c) = iterators;
last_new = c;
}
@@ -20534,8 +20576,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
@@ -20546,18 +20591,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
if (!parens.require_open (parser))
return list;
+ int pos = 1, colon_pos = 0;
+ int iterator_length = 0;
+
+ while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ {
+ const char *identifier =
+ IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = npos - pos + 1;
+ pos = npos;
+ }
+ }
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
+ }
+
bool present = false;
- c_token *token = c_parser_peek_token (parser);
+ tree iterators = NULL_TREE;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ for (int pos = 1; pos < colon_pos; ++pos)
{
- present = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_COMMA)
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ c_parser_error (parser, "too many %<present%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ present = true;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> or "
+ "%<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
}
+ if (colon_pos)
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+
tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
parens.skip_until_found_close (parser);
@@ -20565,6 +20677,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index bb0b113..dba94ab 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -163,7 +163,8 @@ along with GCC; see the file COPYING3. If not see
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| (TREE_CODE (TYPE) == ENUMERAL_TYPE \
&& ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \
- && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE))
+ && (TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE \
+ || c_hardbool_type_attr (TYPE))))
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index ed6e56e..7a95f72 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -641,7 +641,8 @@ struct composite_cache {
};
tree
-composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
+composite_type_internal (tree t1, tree t2, tree cond,
+ struct composite_cache* cache)
{
enum tree_code code1;
enum tree_code code2;
@@ -686,8 +687,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type_internal (pointed_to_1,
- pointed_to_2, cache);
+ tree target = composite_type_internal (pointed_to_1, pointed_to_2,
+ cond, cache);
t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
@@ -695,25 +696,20 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
case ARRAY_TYPE:
{
- tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- cache);
- int quals;
- tree unqual_elt;
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
- bool d1_variable, d2_variable;
- bool d1_zero, d2_zero;
- bool t1_complete, t2_complete;
/* We should not have any type quals on arrays at all. */
gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
&& !TYPE_QUALS_NO_ADDR_SPACE (t2));
- t1_complete = COMPLETE_TYPE_P (t1);
- t2_complete = COMPLETE_TYPE_P (t2);
+ bool t1_complete = COMPLETE_TYPE_P (t1);
+ bool t2_complete = COMPLETE_TYPE_P (t2);
- d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
- d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+ bool d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
+ bool d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+
+ bool d1_variable, d2_variable;
d1_variable = (!d1_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
@@ -722,10 +718,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
- bool use1 = TYPE_DOMAIN (t1)
- && (d2_variable || d2_zero || !d1_variable);
- bool use2 = TYPE_DOMAIN (t2)
- && (d1_variable || d1_zero || !d2_variable);
+ bool use1 = d1 && (d2_variable || d2_zero || !d1_variable);
+ bool use2 = d2 && (d1_variable || d1_zero || !d2_variable);
/* If the first is an unspecified size pick the other one. */
if (d2_variable && c_type_unspecified_p (t1))
@@ -734,25 +728,53 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
use1 = false;
}
- /* Save space: see if the result is identical to one of the args. */
- if (elt == TREE_TYPE (t1) && use1)
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && use2)
- return c_build_type_attribute_variant (t2, attributes);
+ /* If both are VLAs but not unspecified and we are in the
+ conditional operator, we create a conditional to select
+ the size of the active branch. */
+ bool use0 = cond && d1_variable && !c_type_unspecified_p (t1)
+ && d2_variable && !c_type_unspecified_p (t2);
+
+ tree td;
+ tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
+
+ if (!use0)
+ {
+ /* Save space: see if the result is identical to one of the args. */
+ if (elt == TREE_TYPE (t1) && use1)
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && use2)
+ return c_build_type_attribute_variant (t2, attributes);
+
+ if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t2, attributes);
+
+ td = TYPE_DOMAIN (use1 ? t1 : t2);
+ }
+ else
+ {
+ /* Not used in C. */
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d1));
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d2));
- if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t2, attributes);
+ tree d = fold_build3_loc (UNKNOWN_LOCATION, COND_EXPR, sizetype,
+ cond, TYPE_MAX_VALUE (d1),
+ TYPE_MAX_VALUE (d2));
+
+ td = build_index_type (d);
+ }
/* Merge the element types, and have a size if either arg has
one. We may have qualifiers on the element types. To set
up TYPE_MAIN_VARIANT correctly, we need to form the
composite of the unqualified types and add the qualifiers
back at the end. */
- quals = TYPE_QUALS (strip_array_types (elt));
- unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
- t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2));
+ int quals = TYPE_QUALS (strip_array_types (elt));
+ tree unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+
+ t1 = c_build_array_type (unqual_elt, td);
/* Check that a type which has a varying outermost dimension
got marked has having a variable size. */
@@ -819,7 +841,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
gcc_assert (DECL_NAME (a) == DECL_NAME (b));
gcc_checking_assert (!DECL_NAME (a) || comptypes (ta, tb));
- tree t = composite_type_internal (ta, tb, cache);
+ tree t = composite_type_internal (ta, tb, cond, cache);
tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a), t);
DECL_PACKED (f) = DECL_PACKED (a);
@@ -876,8 +898,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
/* Function types: prefer the one that specified arg types.
If both do, merge the arg types. Also merge the return types. */
{
- tree valtype = composite_type_internal (TREE_TYPE (t1),
- TREE_TYPE (t2), cache);
+ tree valtype = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
@@ -956,7 +978,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p2),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
@@ -979,14 +1001,14 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
TREE_VALUE (n)
= composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p1),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
}
}
}
- TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache);
+ TREE_VALUE (n) = composite_type_internal (mv1, mv2, cond, cache);
parm_done: ;
}
@@ -1001,18 +1023,25 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
}
tree
-composite_type (tree t1, tree t2)
+composite_type_cond (tree t1, tree t2, tree cond)
{
gcc_checking_assert (comptypes_check_for_composite (t1, t2));
struct composite_cache cache = { };
- tree n = composite_type_internal (t1, t2, &cache);
+ tree n = composite_type_internal (t1, t2, cond, &cache);
gcc_checking_assert (comptypes_check_for_composite (n, t1));
gcc_checking_assert (comptypes_check_for_composite (n, t2));
return n;
}
+
+tree
+composite_type (tree t1, tree t2)
+{
+ return composite_type_cond (t1, t2, NULL_TREE);
+}
+
/* Return the type of a conditional expression between pointers to
possibly differently qualified versions of compatible types.
@@ -1020,7 +1049,7 @@ composite_type (tree t1, tree t2)
true; if that isn't so, this may crash. */
static tree
-common_pointer_type (tree t1, tree t2)
+common_pointer_type (tree t1, tree t2, tree cond)
{
tree attributes;
unsigned target_quals;
@@ -1047,8 +1076,8 @@ common_pointer_type (tree t1, tree t2)
qualifiers of the two types' targets. */
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
- TYPE_MAIN_VARIANT (pointed_to_2));
+ tree target = composite_type_cond (TYPE_MAIN_VARIANT (pointed_to_1),
+ TYPE_MAIN_VARIANT (pointed_to_2), cond);
/* Strip array types to get correct qualifier for pointers to arrays */
quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1));
@@ -1970,6 +1999,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
ft2 = DECL_BIT_FIELD_TYPE (s2);
}
+ if (!ft1 || !ft2)
+ return false;
+
if (TREE_CODE (ft1) == ERROR_MARK || TREE_CODE (ft2) == ERROR_MARK)
return false;
@@ -2648,6 +2680,20 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
return exp;
}
+/* Wrapper for the overload above, same arguments but for tree rather than
+ c_expr. This is important for hardbools to decay to bools. */
+
+static inline tree
+convert_lvalue_to_rvalue (location_t loc, tree val,
+ bool convert_p, bool read_p, bool for_init = false)
+{
+ struct c_expr expr;
+ memset (&expr, 0, sizeof (expr));
+ expr.value = val;
+ expr = convert_lvalue_to_rvalue (loc, expr, convert_p, read_p, for_init);
+ return expr.value;
+}
+
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
@@ -4926,7 +4972,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
if (!addr_space_superset (as0, as1, &as_common))
gcc_unreachable ();
- common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+ common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1), NULL_TREE);
op0 = convert (common_type, op0);
op1 = convert (common_type, op1);
}
@@ -5271,7 +5317,9 @@ cas_loop:
/* newval = old + val; */
if (rhs_type != rhs_semantic_type)
val = build1 (EXCESS_PRECISION_EXPR, nonatomic_rhs_semantic_type, val);
- rhs = build_binary_op (loc, modifycode, old, val, true);
+ rhs = build_binary_op (loc, modifycode,
+ convert_lvalue_to_rvalue (loc, old, true, true),
+ val, true);
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
{
tree eptype = TREE_TYPE (rhs);
@@ -5727,7 +5775,48 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
goto return_build_unary_op;
}
- if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
+ tree true_res;
+ if (c_hardbool_type_attr (TREE_TYPE (arg), NULL, &true_res))
+ {
+ tree larg = stabilize_reference (arg);
+ tree sarg = save_expr (larg);
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case POSTINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case PREDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ rarg = convert (TREE_TYPE (sarg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, rarg);
+ }
+ break;
+ case POSTDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ tree iarg = convert (TREE_TYPE (larg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, iarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ TREE_SIDE_EFFECTS (val) = 1;
+ }
+ else if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
val = boolean_increment (code, arg);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
@@ -6380,7 +6469,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
addr_space_t as_common;
if (comp_target_types (colon_loc, type1, type2))
- result_type = common_pointer_type (type1, type2);
+ {
+ ifexp = save_expr (ifexp);
+ result_type = common_pointer_type (type1, type2, ifexp);
+ }
else if (null_pointer_constant_p (orig_op1))
result_type = type2;
else if (null_pointer_constant_p (orig_op2))
@@ -7337,8 +7429,10 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
clear_decl_read = true;
}
- newrhs = build_binary_op (location,
- modifycode, lhs, newrhs, true);
+ newrhs = build_binary_op (location, modifycode,
+ convert_lvalue_to_rvalue (location, lhs,
+ true, true),
+ newrhs, true);
if (clear_decl_read)
DECL_READ_P (lhs) = 0;
@@ -12730,11 +12824,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
}
else
{
- struct c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = input;
- expr = convert_lvalue_to_rvalue (loc, expr, true, false);
- input = c_fully_fold (expr.value, false, NULL);
+ input = c_fully_fold (convert_lvalue_to_rvalue (loc, input,
+ true, false),
+ false, NULL);
if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
{
@@ -14390,7 +14482,7 @@ build_binary_op (location_t location, enum tree_code code,
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
if (comp_target_types (location, type0, type1))
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
else if (!addr_space_superset (as0, as1, &as_common))
{
error_at (location, "comparison of pointers to "
@@ -14529,7 +14621,7 @@ build_binary_op (location_t location, enum tree_code code,
if (comp_target_types (location, type0, type1))
{
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn_c99 (location, OPT_Wpedantic,
@@ -15356,12 +15448,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* If the array section is pointer based and the pointer
itself is _Atomic qualified, we need to atomically load
the pointer. */
- c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = ret;
- expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
- expr, false, false);
- ret = expr.value;
+ ret = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
+ ret, false, false);
}
return ret;
}
@@ -16204,7 +16292,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* We've reached the end of a list of expanded nodes. Reset the group
start pointer. */
if (c == grp_sentinel)
- grp_start_p = NULL;
+ {
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc != grp_sentinel;
+ gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+ grp_start_p = NULL;
+ }
switch (OMP_CLAUSE_CODE (c))
{
@@ -16962,6 +17057,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
+ if (OMP_CLAUSE_ITERATORS (c)
+ && c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c)))
+ {
+ t = error_mark_node;
+ break;
+ }
+ /* FALLTHRU */
case OMP_CLAUSE__CACHE_:
{
using namespace omp_addr_tokenizer;
@@ -17690,6 +17792,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc; gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+
if (simdlen
&& safelen
&& tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen),