tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
+ tree orig_qual_type = NULL;
+ size_t orig_qual_indirect = 0;
struct c_arg_info *arg_info = 0;
addr_space_t as1, as2, address_space;
location_t loc = UNKNOWN_LOCATION;
case cdk_function:
case cdk_pointer:
funcdef_syntax = (decl->kind == cdk_function);
- decl = decl->declarator;
if (first_non_attr_kind == cdk_attrs)
first_non_attr_kind = decl->kind;
+ decl = decl->declarator;
break;
case cdk_attrs:
if ((TREE_CODE (type) == ARRAY_TYPE
|| first_non_attr_kind == cdk_array)
&& TYPE_QUALS (element_type))
- type = TYPE_MAIN_VARIANT (type);
+ {
+ orig_qual_type = type;
+ type = TYPE_MAIN_VARIANT (type);
+ }
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0)
| (atomicp ? TYPE_QUAL_ATOMIC : 0)
| ENCODE_QUAL_ADDR_SPACE (address_space));
+ if (type_quals != TYPE_QUALS (element_type))
+ orig_qual_type = NULL_TREE;
/* Applying the _Atomic qualifier to an array type (through the use
of typedefs or typeof) must be detected here. If the qualifier
array_ptr_attrs = NULL_TREE;
array_parm_static = 0;
}
+ orig_qual_indirect++;
break;
}
case cdk_function:
attributes. */
bool really_funcdef = false;
tree arg_types;
+ orig_qual_type = NULL_TREE;
if (funcdef_flag)
{
const struct c_declarator *t = declarator->declarator;
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals, orig_qual_type,
+ orig_qual_indirect);
+ orig_qual_type = NULL_TREE;
size_varies = false;
/* When the pointed-to type involves components of variable size,
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals, orig_qual_type,
+ orig_qual_indirect);
decl = build_decl (declarator->id_loc,
TYPE_DECL, declarator->u.id, type);
if (declspecs->explicit_signed_p)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids const or volatile function types");
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals, orig_qual_type,
+ orig_qual_indirect);
return type;
}
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals, orig_qual_type,
+ orig_qual_indirect);
type = c_build_pointer_type (type);
type_quals = array_ptr_quals;
if (type_quals)
TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
NULL_TREE);
}
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals, orig_qual_type,
+ orig_qual_indirect);
decl = build_decl (declarator->id_loc,
FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern;
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals, orig_qual_type,
+ orig_qual_indirect);
/* C99 6.2.2p7: It is invalid (compile-time undefined
behavior) to create an 'extern' declaration for a
}
/* Make a variant type in the proper way for C/C++, propagating qualifiers
- down to the element type of an array. */
+ down to the element type of an array. If ORIG_QUAL_TYPE is not
+ NULL, then it should be used as the qualified type
+ ORIG_QUAL_INDIRECT levels down in array type derivation (to
+ preserve information about the typedef name from which an array
+ type was derived). */
tree
-c_build_qualified_type (tree type, int type_quals)
+c_build_qualified_type (tree type, int type_quals, tree orig_qual_type,
+ size_t orig_qual_indirect)
{
if (type == error_mark_node)
return type;
{
tree t;
tree element_type = c_build_qualified_type (TREE_TYPE (type),
- type_quals);
+ type_quals, orig_qual_type,
+ orig_qual_indirect - 1);
/* See if we already have an identically qualified type. */
- for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- {
- if (TYPE_QUALS (strip_array_types (t)) == type_quals
- && TYPE_NAME (t) == TYPE_NAME (type)
- && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
- && attribute_list_equal (TYPE_ATTRIBUTES (t),
- TYPE_ATTRIBUTES (type)))
- break;
- }
+ if (orig_qual_type && orig_qual_indirect == 0)
+ t = orig_qual_type;
+ else
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ {
+ if (TYPE_QUALS (strip_array_types (t)) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+ && attribute_list_equal (TYPE_ATTRIBUTES (t),
+ TYPE_ATTRIBUTES (type)))
+ break;
+ }
if (!t)
{
tree domain = TYPE_DOMAIN (type);
type_quals &= ~TYPE_QUAL_RESTRICT;
}
- tree var_type = build_qualified_type (type, type_quals);
+ tree var_type = (orig_qual_type && orig_qual_indirect == 0
+ ? orig_qual_type
+ : build_qualified_type (type, type_quals));
/* A variant type does not inherit the list of incomplete vars from the
type main variant. */
if (RECORD_OR_UNION_TYPE_P (var_type))