diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 32 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 37 |
3 files changed, 57 insertions, 21 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index e517467..bd21440 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2015-12-02 Joseph Myers <joseph@codesourcery.com> + + PR c/68162 + * c-decl.c (grokdeclarator): Set first_non_attr_kind before + following link from declarator to next declarator. Track original + qualified type and pass it to c_build_qualified_type. + * c-typeck.c (c_build_qualified_type): Add arguments + orig_qual_type and orig_qual_indirect. + 2015-12-02 Thomas Schwinge <thomas@codesourcery.com> * c-parser.c (c_parser_omp_clause_name) 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 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index cc2e38e..5070972 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13337,10 +13337,15 @@ c_finish_transaction (location_t loc, tree block, int flags) } /* 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; @@ -13349,18 +13354,22 @@ c_build_qualified_type (tree type, int type_quals) { 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); @@ -13404,7 +13413,9 @@ c_build_qualified_type (tree type, int type_quals) 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)) |