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))))
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);
}
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)
{
}
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. */
{
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;
}
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
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);