Commit 4b011bbf by Jason Merrill Committed by Jason Merrill

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
parent e913996d
2003-10-09 Jason Merrill <jason@redhat.com> 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 * coverage.c (build_ctr_info_value): Use build_decl to make a
VAR_DECL. VAR_DECL.
(create_coverage): Likewise. (create_coverage): Likewise.
......
...@@ -2766,13 +2766,14 @@ static tree builtin_function_2 (const char *, const char *, tree, tree, ...@@ -2766,13 +2766,14 @@ static tree builtin_function_2 (const char *, const char *, tree, tree,
tree tree
c_build_qualified_type (tree type, int type_quals) 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 /* A restrict-qualified pointer type must be a pointer to object or
incomplete type. Note that the use of POINTER_TYPE_P also allows incomplete type. Note that the use of POINTER_TYPE_P also allows
REFERENCE_TYPEs, which is appropriate for C++. Unfortunately, REFERENCE_TYPEs, which is appropriate for C++. */
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. */
if ((type_quals & TYPE_QUAL_RESTRICT) if ((type_quals & TYPE_QUAL_RESTRICT)
&& (!POINTER_TYPE_P (type) && (!POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))) || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
...@@ -2781,10 +2782,6 @@ c_build_qualified_type (tree type, int type_quals) ...@@ -2781,10 +2782,6 @@ c_build_qualified_type (tree type, int type_quals)
type_quals &= ~TYPE_QUAL_RESTRICT; 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); return build_qualified_type (type, type_quals);
} }
...@@ -2793,9 +2790,16 @@ c_build_qualified_type (tree type, int type_quals) ...@@ -2793,9 +2790,16 @@ c_build_qualified_type (tree type, int type_quals)
void void
c_apply_type_quals_to_decl (int type_quals, tree decl) c_apply_type_quals_to_decl (int type_quals, tree decl)
{ {
if ((type_quals & TYPE_QUAL_CONST) tree type = TREE_TYPE (decl);
|| (TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)) 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; TREE_READONLY (decl) = 1;
if (type_quals & TYPE_QUAL_VOLATILE) if (type_quals & TYPE_QUAL_VOLATILE)
{ {
...@@ -2804,11 +2808,15 @@ c_apply_type_quals_to_decl (int type_quals, tree decl) ...@@ -2804,11 +2808,15 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
} }
if (type_quals & TYPE_QUAL_RESTRICT) if (type_quals & TYPE_QUAL_RESTRICT)
{ {
if (!TREE_TYPE (decl) while (type && TREE_CODE (type) == ARRAY_TYPE)
|| !POINTER_TYPE_P (TREE_TYPE (decl)) /* Allow 'restrict' on arrays of pointers.
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl)))) 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'"); 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. /* 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 We can't do it here because it might be pointing to an
incomplete type. */ incomplete type. */
......
2003-10-09 Jason Merrill <jason@redhat.com> 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. * tree.c (build_cplus_new): Use build_decl to create a VAR_DECL.
(build_target_expr_with_type): Likewise. (build_target_expr_with_type): Likewise.
......
...@@ -367,16 +367,14 @@ build_cplus_array_type (tree elt_type, tree index_type) ...@@ -367,16 +367,14 @@ build_cplus_array_type (tree elt_type, tree index_type)
{ {
tree t; tree t;
int type_quals = cp_type_quals (elt_type); 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) if (type_quals != TYPE_UNQUALIFIED)
elt_type = cp_build_qualified_type (elt_type, other_quals); elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
t = build_cplus_array_type_1 (elt_type, index_type); t = build_cplus_array_type_1 (elt_type, index_type);
if (cv_quals) if (type_quals != TYPE_UNQUALIFIED)
t = cp_build_qualified_type (t, cv_quals); t = cp_build_qualified_type (t, type_quals);
return t; return t;
} }
...@@ -420,54 +418,6 @@ cp_build_qualified_type_real (tree type, ...@@ -420,54 +418,6 @@ cp_build_qualified_type_real (tree type,
if (type_quals == cp_type_quals (type)) if (type_quals == cp_type_quals (type))
return 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) if (TREE_CODE (type) == ARRAY_TYPE)
{ {
/* In C++, the qualification really applies to the array element /* In C++, the qualification really applies to the array element
...@@ -522,6 +472,54 @@ cp_build_qualified_type_real (tree type, ...@@ -522,6 +472,54 @@ cp_build_qualified_type_real (tree type,
return build_ptrmemfunc_type (t); 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. */ /* Retrieve (or create) the appropriately qualified variant. */
result = build_qualified_type (type, type_quals); result = build_qualified_type (type, type_quals);
......
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