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 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47939#c6>: 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
This commit is contained in:
parent
701fa326a1
commit
e9e32ee6e8
|
@ -1,3 +1,9 @@
|
|||
2015-12-02 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR c/68162
|
||||
* c-common.h (c_build_qualified_type): Add extra default
|
||||
arguments.
|
||||
|
||||
2015-12-01 Julian Brown <julian@codesourcery.com>
|
||||
Cesar Philippidis <cesar@codesourcery.com>
|
||||
James Norris <James_Norris@mentor.com>
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2015-12-02 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR c/68162
|
||||
* tree.c (c_build_qualified_type): Add extra arguments.
|
||||
|
||||
2015-12-02 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR c++/68290
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2015-12-02 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR c/68162
|
||||
* gcc.dg/pr68162-1.c: New test.
|
||||
|
||||
2015-12-02 Aditya Kumar <aditya.k7@samsung.com>
|
||||
Sebastian Pop <s.pop@samsung.com>
|
||||
|
||||
|
|
|
@ -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); }
|
Loading…
Reference in New Issue