This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH to restrict handling for c++/6392
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 09 Oct 2003 04:31:34 -0400
- Subject: PATCH to restrict handling for c++/6392
PR 6392 complains that gcc rejects "int* __restrict__ data[10];". I agree
that this is a bug; it is entirely reasonable to declare an array of
restricted pointers. This patch reverts my previous wrong-headed patch for
this PR and fixes the bug by enforcing the principle that a qualifier
applied to an array type really applies to the element types.
Note that this patch only fixes the error; we currently want alias sets to
correspond to decls, and have no way of expressing an alias set per element
of an array. So we now just accept and ignore "restrict" on an array.
I'll leave the PR open for that improvement.
Tested x86_64-pc-linux-gnu, applied to trunk.
2003-10-09 Jason Merrill <jason@redhat.com>
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.
*** ./cp/tree.c.~1~ 2003-10-09 02:03:36.000000000 -0400
--- ./cp/tree.c 2003-10-09 02:01:34.000000000 -0400
*************** build_cplus_array_type (tree elt_type, t
*** 367,382 ****
{
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);
t = build_cplus_array_type_1 (elt_type, index_type);
! if (cv_quals)
! t = cp_build_qualified_type (t, cv_quals);
return t;
}
--- 367,380 ----
{
tree t;
int type_quals = cp_type_quals (elt_type);
! 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 (type_quals != TYPE_UNQUALIFIED)
! t = cp_build_qualified_type (t, type_quals);
return t;
}
*************** cp_build_qualified_type_real (tree type,
*** 420,473 ****
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
--- 418,423 ----
*************** cp_build_qualified_type_real (tree type,
*** 522,527 ****
--- 472,525 ----
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);
*** ./c-common.c.~1~ 2003-10-09 02:03:36.000000000 -0400
--- ./c-common.c 2003-09-25 17:19:56.000000000 -0400
*************** static tree builtin_function_2 (const ch
*** 2766,2778 ****
tree
c_build_qualified_type (tree type, int type_quals)
{
/* 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. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& (!POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
--- 2766,2779 ----
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++. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& (!POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
*************** c_build_qualified_type (tree type, int t
*** 2781,2790 ****
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);
}
--- 2782,2787 ----
*************** c_build_qualified_type (tree type, int t
*** 2793,2801 ****
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_READONLY (decl) = 1;
if (type_quals & TYPE_QUAL_VOLATILE)
{
--- 2790,2805 ----
void
c_apply_type_quals_to_decl (int type_quals, tree decl)
{
! 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)
{
*************** c_apply_type_quals_to_decl (int type_qua
*** 2804,2814 ****
}
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))))
error ("invalid use of `restrict'");
! else if (flag_strict_aliasing)
/* 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. */
--- 2808,2822 ----
}
if (type_quals & TYPE_QUAL_RESTRICT)
{
! 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 && 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. */