aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog31
-rw-r--r--gcc/c/c-decl.cc22
-rw-r--r--gcc/c/c-lang.h12
-rw-r--r--gcc/c/c-parser.cc8
-rw-r--r--gcc/c/c-typeck.cc114
5 files changed, 127 insertions, 60 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 351eb4e..47f828f 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,34 @@
+2025-06-12 Jakub Jelinek <jakub@redhat.com>
+
+ * c-lang.h (union lang_type::maybe_objc_info): New type.
+ (struct lang_type): Use union maybe_objc_info info member
+ instead of tree objc_info.
+ * c-decl.cc (finish_struct): Allocate struct lang_type using
+ ggc_internal_cleared_alloc instead of ggc_cleared_alloc,
+ and use sizeof (struct lang_type) for ObjC and otherwise
+ offsetof (struct lang_type, info) as size.
+ (finish_enum): Likewise.
+
+2025-06-11 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120510
+ * c-typeck.cc (composite_type_internal): Activate checking
+ assertions for all types and also inputs.
+ (comptypes_for_composite_check): New helper function.
+ (function_types_compatible_p): Add exception.
+
+2025-06-11 Martin Uecker <uecker@tugraz.at>
+
+ * c-typeck.cc (function_types_compatible_p): Remove unused
+ variables and return true/false instead of 1/0.
+ (type_lists_compatible_p): Return false instead of 0.
+
+2025-06-11 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120303
+ * c-parser.cc (c_parser_generic_selection): Handle error
+ condition.
+
2025-06-09 Martin Uecker <uecker@tugraz.at>
PR c/120510
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 2b0bd66..8bbd6eb 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9790,12 +9790,17 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
len += list_length (x);
/* Use the same allocation policy here that make_node uses, to
- ensure that this lives as long as the rest of the struct decl.
- All decls in an inline function need to be saved. */
-
- space = ggc_cleared_alloc<struct lang_type> ();
- space2 = (sorted_fields_type *) ggc_internal_alloc
- (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+ ensure that this lives as long as the rest of the struct decl.
+ All decls in an inline function need to be saved. */
+
+ space = ((struct lang_type *)
+ ggc_internal_cleared_alloc (c_dialect_objc ()
+ ? sizeof (struct lang_type)
+ : offsetof (struct lang_type,
+ info)));
+ space2 = ((sorted_fields_type *)
+ ggc_internal_alloc (sizeof (struct sorted_fields_type)
+ + len * sizeof (tree)));
len = 0;
space->s = space2;
@@ -10269,7 +10274,10 @@ finish_enum (tree enumtype, tree values, tree attributes)
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = ggc_cleared_alloc<struct lang_type> ();
+ lt = ((struct lang_type *)
+ ggc_internal_cleared_alloc (c_dialect_objc ()
+ ? sizeof (struct lang_type)
+ : offsetof (struct lang_type, info)));
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 4b93d18..2e99b4d 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -35,10 +35,14 @@ struct GTY(()) lang_type {
/* In an ENUMERAL_TYPE, the min and max values. */
tree enum_min;
tree enum_max;
- /* In a RECORD_TYPE, information specific to Objective-C, such
- as a list of adopted protocols or a pointer to a corresponding
- @interface. See objc/objc-act.h for details. */
- tree objc_info;
+ union maybe_objc_info {
+ /* If not c_dialect_objc, this part is not even allocated. */
+ char GTY((tag ("0"))) non_objc;
+ /* In a RECORD_TYPE, information specific to Objective-C, such
+ as a list of adopted protocols or a pointer to a corresponding
+ @interface. See objc/objc-act.h for details. */
+ tree GTY((tag ("1"))) objc_info;
+ } GTY ((desc ("c_dialect_objc ()"))) info;
};
struct GTY(()) lang_decl {
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 85580c5..faa50a4 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -11146,8 +11146,14 @@ c_parser_generic_selection (c_parser *parser)
"ISO C does not support use of type name as %<_Generic%> "
"controlling operand before C2Y");
struct c_type_name *type = c_parser_type_name (parser);
- selector_type = groktypename (type, NULL, NULL);
+ if (type)
+ selector_type = groktypename (type, NULL, NULL);
c_inhibit_evaluation_warnings--;
+ if (!type)
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return error_expr;
+ }
}
else
{
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 539d481..e24629b 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -136,6 +136,7 @@ static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
static void record_maybe_used_decl (tree);
static bool comptypes_internal (const_tree, const_tree,
struct comptypes_data *data);
+static bool comptypes_check_for_composite (tree t1, tree t2);
/* Return true if EXP is a null pointer constant, false otherwise. */
@@ -1002,15 +1003,13 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
tree
composite_type (tree t1, tree t2)
{
+ gcc_checking_assert (comptypes_check_for_composite (t1, t2));
+
struct composite_cache cache = { };
tree n = composite_type_internal (t1, t2, &cache);
- /* For function types there are some cases where qualifiers do
- not match. See PR120510. */
- if (FUNCTION_TYPE != TREE_CODE (n))
- {
- gcc_checking_assert (comptypes (n, t1));
- gcc_checking_assert (comptypes (n, t2));
- }
+
+ gcc_checking_assert (comptypes_check_for_composite (n, t1));
+ gcc_checking_assert (comptypes_check_for_composite (n, t2));
return n;
}
@@ -1454,16 +1453,39 @@ comptypes_verify (tree type1, tree type2)
}
struct comptypes_data {
+
+ /* output */
bool enum_and_int_p;
bool different_types_p;
bool warning_needed;
+
+ /* context */
bool anon_field;
bool pointedto;
+
+ /* configuration */
bool equiv;
+ bool ignore_promoting_args;
const struct tagged_tu_seen_cache* cache;
};
+
+/* Helper function for composite_type. This function ignores when the
+ function type of an old-style declaration is incompatible with a type
+ of a declaration with prototype because some are arguments are not
+ self-promoting. This is ignored only for function types but not
+ ignored in a nested context. */
+
+static bool
+comptypes_check_for_composite (tree t1, tree t2)
+{
+ struct comptypes_data data = { };
+ data.ignore_promoting_args = FUNCTION_TYPE == TREE_CODE (t1);
+ return comptypes_internal (t1, t2, &data);
+}
+
+
/* C implementation of compatible_types_for_indirection_note_p. */
bool
@@ -1593,6 +1615,10 @@ comptypes_equiv_p (tree type1, tree type2)
permitted in C11 typedef redeclarations, then this sets
'different_types_p' in DATA to true; it is never set to
false, but may or may not be set if the types are incompatible.
+ If two functions types are not compatible only because one is
+ an old-style definition that does not have self-promoting arguments,
+ then this can be ignored by setting 'ignore_promoting_args_p'.
+ For 'equiv' we can compute equivalency classes (see above).
This differs from comptypes, in that we don't free the seen
types. */
@@ -2016,14 +2042,8 @@ static bool
function_types_compatible_p (const_tree f1, const_tree f2,
struct comptypes_data *data)
{
- tree args1, args2;
- /* 1 if no need for warning yet, 2 if warning cause has been seen. */
- int val = 1;
- int val1;
- tree ret1, ret2;
-
- ret1 = TREE_TYPE (f1);
- ret2 = TREE_TYPE (f2);
+ tree ret1 = TREE_TYPE (f1);
+ tree ret2 = TREE_TYPE (f2);
/* 'volatile' qualifiers on a function's return type used to mean
the function is noreturn. */
@@ -2035,12 +2055,17 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
- val = comptypes_internal (ret1, ret2, data);
- if (val == 0)
- return 0;
- args1 = TYPE_ARG_TYPES (f1);
- args2 = TYPE_ARG_TYPES (f2);
+ bool ignore_pargs = data->ignore_promoting_args;
+ data->ignore_promoting_args = false;
+
+ if (!comptypes_internal (ret1, ret2, data))
+ return false;
+
+ data->ignore_promoting_args = ignore_pargs;
+
+ tree args1 = TYPE_ARG_TYPES (f1);
+ tree args2 = TYPE_ARG_TYPES (f2);
if ((args1 == NULL_TREE) != (args2 == NULL_TREE))
data->different_types_p = true;
@@ -2051,40 +2076,33 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (args1 == NULL_TREE)
{
if (TYPE_NO_NAMED_ARGS_STDARG_P (f1) != TYPE_NO_NAMED_ARGS_STDARG_P (f2))
- return 0;
- if (!self_promoting_args_p (args2))
- return 0;
+ return false;
+ if (!(data->ignore_promoting_args || self_promoting_args_p (args2)))
+ return false;
+ data->ignore_promoting_args = false;
/* If one of these types comes from a non-prototype fn definition,
compare that with the other type's arglist.
If they don't match, ask for a warning (but no error). */
if (TYPE_ACTUAL_ARG_TYPES (f1)
- && type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
- data) != 1)
- {
- val = 1;
- data->warning_needed = true;
- }
- return val;
+ && !type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), data))
+ data->warning_needed = true;
+ return true;
}
if (args2 == NULL_TREE)
{
if (TYPE_NO_NAMED_ARGS_STDARG_P (f1) != TYPE_NO_NAMED_ARGS_STDARG_P (f2))
- return 0;
- if (!self_promoting_args_p (args1))
- return 0;
+ return false;
+ if (!(data->ignore_promoting_args || self_promoting_args_p (args1)))
+ return false;
+ data->ignore_promoting_args = false;
if (TYPE_ACTUAL_ARG_TYPES (f2)
- && type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
- data) != 1)
- {
- val = 1;
- data->warning_needed = true;
- }
- return val;
+ && !type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), data))
+ data->warning_needed = true;
+ return true;
}
/* Both types have argument lists: compare them and propagate results. */
- val1 = type_lists_compatible_p (args1, args2, data);
- return val1;
+ return type_lists_compatible_p (args1, args2, data);
}
/* Check two lists of types for compatibility, returning false for
@@ -2101,7 +2119,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
/* If one list is shorter than the other,
they fail to match. */
if (args1 == NULL_TREE || args2 == NULL_TREE)
- return 0;
+ return false;
tree a1 = TREE_VALUE (args1);
tree a2 = TREE_VALUE (args2);
tree mv1 = remove_qualifiers (a1);
@@ -2115,12 +2133,12 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (a1 == NULL_TREE)
{
if (c_type_promotes_to (a2) != a2)
- return 0;
+ return false;
}
else if (a2 == NULL_TREE)
{
if (c_type_promotes_to (a1) != a1)
- return 0;
+ return false;
}
/* If one of the lists has an error marker, ignore this arg. */
else if (TREE_CODE (a1) == ERROR_MARK
@@ -2147,7 +2165,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
break;
}
if (memb == NULL_TREE)
- return 0;
+ return false;
}
else if (TREE_CODE (a2) == UNION_TYPE
&& (TYPE_NAME (a2) == NULL_TREE
@@ -2165,10 +2183,10 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
break;
}
if (memb == NULL_TREE)
- return 0;
+ return false;
}
else
- return 0;
+ return false;
}
args1 = TREE_CHAIN (args1);