From e9e32ee6e8df82ba1d103ec2c501ecc7c185bc2e Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 2 Dec 2015 18:24:23 +0000 Subject: [PATCH] Fix TYPE_MAIN_VARIANT construction for arrays of qualified typedefs (PR c/68162). PR c/68162 reports a spurious warning about incompatible types involving arrays of const double, constructed in one place using a typedef for const double and in another place literally using const double. The problem is that the array of the typedef was incorrectly constructed without a TYPE_MAIN_VARIANT being an array of unqualified elements as it should be (though it seems some more recent change resulted in this producing incorrect diagnostics, likely the support for C++-style handling of arrays of qualified type). This patch fixes the logic in grokdeclarator to determine first_non_attr_kind, which is used to determine whether it is necessary to use the TYPE_MAIN_VARIANT of the type in the declaration specifiers. However, fixing that logic introduces a failure of gcc.dg/debug/dwarf2/pr47939-4.c, a test introduced along with first_non_attr_kind. Thus, it is necessary to track the original qualified typedef when qualifying an array type, to use it rather than a newly-constructed type, to avoid regressing regarding typedef names in debug info. This is done along lines I suggested in : track the original type and the number of levels of array indirection at which it appears, and, in possibly affected cases, pass extra arguments to c_build_qualified_type (with default arguments to avoid needing to pass those extra arguments explicitly everywhere). Given Richard's recent fix to dwarf2out.c, this allows the C bug to be fixed without causing debug information regressions. Bootstrapped with no regressions on x86_64-pc-linux-gnu. gcc/c: 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. gcc/c-family: PR c/68162 * c-common.h (c_build_qualified_type): Add extra default arguments. gcc/cp: PR c/68162 * tree.c (c_build_qualified_type): Add extra arguments. gcc/testsuite: PR c/68162 * gcc.dg/pr68162-1.c: New test. From-SVN: r231194 --- gcc/c-family/ChangeLog | 6 ++++++ gcc/c-family/c-common.h | 2 +- gcc/c/ChangeLog | 9 ++++++++ gcc/c/c-decl.c | 32 ++++++++++++++++++++------- gcc/c/c-typeck.c | 37 +++++++++++++++++++++----------- gcc/cp/ChangeLog | 5 +++++ gcc/cp/tree.c | 3 ++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/pr68162-1.c | 6 ++++++ 9 files changed, 82 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr68162-1.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 982a74a6017..b89812f12cb 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2015-12-02 Joseph Myers + + PR c/68162 + * c-common.h (c_build_qualified_type): Add extra default + arguments. + 2015-12-01 Julian Brown Cesar Philippidis James Norris diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index bad8d05e620..6e60e345a3b 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -866,7 +866,7 @@ extern tree pointer_int_sum (location_t, enum tree_code, tree, tree, bool = true); /* Add qualifiers to a type, in the fashion for C. */ -extern tree c_build_qualified_type (tree, int); +extern tree c_build_qualified_type (tree, int, tree = NULL_TREE, size_t = 0); /* Build tree nodes and builtin functions common to both C and C++ language frontends. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index e517467bd6a..bd214403b67 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2015-12-02 Joseph Myers + + 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 * c-parser.c (c_parser_omp_clause_name) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index efb0a52c9c4..9ad821925a0 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 cc2e38e12a7..50709729c79 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)) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f5f97070fac..ebd567a0dce 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2015-12-02 Joseph Myers + + PR c/68162 + * tree.c (c_build_qualified_type): Add extra arguments. + 2015-12-02 Eric Botcazou PR c++/68290 diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d2db31a628a..5dad0a77d41 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -995,7 +995,8 @@ move (tree expr) the C version of this function does not properly maintain canonical types (which are not used in C). */ 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 */) { return cp_build_qualified_type (type, type_quals); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index edbed47c6b6..feb0a0ae523 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-12-02 Joseph Myers + + PR c/68162 + * gcc.dg/pr68162-1.c: New test. + 2015-12-02 Aditya Kumar Sebastian Pop diff --git a/gcc/testsuite/gcc.dg/pr68162-1.c b/gcc/testsuite/gcc.dg/pr68162-1.c new file mode 100644 index 00000000000..a2c495365fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr68162-1.c @@ -0,0 +1,6 @@ +/* Test handling of pointers to arrays of const elements involving a + typedef. PR c/68162. */ + +typedef const double cd; +void f (const double (*)[]); +void g (void) { f ((cd (*)[]) 0); }