re PR middle-end/6392 (Problems with __restrict__ type qualifier (array))

PR c++/6392
        * cp/tree.c (build_cplus_array_type): Handle all quals the same.
        (cp_build_qualified_type_real): Look through arrays first.
        * c-common.c (c_build_qualified_type): Look through arrays first.
        (c_apply_type_quals_to_decl): Look through arrays.

        * c-common.c (c_apply_type_quals_to_decl): Unset TREE_READONLY for
        types with constructors.

From-SVN: r72259
This commit is contained in:
Jason Merrill 2003-10-09 04:38:46 -04:00 committed by Jason Merrill
parent e913996db1
commit 4b011bbf6b
4 changed files with 87 additions and 70 deletions

View File

@ -1,5 +1,12 @@
2003-10-09 Jason Merrill <jason@redhat.com>
PR c++/6392
* c-common.c (c_build_qualified_type): Look through arrays first.
(c_apply_type_quals_to_decl): Look through arrays.
* c-common.c (c_apply_type_quals_to_decl): Unset TREE_READONLY for
types with constructors.
* coverage.c (build_ctr_info_value): Use build_decl to make a
VAR_DECL.
(create_coverage): Likewise.

View File

@ -2766,13 +2766,14 @@ static tree builtin_function_2 (const char *, const char *, tree, tree,
tree
c_build_qualified_type (tree type, int type_quals)
{
if (TREE_CODE (type) == ARRAY_TYPE)
return build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
/* A restrict-qualified pointer type must be a pointer to object or
incomplete type. Note that the use of POINTER_TYPE_P also allows
REFERENCE_TYPEs, which is appropriate for C++. Unfortunately,
the C++ front-end also use POINTER_TYPE for pointer-to-member
values, so even though it should be illegal to use `restrict'
with such an entity we don't flag that here. Thus, special case
code for that case is required in the C++ front-end. */
REFERENCE_TYPEs, which is appropriate for C++. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& (!POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
@ -2781,10 +2782,6 @@ c_build_qualified_type (tree type, int type_quals)
type_quals &= ~TYPE_QUAL_RESTRICT;
}
if (TREE_CODE (type) == ARRAY_TYPE)
return build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
return build_qualified_type (type, type_quals);
}
@ -2793,9 +2790,16 @@ c_build_qualified_type (tree type, int type_quals)
void
c_apply_type_quals_to_decl (int type_quals, tree decl)
{
if ((type_quals & TYPE_QUAL_CONST)
|| (TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE))
tree type = TREE_TYPE (decl);
if (((type_quals & TYPE_QUAL_CONST)
|| (type && TREE_CODE (type) == REFERENCE_TYPE))
/* An object declared 'const' is only readonly after it is
initialized. We don't have any way of expressing this currently,
so we need to be conservative and unset TREE_READONLY for types
with constructors. Otherwise aliasing code will ignore stores in
an inline constructor. */
&& !(type && TYPE_NEEDS_CONSTRUCTING (type)))
TREE_READONLY (decl) = 1;
if (type_quals & TYPE_QUAL_VOLATILE)
{
@ -2804,11 +2808,15 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
}
if (type_quals & TYPE_QUAL_RESTRICT)
{
if (!TREE_TYPE (decl)
|| !POINTER_TYPE_P (TREE_TYPE (decl))
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl))))
while (type && TREE_CODE (type) == ARRAY_TYPE)
/* Allow 'restrict' on arrays of pointers.
FIXME currently we just ignore it. */
type = TREE_TYPE (type);
if (!type
|| !POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
error ("invalid use of `restrict'");
else if (flag_strict_aliasing)
else if (flag_strict_aliasing && type == TREE_TYPE (decl))
/* Indicate we need to make a unique alias set for this pointer.
We can't do it here because it might be pointing to an
incomplete type. */

View File

@ -1,5 +1,9 @@
2003-10-09 Jason Merrill <jason@redhat.com>
PR c++/6392
* tree.c (build_cplus_array_type): Handle all quals the same.
(cp_build_qualified_type_real): Look through arrays first.
* tree.c (build_cplus_new): Use build_decl to create a VAR_DECL.
(build_target_expr_with_type): Likewise.

View File

@ -367,16 +367,14 @@ build_cplus_array_type (tree elt_type, tree index_type)
{
tree t;
int type_quals = cp_type_quals (elt_type);
int cv_quals = type_quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
int other_quals = type_quals & ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
if (cv_quals)
elt_type = cp_build_qualified_type (elt_type, other_quals);
if (type_quals != TYPE_UNQUALIFIED)
elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
t = build_cplus_array_type_1 (elt_type, index_type);
if (cv_quals)
t = cp_build_qualified_type (t, cv_quals);
if (type_quals != TYPE_UNQUALIFIED)
t = cp_build_qualified_type (t, type_quals);
return t;
}
@ -420,54 +418,6 @@ cp_build_qualified_type_real (tree type,
if (type_quals == cp_type_quals (type))
return type;
/* A reference, fucntion or method type shall not be cv qualified.
[dcl.ref], [dct.fct] */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
if (TREE_CODE (type) != REFERENCE_TYPE)
bad_func_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
/* A restrict-qualified type must be a pointer (or reference)
to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE
&& !POINTER_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;
type_quals &= ~TYPE_QUAL_RESTRICT;
}
if (bad_quals == TYPE_UNQUALIFIED)
/*OK*/;
else if (!(complain & (tf_error | tf_ignore_bad_quals)))
return error_mark_node;
else if (bad_func_quals && !(complain & tf_error))
return error_mark_node;
else
{
if (complain & tf_ignore_bad_quals)
/* We're not going to warn about constifying things that can't
be constified. */
bad_quals &= ~TYPE_QUAL_CONST;
bad_quals |= bad_func_quals;
if (bad_quals)
{
tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
if (!(complain & tf_ignore_bad_quals)
|| bad_func_quals)
error ("`%V' qualifiers cannot be applied to `%T'",
bad_type, type);
}
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
/* In C++, the qualification really applies to the array element
@ -522,6 +472,54 @@ cp_build_qualified_type_real (tree type,
return build_ptrmemfunc_type (t);
}
/* A reference, function or method type shall not be cv qualified.
[dcl.ref], [dct.fct] */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
if (TREE_CODE (type) != REFERENCE_TYPE)
bad_func_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
/* A restrict-qualified type must be a pointer (or reference)
to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE
&& !POINTER_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;
type_quals &= ~TYPE_QUAL_RESTRICT;
}
if (bad_quals == TYPE_UNQUALIFIED)
/*OK*/;
else if (!(complain & (tf_error | tf_ignore_bad_quals)))
return error_mark_node;
else if (bad_func_quals && !(complain & tf_error))
return error_mark_node;
else
{
if (complain & tf_ignore_bad_quals)
/* We're not going to warn about constifying things that can't
be constified. */
bad_quals &= ~TYPE_QUAL_CONST;
bad_quals |= bad_func_quals;
if (bad_quals)
{
tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
if (!(complain & tf_ignore_bad_quals)
|| bad_func_quals)
error ("`%V' qualifiers cannot be applied to `%T'",
bad_type, type);
}
}
/* Retrieve (or create) the appropriately qualified variant. */
result = build_qualified_type (type, type_quals);