Commit e9e32ee6 by Joseph Myers Committed by Joseph Myers

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
parent 701fa326
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> 2015-12-01 Julian Brown <julian@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com> Cesar Philippidis <cesar@codesourcery.com>
James Norris <James_Norris@mentor.com> James Norris <James_Norris@mentor.com>
......
...@@ -866,7 +866,7 @@ extern tree pointer_int_sum (location_t, enum tree_code, tree, tree, ...@@ -866,7 +866,7 @@ extern tree pointer_int_sum (location_t, enum tree_code, tree, tree,
bool = true); bool = true);
/* Add qualifiers to a type, in the fashion for C. */ /* 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 /* Build tree nodes and builtin functions common to both C and C++ language
frontends. */ frontends. */
......
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> 2015-12-02 Thomas Schwinge <thomas@codesourcery.com>
* c-parser.c (c_parser_omp_clause_name) * c-parser.c (c_parser_omp_clause_name)
......
...@@ -5351,6 +5351,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5351,6 +5351,8 @@ grokdeclarator (const struct c_declarator *declarator,
tree returned_attrs = NULL_TREE; tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL; bool bitfield = width != NULL;
tree element_type; tree element_type;
tree orig_qual_type = NULL;
size_t orig_qual_indirect = 0;
struct c_arg_info *arg_info = 0; struct c_arg_info *arg_info = 0;
addr_space_t as1, as2, address_space; addr_space_t as1, as2, address_space;
location_t loc = UNKNOWN_LOCATION; location_t loc = UNKNOWN_LOCATION;
...@@ -5389,9 +5391,9 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5389,9 +5391,9 @@ grokdeclarator (const struct c_declarator *declarator,
case cdk_function: case cdk_function:
case cdk_pointer: case cdk_pointer:
funcdef_syntax = (decl->kind == cdk_function); funcdef_syntax = (decl->kind == cdk_function);
decl = decl->declarator;
if (first_non_attr_kind == cdk_attrs) if (first_non_attr_kind == cdk_attrs)
first_non_attr_kind = decl->kind; first_non_attr_kind = decl->kind;
decl = decl->declarator;
break; break;
case cdk_attrs: case cdk_attrs:
...@@ -5513,12 +5515,17 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5513,12 +5515,17 @@ grokdeclarator (const struct c_declarator *declarator,
if ((TREE_CODE (type) == ARRAY_TYPE if ((TREE_CODE (type) == ARRAY_TYPE
|| first_non_attr_kind == cdk_array) || first_non_attr_kind == cdk_array)
&& TYPE_QUALS (element_type)) && 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) type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0) | (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0) | (volatilep ? TYPE_QUAL_VOLATILE : 0)
| (atomicp ? TYPE_QUAL_ATOMIC : 0) | (atomicp ? TYPE_QUAL_ATOMIC : 0)
| ENCODE_QUAL_ADDR_SPACE (address_space)); | 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 /* Applying the _Atomic qualifier to an array type (through the use
of typedefs or typeof) must be detected here. If the qualifier of typedefs or typeof) must be detected here. If the qualifier
...@@ -6013,6 +6020,7 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6013,6 +6020,7 @@ grokdeclarator (const struct c_declarator *declarator,
array_ptr_attrs = NULL_TREE; array_ptr_attrs = NULL_TREE;
array_parm_static = 0; array_parm_static = 0;
} }
orig_qual_indirect++;
break; break;
} }
case cdk_function: case cdk_function:
...@@ -6022,6 +6030,7 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6022,6 +6030,7 @@ grokdeclarator (const struct c_declarator *declarator,
attributes. */ attributes. */
bool really_funcdef = false; bool really_funcdef = false;
tree arg_types; tree arg_types;
orig_qual_type = NULL_TREE;
if (funcdef_flag) if (funcdef_flag)
{ {
const struct c_declarator *t = declarator->declarator; const struct c_declarator *t = declarator->declarator;
...@@ -6122,7 +6131,9 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6122,7 +6131,9 @@ grokdeclarator (const struct c_declarator *declarator,
pedwarn (loc, OPT_Wpedantic, pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types"); "ISO C forbids qualified function types");
if (type_quals) 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; size_varies = false;
/* When the pointed-to type involves components of variable size, /* When the pointed-to type involves components of variable size,
...@@ -6304,7 +6315,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6304,7 +6315,8 @@ grokdeclarator (const struct c_declarator *declarator,
pedwarn (loc, OPT_Wpedantic, pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types"); "ISO C forbids qualified function types");
if (type_quals) 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, decl = build_decl (declarator->id_loc,
TYPE_DECL, declarator->u.id, type); TYPE_DECL, declarator->u.id, type);
if (declspecs->explicit_signed_p) if (declspecs->explicit_signed_p)
...@@ -6357,7 +6369,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6357,7 +6369,8 @@ grokdeclarator (const struct c_declarator *declarator,
pedwarn (loc, OPT_Wpedantic, pedwarn (loc, OPT_Wpedantic,
"ISO C forbids const or volatile function types"); "ISO C forbids const or volatile function types");
if (type_quals) 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; return type;
} }
...@@ -6405,7 +6418,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6405,7 +6418,8 @@ grokdeclarator (const struct c_declarator *declarator,
/* Transfer const-ness of array into that of type pointed to. */ /* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (type_quals) 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 = c_build_pointer_type (type);
type_quals = array_ptr_quals; type_quals = array_ptr_quals;
if (type_quals) if (type_quals)
...@@ -6496,7 +6510,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6496,7 +6510,8 @@ grokdeclarator (const struct c_declarator *declarator,
TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node, TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
NULL_TREE); 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, decl = build_decl (declarator->id_loc,
FIELD_DECL, declarator->u.id, type); FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield; DECL_NONADDRESSABLE_P (decl) = bitfield;
...@@ -6608,7 +6623,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6608,7 +6623,8 @@ grokdeclarator (const struct c_declarator *declarator,
/* An uninitialized decl with `extern' is a reference. */ /* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern; 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 /* C99 6.2.2p7: It is invalid (compile-time undefined
behavior) to create an 'extern' declaration for a behavior) to create an 'extern' declaration for a
......
...@@ -13337,10 +13337,15 @@ c_finish_transaction (location_t loc, tree block, int flags) ...@@ -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 /* 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 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) if (type == error_mark_node)
return type; return type;
...@@ -13349,18 +13354,22 @@ c_build_qualified_type (tree type, int type_quals) ...@@ -13349,18 +13354,22 @@ c_build_qualified_type (tree type, int type_quals)
{ {
tree t; tree t;
tree element_type = c_build_qualified_type (TREE_TYPE (type), 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. */ /* See if we already have an identically qualified type. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) if (orig_qual_type && orig_qual_indirect == 0)
{ t = orig_qual_type;
if (TYPE_QUALS (strip_array_types (t)) == type_quals else
&& TYPE_NAME (t) == TYPE_NAME (type) for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
&& TYPE_CONTEXT (t) == TYPE_CONTEXT (type) {
&& attribute_list_equal (TYPE_ATTRIBUTES (t), if (TYPE_QUALS (strip_array_types (t)) == type_quals
TYPE_ATTRIBUTES (type))) && TYPE_NAME (t) == TYPE_NAME (type)
break; && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
} && attribute_list_equal (TYPE_ATTRIBUTES (t),
TYPE_ATTRIBUTES (type)))
break;
}
if (!t) if (!t)
{ {
tree domain = TYPE_DOMAIN (type); tree domain = TYPE_DOMAIN (type);
...@@ -13404,7 +13413,9 @@ c_build_qualified_type (tree type, int type_quals) ...@@ -13404,7 +13413,9 @@ c_build_qualified_type (tree type, int type_quals)
type_quals &= ~TYPE_QUAL_RESTRICT; 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 /* A variant type does not inherit the list of incomplete vars from the
type main variant. */ type main variant. */
if (RECORD_OR_UNION_TYPE_P (var_type)) if (RECORD_OR_UNION_TYPE_P (var_type))
......
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> 2015-12-02 Eric Botcazou <ebotcazou@adacore.com>
PR c++/68290 PR c++/68290
......
...@@ -995,7 +995,8 @@ move (tree expr) ...@@ -995,7 +995,8 @@ move (tree expr)
the C version of this function does not properly maintain canonical the C version of this function does not properly maintain canonical
types (which are not used in C). */ types (which are not used in C). */
tree 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); return cp_build_qualified_type (type, type_quals);
} }
......
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> 2015-12-02 Aditya Kumar <aditya.k7@samsung.com>
Sebastian Pop <s.pop@samsung.com> Sebastian Pop <s.pop@samsung.com>
......
/* 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); }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment