diff options
Diffstat (limited to 'gcc/c/c-decl.c')
-rw-r--r-- | gcc/c/c-decl.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index efb0a52..9ad8219 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5351,6 +5351,8 @@ grokdeclarator (const struct c_declarator *declarator, 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; @@ -5389,9 +5391,9 @@ grokdeclarator (const struct c_declarator *declarator, 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: @@ -5513,12 +5515,17 @@ grokdeclarator (const struct c_declarator *declarator, 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 @@ -6013,6 +6020,7 @@ grokdeclarator (const struct c_declarator *declarator, array_ptr_attrs = NULL_TREE; array_parm_static = 0; } + orig_qual_indirect++; break; } case cdk_function: @@ -6022,6 +6030,7 @@ grokdeclarator (const struct c_declarator *declarator, attributes. */ bool really_funcdef = false; tree arg_types; + orig_qual_type = NULL_TREE; if (funcdef_flag) { const struct c_declarator *t = declarator->declarator; @@ -6122,7 +6131,9 @@ grokdeclarator (const struct c_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, @@ -6304,7 +6315,8 @@ grokdeclarator (const struct c_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); decl = build_decl (declarator->id_loc, TYPE_DECL, declarator->u.id, type); if (declspecs->explicit_signed_p) @@ -6357,7 +6369,8 @@ grokdeclarator (const struct c_declarator *declarator, 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; } @@ -6405,7 +6418,8 @@ grokdeclarator (const struct c_declarator *declarator, /* 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) @@ -6496,7 +6510,8 @@ grokdeclarator (const struct c_declarator *declarator, 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; @@ -6608,7 +6623,8 @@ grokdeclarator (const struct c_declarator *declarator, /* 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 |