===================================================================
@@ -183,6 +183,9 @@ init_reswords (void)
/* The Objective-C keywords are all context-dependent. */
mask |= D_OBJC;
+ if (!c_dialect_upc ())
+ mask |= D_UPC;
+
ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
for (i = 0; i < num_c_common_reswords; i++)
{
===================================================================
@@ -900,7 +900,7 @@ move (tree expr)
the C version of this function does not properly maintain canonical
types (which are not used in C). */
tree
-c_build_qualified_type (tree type, int type_quals)
+c_build_qualified_type_1 (tree type, int type_quals, tree ARG_UNUSED(layout_qualiefier))
{
return cp_build_qualified_type (type, type_quals);
}
@@ -1849,7 +1849,7 @@ build_exception_variant (tree type, tree
type_quals = TYPE_QUALS (type);
for (v = TYPE_MAIN_VARIANT (type); v; v = TYPE_NEXT_VARIANT (v))
- if (check_qualified_type (v, type, type_quals)
+ if (check_qualified_type (v, type, type_quals, 0)
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), ce_exact))
return v;
===================================================================
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.
#include "timevar.h"
#include "c-family/c-common.h"
#include "c-family/c-objc.h"
+#include "c-family/c-upc.h"
#include "c-family/c-pragma.h"
#include "c-lang.h"
#include "langhooks.h"
@@ -570,6 +571,8 @@ c_build_pointer_type (tree to_type)
: TYPE_ADDR_SPACE (to_type);
enum machine_mode pointer_mode;
+ if (upc_shared_type_p (to_type))
+ return build_pointer_type (to_type);
if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
pointer_mode = targetm.addr_space.pointer_mode (as);
else
@@ -2236,6 +2239,13 @@ merge_decls (tree newdecl, tree olddecl,
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
+ if (TREE_SHARED (newdecl))
+ {
+ TREE_SHARED (olddecl) = 1;
+ if (TREE_CODE (newdecl) == VAR_DECL)
+ TREE_THIS_VOLATILE (newdecl) = 1;
+ }
+
/* Merge deprecatedness. */
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
@@ -2872,6 +2882,8 @@ pushdecl_top_level (tree x)
static void
implicit_decl_warning (tree id, tree olddecl)
{
+ if (upc_diagnose_deprecated_stmt (input_location, id))
+ return;
if (warn_implicit_function_declaration)
{
bool warned;
@@ -3011,6 +3023,8 @@ undeclared_variable (location_t loc, tre
}
else
{
+ if (upc_diagnose_deprecated_stmt (loc, id))
+ return;
if (!objc_diagnose_private_ivar (id))
error_at (loc, "%qE undeclared (first use in this function)", id);
if (!already)
@@ -3830,6 +3844,9 @@ quals_from_declspecs (const struct c_dec
int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
| (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ | (specs->shared_p ? TYPE_QUAL_SHARED : 0)
+ | (specs->strict_p ? TYPE_QUAL_STRICT : 0)
+ | (specs->relaxed_p ? TYPE_QUAL_RELAXED : 0)
| (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
gcc_assert (!specs->type
&& !specs->decl_attr
@@ -4359,7 +4376,23 @@ finish_decl (tree decl, location_t init_
constant_expression_warning (DECL_SIZE (decl));
else
{
- error ("storage size of %q+D isn%'t constant", decl);
+ if (upc_shared_type_p (TREE_TYPE (decl)))
+ {
+ gcc_assert (!flag_upc_threads);
+ if (TYPE_HAS_THREADS_FACTOR (TREE_TYPE (decl)))
+ error ("in the UPC dynamic translation environment, " "THREADS may not appear in declarations "
+ "of shared arrays with indefinite block size; "
+ "the storage size of %q+D cannot be calculated",
+ decl);
+ else
+ error ("in the UPC dynamic translation environment, "
+ "THREADS must appear exactly once in "
+ "declarations of shared arrays; "
+ "the storage size of %q+D cannot be calculated",
+ decl);
+ }
+ else
+ error ("storage size of %q+D isn%'t constant", decl);
TREE_TYPE (decl) = error_mark_node;
}
}
@@ -4398,6 +4431,10 @@ finish_decl (tree decl, location_t init_
if (c_dialect_objc ())
objc_check_decl (decl);
+ /* Give UPC a chance to check the declaration. */
+ if (c_dialect_upc ())
+ upc_check_decl (decl);
+
if (asmspec)
{
/* If this is not a static variable, issue a warning.
@@ -4909,6 +4946,9 @@ grokdeclarator (const struct c_declarato
int constp;
int restrictp;
int volatilep;
+ int sharedp;
+ int strictp;
+ int relaxedp;
int type_quals = TYPE_UNQUALIFIED;
tree name = NULL_TREE;
bool funcdef_flag = false;
@@ -4920,6 +4960,10 @@ grokdeclarator (const struct c_declarato
int array_parm_static = 0;
bool array_parm_vla_unspec_p = false;
tree returned_attrs = NULL_TREE;
+ int upc_threads_ref = 0; /* for static declarations of shared arrays */
+ tree upc_layout_qualifier;
+ tree upc_elem_block_factor;
+ tree upc_block_factor = NULL;
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
@@ -5019,6 +5063,8 @@ grokdeclarator (const struct c_declarato
size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
+ upc_threads_ref = TYPE_HAS_THREADS_FACTOR (type);
+
/* Diagnose defaulting to "int". */
if (declspecs->default_int_p && !in_system_header)
@@ -5063,6 +5109,11 @@ grokdeclarator (const struct c_declarato
constp = declspecs->const_p + TYPE_READONLY (element_type);
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+ sharedp = declspecs->shared_p + upc_shared_type_p (element_type);
+ strictp = declspecs->strict_p + TYPE_STRICT (element_type);
+ relaxedp = declspecs->relaxed_p + TYPE_RELAXED (element_type);
+ upc_elem_block_factor = TYPE_BLOCK_FACTOR (element_type);
+ upc_layout_qualifier = declspecs->upc_layout_qualifier;
as1 = declspecs->address_space;
as2 = TYPE_ADDR_SPACE (element_type);
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
@@ -5075,7 +5126,22 @@ grokdeclarator (const struct c_declarato
pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
if (volatilep > 1)
pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
- }
+ if (sharedp > 1)
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<shared%>");
+ if (strictp > 1)
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<strict%>");
+ if (relaxedp > 1)
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<relaxed%>");
+ }
+ if (strictp && relaxedp)
+ error_at (loc, "UPC shared variable %qE is declared "
+ "both strict and relaxed", name);
+ if (strictp && !sharedp)
+ error_at (loc, "%qE is declared with UPC strict qualifier "
+ "but not shared", name);
+ if (relaxedp && !sharedp)
+ error_at (loc, "%qE is declared with UPC relaxed qualifier "
+ "but not shared", name);
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
error_at (loc, "conflicting named address spaces (%s vs %s)",
@@ -5088,8 +5154,11 @@ grokdeclarator (const struct c_declarato
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ | (sharedp ? TYPE_QUAL_SHARED : 0)
+ | (strictp ? TYPE_QUAL_STRICT : 0)
+ | (relaxedp ? TYPE_QUAL_RELAXED : 0)
| ENCODE_QUAL_ADDR_SPACE (address_space));
-
+
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
@@ -5182,7 +5251,7 @@ grokdeclarator (const struct c_declarato
threadp = false;
}
}
-
+
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator).
@@ -5366,6 +5435,40 @@ grokdeclarator (const struct c_declarato
warn_variable_length_array (name, size);
}
}
+ else if (sharedp && count_upc_threads_refs (size))
+ {
+ /* We have a shared array with a non-constant
+ dimension. If the expression is a factor of
+ THREADS, then we'll need to set the flag
+ in the result type. Otherwise, it is an error. */
+ int n_thread_refs = count_upc_threads_refs (size);
+ if (upc_threads_ref || n_thread_refs > 1)
+ {
+ error_at (loc, "UPC shared array declaration references THREADS "
+ "more than once; the size of %qE "
+ "cannot be calculated", name);
+ size = integer_one_node;
+ }
+ else if (!is_multiple_of_upc_threads (size))
+ {
+ error_at (loc, "UPC shared array dimension is not a simple multiple "
+ "of THREADS; the size of %qE "
+ "cannot be calculated.", name);
+ size = integer_one_node;
+ }
+ else
+ {
+ upc_threads_ref = 1;
+ set_upc_threads_refs_to_one (&size);
+ size = fold (size);
+ if (TREE_CODE (size) != INTEGER_CST)
+ {
+ error_at (loc, "UPC forbids variable-size shared array %qE",
+ name);
+ size = integer_one_node;
+ }
+ }
+ }
else if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope)
{
@@ -5526,6 +5629,18 @@ grokdeclarator (const struct c_declarato
C_TYPE_VARIABLE_SIZE (type) = 1;
}
+ if (upc_threads_ref)
+ {
+ /* We need a unique type copy here for UPC shared
+ array types compiled in a dynamic threads enviroment
+ that reference THREADS as a multiplier; to avoid
+ setting the "has threads factor" bit in
+ a re-used non- UPC shared array type node. */
+ if (size && TREE_CODE (size) == INTEGER_CST)
+ type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ TYPE_HAS_THREADS_FACTOR (type) = 1;
+ }
+
/* The GCC extension for zero-length arrays differs from
ISO flexible array members in that sizeof yields
zero. */
@@ -5581,6 +5696,8 @@ grokdeclarator (const struct c_declarato
continue;
size_varies = false;
+ upc_threads_ref = 0;
+ upc_layout_qualifier = 0;
/* Warn about some types functions can't return. */
if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -5628,6 +5745,12 @@ grokdeclarator (const struct c_declarato
if (VOID_TYPE_P (type) && really_funcdef)
pedwarn (loc, 0,
"function definition has qualified void return type");
+ else if (type_quals & TYPE_QUAL_SHARED)
+ {
+ error_at (loc, "function definition has UPC shared qualified return type");
+ type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+ | TYPE_QUAL_RELAXED);
+ }
else
warning_at (loc, OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
@@ -5660,9 +5783,19 @@ grokdeclarator (const struct c_declarato
&& type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
+
+ if (upc_layout_qualifier)
+ upc_block_factor = upc_grok_layout_qualifier (
+ loc, POINTER_TYPE, type,
+ NULL_TREE, upc_layout_qualifier);
+
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type_1 (type, type_quals,
+ upc_block_factor);
+
size_varies = false;
+ upc_threads_ref = 0;
+ upc_block_factor = 0;
/* When the pointed-to type involves components of variable size,
care must be taken to ensure that the size evaluation code is
@@ -5702,7 +5835,9 @@ grokdeclarator (const struct c_declarato
/* Process type qualifiers (such as const or volatile)
that were given inside the `*'. */
- type_quals = declarator->u.pointer_quals;
+ type_quals = declarator->u.pointer.quals;
+ upc_layout_qualifier = declarator->u.pointer.upc_layout_qual;
+ sharedp = ((type_quals & TYPE_QUAL_SHARED) != 0);
declarator = declarator->declarator;
break;
@@ -5773,6 +5908,14 @@ grokdeclarator (const struct c_declarato
if (bitfield)
check_bitfield_type_and_width (&type, width, name);
+ /* Check for UPC's layout qualifier. */
+ if (upc_layout_qualifier || upc_elem_block_factor)
+ {
+ upc_block_factor = upc_grok_layout_qualifier (loc, TREE_CODE (type), type,
+ upc_elem_block_factor, upc_layout_qualifier);
+ upc_layout_qualifier = 0;
+ }
+
/* Reject invalid uses of _Alignas. */
if (declspecs->alignas_p)
{
@@ -5839,7 +5982,8 @@ grokdeclarator (const struct c_declarato
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type_1 (type, type_quals, upc_block_factor);
+
decl = build_decl (declarator->id_loc,
TYPE_DECL, declarator->u.id, type);
if (declspecs->explicit_signed_p)
@@ -5885,7 +6029,7 @@ grokdeclarator (const struct c_declarato
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids const or volatile function types");
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type_1 (type, type_quals, upc_block_factor);
return type;
}
@@ -5932,7 +6076,8 @@ grokdeclarator (const struct c_declarato
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type_1 (type, type_quals,
+ upc_block_factor);
type = c_build_pointer_type (type);
type_quals = array_ptr_quals;
if (type_quals)
@@ -5944,6 +6089,8 @@ grokdeclarator (const struct c_declarato
"attributes in parameter array declarator ignored");
size_varies = false;
+ upc_threads_ref = 0;
+ upc_block_factor = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
@@ -5955,6 +6102,12 @@ grokdeclarator (const struct c_declarato
type = c_build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
}
+ else if (type_quals & TYPE_QUAL_SHARED)
+ {
+ error ("parameter declared with UPC shared qualifier");
+ type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+ | TYPE_QUAL_RELAXED);
+ }
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
@@ -6002,6 +6155,13 @@ grokdeclarator (const struct c_declarato
error_at (loc, "unnamed field has incomplete type");
type = error_mark_node;
}
+ else if (type_quals & TYPE_QUAL_SHARED)
+ {
+ error_at (loc, "field %qE declared with UPC shared qualifier",
+ name);
+ type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+ | TYPE_QUAL_RELAXED);
+ }
type = c_build_qualified_type (type, type_quals);
decl = build_decl (declarator->id_loc,
FIELD_DECL, declarator->u.id, type);
@@ -6111,7 +6271,16 @@ grokdeclarator (const struct c_declarato
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern;
- type = c_build_qualified_type (type, type_quals);
+ if ((type_quals & TYPE_QUAL_SHARED)
+ && !extern_ref
+ && !((current_scope == file_scope)
+ || (storage_class == csc_static)))
+ {
+ error_at (loc, "UPC does not support shared auto variables");
+ type = error_mark_node;
+ }
+
+ type = c_build_qualified_type_1 (type, type_quals, upc_block_factor);
/* C99 6.2.2p7: It is invalid (compile-time undefined
behavior) to create an 'extern' declaration for a
@@ -6160,6 +6329,11 @@ grokdeclarator (const struct c_declarato
else
{
TREE_STATIC (decl) = (storage_class == csc_static);
+ /* UPC's 'shared' attribute implies that the storage
+ is 'static' to the extent it is stored in
+ memory. */
+ if (type_quals & TYPE_QUAL_SHARED)
+ TREE_STATIC (decl) = 1;
TREE_PUBLIC (decl) = extern_ref;
}
@@ -6235,6 +6409,13 @@ grokdeclarator (const struct c_declarato
"questionable in C++"),
decl);
+ /* Shared variables are given their own link section on
+ most target platforms, and if compiling in pthreads mode
+ regular local file scope variables are made thread local. */
+ if ((TREE_CODE(decl) == VAR_DECL)
+ && !threadp && (TREE_SHARED (decl) || flag_upc_pthreads))
+ upc_set_decl_section (decl);
+
return decl;
}
}
@@ -8441,7 +8622,8 @@ finish_function (void)
if (!decl_function_context (fndecl))
{
invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
- c_genericize (fndecl);
+ /* Lower to GENERIC form before finalization. */
+ lang_hooks.genericize (fndecl);
/* ??? Objc emits functions after finalizing the compilation unit.
This should be cleaned up later and this conditional removed. */
@@ -8769,18 +8951,21 @@ make_pointer_declarator (struct c_declsp
{
tree attrs;
int quals = 0;
+ tree upc_layout_qual = 0;
struct c_declarator *itarget = target;
struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
if (type_quals_attrs)
{
attrs = type_quals_attrs->attrs;
quals = quals_from_declspecs (type_quals_attrs);
+ upc_layout_qual = type_quals_attrs->upc_layout_qualifier;
if (attrs != NULL_TREE)
itarget = build_attrs_declarator (attrs, target);
}
ret->kind = cdk_pointer;
ret->declarator = itarget;
- ret->u.pointer_quals = quals;
+ ret->u.pointer.quals = quals;
+ ret->u.pointer.upc_layout_qual = upc_layout_qual;
return ret;
}
@@ -8796,6 +8981,7 @@ build_null_declspecs (void)
ret->expr = 0;
ret->decl_attr = 0;
ret->attrs = 0;
+ ret->upc_layout_qualifier = 0;
ret->align_log = -1;
ret->typespec_word = cts_none;
ret->storage_class = csc_none;
@@ -8819,6 +9005,9 @@ build_null_declspecs (void)
ret->const_p = false;
ret->volatile_p = false;
ret->restrict_p = false;
+ ret->shared_p = false;
+ ret->strict_p = false;
+ ret->relaxed_p = false;
ret->saturating_p = false;
ret->alignas_p = false;
ret->address_space = ADDR_SPACE_GENERIC;
@@ -8859,6 +9048,23 @@ declspecs_add_qual (source_location loc,
bool dupe = false;
specs->non_sc_seen_p = true;
specs->declspecs_seen_p = true;
+
+ /* A UPC layout qualifier is encoded as an ARRAY_REF,
+ further, it implies the presence of the 'shared' keyword. */
+ if (TREE_CODE (qual) == ARRAY_REF)
+ {
+ if (specs->upc_layout_qualifier)
+ {
+ error ("two or more layout qualifiers specified");
+ return specs;
+ }
+ else
+ {
+ specs->upc_layout_qualifier = qual;
+ qual = ridpointers[RID_SHARED];
+ }
+ }
+
gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
&& C_IS_RESERVED_WORD (qual));
i = C_RID_CODE (qual);
@@ -8879,6 +9085,18 @@ declspecs_add_qual (source_location loc,
specs->restrict_p = true;
specs->locations[cdw_restrict] = loc;
break;
+ case RID_SHARED:
+ dupe = specs->shared_p;
+ specs->shared_p = true;
+ break;
+ case RID_STRICT:
+ dupe = specs->strict_p;
+ specs->strict_p = true;
+ break;
+ case RID_RELAXED:
+ dupe = specs->relaxed_p;
+ specs->relaxed_p = true;
+ break;
default:
gcc_unreachable ();
}
===================================================================
@@ -96,6 +96,10 @@ along with GCC; see the file COPYING3.
#undef LANG_HOOKS_WRITE_GLOBALS
#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
+/* Hook for lowering function body to GENERIC before finalization. */
+#undef LANG_HOOKS_GENERICIZE
+#define LANG_HOOKS_GENERICIZE c_genericize
+
/* Hooks for tree gimplification. */
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr