tm.texi (TARGET_ADDR_SPACE_KEYWORDS): Document.
2009-10-26 Ben Elliston <bje@au.ibm.com> Michael Meissner <meissner@linux.vnet.ibm.com> Ulrich Weigand <uweigand@de.ibm.com> * doc/tm.texi (TARGET_ADDR_SPACE_KEYWORDS): Document. * c-common.c (c_common_reswords): If TARGET_ADDR_SPACE_KEYWORDS is defined, add the named address space keywords. (c_addr_space_name): New function. (complete_array_type): Preserve named address space. (handle_mode_attribute): Use targetm.addr_space.valid_pointer_mode instead of targetm.valid_pointer_mode. * c-common.h (enum rid): Add RID_ADDR_SPACE_0 .. RID_ADDR_SPACE_15, RID_FIRST_ADDR_SPACE and RID_LAST_ADDR_SPACE. (ADDR_SPACE_KEYWORD): New macro. (c_addr_space_name): Add prototype. * c-tree.h (struct c_declspecs): Add address_space member. (declspecs_add_addrspace): Add prototype. * c-pretty-print.c (pp_c_type_qualifier_list): Handle address spaces. * c-parser.c (c_parse_init): Add assertion. (typedef enum c_id_kind): Add C_ID_ADDRSPACE. (c_lex_one_token): Handle address space keywords. (c_token_starts_typename): Likewise. (c_token_starts_declspecs): Likewise. (c_parser_declspecs): Likewise. (c_parser_postfix_expression_after_paren_type): Diagnose compound literal within function qualified with named address space. * c-decl.c (diagnose_mismatched_decls): Diagnose conflicting named address space qualifiers. (shadow_tag_warned): Warn about useless address space qualifiers. (quals_from_declspecs): Handle address space qualifiers. (grokdeclarator): Likewise. (build_null_declspecs): Likewise. (declspecs_add_addrspace): New function. * c-typeck.c (addr_space_superset): New function. (qualify_type): Handle named address spaces. (composite_type): Likewise. (common_pointer_type): Likewise. (comp_target_types): Likewise. (build_conditional_expr): Likewise. (handle_warn_cast_qual): Likewise. (build_c_cast): Likewise. (convert_for_assignment): Likewise. (build_binary_op): Likewise. (pointer_diff): Handle named address spaces. Use intermediate integer type of sufficient size if required. Co-Authored-By: Michael Meissner <meissner@linux.vnet.ibm.com> Co-Authored-By: Ulrich Weigand <uweigand@de.ibm.com> From-SVN: r153574
This commit is contained in:
parent
d4ebfa65c9
commit
36c5e70a3a
|
@ -1,3 +1,56 @@
|
|||
2009-10-26 Ben Elliston <bje@au.ibm.com>
|
||||
Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* doc/tm.texi (TARGET_ADDR_SPACE_KEYWORDS): Document.
|
||||
|
||||
* c-common.c (c_common_reswords): If TARGET_ADDR_SPACE_KEYWORDS is
|
||||
defined, add the named address space keywords.
|
||||
(c_addr_space_name): New function.
|
||||
(complete_array_type): Preserve named address space.
|
||||
(handle_mode_attribute): Use targetm.addr_space.valid_pointer_mode
|
||||
instead of targetm.valid_pointer_mode.
|
||||
|
||||
* c-common.h (enum rid): Add RID_ADDR_SPACE_0 .. RID_ADDR_SPACE_15,
|
||||
RID_FIRST_ADDR_SPACE and RID_LAST_ADDR_SPACE.
|
||||
(ADDR_SPACE_KEYWORD): New macro.
|
||||
(c_addr_space_name): Add prototype.
|
||||
|
||||
* c-tree.h (struct c_declspecs): Add address_space member.
|
||||
(declspecs_add_addrspace): Add prototype.
|
||||
|
||||
* c-pretty-print.c (pp_c_type_qualifier_list): Handle address spaces.
|
||||
|
||||
* c-parser.c (c_parse_init): Add assertion.
|
||||
(typedef enum c_id_kind): Add C_ID_ADDRSPACE.
|
||||
(c_lex_one_token): Handle address space keywords.
|
||||
(c_token_starts_typename): Likewise.
|
||||
(c_token_starts_declspecs): Likewise.
|
||||
(c_parser_declspecs): Likewise.
|
||||
(c_parser_postfix_expression_after_paren_type): Diagnose compound
|
||||
literal within function qualified with named address space.
|
||||
|
||||
* c-decl.c (diagnose_mismatched_decls): Diagnose conflicting named
|
||||
address space qualifiers.
|
||||
(shadow_tag_warned): Warn about useless address space qualifiers.
|
||||
(quals_from_declspecs): Handle address space qualifiers.
|
||||
(grokdeclarator): Likewise.
|
||||
(build_null_declspecs): Likewise.
|
||||
(declspecs_add_addrspace): New function.
|
||||
|
||||
* c-typeck.c (addr_space_superset): New function.
|
||||
(qualify_type): Handle named address spaces.
|
||||
(composite_type): Likewise.
|
||||
(common_pointer_type): Likewise.
|
||||
(comp_target_types): Likewise.
|
||||
(build_conditional_expr): Likewise.
|
||||
(handle_warn_cast_qual): Likewise.
|
||||
(build_c_cast): Likewise.
|
||||
(convert_for_assignment): Likewise.
|
||||
(build_binary_op): Likewise.
|
||||
(pointer_diff): Handle named address spaces. Use intermediate
|
||||
integer type of sufficient size if required.
|
||||
|
||||
2009-10-26 Ben Elliston <bje@au.ibm.com>
|
||||
Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
|
|
@ -710,6 +710,11 @@ const struct c_common_resword c_common_reswords[] =
|
|||
{ "inout", RID_INOUT, D_OBJC },
|
||||
{ "oneway", RID_ONEWAY, D_OBJC },
|
||||
{ "out", RID_OUT, D_OBJC },
|
||||
|
||||
#ifdef TARGET_ADDR_SPACE_KEYWORDS
|
||||
/* Any address space keywords recognized by the target. */
|
||||
TARGET_ADDR_SPACE_KEYWORDS,
|
||||
#endif
|
||||
};
|
||||
|
||||
const unsigned int num_c_common_reswords =
|
||||
|
@ -840,6 +845,19 @@ const struct attribute_spec c_common_format_attribute_table[] =
|
|||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
||||
/* Return identifier for address space AS. */
|
||||
const char *
|
||||
c_addr_space_name (addr_space_t as)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_c_common_reswords; i++)
|
||||
if (c_common_reswords[i].rid == RID_FIRST_ADDR_SPACE + as)
|
||||
return c_common_reswords[i].word;
|
||||
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Push current bindings for the function name VAR_DECLS. */
|
||||
|
||||
void
|
||||
|
@ -6459,9 +6477,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
|
|||
|
||||
if (POINTER_TYPE_P (type))
|
||||
{
|
||||
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
|
||||
tree (*fn)(tree, enum machine_mode, bool);
|
||||
|
||||
if (!targetm.valid_pointer_mode (mode))
|
||||
if (!targetm.addr_space.valid_pointer_mode (mode, as))
|
||||
{
|
||||
error ("invalid pointer mode %qs", p);
|
||||
return NULL_TREE;
|
||||
|
@ -8511,7 +8530,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
|
|||
if (quals == 0)
|
||||
unqual_elt = elt;
|
||||
else
|
||||
unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
|
||||
unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
|
||||
|
||||
/* Using build_distinct_type_copy and modifying things afterward instead
|
||||
of using build_array_type to create a new type preserves all of the
|
||||
|
|
|
@ -126,6 +126,30 @@ enum rid
|
|||
RID_AT_INTERFACE,
|
||||
RID_AT_IMPLEMENTATION,
|
||||
|
||||
/* Named address support, mapping the keyword to a particular named address
|
||||
number. Named address space 0 is reserved for the generic address. If
|
||||
there are more than 254 named addresses, the addr_space_t type will need
|
||||
to be grown from an unsigned char to unsigned short. */
|
||||
RID_ADDR_SPACE_0, /* generic address */
|
||||
RID_ADDR_SPACE_1,
|
||||
RID_ADDR_SPACE_2,
|
||||
RID_ADDR_SPACE_3,
|
||||
RID_ADDR_SPACE_4,
|
||||
RID_ADDR_SPACE_5,
|
||||
RID_ADDR_SPACE_6,
|
||||
RID_ADDR_SPACE_7,
|
||||
RID_ADDR_SPACE_8,
|
||||
RID_ADDR_SPACE_9,
|
||||
RID_ADDR_SPACE_10,
|
||||
RID_ADDR_SPACE_11,
|
||||
RID_ADDR_SPACE_12,
|
||||
RID_ADDR_SPACE_13,
|
||||
RID_ADDR_SPACE_14,
|
||||
RID_ADDR_SPACE_15,
|
||||
|
||||
RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
|
||||
RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
|
||||
|
||||
RID_MAX,
|
||||
|
||||
RID_FIRST_MODIFIER = RID_STATIC,
|
||||
|
@ -263,6 +287,10 @@ struct c_common_resword
|
|||
#define D_CXX_OBJC 0x100 /* In Objective C, and C++, but not C. */
|
||||
#define D_CXXWARN 0x200 /* In C warn with -Wcxx-compat. */
|
||||
|
||||
/* Macro for backends to define named address keywords. */
|
||||
#define ADDR_SPACE_KEYWORD(STRING, VALUE) \
|
||||
{ STRING, RID_FIRST_ADDR_SPACE + (VALUE), D_CONLY | D_EXT }
|
||||
|
||||
/* The reserved keyword table. */
|
||||
extern const struct c_common_resword c_common_reswords[];
|
||||
|
||||
|
@ -760,6 +788,7 @@ extern const struct attribute_spec c_common_format_attribute_table[];
|
|||
|
||||
extern tree (*make_fname_decl) (location_t, tree, int);
|
||||
|
||||
extern const char *c_addr_space_name (addr_space_t as);
|
||||
extern tree identifier_global_value (tree);
|
||||
extern void record_builtin_type (enum rid, const char *, tree);
|
||||
extern tree build_void_list_node (void);
|
||||
|
|
135
gcc/c-decl.c
135
gcc/c-decl.c
|
@ -1746,8 +1746,35 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
|
||||
error ("conflicting type qualifiers for %q+D", newdecl);
|
||||
int new_quals = TYPE_QUALS (newtype);
|
||||
int old_quals = TYPE_QUALS (oldtype);
|
||||
|
||||
if (new_quals != old_quals)
|
||||
{
|
||||
addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
|
||||
addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
|
||||
if (new_addr != old_addr)
|
||||
{
|
||||
if (ADDR_SPACE_GENERIC_P (new_addr))
|
||||
error ("conflicting named address spaces (generic vs %s) "
|
||||
"for %q+D",
|
||||
c_addr_space_name (old_addr), newdecl);
|
||||
else if (ADDR_SPACE_GENERIC_P (old_addr))
|
||||
error ("conflicting named address spaces (%s vs generic) "
|
||||
"for %q+D",
|
||||
c_addr_space_name (new_addr), newdecl);
|
||||
else
|
||||
error ("conflicting named address spaces (%s vs %s) "
|
||||
"for %q+D",
|
||||
c_addr_space_name (new_addr),
|
||||
c_addr_space_name (old_addr),
|
||||
newdecl);
|
||||
}
|
||||
|
||||
if (CLEAR_QUAL_ADDR_SPACE (new_quals)
|
||||
!= CLEAR_QUAL_ADDR_SPACE (old_quals))
|
||||
error ("conflicting type qualifiers for %q+D", newdecl);
|
||||
}
|
||||
else
|
||||
error ("conflicting types for %q+D", newdecl);
|
||||
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
|
||||
|
@ -3605,7 +3632,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
|
|||
else if (!declspecs->tag_defined_p
|
||||
&& (declspecs->const_p
|
||||
|| declspecs->volatile_p
|
||||
|| declspecs->restrict_p))
|
||||
|| declspecs->restrict_p
|
||||
|| declspecs->address_space))
|
||||
{
|
||||
if (warned != 1)
|
||||
pedwarn (input_location, 0,
|
||||
|
@ -3676,7 +3704,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
|
|||
|
||||
if (!warned && !in_system_header && (declspecs->const_p
|
||||
|| declspecs->volatile_p
|
||||
|| declspecs->restrict_p))
|
||||
|| declspecs->restrict_p
|
||||
|| declspecs->address_space))
|
||||
{
|
||||
warning (0, "useless type qualifier in empty declaration");
|
||||
warned = 2;
|
||||
|
@ -3699,7 +3728,8 @@ quals_from_declspecs (const struct c_declspecs *specs)
|
|||
{
|
||||
int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
|
||||
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
|
||||
| (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
|
||||
| (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
|
||||
| (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
|
||||
gcc_assert (!specs->type
|
||||
&& !specs->decl_attr
|
||||
&& specs->typespec_word == cts_none
|
||||
|
@ -4750,6 +4780,7 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
bool bitfield = width != NULL;
|
||||
tree element_type;
|
||||
struct c_arg_info *arg_info = 0;
|
||||
addr_space_t as1, as2, address_space;
|
||||
location_t loc = UNKNOWN_LOCATION;
|
||||
const char *errmsg;
|
||||
tree expr_dummy;
|
||||
|
@ -4880,6 +4911,10 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
constp = declspecs->const_p + TYPE_READONLY (element_type);
|
||||
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
|
||||
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
|
||||
as1 = declspecs->address_space;
|
||||
as2 = TYPE_ADDR_SPACE (element_type);
|
||||
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
|
||||
|
||||
if (pedantic && !flag_isoc99)
|
||||
{
|
||||
if (constp > 1)
|
||||
|
@ -4889,11 +4924,17 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
if (volatilep > 1)
|
||||
pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
|
||||
}
|
||||
|
||||
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
|
||||
error_at (loc, "conflicting named address spaces (%s vs %s)",
|
||||
c_addr_space_name (as1), c_addr_space_name (as2));
|
||||
|
||||
if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
|
||||
type = TYPE_MAIN_VARIANT (type);
|
||||
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
|
||||
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
|
||||
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
|
||||
| (volatilep ? TYPE_QUAL_VOLATILE : 0)
|
||||
| ENCODE_QUAL_ADDR_SPACE (address_space));
|
||||
|
||||
/* Warn about storage classes that are invalid for certain
|
||||
kinds of declarations (parameters, typenames, etc.). */
|
||||
|
@ -5309,7 +5350,14 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
it, but here we want to make sure we don't ever
|
||||
modify the shared type, so we gcc_assert (itype)
|
||||
below. */
|
||||
type = build_array_type (type, itype);
|
||||
{
|
||||
addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
|
||||
if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
|
||||
type = build_qualified_type (type,
|
||||
ENCODE_QUAL_ADDR_SPACE (as));
|
||||
|
||||
type = build_array_type (type, itype);
|
||||
}
|
||||
|
||||
if (type != error_mark_node)
|
||||
{
|
||||
|
@ -5515,6 +5563,59 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
/* Now TYPE has the actual type, apart from any qualifiers in
|
||||
TYPE_QUALS. */
|
||||
|
||||
/* Warn about address space used for things other than static memory or
|
||||
pointers. */
|
||||
address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
|
||||
if (!ADDR_SPACE_GENERIC_P (address_space))
|
||||
{
|
||||
if (decl_context == NORMAL)
|
||||
{
|
||||
switch (storage_class)
|
||||
{
|
||||
case csc_auto:
|
||||
error ("%qs combined with %<auto%> qualifier for %qE",
|
||||
c_addr_space_name (address_space), name);
|
||||
break;
|
||||
case csc_register:
|
||||
error ("%qs combined with %<register%> qualifier for %qE",
|
||||
c_addr_space_name (address_space), name);
|
||||
break;
|
||||
case csc_none:
|
||||
if (current_function_scope)
|
||||
{
|
||||
error ("%qs specified for auto variable %qE",
|
||||
c_addr_space_name (address_space), name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case csc_static:
|
||||
case csc_extern:
|
||||
case csc_typedef:
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
|
||||
{
|
||||
if (name)
|
||||
error ("%qs specified for parameter %qE",
|
||||
c_addr_space_name (address_space), name);
|
||||
else
|
||||
error ("%qs specified for unnamed parameter",
|
||||
c_addr_space_name (address_space));
|
||||
}
|
||||
else if (decl_context == FIELD)
|
||||
{
|
||||
if (name)
|
||||
error ("%qs specified for structure field %qE",
|
||||
c_addr_space_name (address_space), name);
|
||||
else
|
||||
error ("%qs specified for structure field",
|
||||
c_addr_space_name (address_space));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the type and width of a bit-field. */
|
||||
if (bitfield)
|
||||
check_bitfield_type_and_width (&type, width, name);
|
||||
|
@ -8297,9 +8398,29 @@ build_null_declspecs (void)
|
|||
ret->volatile_p = false;
|
||||
ret->restrict_p = false;
|
||||
ret->saturating_p = false;
|
||||
ret->address_space = ADDR_SPACE_GENERIC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add the address space ADDRSPACE to the declaration specifiers
|
||||
SPECS, returning SPECS. */
|
||||
|
||||
struct c_declspecs *
|
||||
declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
|
||||
{
|
||||
specs->non_sc_seen_p = true;
|
||||
specs->declspecs_seen_p = true;
|
||||
|
||||
if (!ADDR_SPACE_GENERIC_P (specs->address_space)
|
||||
&& specs->address_space != as)
|
||||
error ("incompatible address space qualifiers %qs and %qs",
|
||||
c_addr_space_name (as),
|
||||
c_addr_space_name (specs->address_space));
|
||||
else
|
||||
specs->address_space = as;
|
||||
return specs;
|
||||
}
|
||||
|
||||
/* Add the type qualifier QUAL to the declaration specifiers SPECS,
|
||||
returning SPECS. */
|
||||
|
||||
|
|
|
@ -72,6 +72,10 @@ c_parse_init (void)
|
|||
tree id;
|
||||
int mask = 0;
|
||||
|
||||
/* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
|
||||
the c_token structure. */
|
||||
gcc_assert (RID_MAX <= 255);
|
||||
|
||||
mask |= D_CXXONLY;
|
||||
if (!flag_isoc99)
|
||||
mask |= D_C99;
|
||||
|
@ -132,6 +136,8 @@ typedef enum c_id_kind {
|
|||
C_ID_TYPENAME,
|
||||
/* An identifier declared as an Objective-C class name. */
|
||||
C_ID_CLASSNAME,
|
||||
/* An address space identifier. */
|
||||
C_ID_ADDRSPACE,
|
||||
/* Not an identifier. */
|
||||
C_ID_NONE
|
||||
} c_id_kind;
|
||||
|
@ -226,6 +232,13 @@ c_lex_one_token (c_parser *parser, c_token *token)
|
|||
"identifier %qE conflicts with C++ keyword",
|
||||
token->value);
|
||||
}
|
||||
else if (rid_code >= RID_FIRST_ADDR_SPACE
|
||||
&& rid_code <= RID_LAST_ADDR_SPACE)
|
||||
{
|
||||
token->id_kind = C_ID_ADDRSPACE;
|
||||
token->keyword = rid_code;
|
||||
break;
|
||||
}
|
||||
else if (c_dialect_objc ())
|
||||
{
|
||||
if (!objc_is_reserved_word (token->value)
|
||||
|
@ -352,6 +365,8 @@ c_token_starts_typename (c_token *token)
|
|||
{
|
||||
case C_ID_ID:
|
||||
return false;
|
||||
case C_ID_ADDRSPACE:
|
||||
return true;
|
||||
case C_ID_TYPENAME:
|
||||
return true;
|
||||
case C_ID_CLASSNAME:
|
||||
|
@ -422,6 +437,8 @@ c_token_starts_declspecs (c_token *token)
|
|||
{
|
||||
case C_ID_ID:
|
||||
return false;
|
||||
case C_ID_ADDRSPACE:
|
||||
return true;
|
||||
case C_ID_TYPENAME:
|
||||
return true;
|
||||
case C_ID_CLASSNAME:
|
||||
|
@ -1411,6 +1428,7 @@ c_parser_asm_definition (c_parser *parser)
|
|||
const
|
||||
restrict
|
||||
volatile
|
||||
address-space-qualifier
|
||||
|
||||
(restrict is new in C99.)
|
||||
|
||||
|
@ -1419,6 +1437,12 @@ c_parser_asm_definition (c_parser *parser)
|
|||
declaration-specifiers:
|
||||
attributes declaration-specifiers[opt]
|
||||
|
||||
type-qualifier:
|
||||
address-space
|
||||
|
||||
address-space:
|
||||
identifier recognized by the target
|
||||
|
||||
storage-class-specifier:
|
||||
__thread
|
||||
|
||||
|
@ -1459,6 +1483,17 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
|||
{
|
||||
tree value = c_parser_peek_token (parser)->value;
|
||||
c_id_kind kind = c_parser_peek_token (parser)->id_kind;
|
||||
|
||||
if (kind == C_ID_ADDRSPACE)
|
||||
{
|
||||
addr_space_t as
|
||||
= c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
|
||||
declspecs_add_addrspace (specs, as);
|
||||
c_parser_consume_token (parser);
|
||||
attrs_ok = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This finishes the specifiers unless a type name is OK, it
|
||||
is declared as a type name and a type name hasn't yet
|
||||
been seen. */
|
||||
|
@ -5775,6 +5810,14 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
|||
finish_init ();
|
||||
maybe_warn_string_init (type, init);
|
||||
|
||||
if (type != error_mark_node
|
||||
&& !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
|
||||
&& current_function_decl)
|
||||
{
|
||||
error ("compound literal qualified by address-space qualifier");
|
||||
type = error_mark_node;
|
||||
}
|
||||
|
||||
if (!flag_isoc99)
|
||||
pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
|
||||
non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
|
||||
|
|
|
@ -225,7 +225,11 @@ pp_c_space_for_pointer_operator (c_pretty_printer *pp, tree t)
|
|||
const
|
||||
restrict -- C99
|
||||
__restrict__ -- GNU C
|
||||
volatile */
|
||||
address-space-qualifier -- GNU C
|
||||
volatile
|
||||
|
||||
address-space-qualifier:
|
||||
identifier -- GNU C */
|
||||
|
||||
void
|
||||
pp_c_type_qualifier_list (c_pretty_printer *pp, tree t)
|
||||
|
@ -245,6 +249,12 @@ pp_c_type_qualifier_list (c_pretty_printer *pp, tree t)
|
|||
pp_c_cv_qualifier (pp, "volatile");
|
||||
if (qualifiers & TYPE_QUAL_RESTRICT)
|
||||
pp_c_cv_qualifier (pp, flag_isoc99 ? "restrict" : "__restrict__");
|
||||
|
||||
if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t)))
|
||||
{
|
||||
const char *as = c_addr_space_name (TYPE_ADDR_SPACE (t));
|
||||
pp_c_identifier (pp, as);
|
||||
}
|
||||
}
|
||||
|
||||
/* pointer:
|
||||
|
|
|
@ -277,6 +277,8 @@ struct c_declspecs {
|
|||
BOOL_BITFIELD restrict_p : 1;
|
||||
/* Whether "_Sat" was specified. */
|
||||
BOOL_BITFIELD saturating_p : 1;
|
||||
/* The address space that the declaration belongs to. */
|
||||
addr_space_t address_space;
|
||||
};
|
||||
|
||||
/* The various kinds of declarators in C. */
|
||||
|
@ -476,6 +478,8 @@ extern struct c_declspecs *declspecs_add_type (location_t,
|
|||
struct c_typespec);
|
||||
extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
|
||||
extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
|
||||
extern struct c_declspecs *declspecs_add_addrspace (struct c_declspecs *,
|
||||
addr_space_t);
|
||||
extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
|
||||
|
||||
/* in c-objc-common.c */
|
||||
|
|
271
gcc/c-typeck.c
271
gcc/c-typeck.c
|
@ -284,14 +284,55 @@ c_type_promotes_to (tree type)
|
|||
return type;
|
||||
}
|
||||
|
||||
/* Return true if between two named address spaces, whether there is a superset
|
||||
named address space that encompasses both address spaces. If there is a
|
||||
superset, return which address space is the superset. */
|
||||
|
||||
static bool
|
||||
addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
|
||||
{
|
||||
if (as1 == as2)
|
||||
{
|
||||
*common = as1;
|
||||
return true;
|
||||
}
|
||||
else if (targetm.addr_space.subset_p (as1, as2))
|
||||
{
|
||||
*common = as2;
|
||||
return true;
|
||||
}
|
||||
else if (targetm.addr_space.subset_p (as2, as1))
|
||||
{
|
||||
*common = as1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return a variant of TYPE which has all the type qualifiers of LIKE
|
||||
as well as those of TYPE. */
|
||||
|
||||
static tree
|
||||
qualify_type (tree type, tree like)
|
||||
{
|
||||
addr_space_t as_type = TYPE_ADDR_SPACE (type);
|
||||
addr_space_t as_like = TYPE_ADDR_SPACE (like);
|
||||
addr_space_t as_common;
|
||||
|
||||
/* If the two named address spaces are different, determine the common
|
||||
superset address space. If there isn't one, raise an error. */
|
||||
if (!addr_space_superset (as_type, as_like, &as_common))
|
||||
{
|
||||
as_common = as_type;
|
||||
error ("%qT and %qT are in disjoint named address spaces",
|
||||
type, like);
|
||||
}
|
||||
|
||||
return c_build_qualified_type (type,
|
||||
TYPE_QUALS (type) | TYPE_QUALS (like));
|
||||
TYPE_QUALS_NO_ADDR_SPACE (type)
|
||||
| TYPE_QUALS_NO_ADDR_SPACE (like)
|
||||
| ENCODE_QUAL_ADDR_SPACE (as_common));
|
||||
}
|
||||
|
||||
/* Return true iff the given tree T is a variable length array. */
|
||||
|
@ -371,7 +412,8 @@ composite_type (tree t1, tree t2)
|
|||
bool t1_complete, t2_complete;
|
||||
|
||||
/* We should not have any type quals on arrays at all. */
|
||||
gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
|
||||
gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
|
||||
&& !TYPE_QUALS_NO_ADDR_SPACE (t2));
|
||||
|
||||
t1_complete = COMPLETE_TYPE_P (t1);
|
||||
t2_complete = COMPLETE_TYPE_P (t2);
|
||||
|
@ -585,6 +627,8 @@ common_pointer_type (tree t1, tree t2)
|
|||
tree pointed_to_2, mv2;
|
||||
tree target;
|
||||
unsigned target_quals;
|
||||
addr_space_t as1, as2, as_common;
|
||||
int quals1, quals2;
|
||||
|
||||
/* Save time if the two types are the same. */
|
||||
|
||||
|
@ -616,10 +660,24 @@ common_pointer_type (tree t1, tree t2)
|
|||
/* For function types do not merge const qualifiers, but drop them
|
||||
if used inconsistently. The middle-end uses these to mark const
|
||||
and noreturn functions. */
|
||||
quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
|
||||
quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
|
||||
|
||||
if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
|
||||
target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
|
||||
target_quals = (quals1 & quals2);
|
||||
else
|
||||
target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
|
||||
target_quals = (quals1 | quals2);
|
||||
|
||||
/* If the two named address spaces are different, determine the common
|
||||
superset address space. This is guaranteed to exist due to the
|
||||
assumption that comp_target_type returned non-zero. */
|
||||
as1 = TYPE_ADDR_SPACE (pointed_to_1);
|
||||
as2 = TYPE_ADDR_SPACE (pointed_to_2);
|
||||
if (!addr_space_superset (as1, as2, &as_common))
|
||||
gcc_unreachable ();
|
||||
|
||||
target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
|
||||
|
||||
t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
@ -1103,20 +1161,28 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
|
|||
return attrval == 2 && val == 1 ? 2 : val;
|
||||
}
|
||||
|
||||
/* Return 1 if TTL and TTR are pointers to types that are equivalent,
|
||||
ignoring their qualifiers. */
|
||||
/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
|
||||
their qualifiers, except for named address spaces. If the pointers point to
|
||||
different named addresses, then we must determine if one address space is a
|
||||
subset of the other. */
|
||||
|
||||
static int
|
||||
comp_target_types (location_t location, tree ttl, tree ttr)
|
||||
{
|
||||
int val;
|
||||
tree mvl, mvr;
|
||||
tree mvl = TREE_TYPE (ttl);
|
||||
tree mvr = TREE_TYPE (ttr);
|
||||
addr_space_t asl = TYPE_ADDR_SPACE (mvl);
|
||||
addr_space_t asr = TYPE_ADDR_SPACE (mvr);
|
||||
addr_space_t as_common;
|
||||
bool enum_and_int_p;
|
||||
|
||||
/* Fail if pointers point to incompatible address spaces. */
|
||||
if (!addr_space_superset (asl, asr, &as_common))
|
||||
return 0;
|
||||
|
||||
/* Do not lose qualifiers on element types of array types that are
|
||||
pointer targets by taking their TYPE_MAIN_VARIANT. */
|
||||
mvl = TREE_TYPE (ttl);
|
||||
mvr = TREE_TYPE (ttr);
|
||||
if (TREE_CODE (mvl) != ARRAY_TYPE)
|
||||
mvl = TYPE_MAIN_VARIANT (mvl);
|
||||
if (TREE_CODE (mvr) != ARRAY_TYPE)
|
||||
|
@ -3063,11 +3129,43 @@ static tree
|
|||
pointer_diff (location_t loc, tree op0, tree op1)
|
||||
{
|
||||
tree restype = ptrdiff_type_node;
|
||||
tree result, inttype;
|
||||
|
||||
addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
|
||||
addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
|
||||
tree target_type = TREE_TYPE (TREE_TYPE (op0));
|
||||
tree con0, con1, lit0, lit1;
|
||||
tree orig_op1 = op1;
|
||||
|
||||
/* If the operands point into different address spaces, we need to
|
||||
explicitly convert them to pointers into the common address space
|
||||
before we can subtract the numerical address values. */
|
||||
if (as0 != as1)
|
||||
{
|
||||
addr_space_t as_common;
|
||||
tree common_type;
|
||||
|
||||
/* Determine the common superset address space. This is guaranteed
|
||||
to exist because the caller verified that comp_target_types
|
||||
returned non-zero. */
|
||||
if (!addr_space_superset (as0, as1, &as_common))
|
||||
gcc_unreachable ();
|
||||
|
||||
common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
|
||||
op0 = convert (common_type, op0);
|
||||
op1 = convert (common_type, op1);
|
||||
}
|
||||
|
||||
/* Determine integer type to perform computations in. This will usually
|
||||
be the same as the result type (ptrdiff_t), but may need to be a wider
|
||||
type if pointers for the address space are wider than ptrdiff_t. */
|
||||
if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0)))
|
||||
inttype = lang_hooks.types.type_for_size
|
||||
(TYPE_PRECISION (TREE_TYPE (op0)), 0);
|
||||
else
|
||||
inttype = restype;
|
||||
|
||||
|
||||
if (TREE_CODE (target_type) == VOID_TYPE)
|
||||
pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
|
||||
"pointer of type %<void *%> used in subtraction");
|
||||
|
@ -3125,8 +3223,8 @@ pointer_diff (location_t loc, tree op0, tree op1)
|
|||
in case restype is a short type. */
|
||||
|
||||
op0 = build_binary_op (loc,
|
||||
MINUS_EXPR, convert (restype, op0),
|
||||
convert (restype, op1), 0);
|
||||
MINUS_EXPR, convert (inttype, op0),
|
||||
convert (inttype, op1), 0);
|
||||
/* This generates an error if op1 is pointer to incomplete type. */
|
||||
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
|
||||
error_at (loc, "arithmetic on pointer to an incomplete type");
|
||||
|
@ -3135,8 +3233,11 @@ pointer_diff (location_t loc, tree op0, tree op1)
|
|||
op1 = c_size_in_bytes (target_type);
|
||||
|
||||
/* Divide by the size, in easiest possible way. */
|
||||
return fold_build2_loc (loc, EXACT_DIV_EXPR, restype,
|
||||
op0, convert (restype, op1));
|
||||
result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
|
||||
op0, convert (inttype, op1));
|
||||
|
||||
/* Convert to final result type if necessary. */
|
||||
return convert (restype, result);
|
||||
}
|
||||
|
||||
/* Construct and perhaps optimize a tree representation
|
||||
|
@ -3956,12 +4057,22 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
|
|||
}
|
||||
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
|
||||
{
|
||||
addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
|
||||
addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2));
|
||||
addr_space_t as_common;
|
||||
|
||||
if (comp_target_types (colon_loc, type1, type2))
|
||||
result_type = common_pointer_type (type1, type2);
|
||||
else if (null_pointer_constant_p (orig_op1))
|
||||
result_type = qualify_type (type2, type1);
|
||||
result_type = type2;
|
||||
else if (null_pointer_constant_p (orig_op2))
|
||||
result_type = qualify_type (type1, type2);
|
||||
result_type = type1;
|
||||
else if (!addr_space_superset (as1, as2, &as_common))
|
||||
{
|
||||
error_at (colon_loc, "pointers to disjoint address spaces "
|
||||
"used in conditional expression");
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (VOID_TYPE_P (TREE_TYPE (type1)))
|
||||
{
|
||||
if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
|
||||
|
@ -3982,10 +4093,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
|
|||
}
|
||||
else
|
||||
{
|
||||
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
|
||||
|
||||
if (!objc_ok)
|
||||
pedwarn (colon_loc, 0,
|
||||
"pointer type mismatch in conditional expression");
|
||||
result_type = build_pointer_type (void_type_node);
|
||||
result_type = build_pointer_type
|
||||
(build_qualified_type (void_type_node, qual));
|
||||
}
|
||||
}
|
||||
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
|
||||
|
@ -4144,7 +4258,8 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
|
|||
/* Issue -Wcast-qual warnings when appropriate. TYPE is the type to
|
||||
which we are casting. OTYPE is the type of the expression being
|
||||
cast. Both TYPE and OTYPE are pointer types. -Wcast-qual appeared
|
||||
on the command line. */
|
||||
on the command line. Named address space qualifiers are not handled
|
||||
here, because they result in different warnings. */
|
||||
|
||||
static void
|
||||
handle_warn_cast_qual (tree type, tree otype)
|
||||
|
@ -4170,9 +4285,11 @@ handle_warn_cast_qual (tree type, tree otype)
|
|||
taken away. */
|
||||
if (TREE_CODE (in_otype) == FUNCTION_TYPE
|
||||
&& TREE_CODE (in_type) == FUNCTION_TYPE)
|
||||
added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
|
||||
added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
|
||||
& ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
|
||||
else
|
||||
discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
|
||||
discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
|
||||
& ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
|
||||
}
|
||||
while (TREE_CODE (in_type) == POINTER_TYPE
|
||||
&& TREE_CODE (in_otype) == POINTER_TYPE);
|
||||
|
@ -4321,6 +4438,36 @@ build_c_cast (location_t loc, tree type, tree expr)
|
|||
&& TREE_CODE (otype) == POINTER_TYPE)
|
||||
handle_warn_cast_qual (type, otype);
|
||||
|
||||
/* Warn about conversions between pointers to disjoint
|
||||
address spaces. */
|
||||
if (TREE_CODE (type) == POINTER_TYPE
|
||||
&& TREE_CODE (otype) == POINTER_TYPE
|
||||
&& !null_pointer_constant_p (value))
|
||||
{
|
||||
addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
|
||||
addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (otype));
|
||||
addr_space_t as_common;
|
||||
|
||||
if (!addr_space_superset (as_to, as_from, &as_common))
|
||||
{
|
||||
if (ADDR_SPACE_GENERIC_P (as_from))
|
||||
warning_at (loc, 0, "cast to %s address space pointer "
|
||||
"from disjoint generic address space pointer",
|
||||
c_addr_space_name (as_to));
|
||||
|
||||
else if (ADDR_SPACE_GENERIC_P (as_to))
|
||||
warning_at (loc, 0, "cast to generic address space pointer "
|
||||
"from disjoint %s address space pointer",
|
||||
c_addr_space_name (as_from));
|
||||
|
||||
else
|
||||
warning_at (loc, 0, "cast to %s address space pointer "
|
||||
"from disjoint %s address space pointer",
|
||||
c_addr_space_name (as_to),
|
||||
c_addr_space_name (as_from));
|
||||
}
|
||||
}
|
||||
|
||||
/* Warn about possible alignment problems. */
|
||||
if (STRICT_ALIGNMENT
|
||||
&& TREE_CODE (type) == POINTER_TYPE
|
||||
|
@ -4915,7 +5062,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
certain things, it is okay to use a const or volatile
|
||||
function where an ordinary one is wanted, but not
|
||||
vice-versa. */
|
||||
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
|
||||
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
|
||||
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
|
||||
WARN_FOR_ASSIGNMENT (location, 0,
|
||||
G_("passing argument %d of %qE "
|
||||
"makes qualified function "
|
||||
|
@ -4929,7 +5077,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
G_("return makes qualified function "
|
||||
"pointer from unqualified"));
|
||||
}
|
||||
else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
|
||||
else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
|
||||
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
|
||||
WARN_FOR_ASSIGNMENT (location, 0,
|
||||
G_("passing argument %d of %qE discards "
|
||||
"qualifiers from pointer target type"),
|
||||
|
@ -4962,6 +5111,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
tree mvr = ttr;
|
||||
bool is_opaque_pointer;
|
||||
int target_cmp = 0; /* Cache comp_target_types () result. */
|
||||
addr_space_t asl;
|
||||
addr_space_t asr;
|
||||
|
||||
if (TREE_CODE (mvl) != ARRAY_TYPE)
|
||||
mvl = TYPE_MAIN_VARIANT (mvl);
|
||||
|
@ -4982,6 +5133,36 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
"request for implicit conversion "
|
||||
"from %qT to %qT not permitted in C++", rhstype, type);
|
||||
|
||||
/* See if the pointers point to incompatible address spaces. */
|
||||
asl = TYPE_ADDR_SPACE (ttl);
|
||||
asr = TYPE_ADDR_SPACE (ttr);
|
||||
if (!null_pointer_constant_p (rhs)
|
||||
&& asr != asl && !targetm.addr_space.subset_p (asr, asl))
|
||||
{
|
||||
switch (errtype)
|
||||
{
|
||||
case ic_argpass:
|
||||
error_at (location, "passing argument %d of %qE from pointer to "
|
||||
"non-enclosed address space", parmnum, rname);
|
||||
break;
|
||||
case ic_assign:
|
||||
error_at (location, "assignment from pointer to "
|
||||
"non-enclosed address space");
|
||||
break;
|
||||
case ic_init:
|
||||
error_at (location, "initialization from pointer to "
|
||||
"non-enclosed address space");
|
||||
break;
|
||||
case ic_return:
|
||||
error_at (location, "return from pointer to "
|
||||
"non-enclosed address space");
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Check if the right-hand side has a format attribute but the
|
||||
left-hand side doesn't. */
|
||||
if (warn_missing_format_attribute
|
||||
|
@ -5045,7 +5226,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
else if (TREE_CODE (ttr) != FUNCTION_TYPE
|
||||
&& TREE_CODE (ttl) != FUNCTION_TYPE)
|
||||
{
|
||||
if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
|
||||
if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
|
||||
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
|
||||
{
|
||||
/* Types differing only by the presence of the 'volatile'
|
||||
qualifier are acceptable if the 'volatile' has been added
|
||||
|
@ -5085,7 +5267,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
that say the function will not do certain things,
|
||||
it is okay to use a const or volatile function
|
||||
where an ordinary one is wanted, but not vice-versa. */
|
||||
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
|
||||
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
|
||||
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
|
||||
WARN_FOR_ASSIGNMENT (location, 0,
|
||||
G_("passing argument %d of %qE makes "
|
||||
"qualified function pointer "
|
||||
|
@ -9193,24 +9376,34 @@ build_binary_op (location_t location, enum tree_code code,
|
|||
{
|
||||
tree tt0 = TREE_TYPE (type0);
|
||||
tree tt1 = TREE_TYPE (type1);
|
||||
addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
|
||||
addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
|
||||
addr_space_t as_common = ADDR_SPACE_GENERIC;
|
||||
|
||||
/* Anything compares with void *. void * compares with anything.
|
||||
Otherwise, the targets must be compatible
|
||||
and both must be object or both incomplete. */
|
||||
if (comp_target_types (location, type0, type1))
|
||||
result_type = common_pointer_type (type0, type1);
|
||||
else if (null_pointer_constant_p (orig_op0))
|
||||
result_type = type1;
|
||||
else if (null_pointer_constant_p (orig_op1))
|
||||
result_type = type0;
|
||||
else if (!addr_space_superset (as0, as1, &as_common))
|
||||
{
|
||||
error_at (location, "comparison of pointers to "
|
||||
"disjoint address spaces");
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (VOID_TYPE_P (tt0))
|
||||
{
|
||||
/* op0 != orig_op0 detects the case of something
|
||||
whose value is 0 but which isn't a valid null ptr const. */
|
||||
if (pedantic && !null_pointer_constant_p (orig_op0)
|
||||
&& TREE_CODE (tt1) == FUNCTION_TYPE)
|
||||
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
|
||||
pedwarn (location, OPT_pedantic, "ISO C forbids "
|
||||
"comparison of %<void *%> with function pointer");
|
||||
}
|
||||
else if (VOID_TYPE_P (tt1))
|
||||
{
|
||||
if (pedantic && !null_pointer_constant_p (orig_op1)
|
||||
&& TREE_CODE (tt0) == FUNCTION_TYPE)
|
||||
if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
|
||||
pedwarn (location, OPT_pedantic, "ISO C forbids "
|
||||
"comparison of %<void *%> with function pointer");
|
||||
}
|
||||
|
@ -9221,7 +9414,11 @@ build_binary_op (location_t location, enum tree_code code,
|
|||
"comparison of distinct pointer types lacks a cast");
|
||||
|
||||
if (result_type == NULL_TREE)
|
||||
result_type = ptr_type_node;
|
||||
{
|
||||
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
|
||||
result_type = build_pointer_type
|
||||
(build_qualified_type (void_type_node, qual));
|
||||
}
|
||||
}
|
||||
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
|
||||
{
|
||||
|
@ -9265,6 +9462,10 @@ build_binary_op (location_t location, enum tree_code code,
|
|||
short_compare = 1;
|
||||
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|
||||
{
|
||||
addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
|
||||
addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
|
||||
addr_space_t as_common;
|
||||
|
||||
if (comp_target_types (location, type0, type1))
|
||||
{
|
||||
result_type = common_pointer_type (type0, type1);
|
||||
|
@ -9276,9 +9477,17 @@ build_binary_op (location_t location, enum tree_code code,
|
|||
pedwarn (location, OPT_pedantic, "ISO C forbids "
|
||||
"ordered comparisons of pointers to functions");
|
||||
}
|
||||
else if (!addr_space_superset (as0, as1, &as_common))
|
||||
{
|
||||
error_at (location, "comparison of pointers to "
|
||||
"disjoint address spaces");
|
||||
return error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_type = ptr_type_node;
|
||||
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
|
||||
result_type = build_pointer_type
|
||||
(build_qualified_type (void_type_node, qual));
|
||||
pedwarn (location, 0,
|
||||
"comparison of distinct pointer types lacks a cast");
|
||||
}
|
||||
|
|
|
@ -9855,6 +9855,18 @@ Internally, address spaces are represented as a small integer in the
|
|||
range 0 to 15 with address space 0 being reserved for the generic
|
||||
address space.
|
||||
|
||||
@defmac TARGET_ADDR_SPACE_KEYWORDS
|
||||
A list of @code{ADDR_SPACE_KEYWORD} macros to define each named
|
||||
address keyword. The @code{ADDR_SPACE_KEYWORD} macro takes two
|
||||
arguments, the keyword string and the number of the named address
|
||||
space. For example, the SPU port uses the following to declare
|
||||
@code{__ea} as the keyword for named address space #1:
|
||||
@smallexample
|
||||
#define ADDR_SPACE_EA 1
|
||||
#define TARGET_ADDR_SPACE_KEYWORDS ADDR_SPACE_KEYWORD ("__ea", ADDR_SPACE_EA)
|
||||
@end smallexample
|
||||
@end defmac
|
||||
|
||||
@deftypefn {Target Hook} {enum machine_mode} TARGET_ADDR_SPACE_POINTER_MODE (addr_space_t @var{address_space})
|
||||
Define this to return the machine mode to use for pointers to
|
||||
@var{address_space} if the target supports named address spaces.
|
||||
|
|
Loading…
Reference in New Issue