diff options
Diffstat (limited to 'gcc/c/c-typeck.c')
-rw-r--r-- | gcc/c/c-typeck.c | 401 |
1 files changed, 370 insertions, 31 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index b6b45558a54..4cd52d36ac3 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -43,6 +43,8 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "tree-inline.h" #include "omp-low.h" +#include "c-upc.h" +#include "c-upc-low.h" #include "c-family/c-objc.h" #include "c-family/c-ubsan.h" #include "cilk.h" @@ -91,6 +93,7 @@ static tree lookup_field (tree, tree); static int convert_arguments (location_t, vec<location_t>, tree, vec<tree, va_gc> *, vec<tree, va_gc> *, tree, tree); +static tree c_pointer_int_sum (location_t, enum tree_code, tree, tree); static tree pointer_diff (location_t, tree, tree); static tree convert_for_assignment (location_t, location_t, tree, tree, tree, enum impl_conv, bool, tree, tree, int); @@ -317,9 +320,12 @@ addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common) static tree qualify_type (tree type, tree like) { + tree result_type; addr_space_t as_type = TYPE_ADDR_SPACE (type); addr_space_t as_like = TYPE_ADDR_SPACE (like); addr_space_t as_common; + int result_quals; + tree result_block_factor = NULL_TREE; /* If the two named address spaces are different, determine the common superset address space. If there isn't one, raise an error. */ @@ -330,10 +336,31 @@ qualify_type (tree type, tree like) type, like); } - return c_build_qualified_type (type, - TYPE_QUALS_NO_ADDR_SPACE (type) - | TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (like) - | ENCODE_QUAL_ADDR_SPACE (as_common)); + result_quals = TYPE_QUALS_NO_ADDR_SPACE (type) + | TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (like) + | ENCODE_QUAL_ADDR_SPACE (as_common); + + if (result_quals & TYPE_QUAL_SHARED) + { + tree b1 = TYPE_BLOCK_FACTOR (type); + tree b2 = TYPE_BLOCK_FACTOR (like); + /* We can merge in a new UPC blocking factor only + if one/other is NULL. Otherwise, they must match. */ + if (b1 != b2) + { + if (b1 && !b2) + result_block_factor = b1; + else if (!b1 && b2) + result_block_factor = b2; + else + gcc_unreachable (); + } + } + + result_type = c_build_qualified_type (type, result_quals, + result_block_factor); + + return result_type; } /* Return true iff the given tree T is a variable length array. */ @@ -626,6 +653,7 @@ common_pointer_type (tree t1, tree t2) tree pointed_to_2, mv2; tree target; unsigned target_quals; + tree target_block_factor = NULL_TREE; addr_space_t as1, as2, as_common; int quals1, quals2; @@ -668,6 +696,10 @@ common_pointer_type (tree t1, tree t2) else target_quals = (quals1 | quals2); + if (target_quals & TYPE_QUAL_SHARED) + target_block_factor = TYPE_BLOCK_FACTOR ( + strip_array_types (pointed_to_1)); + /* 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. */ @@ -677,8 +709,9 @@ common_pointer_type (tree t1, tree t2) gcc_unreachable (); target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common); + t2 = c_build_qualified_type (target, target_quals, target_block_factor); - t1 = build_pointer_type (c_build_qualified_type (target, target_quals)); + t1 = build_pointer_type (t2); return build_type_attribute_variant (t1, attributes); } @@ -1086,6 +1119,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p, if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) return 0; + /* If the type is UPC qualified, the block sizes have + to be equal. The block sizes are either NULL + or are the same integer constant. */ + if ((TYPE_QUALS (t1) & TYPE_QUAL_SHARED) + && (TYPE_BLOCK_FACTOR (t1) != TYPE_BLOCK_FACTOR (t2))) + return 0; + /* Allow for two different type nodes which have essentially the same definition. Note that we already checked for equality of the type qualifiers (just above). */ @@ -2096,6 +2136,10 @@ default_conversion (tree exp) /* Functions and arrays have been converted during parsing. */ gcc_assert (code != FUNCTION_TYPE); + + if (code == ARRAY_TYPE && SHARED_TYPE_P (type)) + return array_to_pointer_conversion (input_location, exp); + if (code == ARRAY_TYPE) return exp; @@ -2350,6 +2394,7 @@ build_component_ref (location_t loc, tree datum, tree component) error_at (loc, "%qT has no member named %qE", type, component); return error_mark_node; } + gcc_assert (!TREE_SHARED (field)); /* Accessing elements of atomic structures or unions is undefined behavior (C11 6.5.2.3#5). */ @@ -2371,6 +2416,8 @@ build_component_ref (location_t loc, tree datum, tree component) do { tree subdatum = TREE_VALUE (field); + tree sub_elem_type = strip_array_types (TREE_TYPE (subdatum)); + tree upc_block_factor = NULL_TREE; int quals; tree subtype; bool use_datum_quals; @@ -2385,10 +2432,15 @@ build_component_ref (location_t loc, tree datum, tree component) use_datum_quals = (datum_lvalue || TREE_CODE (TREE_TYPE (subdatum)) != ARRAY_TYPE); - quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum))); + quals = TYPE_QUALS (sub_elem_type); if (use_datum_quals) quals |= TYPE_QUALS (TREE_TYPE (datum)); - subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals); + /* All references to UPC shared struct components + are defined to have an indefinite (zero) blocking factor. */ + if (quals & TYPE_QUAL_SHARED) + upc_block_factor = size_zero_node; + subtype = c_build_qualified_type (TREE_TYPE (subdatum), + quals, upc_block_factor); ref = build3 (COMPONENT_REF, subtype, datum, subdatum, NULL_TREE); @@ -2399,6 +2451,8 @@ build_component_ref (location_t loc, tree datum, tree component) if (TREE_THIS_VOLATILE (subdatum) || (use_datum_quals && TREE_THIS_VOLATILE (datum))) TREE_THIS_VOLATILE (ref) = 1; + if (TREE_SHARED (datum)) + TREE_SHARED (ref) = 1; if (TREE_DEPRECATED (subdatum)) warn_deprecated_use (subdatum, NULL_TREE); @@ -2496,6 +2550,7 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring) TREE_SIDE_EFFECTS (ref) = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer); TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t); + TREE_SHARED (ref) = SHARED_TYPE_P (t); protected_set_expr_location (ref, loc); return ref; } @@ -2584,7 +2639,8 @@ build_array_ref (location_t loc, tree array, tree index) bool non_lvalue = convert_vector_to_pointer_for_subscript (loc, &array, index); - if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) + if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE + && !SHARED_TYPE_P (TREE_TYPE (array))) { tree rval, type; @@ -3644,6 +3700,23 @@ parser_build_binary_op (location_t location, enum tree_code code, return result; } +/* Return a tree for the sum or difference (RESULTCODE says which) + of pointer PTROP and integer INTOP. */ + +static +tree +c_pointer_int_sum (location_t location, enum tree_code resultcode, + tree ptrop, tree intop) +{ + /* The result is a pointer of the same type that is being added. */ + tree result_type = TREE_TYPE (ptrop); + + if (SHARED_TYPE_P (TREE_TYPE (result_type))) + return upc_pts_int_sum (location, resultcode, ptrop, intop); + + return pointer_int_sum (location, resultcode, ptrop, intop); +} + /* Return a tree for the difference of pointers OP0 and OP1. The resulting tree has type int. */ @@ -3656,6 +3729,7 @@ pointer_diff (location_t loc, tree op0, tree op1) 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 subtrahend_type = TREE_TYPE (TREE_TYPE (op1)); tree orig_op1 = op1; /* If the operands point into different address spaces, we need to @@ -3692,6 +3766,9 @@ pointer_diff (location_t loc, tree op0, tree op1) pedwarn (loc, OPT_Wpointer_arith, "pointer to a function used in subtraction"); + if (SHARED_TYPE_P (target_type) || SHARED_TYPE_P (subtrahend_type)) + return upc_pts_diff (op0, op1); + /* First do the subtraction as integers; then drop through to build the divide operator. Do not do default conversions on the minus operator @@ -4293,6 +4370,11 @@ build_unary_op (location_t location, "wrong type argument to decrement"); } + /* UPC pointer-to-shared types cannot be + incremented/decremented directly. */ + if (SHARED_TYPE_P (TREE_TYPE (argtype))) + return upc_pts_increment (location, code, arg); + inc = c_size_in_bytes (TREE_TYPE (argtype)); inc = convert_to_ptrofftype_loc (location, inc); } @@ -4507,6 +4589,10 @@ build_unary_op (location_t location, ret = build1 (code, argtype, arg); return_build_unary_op: gcc_assert (ret != error_mark_node); + /* The result of an operation on objects that + are UPC shared qualified, must not be shared qualified. */ + if (SHARED_TYPE_P (TREE_TYPE (ret))) + TREE_TYPE (ret) = build_unshared_type (TREE_TYPE (ret)); if (TREE_CODE (ret) == INTEGER_CST && !TREE_OVERFLOW (ret) && !(TREE_CODE (xarg) == INTEGER_CST && !TREE_OVERFLOW (xarg))) ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); @@ -4950,7 +5036,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, "pointer/integer type mismatch in conditional expression"); else { - op2 = null_pointer_node; + op2 = !SHARED_TYPE_P (TREE_TYPE (type1)) + ? null_pointer_node : upc_null_pts_node; } result_type = type1; } @@ -4961,7 +5048,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, "pointer/integer type mismatch in conditional expression"); else { - op1 = null_pointer_node; + op1 = !SHARED_TYPE_P (TREE_TYPE (type2)) + ? null_pointer_node : upc_null_pts_node; } result_type = type2; } @@ -5256,6 +5344,12 @@ build_c_cast (location_t loc, tree type, tree expr) if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr))) return build1 (NOP_EXPR, type, expr); + if (SHARED_TYPE_P (type)) + { + error_at (loc, "UPC does not allow casts to a shared type"); + return error_mark_node; + } + type = TYPE_MAIN_VARIANT (type); if (TREE_CODE (type) == ARRAY_TYPE) @@ -5277,6 +5371,22 @@ build_c_cast (location_t loc, tree type, tree expr) return error_mark_node; } + if (integer_zerop (value) + && POINTER_TYPE_P (type) + && SHARED_TYPE_P (TREE_TYPE (type)) + && POINTER_TYPE_P (TREE_TYPE (expr)) + && ! SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (expr)))) + { + value = upc_null_pts_node; + } + + if (!SHARED_TYPE_P (type) && SHARED_TYPE_P (TREE_TYPE (expr))) + { + /* UPC disallows things like: + (int)p = <expr>; (where p is a shared int) */ + value = non_lvalue (value); + } + if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value))) { if (RECORD_OR_UNION_TYPE_P (type)) @@ -5327,6 +5437,17 @@ build_c_cast (location_t loc, tree type, tree expr) otype = TREE_TYPE (value); + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == POINTER_TYPE) + { + int t_shared = SHARED_TYPE_P (TREE_TYPE (type)); + int o_shared = SHARED_TYPE_P (TREE_TYPE (otype)); + if ((!t_shared && o_shared) + || (t_shared && o_shared + && !lang_hooks.types_compatible_p (type, otype))) + return build1 (CONVERT_EXPR, type, value); + } + /* Optionally warn about potentially worrisome casts. */ if (warn_cast_qual && TREE_CODE (type) == POINTER_TYPE @@ -5377,6 +5498,33 @@ build_c_cast (location_t loc, tree type, tree expr) warning_at (loc, OPT_Wcast_align, "cast increases required alignment of target type"); + if (POINTER_TYPE_P (type) + && SHARED_TYPE_P (TREE_TYPE (type)) + && POINTER_TYPE_P (otype) + && !SHARED_TYPE_P (TREE_TYPE (otype))) + { + error_at (loc, "UPC does not allow casts from a local pointer to a pointer-to-shared"); + return error_mark_node; + } + + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == INTEGER_TYPE + && SHARED_TYPE_P (TREE_TYPE (type)) + && !integer_zerop (value)) + { + error_at (loc, "UPC does not allow casts from an integer to a pointer-to-shared"); + return error_mark_node; + } + + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (otype) == POINTER_TYPE + && SHARED_TYPE_P (TREE_TYPE (otype))) + { + /* UPC pointer-to-shared -> integer + This will be lowered by the genericize pass. */ + return build1 (CONVERT_EXPR, type, value); + } + if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype)) @@ -5699,6 +5847,12 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, newrhs = c_fully_fold (newrhs, false, NULL); if (rhs_semantic_type) newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs); + /* If the lhs is UPC 'shared' qualified, we drop the qualifier + for the purposes of conversions from rhstype to lhstype. + This will prevent the inadvertent creation of temporaries + with "shared" asserted. */ + if (SHARED_TYPE_P (lhstype)) + lhstype = build_unshared_type (lhstype); newrhs = convert_for_assignment (location, rhs_loc, lhstype, newrhs, rhs_origtype, ic_assign, npc, NULL_TREE, NULL_TREE, 0); @@ -6012,6 +6166,34 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } \ } while (0) + /* Similar to WARN_FOR_ASSIGNMENT, but used to diagnose certain + error conditions defined by the UPC language specification + when converting between pointer-to-shared types and other types. */ +#define ERROR_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE) \ + do { \ + switch (errtype) \ + { \ + case ic_argpass: \ + error_at (LOCATION, AR, parmnum, rname); \ + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ + ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \ + "expected %qT but argument is of type %qT", \ + type, rhstype); \ + break; \ + case ic_assign: \ + error_at (LOCATION, AS); \ + break; \ + case ic_init: \ + error_at (LOCATION, IN); \ + break; \ + case ic_return: \ + error_at (LOCATION, RE); \ + break; \ + default: \ + gcc_unreachable (); \ + } \ + } while (0) + /* This macro is used to emit diagnostics to ensure that all format strings are complete sentences, visible to gettext and checked at compile time. It is the same as PEDWARN_FOR_ASSIGNMENT but with an @@ -6255,7 +6437,9 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, /* Can convert integer zero to any pointer type. */ if (null_pointer_constant) { - rhs = null_pointer_node; + tree ttl = TREE_TYPE (memb_type); + rhs = !SHARED_TYPE_P (ttl) + ? null_pointer_node : upc_null_pts_node; break; } } @@ -6345,6 +6529,43 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC) : TYPE_MAIN_VARIANT (mvr)); + if ((SHARED_TYPE_P (ttl) && !SHARED_TYPE_P (ttr)) + && !integer_zerop (rhs)) + { + error_at (location, "UPC does not allow assignments from a local pointer " + "to a pointer-to-shared"); + return error_mark_node; + } + if (!SHARED_TYPE_P (ttl) && SHARED_TYPE_P (ttr)) + { + if (upc_is_null_pts_p (rhs)) + { + return null_pointer_node; + } + else + { + error_at (location, "UPC does not allow assignments " + "from a pointer-to-shared to a local pointer"); + return error_mark_node; + } + } + if (SHARED_TYPE_P (ttl) && SHARED_TYPE_P (ttr) && (ttl != ttr) + && !(VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr))) + { + const tree bs_l = get_block_factor (ttl); + const tree bs_r = get_block_factor (ttr); + /* Both source and destination are non-void pointers to shared, + whose target types are not equal. + UPC dictates that their blocking factors must be equal. */ + if (!tree_int_cst_equal (bs_l, bs_r)) + { + error_at (location, "UPC does not allow assignment " + "between pointers to shared with " + "differing block sizes without a cast"); + return error_mark_node; + } + } + /* Opaque pointers are treated like void pointers. */ is_opaque_pointer = vector_targets_convertible_p (ttl, ttr); @@ -6583,6 +6804,19 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } else if (codel == POINTER_TYPE && coder == INTEGER_TYPE) { + if (!null_pointer_constant && SHARED_TYPE_P (TREE_TYPE (type))) + { + ERROR_FOR_ASSIGNMENT (location, 0, + G_("passing argument %d of %qE attempts to make " + "a UPC pointer-to-shared value from an integer"), + G_("assignment attempts to make a UPC pointer-to-shared " + "value from an integer"), + G_("initialization attempts to make a UPC pointer-to-shared " + "value from an integer without a cast"), + G_("return makes a UPC pointer-to-shared value from an " + "integer")); + return error_mark_node; + } /* An explicit constant 0 can convert to a pointer, or one that results from arithmetic, even including a cast to integer type. */ @@ -6688,21 +6922,31 @@ valid_compound_expr_initializer (tree value, tree endtype) void store_init_value (location_t init_loc, tree decl, tree init, tree origtype) { - tree value, type; - bool npc = false; + const bool npc = init && null_pointer_constant_p (init); + const bool is_upc_decl_init = upc_check_decl_init (decl, init); + const bool require_constant = TREE_STATIC (decl) && !is_upc_decl_init; + tree type = TREE_TYPE (decl); + tree value; /* If variable's type was invalidly declared, just ignore it. */ - type = TREE_TYPE (decl); if (TREE_CODE (type) == ERROR_MARK) return; /* Digest the specified initializer into an expression. */ - if (init) - npc = null_pointer_constant_p (init); value = digest_init (init_loc, type, init, origtype, npc, - true, TREE_STATIC (decl)); + true, require_constant); + + /* UPC cannot initialize certain values at compile time. + For example, the address of a UPC 'shared' variable must + be evaluated at runtime. */ + + if (is_upc_decl_init) + { + upc_decl_init (decl, value); + return; + } /* Store the expression if valid; else report error. */ @@ -7508,6 +7752,9 @@ really_start_incremental_init (tree type) designator_depth = 0; designator_erroneous = 0; + /* The result of the constructor must not be UPC shared qualified */ + if (SHARED_TYPE_P (constructor_type)) + constructor_type = build_unshared_type (constructor_type); if (RECORD_OR_UNION_TYPE_P (constructor_type)) { constructor_fields = TYPE_FIELDS (constructor_type); @@ -9793,6 +10040,20 @@ c_finish_return (location_t loc, tree retval, tree origtype) TREE_NO_WARNING (ret_stmt) |= no_warning; return add_stmt (ret_stmt); } + +/* Convert EXPR to TYPE if the type of EXPR is + assignment compatible with TYPE. + Otherwise, issue an error (or warning) as appropriate. */ + +tree +c_cvt_expr_for_assign (location_t loc, tree type, tree expr) +{ + if (expr == NULL_TREE || expr == error_mark_node) + return expr; + return convert_for_assignment (loc, UNKNOWN_LOCATION, type, + expr, TREE_TYPE (expr), + ic_assign, false, NULL_TREE, NULL_TREE, 0); +} struct c_switch { /* The SWITCH_EXPR being built. */ @@ -10736,12 +10997,12 @@ build_binary_op (location_t location, enum tree_code code, /* Handle the pointer + int case. */ if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { - ret = pointer_int_sum (location, PLUS_EXPR, op0, op1); + ret = c_pointer_int_sum (location, PLUS_EXPR, op0, op1); goto return_build_binary_op; } else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE) { - ret = pointer_int_sum (location, PLUS_EXPR, op1, op0); + ret = c_pointer_int_sum (location, PLUS_EXPR, op1, op0); goto return_build_binary_op; } else @@ -10760,7 +11021,7 @@ build_binary_op (location_t location, enum tree_code code, /* Handle pointer minus int. Just like pointer plus int. */ else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { - ret = pointer_int_sum (location, MINUS_EXPR, op0, op1); + ret = c_pointer_int_sum (location, MINUS_EXPR, op0, op1); goto return_build_binary_op; } else @@ -11116,6 +11377,33 @@ build_binary_op (location_t location, enum tree_code code, addr_space_t as1 = TYPE_ADDR_SPACE (tt1); addr_space_t as_common = ADDR_SPACE_GENERIC; + if ((SHARED_TYPE_P (tt0) + && !(SHARED_TYPE_P (tt1) || integer_zerop(op1))) + || (SHARED_TYPE_P (tt1) + && !(SHARED_TYPE_P (tt0) || integer_zerop(op0)))) + { + error_at (location, "UPC does not allow comparisons " + "between pointers to shared and " + "local pointers"); + return error_mark_node; + } + if (SHARED_TYPE_P (tt0) + && SHARED_TYPE_P (tt1) && (tt0 != tt1) + && !(VOID_TYPE_P (tt0) || VOID_TYPE_P (tt1))) + { + const tree bs_0 = get_block_factor (tt0); + const tree bs_1 = get_block_factor (tt1); + /* Both source and destination are non-void pointers to shared, + whose target types are not equal. + UPC dictates that their blocking factors must be equal. */ + if (!tree_int_cst_equal (bs_0, bs_1)) + { + error_at (location, "UPC does not allow comparison " + "between pointers to shared with " + "differing block sizes without a cast"); + return error_mark_node; + } + } /* Anything compares with void *. void * compares with anything. Otherwise, the targets must be compatible and both must be object or both incomplete. */ @@ -11147,9 +11435,17 @@ build_binary_op (location_t location, enum tree_code code, if (result_type == NULL_TREE) { - int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - result_type = build_pointer_type - (build_qualified_type (void_type_node, qual)); + if (SHARED_TYPE_P(tt0) || SHARED_TYPE_P(tt1)) + { + result_type = upc_pts_type_node; + } + else + { + 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 && code1 == INTEGER_TYPE) @@ -11221,10 +11517,35 @@ 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)); + const tree tt0 = TREE_TYPE (type0); + const 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; + if (SHARED_TYPE_P (tt0) != SHARED_TYPE_P (tt1)) + { + error_at (location, "UPC does not allow comparisons between " + "pointers to shared and local pointers"); + return error_mark_node; + } + if (SHARED_TYPE_P (tt0) + && SHARED_TYPE_P (tt1) && (tt0 != tt1) + && !(VOID_TYPE_P (tt0) || VOID_TYPE_P (tt1))) + { + const tree bs_0 = get_block_factor (tt0); + const tree bs_1 = get_block_factor (tt1); + /* Both source and destination are non-void pointers to shared, + whose target types are not equal. + UPC dictates that their blocking factors must be equal. */ + if (!tree_int_cst_equal (bs_0, bs_1)) + { + error_at (location, "UPC does not allow comparison " + "between pointers to shared with " + "differing block sizes without a cast"); + return error_mark_node; + } + } if (comp_target_types (location, type0, type1)) { result_type = common_pointer_type (type0, type1); @@ -11247,6 +11568,11 @@ build_binary_op (location_t location, enum tree_code code, "disjoint address spaces"); return error_mark_node; } + else if (SHARED_TYPE_P (TREE_TYPE (type0)) + || SHARED_TYPE_P (TREE_TYPE (type1))) + { + result_type = upc_pts_type_node; + } else { int qual = ENCODE_QUAL_ADDR_SPACE (as_common); @@ -13461,10 +13787,16 @@ c_finish_transaction (location_t loc, tree block, int flags) NULL, then it should be used as the qualified type ORIG_QUAL_INDIRECT levels down in array type derivation (to preserve information about the typedef name from which an array - type was derived). */ + type was derived). + + LAYOUT_QUALIFIER is the UPC "blocking factor". It is an integral + constant that specifies the size of the blocks that will be + distributed across threads. It is NULL, when not compiling UPC. */ tree -c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, +c_build_qualified_type (tree type, int type_quals, + tree layout_qualifier, + tree orig_qual_type, size_t orig_qual_indirect) { if (type == error_mark_node) @@ -13474,7 +13806,9 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, { tree t; tree element_type = c_build_qualified_type (TREE_TYPE (type), - type_quals, orig_qual_type, + type_quals, + layout_qualifier, + orig_qual_type, orig_qual_indirect - 1); /* See if we already have an identically qualified type. */ @@ -13483,7 +13817,10 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, else for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) { - if (TYPE_QUALS (strip_array_types (t)) == type_quals + const tree t_elem_type = strip_array_types (t); + tree t_elem_block_factor = TYPE_BLOCK_FACTOR (t_elem_type); + if (TYPE_QUALS (t_elem_type) == type_quals + && t_elem_block_factor == layout_qualifier && TYPE_NAME (t) == TYPE_NAME (type) && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) && attribute_list_equal (TYPE_ATTRIBUTES (t), @@ -13514,7 +13851,8 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1; } TYPE_CANONICAL (t) - = c_build_qualified_type (unqualified_canon, type_quals); + = c_build_qualified_type (unqualified_canon, type_quals, + layout_qualifier); } else TYPE_CANONICAL (t) = t; @@ -13535,7 +13873,8 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, tree var_type = (orig_qual_type && orig_qual_indirect == 0 ? orig_qual_type - : build_qualified_type (type, type_quals)); + : build_qualified_type (type, type_quals, + layout_qualifier)); /* A variant type does not inherit the list of incomplete vars from the type main variant. */ if (RECORD_OR_UNION_TYPE_P (var_type) |