diff mbox

[UPC,01/22] front-end changes

Message ID 20151201060230.GA31015@intrepid.com
State New
Headers show

Commit Message

Gary Funck Dec. 1, 2015, 6:02 a.m. UTC
Background
----------

An overview email, describing the UPC-related changes is here:
  https://gcc.gnu.org/ml/gcc-patches/2015-12/msg00005.html

The GUPC branch is described here:
  http://gcc.gnu.org/projects/gupc.html

The UPC-related source code differences are summarized here:
  http://gccupc.org/gupc-changes

All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
bootstrapped; no test suite regressions were introduced,
relative to the GCC trunk.

If you are on the cc-list, your name was chosen either
because you are listed as a maintainer for the area that
applies to the patches described in this email, or you
were a frequent contributor of patches made to files listed
in this email.

In the change log entries included in each patch, the directory
containing the affected files is listed, followed by the files.
When the patches are applied, the change log entries will be
distributed to the appropriate ChangeLog file.

Overview
--------

UPC introduces the following keywords:

    relaxed	shared		strict
    upc_barrier	upc_blocksizeof	upc_elemsizeof
    upc_forall	upc_localsizeof	upc_notify	upc_wait

UPC has three new type qualifiers: shared, strict, and relaxed.
In addition, UPC defines a "layout qualifier", also known as the
"blocking factor".  The "layout qualifier" is an integral constant
which defaults to the value 1.  The maximum blocking factor is
implementation defined.  A value of 0 indicates that there is no
distribution across threads; this is called the "indefinite blocking factor".

The following example illustrates the use of the UPC "shared" qualifier
combined with a layout qualifier.

    #define BLKSIZE 5
    #define N_PER_THREAD (4 * BLKSIZE)
    shared [BLKSIZE] double A[N_PER_THREAD*THREADS];

Above the "[BLKSIZE]" construct is the UPC layout factor; this
specifies that the shared array, A, distributes its elements across
each thread in blocks of 5 elements.  If the program is run with two
threads, then A is distributed as shown below:

    Thread 0	Thread 1
    --------	---------
    A[ 0.. 4]	A[ 5.. 9]
    A[10..14]	A[15..19]
    A[20..24]	A[25..29]
    A[30..34]	A[35..39]

The elements shown for thread 0 are defined as having "affinity"
to thread 0.  Similarly, those elements shown for thread 1 have
affinity to thread 1.  In UPC, a pointer to a shared object can be
cast to a thread local pointer (a "C" pointer), when the designated
shared object has affinity to the referencing thread.

A UPC "pointer-to-shared" (PTS) is a pointer that references a UPC
shared object.  A UPC pointer-to-shared is a "fat" pointer with the
following logical fields:
   (virt_addr, thread, phase)

The virtual address (virt_addr) field is combined with the thread
number (thread) to derive the location of the referenced object
within the UPC shared address space.  The phase field is used
keep track of the current block offset for PTS's that have
a blocking factor that is greater than one.

GUPC implements pointer-to-shared objects using a "struct" internal
representation.  Until recently, GUPC also supported a "packed"
representation, which is more space efficient, but limits the range of
various fields in the UPC pointer-to-shared representation.  We have
decided to support only the "struct" representation so that the
compiler uses a single ABI that supports the full range of addresses,
threads, and blocking factors.

GCC's internal tree representation is extended to record the UPC
"shared", "strict", "relaxed" qualifiers, and the layout qualifier.

UPC introduces several additional new statements:
  - upc_barrier, upc_notify, and upc_wait are synchronization statements.
  - upc_forall is an iterating statement which extends the for statement
    by adding an additional "affinity" clause.  Only iterations where
    the affinity clause is true will be executed on a given thread.

UPC introduces the following unary operators which have a similar
form to C's "sizeof" operator:

  - upc_blocksizeof returns the blocking factor of a UPC shared type
  or expression.
  - upc_elemsizeof returns the element size of a UPC shared type
  or expression.
  - upc_localsizeof returns the maximum size allocated to a thread of
  a UPC shared type or expression.

UPC introduces two reserved identifiers:

  - THREADS gives the number of UPC threads allocated to a UPC program.
  The value may be specified at compile-time via the -fupc-threads=N switch
  (a static thread count), or at run time (a dynamic thread count).
  It is common practice to include THREADS as a multiplier in an array
  index declaration.  If the THREADS multiplier is given at runtime
  (dynamic), the array dimension is said to be "THREADS scaled".
  - MYTHREAD returns the thread number of the current executing thread.
  It is in the range 0..(THREADS-1).

To compile a UPC program, the -fupc compiler switch must be supplied.
The driver program, gupc (aka upc), will implicitly add the -fupc switch
and invoke GCC.  Within GCC, the flag_upc variable is set if -fupc
is supplied; this variable is tested to determine if UPC constructs
should be accepted.

In general, parsing and processing of regular "C" code is ensured
by either protecting the UPC logic with a test for flag_upc, or
by testing the TREE_SHARED() or TYPE_SHARED() flags.  Since
the "shared" flag can only be set when compiling UPC code, it
is safe to test for the shared flag without the need to first
check that flag_upc has been asserted.

To accommodate UPC's "layout qualifier", c_build_qualified_type()
was renamed to c_build_qualified_type_1() and an additional
"layout_qualifier" argument was added.  To limit the impact of this
change on both the C and C++ front-ends, c_build_qualified_type()
is re-defined as a macro which passes a NULL value for the layout_qualifier.

When the -fupc-pthreads-model-tls compilation switch is asserted
UPC threads are implemented as POSIX threads (pthreads).  (Normally,
a UPC thread is mapped to an OS process.)  In this compilation mode,
all file scope "C" variables are "localized" by internally designating
them as TLS (thread-local storage) variables.  This is necessary to
preserve the view that UPC threads have separate per-thread file scope
variables.  The logic in c-family/c-lex.c that tracks the depth of C
system headers is generalized so that it is no longer contingent upon
NO_IMPLICIT_EXTERN_C being asserted.  If c_header_level is greater
than 0, then a variable declaration is assumed to be declared in a
system header, and is not subject to localization.

UPC defines two new kinds of pragmas:

  - #pragma [ upc strict | relaxed | upc_code | c_code ]
  The 'strict' and 'relaxed' clauses can be introduced only
  immediately following an opening brace ({) symbol.  They introduce
  a default UPC consistency mode (relaxed or strict) within the
  bracketed scope.  The 'upc_code' clause specifies that following
  text is to be compiled as UPC code, and the 'c_code' clause specifies
  that the following text is regular C code (and UPC keywords are disabled).
  - #pragma pupc [ on | off ]
  The 'pupc' pragma is defined by the UPC performance monitoring standard.

When UPC shared variable declarations are parsed, they will be assigned
to a "upc_shared" linker section.  This is done in grokdeclarator()
where it calls upc_set_decl_section().  This linker section is ideally
not loadable and is used only to coalesce UPC shared variables and to
assign offsets of those variables within the UPC global shared region.

The UPC lowering pass, upc_genericize(), is called just prior
to c_genericize() in finish_function().  upc_genericize() will
lower all UPC constructs into GENERIC.

In c/c-tree.h, the 'pointer_quals' field is re-implemented as a struct
to support the addition of the UPC "layout qualifier".

	 /* For pointers, the qualifiers on the pointer type.  */
    -    int pointer_quals;
    +    struct {
    +      int quals;
    +      tree upc_layout_qual;
    +    } pointer;

2015-11-30  Gary Funck  <gary@intrepid.com>

	gcc/c-family/
	* c-common.c (flag_upc_threads, flag_upc_pthreads,
	upc_pthreads_model): New.  Declare UPC-related flag variables.
	(c_common_r): Define UPC keywords.
	(c_fully_fold_internal): Avoid attempts to fold references
	to UPC shared components.
	(pointer_int_sum): Drop the shared qualifier on the result type.
	(c_apply_type_quals_to_decl): Apply UPC qualifiers.
	(c_common_get_alias_set): Make UPC pointers-to-shared conflict
	with everything else.
	(upc_num_threads): New.
	(c_sizeof_or_alignof_type): Issue error for mis-use of
	UPC "shared void *" type.
	(c_sizeof_or_alignof_type): Handle sizeof applied to
	UPC shared arrays with index scaled by THREADS.
	(complete_array_type): For incomplete array types,
	force an indefinite layout qualifier.
	(c_common_init_ts): call MARK_TS_COMMON for
	UPC_FORALL_STMT and UPC_SYNC_STMT.
	* c-common.def (UPC_FORALL_STMT, UPC_SYNC_STMT):
	New.  Define UPC-specific statement tree nodes.
	* c-common.h (rid): Add UPC keywords.
	(UPC_IS_KEYWORD): New macro.
	(D_UPC): New macro.
	(flag_upc_threads): New variable extern.
	(flag_upc_pthreads): New variable extern.
	(upc_pthreads_model_kind): New enum.
	(upc_pthreads_model): New variable extern.
	(c_build_qualified_type_1): New prototype, renames
	c_build_qualified_type and adds a UPC layout qualifier argument.
	(c_build_qualified_type): New macro.  Pass NULL for UPC layout
	qualifier to c_build_qualified_type_1().
	(upc_num_threads): New prototype.
	(UPC_SYNC_OP): New macro.  Access the operation field of a
	UPC synchronization statement.
	(UPC_SYNC_ID): New macro.  Access the barrier identifier field of a
	UPC synchronization statement.
	(UPC_SYNC_NOTIFY_OP): New macro.
	(UPC_SYNC_WAIT_OP): New macro.
	(UPC_SYNC_BARRIER_OP): New macro.
	* c-cppbuiltin.c: #include "c-upc-pts.h".
	(strip_section_prefix): New. Remove section name prefixes
	used for Darwin.
	(upc_cpp_builtins): New. Generate UPC specific pre-defined macros.
	(c_cpp_builtins): Call upc_cpp_builtins(), if -fupc is asserted.
	* c-lex.c (fe_file_change): Track C header level for regular "C"
	in addition to C++.  Used by UPC when UPC threads are mapped
	to pthreads; in this case, file scope variables (that are not
	declared in a system header) are converted to TLS variables.
	* c-pragma.c: #include "langhooks.h".
	(UPC_CMODE_STACK_INCREMENT): New macro.
	(pragma_upc_permitted): New variable.
	(upc_cmode): New variable.
	(upc_cmode_stack): New variable.
	(upc_cmode_stack_in_use): New variable.
	(upc_cmode_stack_allocated): New variable.
	(init_pragma_upc): New.  Initialize the variables used to manage
	the current UPC consistency mode (strict/relaxed).
	(handle_pragma_upc): New.  Handle #pragma upc.
	(set_upc_consistency_mode): New.
	(get_upc_consistency_mode): New.
	(permit_pragma_upc): New.
	(deny_pragma_upc): New.
	(pragma_upc_permitted_p): New.
	(push_upc_consistency_mode): New.
	(pop_upc_consistency_mode): New.
	(pragma_pupc_on): New variable.
	(init_pragma_pupc): New.
	(handle_pragma_pupc): New.
	(get_upc_pupc_mode): New.
	(disable_pupc_mode): New.
	(set_pupc_mode): New.
	(handle_pragma_pupc): New.
	(init_pragma): Register the "upc" and "pupc" pragmas,
	if -fupc is asserted.
	* c-pragma.h (deny_pragma_upc): New prototype.
	(get_upc_consistency_mode): New prototype.
	(permit_pragma_upc): New prototype.
	(pop_upc_consistency_mode): New prototype.
	(pragma_upc_permitted_p): New prototype.
	(push_upc_consistency_mode): New prototype.
	(set_upc_consistency_mode): New prototype.
	* c-pretty-print.c (pp_c_cv_qualifiers): Print UPC qualifiers:
	shared, strict, and relaxed.
	gcc/c/
	* c-convert.c: #include "c-upc.h".
	(convert): Drop the 'shared' qualifier when considering conversions
	of expression values.
	* c-decl.c: Add #include "c-upc.h".
	Add #include "c-upc-low.h".
	(c_build_pointer_type): Call build_pointer_type() directly for
	UPC pointers-to-shared.
	(merge_decls): Merge UPC shared flag and layout qualifier
	for variable declarations, set it as volatile.
	(implicit_decl_warning): Add logic to diagnose use of
	deprecated UPC statements ("barrier" instead of "upc_barrier", etc.).
	(undeclared_variable): Likewise.
	(quals_from_declspecs): Extract UPC qualifiers from declspec.
	(finish_decl): Add UPC-specific error diagnostics.
	(finish_decl): Call upc_check_decl(), if -fupc is asserted.
	(grokdeclarator): sharedp, strictp, relaxedp: New variables.
	(grokdeclarator): upc_threads_ref, upc_layout_qualifier,
	upc_elem_block_factor, upc_block_factor: New variables.
	(grokdeclarator): Handle UPC qualifiers (shared, strict, relaxed)
	and UPC layout qualifiers (blocking factor).
	(grokdeclarator): Change calls to c_build_qualified_type() into calls
	to c_build_qualified_type_1(), passing the UPC layout qualifier.
	(grokdeclarator): Call upc_set_decl_section() for UPC shared
	variables, or file scope variables if -fupc-pthreads-model-tls
	is asserted.
	(finish_function): Call upc_genericize(), if -fupc is asserted.
	(make_pointer_declarator): upc_layout_qual: New variable.
	(make_pointer_declarator): Augment pointer qualifiers
	with UPC layout qualifier (blocking factor).
	(build_null_declspecs): Initialize 'upc_layout_qualifier' field.
	Initialize shared_p, strict_p, and relaxed_p fields.
	(declspecs_add_qual): Process UPC shared, strict, relaxed,
	and layout qualifiers.
	* c-objc-common.c: Add #include "options.h"
	Add #include "c-upc-lang.h".  Add #include "c-upc.h".
	(c_objc_common_init): Call upc_lang_init() if -fupc asserted
	and c_common_init() succeeded.
	(upc_types_compatible_p): New. Check for the possible need
	to convert UPC-specific types.
	(c_types_compatible_p): Call upc_types_compatible_p() if comptypes()
	failed and -fupc is asserted.
	* c-parser.c: Add #include "c-upc.h".
	Add #include "c-upc-gasp.h". Add #include "c-upc-pts-ops.h".
	(c_parse_init): Disable UPC keywords, unless -fupc is asserted.
	(c_token_starts_typename): Add UPC qualifiers: shared, strict,
	and relaxed as tokens that can start a typename.
	(c_token_is_qualifier): Add UPC qualifiers: shared, strict,
	and relaxed as qualifier tokens.
	(c_token_starts_declspecs): Add UPC qualifiers: shared, strict,
	and relaxed as tokens that can start a declspec.
	(c_parser_declspecs): Parse UPC qualifiers: shared, strict,
	and relaxed.
	(c_parser_compound_statement_nostart): Process (and allow)
	all #pragma upc statements that occur just after an
	opening brace.  This the only place they're allowed.
	Call push_upc_consistency_mode() and pop_upc_consistency_mode()
	for opening and closing brackets, respectively.
	(c_parser_statement_after_labels): Call c_parser_upc_sync_statement()
	to parse upc_barrier, upc_notify, and upc_wait statements.
	Call c_parser_upc_forall_statement() to parse a upc_forall statement.
	(c_parser_unary_expression): Parse upc_blocksizeof,
	upc_elemsizeof, upc_localsizeof operators.
	(upc_blocksizeof_expr): New. Return the result of upc_blocksizeof
	applied to EXPR.
	(upc_blocksizeof_type): New. Return the result of upc_blocksizeof
	applied to T.
	(upc_elemsizeof_expr): New. Return the result of upc_elemsizeof
	applied to EXPR.
	(upc_elemsizeof_type): New. Return the result of upc_elemsizeof
	applied to T.
	(upc_localsizeof_expr): New. Return the result of upc_localsizeof
	applied to EXPR.
	(upc_localsizeof_type): New. Return the result of upc_localsizeof
	applied to T.
	(c_parser_sizeof_expression): keyword: New variable.
	Handle upc_*_sizeof (type) operations, based on the value of keyword.
	Handle upc_*_sizeof (expr) operations, based on the value of keyword.
	(c_parser_upc_shared_qual): New. Parse UPC shared qualifier,
	inclusive of the layout qualifier (blocking factor).
	(upc_affinity_test): New.  Implement UPC's upc_forall 'affinity' test.
	(c_parser_upc_forall_statement): New. Parse a UPC upc_forall statement.
	(upc_build_sync_stmt): New. For the given kind of UPC synchronization
	statement build a UPC_SYNC_STMT tree node; add it to
	the current statement list.
	(c_parser_upc_sync_statement): New. Parse a UPC synchronization
	statement (upc_barrier, upc_notify, and upc_wait).
	* c-tree.h (struct c_declspecs): upc_layout_qualifier: New field.
	For UPC, this is the blocking factor (layout qualifier).
	shared_p: New field.  Indicates that "shared" was specified.
	strict_p: New field.  Indicates that "strict" was specified.
	relaxed_p: New field.  Indicates that "relaxed" was specified.
	struct pointer: New struct field.  Replaces 'pointer_quals'
	by including 'quals' as a field and introduces a 'upc_layout_qual'
	field to hold the UPC layout qualifier, if present.
	(c_cvt_expr_for_assign): New prototype.
	* c-typeck.c: Add #include "c-upc.h".
	Add #include "c-upc-low.h".
	(qualify_type): result_type: New variable.
	result_quals: New variable.
	result_block_factor: New variable.
	Add logic to merge in a new UPC blocking factor only
	if one/other is NULL. Otherwise, they must match.
	Call c_build_qualified_type_1 with UPC layout qualifier
	(if present) instead of build_qualified_type().
	(common_pointer_type): target_block_factor: New variable.
	If 'target_quals' include "shared", then set 'target_block_factor'
	to the value present in the pointed-to type.
	Call c_build_qualified_type_1() with 'target_block_factor'
	instead of calling build_pointer_type().
	(comptypes_internal): If the type is UPC shared qualified,
	the block sizes have to be equal.
	(default_conversion): Call array_to_pointer_conversion()
	for conversions involving UPC shared array types.
	This helps the UPC lowering pass and bypasses code that
	attempts to optimize regular array references.
	(build_component_ref): Add a gcc_assert() to insure
	that the field tree node does not assert TREE_SHARED().
	sub_elem_type: New variable.
	upc_block_factor: New variable.
	For all references to UPC shared struct components,
	set the UPC blocking factor to 0, as required by the language spec.
	If 'datum' asserts TREE_SHARED(), then set it in 'ref'.
	(build_indirect_ref): If 't' asserts TREE_SHARED(), then
	set it in 'ref'.
	(build_array_ref): For UPC shared array types, avoid checking
	for register arrays.
	(c_pointer_int_sum): New. Return a tree for the sum or difference
	of pointer PTROP and integer INTOP.  Call upc_pts_int_sum()
	for expressions involving UPC pointer-to-shared types.
	(pointer_diff): subtrahend_type: New variable.
	Call upc_pts_diff() if either the target type or
	the subtrahend type is a UPC shared type.
	(build_unary_op): Call upc_pts_increment() for increment/decrement
	operations for UPC shared type values.
	Ensure that the result of an operation on objects that
	are UPC shared qualified, must not be shared qualified.
	(build_conditional_expr): For operations involving UPC shared types,
	return 'upc_null_pts_node' instead of 'null_pointer_node'.
	(build_c_cast): Issue error on attempt to cast to a UPC shared type;
	casts to pointers-to-shared are allowed.
	If a regular "C" null pointer is being cast to UPC pointer-to-shared,
	then set the value to 'upc_null_pts_node'.
	If casting a value that is not UPC shared into a shared type,
	then wrap the value in a non-lvalue expression.
	t_shared: New variable.
	o_shared: New variable.
	For conversions from a pointer-to-shared to a regular "C" pointer,
	or between two pointers-to-shared that are incompatible,
	(as determined the UPC language definition),
	return an explicit COVERT operation.
	Diagnose an attempt to cast a local pointer or an integer to a
	UPC pointer-to-shared as an error.
	For conversions from a UPC pointer-to-shared into an integer,
	return an explicit CONVERT operation.  The UPC lowering pass
	will handle this conversion.
	(build_modify_expr): Drop the shared qualifier, if the lhs is
	UPC shared qualified.  This will prevent the inadvertent creation
	of temporaries with "shared" asserted.
	(ERROR_FOR_ASSIGNMENT): New macro.
	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.
	(convert_for_assignment): For null pointer constants where the
	value's type is a UPC shared type, return upc_null_pts_node.
	Diagnose attempts to assign a regular "C" pointer into
	a UPC pointer-to-shared as an error.
	For conversions from a UPC null pointer-to-shared into a
	regular "C" pointer, return null_pointer_node.
	Diagnose attempts to assign a UPC pointer-to-shared into
	a regular "C" pointer as an error.
	Diagnose assignments between UPC pointers-to-shared
	with differing block sizes without a cast, as an error.
	Diagnose various cases where an attempt to make UPC pointer-to-shared
	value from an integer, as an error.
	(store_init_value): is_upc_decl_init: New variable.
	Stores the result of calling upc_check_decl_init().
	require_constant: New variable. Will be true if the
	declaration is static does not require UPC-related
	initialization code.
	Call upc_decl_init() if the initialization involves UPC
	constructs that require active initialization when the
	program executes.
	(really_start_incremental_init): Ensure that the result type
	for a construct is not UPC shared qualified.
	(c_cvt_expr_for_assign): New.  Convert EXPR to TYPE if the type of EXPR
	is assignment compatible with TYPE.
	(build_binary_op): Call c_pointer_int_sum() instead of
	pointer_int_sum().
	Diagnose an attempt to compare a UPC pointer-to-shared into
	a regular "C" pointer, as an error.
	Diagnose an attempt to compare UPC pointers-to-shared with
	differing block sizes, as an error.
	For operations that return a UPC "shared void *" result,
	return upc_pts_type_node instead of calling build_pointer_type().
	(c_build_qualified_type_1): Rename from c_build_qualified_type()
	and add a 'layout_qualifier' argument.
	When creating a new qualified type, also consider
	the UPC layout qualifier (blocking factor) when checking
	type equivalence.
	Adjust recursive call to c_build_qualified_type_1().
	* c-upc-gasp.h: New.
	* c-upc.c: New.
	* c-upc.h: New.

Comments

Eric Botcazou Dec. 1, 2015, 8:12 a.m. UTC | #1
> All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
> bootstrapped; no test suite regressions were introduced,
> relative to the GCC trunk.

That's not all languages though, Ada and Java are missing.
Gary Funck Dec. 1, 2015, 8:19 a.m. UTC | #2
On 12/01/15 09:12:44, Eric Botcazou wrote:
> > All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
> > bootstrapped; no test suite regressions were introduced,
> > relative to the GCC trunk.
> 
> That's not all languages though, Ada and Java are missing.

OK. I'll bootstrap and run tests on those as well, and
report back in a day/two.

thanks,
- Gary
David Malcolm Dec. 1, 2015, 5:10 p.m. UTC | #3
On Tue, 2015-12-01 at 00:19 -0800, Gary Funck wrote:
> On 12/01/15 09:12:44, Eric Botcazou wrote:
> > > All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
> > > bootstrapped; no test suite regressions were introduced,
> > > relative to the GCC trunk.
> > 
> > That's not all languages though, Ada and Java are missing.
> 
> OK. I'll bootstrap and run tests on those as well, and
> report back in a day/two.

There's also the jit, which looks like a language to the rest of gcc.
Gary Funck Dec. 2, 2015, 4:51 p.m. UTC | #4
On 12/01/15 09:12:44, Eric Botcazou wrote:
> > All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
> > bootstrapped; no test suite regressions were introduced,
> > relative to the GCC trunk.
> 
> That's not all languages though, Ada and Java are missing.

Full bootstrap, no regressions relative to trunk for:
  ada,c,c++,fortran,go,java,lto,objc,obj-c++

Didn't do jit in this build, will add it in.
diff mbox

Patch

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-common.c	(.../branches/gupc)	(revision 231080)
@@ -228,6 +228,20 @@  int print_struct_values;
 
 const char *constant_string_class_name;
 
+/* UPC language option variables.  */
+
+/* Nonzero whenever UPC -fupc-threads=N is asserted.
+   The value N gives the number of UPC threads to be
+   defined at compile-time.  */
+int flag_upc_threads;
+
+/* Nonzero whenever UPC -fupc-pthreads-model-* is asserted.  */
+int flag_upc_pthreads;
+
+/* The implementation model for UPC threads that
+   are mapped to POSIX threads, specified at compilation
+   time by the -fupc-pthreads-model-* switch.  */
+upc_pthreads_model_kind upc_pthreads_model;
 
 /* C++ language option variables.  */
 
@@ -408,8 +422,9 @@  static int resort_field_decl_cmp (const
    C --std=c89: D_C99 | D_CXXONLY | D_OBJC | D_CXX_OBJC
    C --std=c99: D_CXXONLY | D_OBJC
    ObjC is like C except that D_OBJC and D_CXX_OBJC are not set
-   C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC
-   C++ --std=c0x: D_CONLY | D_OBJC
+   UPC is like C except that D_UPC is not set
+   C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC | D_UPC
+   C++ --std=c0x: D_CONLY | D_OBJC | D_UPC
    ObjC++ is like C++ except that D_OBJC is not set
 
    If -fno-asm is used, D_ASM is added to the mask.  If
@@ -625,6 +640,19 @@  const struct c_common_resword c_common_r
   { "inout",		RID_INOUT,		D_OBJC },
   { "oneway",		RID_ONEWAY,		D_OBJC },
   { "out",		RID_OUT,		D_OBJC },
+
+  /* UPC keywords */
+  { "shared",		RID_SHARED,		D_UPC },
+  { "relaxed",		RID_RELAXED,		D_UPC },
+  { "strict",		RID_STRICT,		D_UPC },
+  { "upc_barrier",	RID_UPC_BARRIER,	D_UPC },
+  { "upc_blocksizeof",	RID_UPC_BLOCKSIZEOF,	D_UPC },
+  { "upc_elemsizeof",	RID_UPC_ELEMSIZEOF,	D_UPC },
+  { "upc_forall",	RID_UPC_FORALL,		D_UPC },
+  { "upc_localsizeof",	RID_UPC_LOCALSIZEOF,	D_UPC },
+  { "upc_notify",	RID_UPC_NOTIFY,		D_UPC },
+  { "upc_wait",		RID_UPC_WAIT,		D_UPC },
+
   /* These are recognized inside a property attribute list */
   { "assign",	        RID_ASSIGN,		D_OBJC }, 
   { "copy",	        RID_COPY,		D_OBJC }, 
@@ -1467,11 +1495,14 @@  c_fully_fold_internal (tree expr, bool i
 	goto out;
 
       /* ??? Cope with user tricks that amount to offsetof.  The middle-end is
-	 not prepared to deal with them if they occur in initializers.  */
+	 not prepared to deal with them if they occur in initializers.
+	 Avoid attempts to fold references to UPC shared components
+	 due to the complexities of UPC pointer-to-shared arithmetic.  */
       if (op0 != orig_op0
 	  && code == ADDR_EXPR
 	  && (op1 = get_base_address (op0)) != NULL_TREE
 	  && INDIRECT_REF_P (op1)
+	  && !SHARED_TYPE_P (TREE_TYPE (op1))
 	  && TREE_CONSTANT (TREE_OPERAND (op1, 0)))
 	ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0));
       else if (op0 != orig_op0 || in_init)
@@ -4797,6 +4828,11 @@  pointer_int_sum (location_t loc, enum tr
   /* The result is a pointer of the same type that is being added.  */
   tree result_type = TREE_TYPE (ptrop);
 
+  /* If the pointer lives in UPC shared memory, then
+     drop the 'shared' qualifier.  */
+  if (TREE_SHARED (ptrop) || SHARED_TYPE_P (result_type))
+    result_type = build_unshared_type (result_type);
+
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
       if (complain && warn_pointer_arith)
@@ -5212,6 +5248,17 @@  c_apply_type_quals_to_decl (int type_qua
 	  || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
 	error ("invalid use of %<restrict%>");
     }
+  if (type_quals & TYPE_QUAL_SHARED)
+    {
+      TREE_SHARED (decl) = 1;
+      if (type_quals & TYPE_QUAL_STRICT)
+	TREE_STRICT(decl) = 1;
+      else if (type_quals & TYPE_QUAL_RELAXED)
+	TREE_RELAXED(decl) = 1;
+      /* The declaration's type should have been previously defined
+	 as a UPC shared type.  */
+      gcc_assert (SHARED_TYPE_P (type));
+    }
 }
 
 struct c_type_hasher : ggc_ptr_hash<tree_node>
@@ -5328,6 +5375,18 @@  c_common_get_alias_set (tree t)
 	return get_alias_set (t1);
     }
 
+  /* For the time being, make UPC pointers-to-shared conflict
+     with everything else.  Ideally, UPC pointers-to-shared should
+     only conflict with the internal type used to represent
+     the UPC pointer-to-shared (i.e., upc_pts_rep_type_node).  */
+
+  if (TYPE_P (t) ? (TREE_CODE (t) == POINTER_TYPE
+		    && SHARED_TYPE_P (TREE_TYPE (t)))
+                 : (TREE_TYPE(t)
+		    && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
+		    && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (t)))))
+    return 0;
+
   /* Handle the case of multiple type nodes referring to "the same" type,
      which occurs with IMA.  These share an alias set.  FIXME:  Currently only
      C90 is handled.  (In C99 type compatibility is not transitive, which
@@ -5385,6 +5444,44 @@  c_common_get_alias_set (tree t)
   return -1;
 }
 
+/* Return the value of THREADS.
+
+   UPC defines a reserved variable, THREADS, which returns the
+   number of threads that will be created when the UPC program
+   executes.  The value of threads can be specified at runtime via
+   the -fupc-threads=N switch, where N is an integer specifying
+   the number of threads.  When the value of THREADS is specified
+   at compile-time, this is called the "static threads compilation
+   environment".
+
+   In the static threads compilation environment, THREADS is a
+   pre-defined preprocessor macro with the value, N.
+
+   If no value for threads is given at compile-time, then the value
+   must be specified when the application program is executed.
+   This method of establishing the value of THREADS is called
+   the "dynamic threads compilation environment".  */
+
+tree
+upc_num_threads (void)
+{
+  tree n;
+  gcc_assert (flag_upc);
+  n = flag_upc_threads ? ssize_int (flag_upc_threads)
+    : lookup_name (get_identifier ("THREADS"));
+  if (!n)
+    {
+      error ("the UPC-required THREADS variable is undefined; "
+	     "when compiling pre-processed source, "
+	     "all -fupc-* switches must be passed on the command line, "
+	     "asserting the same values as supplied when the "
+	     "original source file was preprocessed");
+      abort ();
+    }
+
+  return n;
+}
+
 /* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where
    the IS_SIZEOF parameter indicates which operator is being applied.
    The COMPLAIN flag controls whether we should diagnose possibly
@@ -5431,11 +5528,16 @@  c_sizeof_or_alignof_type (location_t loc
     }
   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
     {
-      if (type_code == VOID_TYPE
-	  && complain && warn_pointer_arith)
-	pedwarn (loc, OPT_Wpointer_arith,
-		 "invalid application of %qs to a void type", op_name);
-      else if (!complain)
+      if (complain)
+        {
+	  if (type_code == VOID_TYPE && SHARED_TYPE_P (type))
+	    error_at (loc, "invalid application of %qs"
+	                   " to %<shared void%> type", op_name);
+          else if (type_code == VOID_TYPE && warn_pointer_arith)
+	    pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+		     "invalid application of %qs to a void type", op_name);
+        }
+      else
         return error_mark_node;
       value = size_one_node;
     }
@@ -5468,6 +5570,14 @@  c_sizeof_or_alignof_type (location_t loc
 	value = size_int (TYPE_ALIGN_UNIT (type));
     }
 
+  if (is_sizeof && (TREE_CODE (type) == ARRAY_TYPE)
+      && SHARED_TYPE_P (type)
+      && TYPE_HAS_THREADS_FACTOR (type))
+    {
+      const tree n_threads = convert (sizetype, upc_num_threads ());
+      value = size_binop (MULT_EXPR, value, n_threads);
+    }
+
   /* VALUE will have the middle-end integer type sizetype.
      However, we should really return a value of type `size_t',
      which is just a typedef for an ordinary integer type.  */
@@ -11093,6 +11203,10 @@  complete_array_type (tree *ptype, tree i
     }
 
   type = *ptype;
+  /* Force an indefinite layout factor.  */ 
+  if (SHARED_TYPE_P (type))
+    type = c_build_qualified_type_1 (type, TYPE_QUAL_SHARED,
+                                     size_zero_node);
   elt = TREE_TYPE (type);
   quals = TYPE_QUALS (strip_array_types (elt));
   if (quals == 0)
@@ -12862,6 +12976,8 @@  c_common_init_ts (void)
   MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
   MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
   MARK_TS_TYPED (ARRAY_NOTATION_REF);
+  MARK_TS_COMMON (UPC_FORALL_STMT);
+  MARK_TS_COMMON (UPC_SYNC_STMT);
 }
 
 /* Build a user-defined numeric literal out of an integer constant type VALUE
Index: gcc/c-family/c-common.def
===================================================================
--- gcc/c-family/c-common.def	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-common.def	(.../branches/gupc)	(revision 231080)
@@ -62,6 +62,24 @@  DEFTREECODE (SIZEOF_EXPR, "sizeof_expr",
    Operand 3 is the stride.  */
 DEFTREECODE (ARRAY_NOTATION_REF, "array_notation_ref", tcc_reference, 4) 
 
+/* Used to represent a `upc_forall' statement.  The operands are
+   UPC_FORALL_INIT_STMT, UPC_FORALL_COND, UPC_FORALL_EXPR,
+   UPC_FORALL_BODY, and UPC_FORALL_AFFINITY respectively.  */
+
+DEFTREECODE (UPC_FORALL_STMT, "upc_forall_stmt", tcc_statement, 5)
+
+/* Used to represent a UPC synchronization statement.  The first
+   operand is the synchronization operation, UPC_SYNC_OP:
+   UPC_SYNC_NOTIFY_OP	1	Notify operation
+   UPC_SYNC_WAIT_OP	2	Wait operation
+   UPC_SYNC_BARRIER_OP	3	Barrier operation
+
+   The second operand, UPC_SYNC_ID is the (optional) expression
+   whose value specifies the barrier identifier which is checked
+   by the various synchronization operations.  */
+
+DEFTREECODE (UPC_SYNC_STMT, "upc_sync_stmt", tcc_statement, 2)
+
 /*
 Local variables:
 mode:c
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-common.h	(.../branches/gupc)	(revision 231080)
@@ -54,9 +54,9 @@  never after.
 */
 
 /* Reserved identifiers.  This is the union of all the keywords for C,
-   C++, and Objective-C.  All the type modifiers have to be in one
+   C++, Objective-C, and UPC.  All the type modifiers have to be in one
    block at the beginning, because they are used as mask bits.  There
-   are 28 type modifiers; if we add many more we will have to redesign
+   are 31 type modifiers; if we add many more we will have to redesign
    the mask mechanism.  */
 
 enum rid
@@ -69,6 +69,9 @@  enum rid
   RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
   RID_NORETURN, RID_ATOMIC,
 
+  /* UPC type qualifiers */
+  RID_SHARED, RID_RELAXED, RID_STRICT,
+
   /* C extensions */
   RID_COMPLEX, RID_THREAD, RID_SAT,
 
@@ -173,6 +176,11 @@  enum rid
   RID_AT_INTERFACE,
   RID_AT_IMPLEMENTATION,
 
+  /* UPC */
+  RID_UPC_BARRIER, RID_UPC_BLOCKSIZEOF, RID_UPC_ELEMSIZEOF,
+  RID_UPC_FORALL, RID_UPC_LOCALSIZEOF,
+  RID_UPC_NOTIFY, RID_UPC_WAIT,
+
   /* 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
@@ -221,6 +229,10 @@  enum rid
 
   RID_FIRST_CXX11 = RID_CONSTEXPR,
   RID_LAST_CXX11 = RID_STATIC_ASSERT,
+  RID_FIRST_UPC_QUAL = RID_SHARED,
+  RID_LAST_UPC_QUAL = RID_STRICT,
+  RID_FIRST_UPC_KW = RID_UPC_BARRIER,
+  RID_LAST_UPC_KW = RID_UPC_WAIT,
   RID_FIRST_AT = RID_AT_ENCODE,
   RID_LAST_AT = RID_AT_IMPLEMENTATION,
   RID_FIRST_PQ = RID_IN,
@@ -253,6 +265,13 @@  enum rid
    || rid == RID_PUBLIC || rid == RID_PROTECTED || rid == RID_PRIVATE	\
    || rid == RID_TRY || rid == RID_THROW || rid == RID_CATCH)
 
+/* Test whether a reserved ID designates a UPC keyword.  */
+#define UPC_IS_KEYWORD(rid) \
+  (((unsigned int) (rid) >= (unsigned int) RID_FIRST_UPC_QUAL && \
+    (unsigned int) (rid) <= (unsigned int) RID_LAST_UPC_QUAL) || \
+   ((unsigned int) (rid) >= (unsigned int) RID_FIRST_UPC_KW && \
+    (unsigned int) (rid) <= (unsigned int) RID_LAST_UPC_KW))
+
 /* The elements of `ridpointers' are identifier nodes for the reserved
    type names and storage classes.  It is indexed by a RID_... value.  */
 extern GTY ((length ("(int) RID_MAX"))) tree *ridpointers;
@@ -395,6 +414,7 @@  extern machine_mode c_default_pointer_mo
 #define D_CXXWARN	0x200	/* In C warn with -Wcxx-compat.  */
 #define D_CXX_CONCEPTS  0x400   /* In C++, only with concepts. */
 #define D_TRANSMEM	0X800   /* C++ transactional memory TS.  */
+#define D_UPC		0x1000	/* In UPC, and neither C nor C++.  */
 
 #define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS
 
@@ -612,6 +632,25 @@  extern const char *pch_file;
 
 extern int flag_iso;
 
+/* Nonzero whenever UPC -fupc-threads=N is asserted.
+   The value N gives the number of UPC threads to be
+   defined at compile-time.  */
+extern int flag_upc_threads;
+
+/* Nonzero whenever UPC -fupc-pthreads-model-* is asserted.  */
+extern int flag_upc_pthreads;
+
+typedef enum
+  {
+    upc_pthreads_no_model = 0,
+    upc_pthreads_tls_model = 1
+  } upc_pthreads_model_kind;
+
+/* The implementation model for UPC threads that
+   are mapped to POSIX threads, specified at compilation
+   time by the -fupc-pthreads-model-* switch.  */
+extern upc_pthreads_model_kind upc_pthreads_model;
+
 /* C/ObjC language option variables.  */
 
 
@@ -866,7 +905,8 @@  extern tree pointer_int_sum (location_t,
 			     bool = true);
 
 /* Add qualifiers to a type, in the fashion for C.  */
-extern tree c_build_qualified_type (tree, int);
+extern tree c_build_qualified_type_1 (tree, int, tree);
+#define c_build_qualified_type(TYPE, QUALS) c_build_qualified_type_1 (TYPE, QUALS, 0)
 
 /* Build tree nodes and builtin functions common to both C and C++ language
    frontends.  */
@@ -896,6 +936,7 @@  extern int self_promoting_args_p (const_
 extern tree strip_pointer_operator (tree);
 extern tree strip_pointer_or_array_types (tree);
 extern HOST_WIDE_INT c_common_to_target_charset (HOST_WIDE_INT);
+extern tree upc_num_threads (void);
 
 /* This is the basic parsing function.  */
 extern void c_parse_file (void);
@@ -1112,6 +1153,9 @@  extern void c_stddef_cpp_builtins (void)
 extern void fe_file_change (const line_map_ordinary *);
 extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char);
 
+/* In c-lex.c  */
+extern int c_header_level;	/* In system header, if > 0.  */
+
 /* In c-ppoutput.c  */
 extern void init_pp_output (FILE *);
 extern void preprocess_file (cpp_reader *);
@@ -1295,6 +1339,25 @@  c_tree_chain_next (tree t)
   return NULL;
 }
 
+/* Used to represent a UPC synchronization statement.
+   The first operand is the synchronization operation, UPC_SYNC_OP:
+   UPC_SYNC_NOTIFY_OP	1	Notify operation
+   UPC_SYNC_WAIT_OP	2	Wait operation
+   UPC_SYNC_BARRIER_OP	3	Barrier operation
+
+   The second operand, UPC_SYNC_ID is the (optional) expression
+   whose value specifies the barrier identifier which is checked
+   by the various synchronization operations.  */
+
+#define UPC_SYNC_OP(NODE)	TREE_OPERAND (UPC_SYNC_STMT_CHECK (NODE), 0)
+#define UPC_SYNC_ID(NODE)	TREE_OPERAND (UPC_SYNC_STMT_CHECK (NODE), 1)
+
+/* Values of the first operand in a UPC_SYNC_STMT */
+
+#define UPC_SYNC_NOTIFY_OP	1	/* Notify operation */
+#define UPC_SYNC_WAIT_OP	2	/* Wait operation */
+#define UPC_SYNC_BARRIER_OP	3	/* Barrier operation */
+
 /* Mask used by tm_stmt_attr.  */
 #define TM_STMT_ATTR_OUTER	2
 #define TM_STMT_ATTR_ATOMIC	4
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-cppbuiltin.c	(.../branches/gupc)	(revision 231080)
@@ -27,6 +27,7 @@  along with GCC; see the file COPYING3.
 #include "stor-layout.h"
 #include "flags.h"
 #include "c-pragma.h"
+#include "c-upc-pts.h"
 #include "output.h"		/* For user_label_prefix.  */
 #include "debug.h"		/* For dwarf2out_do_cfi_asm.  */
 #include "common/common-target.h"
@@ -766,6 +767,92 @@  cpp_iec_559_complex_value (void)
   return ret;
 }
 
+/* Return the section name with any leading "__DATA," or "__TEXT," removed.
+   (Darwin adds them to the section name).  */
+static const char *
+strip_section_prefix (const char *section_name)
+{
+  const char *name = section_name;
+  if ((strncmp (name, "__DATA,", 7) == 0)
+      || (strncmp (name, "__TEXT,", 7) == 0))
+    name += 7;
+  return name;
+}
+
+/* Generate UPC specific pre-defined macros.  */
+
+static void
+upc_cpp_builtins (cpp_reader * pfile)
+{
+  char def_buf[256];
+  cpp_define (pfile, "__UPC__=1");
+  cpp_define (pfile, "__GUPC__=1");
+  /* Define __GCC_UPC__ for backward compatibility.  */
+  cpp_define (pfile, "__GCC_UPC__=1");
+  cpp_define (pfile, "__UPC_VERSION__=201311L");
+  (void) sprintf (def_buf, "UPC_MAX_BLOCK_SIZE=%lu",
+		  (unsigned long) UPC_MAX_BLOCK_SIZE);
+  cpp_define (pfile, def_buf);
+  cpp_define (pfile, "__UPC_PTS_STRUCT_REP__=1");
+  (void) sprintf (def_buf, "__UPC_VADDR_TYPE__=%s", UPC_PTS_VADDR_TYPE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_THREAD_TYPE__=%s", UPC_PTS_THREAD_TYPE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_PHASE_TYPE__=%s", UPC_PTS_PHASE_TYPE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_PTS_ALIGN__=%d",
+			   (2 * POINTER_SIZE) / BITS_PER_UNIT);
+  cpp_define (pfile, def_buf);
+  cpp_define (pfile, "__UPC_VADDR_FIRST__=1");
+  (void) sprintf (def_buf, "__UPC_PTS_SIZE__=%d", UPC_PTS_SIZE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_VADDR_SIZE__=%d", UPC_PTS_VADDR_SIZE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_THREAD_SIZE__=%d", UPC_PTS_THREAD_SIZE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_PHASE_SIZE__=%d", UPC_PTS_PHASE_SIZE);
+  cpp_define (pfile, def_buf);
+  if (flag_upc_threads)
+    {
+      cpp_define (pfile, "__UPC_STATIC_THREADS__=1");
+      (void) sprintf (def_buf, "THREADS=%d", flag_upc_threads);
+      cpp_define (pfile, def_buf);
+    }
+  else
+    {
+      cpp_define (pfile, "__UPC_DYNAMIC_THREADS__=1");
+    }
+  if (flag_upc_pthreads && (upc_pthreads_model == upc_pthreads_tls_model))
+    {
+      cpp_define (pfile, "__UPC_PTHREADS_MODEL_TLS__=1");
+    }
+  /* If debugging or instrumentation is enabled,
+     then disable inlining of the runtime.  */
+  if (flag_upc_debug || flag_upc_instrument)
+    flag_upc_inline_lib = 0;
+  /* If -f[no-]upc-inline-lib hasn't been asserted, force inlining of the
+     runtime library if optimization is enabled.  */
+  if (flag_upc_inline_lib < 0)
+    flag_upc_inline_lib = (optimize >= 1);
+  if (flag_upc_inline_lib)
+    cpp_define (parse_in, "__UPC_INLINE_LIB__=1");
+  /* UPC profiling instrumentation code will be generated.  */
+  if (flag_upc_instrument)
+    {
+      cpp_define (parse_in, "__UPC_PUPC_INST__=1");
+    }
+  if (targetm.upc.link_script_p ())
+    {
+      cpp_define (parse_in, "__UPC_LINK_SCRIPT__=1");
+    }
+  builtin_define_with_value ("__UPC_SHARED_SECTION_NAME__",
+	 strip_section_prefix (targetm.upc.shared_section_name ()), 0);
+  builtin_define_with_value ("__UPC_PGM_INFO_SECTION_NAME__",
+	 strip_section_prefix (targetm.upc.pgm_info_section_name ()), 0);
+  builtin_define_with_value ("__UPC_INIT_ARRAY_SECTION_NAME__",
+	 strip_section_prefix (targetm.upc.init_array_section_name ()), 0);
+}
+
 /* Hook that registers front end and target-specific built-ins.  */
 void
 c_cpp_builtins (cpp_reader *pfile)
@@ -1226,6 +1313,10 @@  c_cpp_builtins (cpp_reader *pfile)
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201511");
 
+  /* Add UPC defines */
+  if (flag_upc)
+    upc_cpp_builtins (pfile);
+
   for (i = 0; i < NUM_INT_N_ENTS; i ++)
     if (int_n_enabled_p[i])
       {
Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-lex.c	(.../branches/gupc)	(revision 231080)
@@ -35,7 +35,7 @@  static int header_time, body_time;
 static splay_tree file_info_tree;
 
 int pending_lang_change; /* If we need to switch languages - C++ only */
-int c_header_level;	 /* depth in C headers - C++ only */
+int c_header_level;	 /* depth in C headers - C++ and UPC */
 
 static tree interpret_integer (const cpp_token *, unsigned int,
 			       enum overflow_type *);
@@ -202,27 +202,27 @@  fe_file_change (const line_map_ordinary
 
 	  input_location = new_map->start_location;
 	  (*debug_hooks->start_source_file) (line, LINEMAP_FILE (new_map));
-#ifndef NO_IMPLICIT_EXTERN_C
 	  if (c_header_level)
 	    ++c_header_level;
 	  else if (LINEMAP_SYSP (new_map) == 2)
 	    {
 	      c_header_level = 1;
+#ifndef NO_IMPLICIT_EXTERN_C
 	      ++pending_lang_change;
-	    }
 #endif
+	    }
 	}
     }
   else if (new_map->reason == LC_LEAVE)
     {
-#ifndef NO_IMPLICIT_EXTERN_C
       if (c_header_level && --c_header_level == 0)
 	{
 	  if (LINEMAP_SYSP (new_map) == 2)
 	    warning (0, "badly nested C headers from preprocessor");
+#ifndef NO_IMPLICIT_EXTERN_C
 	  --pending_lang_change;
-	}
 #endif
+	}
       input_location = new_map->start_location;
 
       (*debug_hooks->end_source_file) (LINEMAP_LINE (new_map));
Index: gcc/c-family/c-pragma.c
===================================================================
--- gcc/c-family/c-pragma.c	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-pragma.c	(.../branches/gupc)	(revision 231080)
@@ -30,6 +30,7 @@  along with GCC; see the file COPYING3.
 #include "attribs.h"
 #include "varasm.h"
 #include "c-pragma.h"
+#include "langhooks.h"
 #include "opts.h"
 #include "plugin.h"
 
@@ -553,6 +554,237 @@  add_to_renaming_pragma_list (tree oldnam
 /* The current prefix set by #pragma extern_prefix.  */
 GTY(()) tree pragma_extern_prefix;
 
+/* variables used to implement #pragma upc semantics */
+#ifndef UPC_CMODE_STACK_INCREMENT
+#define UPC_CMODE_STACK_INCREMENT 32
+#endif
+static int pragma_upc_permitted;
+static int upc_cmode;
+static int *upc_cmode_stack;
+static int upc_cmode_stack_in_use;
+static int upc_cmode_stack_allocated;
+
+static void init_pragma_upc (void);
+static void handle_pragma_upc (cpp_reader * ARG_UNUSED (dummy));
+
+/* Initialize the variables used to manage the current UPC consistency
+   mode (strict/relaxed).  */
+
+static void
+init_pragma_upc (void)
+{
+  pragma_upc_permitted = 0;
+  upc_cmode = 0;
+  upc_cmode_stack = (int *) xcalloc (UPC_CMODE_STACK_INCREMENT,
+                                     sizeof (int));
+  upc_cmode_stack_allocated = UPC_CMODE_STACK_INCREMENT;
+  upc_cmode_stack_in_use = 0;
+}
+
+/*
+ *  #pragma upc strict
+ *  #pragma upc relaxed
+ *  #pragma upc upc_code
+ *  #pragma upc c_code
+ */
+static void
+handle_pragma_upc (cpp_reader * ARG_UNUSED (dummy))
+{
+  tree x;
+  enum cpp_ttype t;
+  enum upc_pragma_op {p_strict, p_relaxed, p_upc_code,
+        p_c_code, p_detect_upc, p_unknown};
+  enum upc_pragma_op upc_pragma = p_unknown;
+
+  t = pragma_lex (&x);
+  if (t == CPP_NAME)
+    {
+      const char *op = IDENTIFIER_POINTER (x);
+      if (!strcmp (op, "strict"))
+        upc_pragma = p_strict;
+      else if (!strcmp (op, "relaxed"))
+        upc_pragma = p_relaxed;
+      else if (!strcmp (op, "upc_code"))
+        upc_pragma = p_upc_code;
+      else if (!strcmp (op, "c_code"))
+        upc_pragma = p_c_code;
+      else if (!strcmp (op, "detect_upc"))
+        {
+	  const char *detect_op;
+          upc_pragma = p_detect_upc;
+          t = pragma_lex (&x);
+          if (t != CPP_NAME)
+            GCC_BAD ("missing [suspend_insertion|resume_insertion]"
+	             " after %<#pragma UPC detect_upc%>");
+          detect_op = IDENTIFIER_POINTER (x);
+          if (strcmp (detect_op, "suspend_insertion") == 0)
+	    /* no action */;
+          else if (strcmp (detect_op, "resume_insertion") == 0)
+	    /* no action */;
+          else
+            GCC_BAD ("expected [suspend_insertion|resume_insertion]"
+	             " after %<#pragma UPC detect_upc%>");
+	}
+      else
+	GCC_BAD2 ("unknown action '%s' for '#pragma upc' - ignored", op);
+    }
+  else
+    warning (OPT_Wpragmas, "missing parameter after #pragma upc");
+
+  t = pragma_lex (&x);
+  if (t != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of #pragma upc");
+
+  if ((upc_pragma == p_strict) || (upc_pragma == p_relaxed))
+    {
+      if (pragma_upc_permitted_p ())
+        {
+          int consistency_mode = (upc_pragma == p_strict);
+          set_upc_consistency_mode (consistency_mode);
+        }
+       else
+         warning (OPT_Wpragmas, "#pragma upc not allowed in this context");
+    }
+  else if ((upc_pragma == p_upc_code) || (upc_pragma == p_c_code))
+    {
+      flag_upc = (upc_pragma == p_upc_code);
+      lang_hooks.upc.toggle_keywords (flag_upc);
+    }
+  else if (upc_pragma == p_detect_upc)
+    {
+      /* Skip: This is a Berkeley-specific pragma that requires no action.  */
+    }
+}
+
+/* Set the current setting of the UPC consistency mode
+   that is in effect.  */
+
+void
+set_upc_consistency_mode (int mode)
+{
+  upc_cmode = mode;
+}
+
+/* Return the current setting of the UPC consistency mode.  */
+
+int
+get_upc_consistency_mode (void)
+{
+  return upc_cmode;
+}
+
+/* Called from the parser just after the bracket that opens a compound
+   statement has been parsed.  Set the flag that allows the pragma
+   in this context.  */
+
+void
+permit_pragma_upc (void)
+{
+  pragma_upc_permitted = 1;
+}
+
+/* Called just before the body of a compound statement is parsed.
+   Clear the flag that allows the pragma.  */
+
+void
+deny_pragma_upc (void)
+{
+  pragma_upc_permitted = 0;
+}
+
+/* A #pragma upc is permitted either at the outermost scope,
+   or directly after the bracket that opens a compound statement.  */
+
+int
+pragma_upc_permitted_p (void)
+{
+   return !current_function_decl || pragma_upc_permitted;
+}
+
+/* Called at the beginning of every compound statement.
+   Pushes the old value of the current UPC consistency mode
+   onto the stack.  */
+
+void
+push_upc_consistency_mode (void)
+{
+  if (upc_cmode_stack_in_use == upc_cmode_stack_allocated)
+    {
+      upc_cmode_stack_allocated += UPC_CMODE_STACK_INCREMENT;
+      upc_cmode_stack = (int *) xrealloc (upc_cmode_stack,
+			 upc_cmode_stack_allocated * sizeof (int));
+    }
+  upc_cmode_stack[upc_cmode_stack_in_use++] = upc_cmode;
+}
+
+/* Called at the end of every compound statement.
+   Sets the current consistency mode to the previously saved value.  */
+
+void
+pop_upc_consistency_mode (void)
+{
+  if (upc_cmode_stack_in_use <= 0)
+    abort ();
+  upc_cmode = upc_cmode_stack[--upc_cmode_stack_in_use];
+}
+
+static int pragma_pupc_on;
+static void init_pragma_pupc (void);
+static void handle_pragma_pupc (cpp_reader *);
+
+/* Pragma pupc defaults to being on */
+static void
+init_pragma_pupc (void)
+{
+  pragma_pupc_on = 1;
+}
+
+int
+get_upc_pupc_mode (void)
+{
+  return pragma_pupc_on;
+}
+
+int
+disable_pupc_mode (void)
+{
+  int old_pupc = pragma_pupc_on;
+  pragma_pupc_on = 0;
+  return old_pupc;
+}
+
+void
+set_pupc_mode (int new_pupc)
+{
+  pragma_pupc_on = new_pupc;
+}
+
+/*
+ *  #pragma pupc on
+ *  #pragma pupc off
+ */
+static void
+handle_pragma_pupc (cpp_reader *dummy ATTRIBUTE_UNUSED)
+{
+  tree x;
+  enum cpp_ttype t;
+
+  t = pragma_lex(&x);
+  if (t == CPP_NAME) {
+    const char *op = IDENTIFIER_POINTER (x);
+    if (!strcmp (op, "on"))
+      pragma_pupc_on = 1;
+    else if (!strcmp (op, "off"))
+      pragma_pupc_on = 0;
+    else
+	    GCC_BAD2 ("unknown action '%s' for '#pragma pupc' - ignored", op);
+  }
+  
+  t = pragma_lex (&x);
+  if (t != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of #pragma pupc");
+}
+
 /* Hook from the front ends to apply the results of one of the preceding
    pragmas that rename variables.  */
 
@@ -1542,6 +1774,14 @@  init_pragma (void)
 
   c_register_pragma_with_expansion (0, "message", handle_pragma_message);
 
+  if (flag_upc)
+    {
+      c_register_pragma (0, "upc", handle_pragma_upc);
+      init_pragma_upc ();
+      c_register_pragma (0, "pupc", handle_pragma_pupc);
+      init_pragma_pupc ();
+    }
+
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS ();
 #endif
Index: gcc/c-family/c-pragma.h
===================================================================
--- gcc/c-family/c-pragma.h	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-pragma.h	(.../branches/gupc)	(revision 231080)
@@ -236,6 +236,15 @@  extern void add_to_renaming_pragma_list
 
 extern enum cpp_ttype pragma_lex (tree *, location_t *loc = NULL);
 
+/* UPC-related pragma handling.  */
+extern void deny_pragma_upc (void);
+extern int get_upc_consistency_mode (void);
+extern void permit_pragma_upc (void);
+extern void pop_upc_consistency_mode (void);
+extern int pragma_upc_permitted_p (void);
+extern void push_upc_consistency_mode (void);
+extern void set_upc_consistency_mode (int);
+
 /* Flags for use with c_lex_with_flags.  The values here were picked
    so that 0 means to translate and join strings.  */
 #define C_LEX_STRING_NO_TRANSLATE 1 /* Do not lex strings into
Index: gcc/c-family/c-pretty-print.c
===================================================================
--- gcc/c-family/c-pretty-print.c	(.../trunk)	(revision 231059)
+++ gcc/c-family/c-pretty-print.c	(.../branches/gupc)	(revision 231080)
@@ -186,6 +186,13 @@  pp_c_cv_qualifiers (c_pretty_printer *pp
   if (qualifiers & TYPE_QUAL_RESTRICT)
     pp_c_ws_string (pp, (flag_isoc99 && !c_dialect_cxx ()
 			 ? "restrict" : "__restrict__"));
+  if (qualifiers & TYPE_QUAL_RELAXED)
+    pp_c_ws_string (pp, "relaxed");
+  if (qualifiers & TYPE_QUAL_STRICT)
+    pp_c_ws_string (pp, "strict");
+  if (qualifiers & TYPE_QUAL_SHARED)
+    pp_c_ws_string (pp, "shared");
+
 }
 
 /* Pretty-print T using the type-cast notation '( type-name )'.  */
Index: gcc/c/c-convert.c
===================================================================
--- gcc/c/c-convert.c	(.../trunk)	(revision 231059)
+++ gcc/c/c-convert.c	(.../branches/gupc)	(revision 231080)
@@ -29,6 +29,7 @@  along with GCC; see the file COPYING3.
 #include "target.h"
 #include "c-tree.h"
 #include "convert.h"
+#include "c-upc.h"
 #include "langhooks.h"
 #include "ubsan.h"
 
@@ -87,6 +88,11 @@  convert (tree type, tree expr)
 
   STRIP_TYPE_NOPS (e);
 
+  /* Drop 'shared' qualifier when considering conversions
+     of expression values.  */
+  if (SHARED_TYPE_P (type))
+    type = build_unshared_type(type);
+
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))
       && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE
 	  || TREE_CODE (e) == COMPLEX_EXPR))
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(.../trunk)	(revision 231059)
+++ gcc/c/c-decl.c	(.../branches/gupc)	(revision 231080)
@@ -38,6 +38,8 @@  along with GCC; see the file COPYING3.
 #include "stor-layout.h"
 #include "varasm.h"
 #include "attribs.h"
+#include "c-upc.h"
+#include "c-upc-low.h"
 #include "toplev.h"
 #include "debug.h"
 #include "c-family/c-objc.h"
@@ -635,6 +637,8 @@  c_build_pointer_type (tree to_type)
 					      : TYPE_ADDR_SPACE (to_type);
   machine_mode pointer_mode;
 
+  if (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
@@ -2397,6 +2401,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 (olddecl) = 1;
+    }
+
   /* Merge deprecatedness.  */
   if (TREE_DEPRECATED (newdecl))
     TREE_DEPRECATED (olddecl) = 1;
@@ -3089,6 +3100,8 @@  pushdecl_top_level (tree x)
 static void
 implicit_decl_warning (location_t loc, tree id, tree olddecl)
 {
+  if (upc_diagnose_deprecated_stmt (input_location, id))
+    return;
   if (warn_implicit_function_declaration)
     {
       bool warned;
@@ -3419,6 +3432,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)
@@ -4252,6 +4267,9 @@  quals_from_declspecs (const struct c_dec
 	       | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
 	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
 	       | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 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
@@ -4797,7 +4815,24 @@  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 (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;
 	    }
 	}
@@ -4836,6 +4871,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 (flag_upc)
+	upc_check_decl (decl);
+
       if (asmspec)
 	{
 	  /* If this is not a static variable, issue a warning.
@@ -5338,6 +5377,9 @@  grokdeclarator (const struct c_declarato
   int restrictp;
   int volatilep;
   int atomicp;
+  int sharedp;
+  int strictp;
+  int relaxedp;
   int type_quals = TYPE_UNQUALIFIED;
   tree name = NULL_TREE;
   bool funcdef_flag = false;
@@ -5349,6 +5391,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;
@@ -5448,6 +5494,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_at (input_location))
@@ -5493,6 +5541,11 @@  grokdeclarator (const struct c_declarato
   restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
   volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
   atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
+  sharedp = declspecs->shared_p + 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;
@@ -5505,6 +5558,21 @@  grokdeclarator (const struct c_declarato
     pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<volatile%>");
   if (atomicp > 1)
     pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
+  if (sharedp > 1)
+    pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<shared%>");
+  if (strictp > 1)
+    pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<strict%>");
+  if (relaxedp > 1)
+    pedwarn_c90 (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)",
@@ -5518,6 +5586,9 @@  grokdeclarator (const struct c_declarato
 		| (restrictp ? TYPE_QUAL_RESTRICT : 0)
 		| (volatilep ? TYPE_QUAL_VOLATILE : 0)
 		| (atomicp ? TYPE_QUAL_ATOMIC : 0)
+		| (sharedp ? TYPE_QUAL_SHARED : 0)
+		| (strictp ? TYPE_QUAL_STRICT : 0)
+		| (relaxedp ? TYPE_QUAL_RELAXED : 0)
 		| ENCODE_QUAL_ADDR_SPACE (address_space));
 
   /* Applying the _Atomic qualifier to an array type (through the use
@@ -5805,6 +5876,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)
 		  {
@@ -5977,6 +6082,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 environment
+		       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.  */
@@ -6036,6 +6153,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)
@@ -6083,6 +6202,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");
@@ -6121,9 +6246,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
@@ -6163,7 +6298,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;
@@ -6247,6 +6384,14 @@  grokdeclarator (const struct c_declarato
 	}
     }
 
+  /* 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)
     {
@@ -6304,7 +6449,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)
@@ -6357,7 +6503,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;
     }
 
@@ -6405,7 +6551,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)
@@ -6435,6 +6582,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);
 
@@ -6496,6 +6649,13 @@  grokdeclarator (const struct c_declarato
 	    TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
 						   NULL_TREE);
 	  }
+        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);
@@ -6608,7 +6768,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
@@ -6657,6 +6826,10 @@  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;
 	  }
 
@@ -6731,6 +6904,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;
   }
 }
@@ -9061,6 +9241,8 @@  finish_function (void)
       if (!decl_function_context (fndecl))
 	{
 	  invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
+          if (flag_upc)
+            upc_genericize (fndecl);
 	  c_genericize (fndecl);
 
 	  /* ??? Objc emits functions after finalizing the compilation unit.
@@ -9390,18 +9572,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;
 }
 
@@ -9417,6 +9602,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;
@@ -9442,6 +9628,9 @@  build_null_declspecs (void)
   ret->volatile_p = false;
   ret->atomic_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;
@@ -9482,6 +9671,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);
@@ -9506,6 +9712,18 @@  declspecs_add_qual (source_location loc,
       dupe = specs->atomic_p;
       specs->atomic_p = true;
       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 ();
     }
Index: gcc/c/c-objc-common.c
===================================================================
--- gcc/c/c-objc-common.c	(.../trunk)	(revision 231059)
+++ gcc/c/c-objc-common.c	(.../branches/gupc)	(revision 231080)
@@ -21,11 +21,14 @@  along with GCC; see the file COPYING3.
 #include "system.h"
 #include "coretypes.h"
 #include "c-tree.h"
+#include "options.h"
 #include "intl.h"
 #include "c-family/c-pretty-print.h"
 #include "tree-pretty-print.h"
 #include "langhooks.h"
 #include "c-objc-common.h"
+#include "c-upc-lang.h"
+#include "c-upc.h"
 
 #include <new>                          // For placement new.
 
@@ -59,7 +62,14 @@  c_objc_common_init (void)
 {
   c_init_decl_processing ();
 
-  return c_common_init ();
+  if (c_common_init () == false)
+    return false;
+
+  if (flag_upc)
+    upc_lang_init ();
+
+  return true;
+
 }
 
 /* Called during diagnostic message formatting process to print a
@@ -212,10 +222,87 @@  c_initialize_diagnostics (diagnostic_con
   diagnostic_format_decoder (context) = &c_tree_printer;
 }
 
+/* Check for the possible need to convert UPC-specific types.  */
+
+static int
+upc_types_compatible_p (tree x, tree y)
+{
+  if (POINTER_TYPE_P (x) && POINTER_TYPE_P (y))
+    {
+      const tree ttx = TREE_TYPE (x);
+      const tree tty = TREE_TYPE (y);
+      if (SHARED_TYPE_P (ttx) && SHARED_TYPE_P (tty))
+	{
+	  tree bx, by, sx, sy;
+	  int x_has_zero_phase, y_has_zero_phase;
+	  int result;
+	  /* If both types are generic UPC pointers-to-shared,
+	     then they're compatible.  */
+	  if (VOID_TYPE_P (ttx) && VOID_TYPE_P (tty))
+	    return 1;
+	  /* Intermediate conversions to (shared void *) (defined
+	     to be a "generic pointer-to-shared" in the UPC
+	     specification) cannot always be optimized away.
+	     For example,
+	       p1 = (shared void *) p2;
+	     preserves the phase of p2, when assigning to p1.
+	     We need to be conservative, and not consider conversions
+	     involving a generic UPC pointer-to-shared value to be
+	     equivalent.  */
+	  if (VOID_TYPE_P (ttx) != VOID_TYPE_P (tty))
+	    return 0;
+	  bx = get_block_factor (ttx);
+	  by = get_block_factor (tty);
+	  sx = TYPE_SIZE (ttx);
+	  sy = TYPE_SIZE (tty);
+	  x_has_zero_phase = (integer_zerop (bx) || integer_onep (bx));
+	  y_has_zero_phase = (integer_zerop (by) || integer_onep (by));
+	  /* Normalize type size so that 0 => NULL.  */
+	  if (sx && integer_zerop (sx))
+	    sx = NULL_TREE;
+	  if (sy && integer_zerop (sy))
+	    sy = NULL_TREE;
+	  /* If the target types have the same UPC block size
+	     (or they both have a phase value of zero) 
+	     and the same size and the target types are
+	     otherwise compatible, then the pointer-to-shared
+	     types are compatible.  */
+	  result = (tree_int_cst_equal (bx, by)
+		    || (x_has_zero_phase && y_has_zero_phase))
+	           && tree_int_cst_equal (sx, sy);
+	  return result;
+	}
+      /* If one operand has a UPC shared type,
+         and the other operand's type is not a UPC shared type,
+         then they aren't equivalent.  */
+      else if (SHARED_TYPE_P (ttx) != SHARED_TYPE_P (tty))
+	return 0;
+    }
+  else if (SHARED_TYPE_P (x) || SHARED_TYPE_P (y))
+    {
+      /* In UPC, blocking factors can be applied to
+         non-pointer objects/types.  They're compatible
+         if the block sizes are equal.  */
+      const tree bx = get_block_factor (x);
+      const tree by = get_block_factor (y);
+      return tree_int_cst_equal (bx, by)
+	&& c_types_compatible_p (TYPE_MAIN_VARIANT (x),
+				 TYPE_MAIN_VARIANT (y));
+    }
+  /* Otherwise, they're not compatible.
+     comptypes() should be called before this function
+     in order to implement a full "C" compatibility check.  */
+  return 0;
+}
+
 int
 c_types_compatible_p (tree x, tree y)
 {
-  return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
+  int result;
+  result = comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
+  if (!result && flag_upc)
+    result = upc_types_compatible_p (x, y);
+  return result;
 }
 
 /* Determine if the type is a vla type for the backend.  */
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(.../trunk)	(revision 231059)
+++ gcc/c/c-parser.c	(.../branches/gupc)	(revision 231080)
@@ -51,6 +51,9 @@  along with GCC; see the file COPYING3.
 #include "c-family/c-pragma.h"
 #include "c-lang.h"
 #include "c-family/c-objc.h"
+#include "c-upc.h"
+#include "c-upc-gasp.h"
+#include "c-upc-pts-ops.h"
 #include "plugin.h"
 #include "omp-low.h"
 #include "builtins.h"
@@ -106,6 +109,9 @@  c_parse_init (void)
   if (!c_dialect_objc ())
     mask |= D_OBJC | D_CXX_OBJC;
 
+  if (!flag_upc)
+    mask |= D_UPC;
+
   ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
   for (i = 0; i < num_c_common_reswords; i++)
     {
@@ -545,6 +551,11 @@  c_token_starts_typename (c_token *token)
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
+        /* UPC qualifiers */
+	case RID_SHARED:
+	case RID_STRICT:
+	case RID_RELAXED:
+	  return true;
 	default:
 	  if (token->keyword >= RID_FIRST_INT_N
 	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
@@ -626,6 +637,11 @@  c_token_is_qualifier (c_token *token)
 	case RID_ATTRIBUTE:
 	case RID_ATOMIC:
 	  return true;
+        case RID_SHARED:
+        case RID_STRICT:
+        case RID_RELAXED:
+	  /* UPC qualifiers */
+	  return true;
 	default:
 	  return false;
 	}
@@ -707,6 +723,11 @@  c_token_starts_declspecs (c_token *token
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
+        /* UPC qualifiers */
+	case RID_SHARED:
+	case RID_STRICT:
+	case RID_RELAXED:
+	  return true;
 	default:
 	  if (token->keyword >= RID_FIRST_INT_N
 	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
@@ -1315,6 +1336,14 @@  static tree c_parser_array_notation (loc
 static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
 static void c_parser_cilk_grainsize (c_parser *);
 
+/* These UPC parser functions are only ever called when
+   compiling UPC.  */
+static void c_parser_upc_forall_statement (c_parser *);
+static void c_parser_upc_sync_statement (c_parser *, int);
+static void c_parser_upc_shared_qual (source_location,
+                                      c_parser *,
+				      struct c_declspecs *);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -2512,6 +2541,17 @@  c_parser_declspecs (c_parser *parser, st
 	  declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
 	  c_parser_consume_token (parser);
 	  break;
+        /* UPC qualifiers */
+	case RID_SHARED:
+	  attrs_ok = true;
+          c_parser_upc_shared_qual (loc, parser, specs);
+	  break;
+	case RID_STRICT:
+	case RID_RELAXED:
+	  attrs_ok = true;
+	  declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  break;
 	case RID_ATTRIBUTE:
 	  if (!attrs_ok)
 	    goto out;
@@ -4662,6 +4702,19 @@  c_parser_compound_statement_nostart (c_p
       c_parser_consume_token (parser);
       return;
     }
+  /* Process all #pragma's just after the opening brace.  This
+     handles #pragma upc, which can only appear just after
+     the opening brace, when it appears within a function body.  */
+  push_upc_consistency_mode ();
+  permit_pragma_upc ();
+  while (c_parser_next_token_is (parser, CPP_PRAGMA))
+    {
+      location_t loc ATTRIBUTE_UNUSED = c_parser_peek_token (parser)->location;
+      if (c_parser_pragma (parser, pragma_compound))
+        last_label = false, last_stmt = true;
+      parser->error = false;
+    }
+  deny_pragma_upc ();
   while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
     {
       location_t loc = c_parser_peek_token (parser)->location;
@@ -4768,6 +4821,7 @@  c_parser_compound_statement_nostart (c_p
   if (last_label)
     error_at (label_loc, "label at end of compound statement");
   c_parser_consume_token (parser);
+  pop_upc_consistency_mode ();
   /* Restore the value we started with.  */
   mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
 }
@@ -5154,6 +5208,22 @@  c_parser_statement_after_labels (c_parse
 	  gcc_assert (c_dialect_objc ());
 	  c_parser_objc_synchronized_statement (parser);
 	  break;
+	case RID_UPC_FORALL:
+          gcc_assert (flag_upc);
+	  c_parser_upc_forall_statement (parser);
+	  break;
+        case RID_UPC_NOTIFY:
+          gcc_assert (flag_upc);
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_NOTIFY_OP);
+	  goto expect_semicolon;
+        case RID_UPC_WAIT:
+          gcc_assert (flag_upc);
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_WAIT_OP);
+	  goto expect_semicolon;
+        case RID_UPC_BARRIER:
+          gcc_assert (flag_upc);
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_BARRIER_OP);
+	  goto expect_semicolon;
 	default:
 	  goto expr_stmt;
 	}
@@ -6744,6 +6814,11 @@  c_parser_unary_expression (c_parser *par
 	{
 	case RID_SIZEOF:
 	  return c_parser_sizeof_expression (parser);
+	case RID_UPC_BLOCKSIZEOF:
+	case RID_UPC_ELEMSIZEOF:
+	case RID_UPC_LOCALSIZEOF:
+          gcc_assert (flag_upc);
+	  return c_parser_sizeof_expression (parser);
 	case RID_ALIGNOF:
 	  return c_parser_alignof_expression (parser);
 	case RID_EXTENSION:
@@ -6776,6 +6851,147 @@  c_parser_unary_expression (c_parser *par
     }
 }
 
+/* Return the result of upc_blocksizeof applied to EXPR.  */
+
+static
+struct c_expr
+upc_blocksizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_blocksizeof (loc, TREE_TYPE (expr.value));
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of upc_blocksizeof applied to T, a structure
+   for the type name passed to sizeof (rather than the type itself).  */
+
+static
+struct c_expr
+upc_blocksizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  type = groktypename (t, NULL, NULL);
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_blocksizeof (loc, type);
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+    }
+  return ret;
+}
+
+/* Return the result of upc_elemsizeof applied to EXPR.  */
+
+static
+struct c_expr
+upc_elemsizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_elemsizeof (loc, TREE_TYPE (expr.value));
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of upc_elemsizeof applied to T, a structure
+   for the type name passed to sizeof (rather than the type itself).  */
+
+static
+struct c_expr
+upc_elemsizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  type = groktypename (t, NULL, NULL);
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_elemsizeof (loc, type);
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+    }
+  return ret;
+}
+
+/* Return the result of upc_localsizeof applied to EXPR.  */
+
+static
+struct c_expr
+upc_localsizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_localsizeof (loc, TREE_TYPE (expr.value));
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of upc_localsizeof applied to T, a structure
+   for the type name passed to sizeof (rather than the type itself).  */
+
+static
+struct c_expr
+upc_localsizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  type = groktypename (t, NULL, NULL);
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_localsizeof (loc, type);
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+    }
+  return ret;
+}
+
 /* Parse a sizeof expression.  */
 
 static struct c_expr
@@ -6784,7 +7000,7 @@  c_parser_sizeof_expression (c_parser *pa
   struct c_expr expr;
   struct c_expr result;
   location_t expr_loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+  enum rid keyword = c_parser_peek_token (parser)->keyword;
 
   location_t start;
   location_t finish = UNKNOWN_LOCATION;
@@ -6826,7 +7042,23 @@  c_parser_sizeof_expression (c_parser *pa
       /* sizeof ( type-name ).  */
       c_inhibit_evaluation_warnings--;
       in_sizeof--;
-      result = c_expr_sizeof_type (expr_loc, type_name);
+      /* Handle sizeof (type) and upc_*_sizeof (type) operations.  */
+      switch (keyword)
+        {
+	case RID_SIZEOF:
+          result = c_expr_sizeof_type (expr_loc, type_name);
+	  break;
+        case RID_UPC_BLOCKSIZEOF:
+          result = upc_blocksizeof_type (expr_loc, type_name);
+	  break;
+        case RID_UPC_ELEMSIZEOF:
+          result = upc_elemsizeof_type (expr_loc, type_name);
+	  break;
+        case RID_UPC_LOCALSIZEOF:
+          result = upc_localsizeof_type (expr_loc, type_name);
+	  break;
+        default: gcc_unreachable ();
+        }
     }
   else
     {
@@ -6840,7 +7072,23 @@  c_parser_sizeof_expression (c_parser *pa
       if (TREE_CODE (expr.value) == COMPONENT_REF
 	  && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
 	error_at (expr_loc, "%<sizeof%> applied to a bit-field");
-      result = c_expr_sizeof_expr (expr_loc, expr);
+      /* Handle sizeof (expr) and upc_*_sizeof (expr) operations.  */
+      switch (keyword)
+        {
+	case RID_SIZEOF:
+          result = c_expr_sizeof_expr (expr_loc, expr);
+	  break;
+        case RID_UPC_BLOCKSIZEOF:
+          result = upc_blocksizeof_expr (expr_loc, expr);
+	  break;
+        case RID_UPC_ELEMSIZEOF:
+          result = upc_elemsizeof_expr (expr_loc, expr);
+	  break;
+        case RID_UPC_LOCALSIZEOF:
+          result = upc_localsizeof_expr (expr_loc, expr);
+	  break;
+        default: gcc_unreachable ();
+        }
     }
   if (finish != UNKNOWN_LOCATION)
     set_c_expr_source_range (&result, start, finish);
@@ -9832,6 +10080,316 @@  c_parser_objc_at_dynamic_declaration (c_
   objc_add_dynamic_declaration (loc, list);
 }
 
+/* Parse UPC shared qualifier
+
+   shared-type-qualifier: shared layout-qualifier-opt
+   layout-qualifier: [ constant-expression-opt ] | [ * ]
+
+*/
+static void
+c_parser_upc_shared_qual (source_location loc,
+                          c_parser *parser,
+			  struct c_declspecs *specs)
+{
+  tree array_qual, arg1;
+
+  /* consume "shared" part */
+  c_parser_consume_token (parser);
+
+  /* check for shared array layout specifier */
+  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    {
+      declspecs_add_qual (loc, specs, ridpointers[RID_SHARED]);
+      return;
+    }
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+    {
+      /*  [] layout specifier */ 
+      arg1 = size_zero_node;
+    }
+  else if (c_parser_next_token_is (parser, CPP_MULT))
+    {
+      /*  [*] layout specifier */ 
+      arg1 = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
+      c_parser_consume_token (parser);
+    }
+  else
+    {
+      /*  [ expression ] layout specifier */ 
+      arg1 = c_parser_expression (parser).value;
+    }
+  array_qual = build4 (ARRAY_REF, NULL_TREE, NULL_TREE, 
+                 arg1, NULL_TREE, NULL_TREE);
+  declspecs_add_qual (loc, specs, array_qual);
+
+  if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+    {
+      c_parser_error (parser, "expected ]");
+    }
+  c_parser_consume_token (parser);
+}
+
+/* Implement UPC's upc_forall 'affinity' test.
+   If the type of AFFINITY is a UPC pointer-to-shared type,
+   rewrite it into:
+     upc_threadof (AFFINITY) == MYTHREAD
+   If AFFINITY is an integer expression, then
+   rewrite it into:
+     (AFFINITY % THREADS) == MYTHREAD   */
+
+static tree
+upc_affinity_test (location_t loc, tree affinity)
+{
+  tree mythread;
+  tree affinity_test;
+
+  gcc_assert (affinity != NULL_TREE);
+
+  if (TREE_CODE (TREE_TYPE (affinity)) == POINTER_TYPE
+      && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (affinity))))
+    {
+      /* We have a pointer to a UPC shared object and the affinity is
+         determined by the thread component of the address.  */
+      const tree pts_rep = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node,
+				   save_expr (affinity));
+      affinity = upc_pts_build_threadof (loc, pts_rep);
+    }
+  else if (TREE_CODE (TREE_TYPE (affinity)) == INTEGER_TYPE)
+    {
+      tree n_threads = upc_num_threads ();
+      affinity =
+	build_binary_op (loc, FLOOR_MOD_EXPR, affinity, n_threads, 0);
+    }
+  else
+    {
+      error
+	("UPC affinity expression is neither an integer nor the address of "
+	 "a shared object");
+      return error_mark_node;
+    }
+
+  /* Generate an external reference to the "MYTHREAD" identifier.  */
+
+  mythread = lookup_name (get_identifier ("MYTHREAD"));
+  gcc_assert (mythread != NULL_TREE);
+  TREE_USED (mythread) = 1;
+
+  /* AFFINITY now contains an integer value that can be compared to MY_THREAD.
+     Create an expression that tests if AFFINITY is equal to MYTHREAD.  */
+
+  if (!c_types_compatible_p (TREE_TYPE (affinity), TREE_TYPE (mythread)))
+    affinity = convert (TREE_TYPE (mythread), affinity);
+  affinity_test = c_objc_common_truthvalue_conversion (loc,
+				   build_binary_op (loc, EQ_EXPR,
+						    affinity, mythread, 1));
+  /* Remove any MAYBE_CONST_EXPR's.  */
+
+  affinity_test = c_fully_fold (affinity_test, false, NULL);
+
+  return affinity_test;
+}
+
+/* Parse a UPC upc_forall statement
+
+   upc_forall-statement:
+     upc_forall ( expression[opt] ; expression[opt] ;
+                  expression[opt] ; affinity[opt] ) statement
+   affinity: expression | continue  */
+
+static void
+c_parser_upc_forall_statement (c_parser *parser)
+{
+  tree block, cond, incr, save_break, save_cont, body;
+  tree affinity;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t affinity_loc = UNKNOWN_LOCATION;
+  const int profile_upc_forall = flag_upc_instrument && get_upc_pupc_mode();
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_UPC_FORALL));
+  c_parser_consume_token (parser);
+  block = c_begin_compound_stmt (flag_isoc99);
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      /* Parse the initialization declaration or expression.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	{
+	  c_parser_consume_token (parser);
+	  c_finish_expr_stmt (loc, NULL_TREE);
+	}
+      else if (c_parser_next_token_starts_declspecs (parser))
+	{
+	  c_parser_declaration_or_fndef (parser, true, true, true,
+	                                 true, true, NULL, vNULL);
+	  check_for_loop_decls (loc, true);
+	}
+      else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+	{
+	  /* __extension__ can start a declaration, but is also an
+	     unary operator that can start an expression.  Consume all
+	     but the last of a possible series of __extension__ to
+	     determine which.  */
+	  while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
+		 && (c_parser_peek_2nd_token (parser)->keyword
+		     == RID_EXTENSION))
+	    c_parser_consume_token (parser);
+	  if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+	    {
+	      int ext;
+	      ext = disable_extension_diagnostics ();
+	      c_parser_consume_token (parser);
+	      c_parser_declaration_or_fndef (parser, true, true, true, true, true,
+	                                     NULL, vNULL);
+	      restore_extension_diagnostics (ext);
+	      check_for_loop_decls (loc, true);
+	    }
+	  else
+	    goto init_expr;
+	}
+      else
+	{
+	init_expr:
+	  c_finish_expr_stmt (loc, c_parser_expression (parser).value);
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+	}
+      /* Parse the loop condition.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	{
+	  c_parser_consume_token (parser);
+	  cond = NULL_TREE;
+	}
+      else
+	{
+	  cond = c_parser_condition (parser);
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+	}
+      /* Parse the increment expression.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	incr = c_process_expr_stmt (loc, NULL_TREE);
+      else
+	incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      /* Parse the UPC affinity expression.  */
+      affinity_loc = c_parser_peek_token (parser)->location;
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+        {
+	  affinity = NULL_TREE;
+        }
+      else if (c_parser_peek_token (parser)->type == CPP_KEYWORD
+               && c_parser_peek_token (parser)->keyword == RID_CONTINUE)
+	{
+	  affinity = NULL_TREE;
+	  c_parser_consume_token (parser);
+	}
+      else
+	{
+	  affinity = c_parser_expression_conv (parser).value;
+          affinity = c_fully_fold (affinity, false, NULL);
+	}
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (affinity)
+        affinity = upc_affinity_test (affinity_loc, affinity);
+    }
+  else
+    {
+      cond = error_mark_node;
+      incr = error_mark_node;
+      affinity = error_mark_node;
+    }
+  save_break = c_break_label;
+  c_break_label = NULL_TREE;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  if (profile_upc_forall)
+    {
+      const tree gasp_start = upc_instrument_forall (loc, 1 /* start */);
+      add_stmt (gasp_start);
+    }
+  loc = c_parser_peek_token (parser)->location;
+  if (affinity != NULL_TREE && affinity != error_mark_node)
+    {
+      tree upc_forall_depth = upc_rts_forall_depth_var ();
+      tree inc_depth, depth_gt_one;
+      inc_depth = build_unary_op (loc, PREINCREMENT_EXPR, upc_forall_depth, 0);
+      c_finish_expr_stmt (loc, inc_depth);
+      depth_gt_one = build_binary_op (affinity_loc,
+				      GT_EXPR, upc_forall_depth, integer_one_node, 0);
+      depth_gt_one = c_objc_common_truthvalue_conversion (affinity_loc, depth_gt_one);
+      depth_gt_one = c_fully_fold (depth_gt_one, false, NULL);
+      affinity = build_binary_op (affinity_loc, TRUTH_OR_EXPR,
+                                  depth_gt_one, affinity, 0);
+      body = build3 (COND_EXPR, void_type_node, affinity,
+		     body, NULL_TREE);
+      c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+      c_finish_expr_stmt (loc,
+        build_unary_op (loc, PREDECREMENT_EXPR, upc_forall_depth, 0));
+    }
+  else
+    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+  if (profile_upc_forall)
+    {
+      const tree gasp_end = upc_instrument_forall (loc, 0 /* start */);
+      add_stmt (gasp_end);
+    }
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+}
+
+/* For the given kind of UPC synchronization statement given
+   by SYNC_KIND (UPC_SYNC_NOTIFY_OP, UPC_SYNC_WAIT_OP,
+   or UPC_SYNC_BARRIER_OP), build a UPC_SYNC_STMT tree node,
+   and add it to the current statement list.  The value of
+   SYNC_EXPR will be non-null if an expression is present
+   in the UPC statement being compiled.
+
+   If SYNC_EXPR is supplied, it must be assignment compatible
+   with type 'int'.  */
+
+static tree
+upc_build_sync_stmt (location_t loc, tree sync_kind, tree sync_expr)
+{
+  if (sync_expr != NULL_TREE)
+    {
+      mark_exp_read (sync_expr);
+      sync_expr = c_cvt_expr_for_assign (loc, integer_type_node, sync_expr);
+      if (sync_expr == error_mark_node)
+        {
+	  inform (loc, "UPC synchronization statement expressions "
+	               "must be assignment compatible with type `int'");
+          sync_expr = NULL_TREE;
+        }
+    }
+  return add_stmt (build_stmt (loc, UPC_SYNC_STMT, sync_kind, sync_expr));
+}
+
+/* Parse an upc-sync-statement.
+
+   upc_barrier, upc_wait, upc_notify
+*/
+
+static void
+c_parser_upc_sync_statement (c_parser *parser, int sync_kind)
+{
+  location_t loc;
+  tree expr = NULL_TREE;
+  tree stmt;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_UPC_BARRIER) ||
+              c_parser_next_token_is_keyword (parser, RID_UPC_NOTIFY) ||
+              c_parser_next_token_is_keyword (parser, RID_UPC_WAIT));
+  loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  if (c_parser_peek_token (parser)->type != CPP_SEMICOLON)
+    {
+      loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_expression (parser).value;
+      if (expr == error_mark_node)
+         expr = NULL;
+    }
+  stmt = size_int (sync_kind);
+  (void) upc_build_sync_stmt (loc, stmt, expr);
+}
+
 
 /* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
    should be considered, statements.  ALLOW_STMT is true if we're within
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h	(.../trunk)	(revision 231059)
+++ gcc/c/c-tree.h	(.../branches/gupc)	(revision 231080)
@@ -279,6 +279,9 @@  struct c_declspecs {
      NULL; attributes (possibly from multiple lists) will be passed
      separately.  */
   tree attrs;
+  /* For UPC, this is the blocking factor (layout qualifier).
+     For example, shared [10] int x;  */
+  tree upc_layout_qualifier;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
@@ -345,6 +348,12 @@  struct c_declspecs {
   BOOL_BITFIELD atomic_p : 1;
   /* Whether "_Sat" was specified.  */
   BOOL_BITFIELD saturating_p : 1;
+  /* Whether "shared" was specified.  */
+  BOOL_BITFIELD shared_p : 1;
+  /* Whether "strict" was specified.  */
+  BOOL_BITFIELD strict_p : 1;
+  /* Whether "relaxed" was specified.  */
+  BOOL_BITFIELD relaxed_p : 1;
   /* Whether any alignment specifier (even with zero alignment) was
      specified.  */
   BOOL_BITFIELD alignas_p : 1;
@@ -422,7 +431,10 @@  struct c_declarator {
       BOOL_BITFIELD vla_unspec_p : 1;
     } array;
     /* For pointers, the qualifiers on the pointer type.  */
-    int pointer_quals;
+    struct {
+      int quals;
+      tree upc_layout_qual;
+    } pointer;
     /* For attributes.  */
     tree attrs;
   } u;
@@ -662,6 +674,7 @@  extern void c_finish_omp_cancellation_po
 extern tree c_finish_omp_clauses (tree, bool, bool = false);
 extern tree c_build_va_arg (location_t, tree, tree);
 extern tree c_finish_transaction (location_t, tree, int);
+extern tree c_cvt_expr_for_assign (location_t, tree, tree);
 extern bool c_tree_equal (tree, tree);
 extern tree c_build_function_call_vec (location_t, vec<location_t>, tree,
 				       vec<tree, va_gc> *, vec<tree, va_gc> *);
Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c	(.../trunk)	(revision 231059)
+++ gcc/c/c-typeck.c	(.../branches/gupc)	(revision 231080)
@@ -43,6 +43,8 @@  along with GCC; see the file COPYING3.
 #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"
@@ -90,6 +92,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);
@@ -316,9 +319,12 @@  addr_space_superset (addr_space_t as1, a
 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.  */
@@ -329,10 +335,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_1 (type, result_quals,
+			                  result_block_factor);
+
+  return result_type;
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -623,6 +650,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;
 
@@ -665,6 +693,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.  */
@@ -674,8 +706,9 @@  common_pointer_type (tree t1, tree t2)
     gcc_unreachable ();
 
   target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
+  t2 = c_build_qualified_type_1 (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);
 }
 
@@ -1083,6 +1116,13 @@  comptypes_internal (const_tree type1, co
   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).  */
@@ -2093,6 +2133,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;
 
@@ -2347,6 +2391,7 @@  build_component_ref (location_t loc, tre
 	    error_at (loc, "%qT has no member named %qE", type, component);
 	  return error_mark_node;
 	}
+      gcc_assert (!TREE_SHARED (field));
 
       /* Chain the COMPONENT_REFs if necessary down to the FIELD.
 	 This might be better solved in future the way the C++ front
@@ -2356,6 +2401,8 @@  build_component_ref (location_t loc, tre
       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;
@@ -2370,10 +2417,15 @@  build_component_ref (location_t loc, tre
 	  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_1 (TREE_TYPE (subdatum),
+	                                      quals, upc_block_factor);
 
 	  ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
 			NULL_TREE);
@@ -2384,6 +2436,8 @@  build_component_ref (location_t loc, tre
 	  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);
@@ -2481,6 +2535,7 @@  build_indirect_ref (location_t loc, tree
 	  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;
 	}
@@ -2569,7 +2624,8 @@  build_array_ref (location_t loc, tree ar
   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;
 
@@ -3612,6 +3668,23 @@  parser_build_binary_op (location_t locat
   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.  */
 
@@ -3624,6 +3697,7 @@  pointer_diff (location_t loc, tree op0,
   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
@@ -3660,6 +3734,9 @@  pointer_diff (location_t loc, tree op0,
     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
@@ -4174,6 +4251,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);
 	  }
@@ -4387,6 +4469,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);
@@ -4830,7 +4916,8 @@  build_conditional_expr (location_t colon
 		 "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;
     }
@@ -4841,7 +4928,8 @@  build_conditional_expr (location_t colon
 		 "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;
     }
@@ -5136,6 +5224,12 @@  build_c_cast (location_t loc, tree type,
   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 ("UPC does not allow casts to a shared type");
+      return error_mark_node;
+    }
+
   type = TYPE_MAIN_VARIANT (type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
@@ -5157,6 +5251,22 @@  build_c_cast (location_t loc, tree type,
 	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))
@@ -5207,6 +5317,17 @@  build_c_cast (location_t loc, tree type,
 
       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
@@ -5257,6 +5378,33 @@  build_c_cast (location_t loc, tree type,
 	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))
@@ -5579,6 +5727,12 @@  build_modify_expr (location_t location,
       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);
@@ -5892,6 +6046,34 @@  convert_for_assignment (location_t locat
       }                                                                  \
   } 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
@@ -6135,7 +6317,9 @@  convert_for_assignment (location_t locat
 	  /* 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;
 	    }
 	}
@@ -6225,6 +6409,43 @@  convert_for_assignment (location_t locat
 	       ? 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);
 
@@ -6463,6 +6684,19 @@  convert_for_assignment (location_t locat
     }
   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.  */
@@ -6568,21 +6802,31 @@  valid_compound_expr_initializer (tree va
 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.  */
 
@@ -7388,6 +7632,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);
@@ -9662,6 +9909,20 @@  c_finish_return (location_t loc, tree re
   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.  */
@@ -10639,12 +10900,12 @@  build_binary_op (location_t location, en
       /* 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
@@ -10663,7 +10924,7 @@  build_binary_op (location_t location, en
       /* 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
@@ -11015,6 +11276,33 @@  build_binary_op (location_t location, en
 	  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.  */
@@ -11046,9 +11334,17 @@  build_binary_op (location_t location, en
 
 	  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)
@@ -11106,10 +11402,35 @@  build_binary_op (location_t location, en
 	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);
@@ -11132,6 +11453,11 @@  build_binary_op (location_t location, en
 			"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);
@@ -13320,7 +13646,7 @@  c_finish_transaction (location_t loc, tr
    down to the element type of an array.  */
 
 tree
-c_build_qualified_type (tree type, int type_quals)
+c_build_qualified_type_1 (tree type, int type_quals, tree layout_qualifier)
 {
   if (type == error_mark_node)
     return type;
@@ -13328,13 +13654,17 @@  c_build_qualified_type (tree type, int t
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree t;
-      tree element_type = c_build_qualified_type (TREE_TYPE (type),
-						  type_quals);
+      tree element_type = c_build_qualified_type_1 (TREE_TYPE (type),
+						    type_quals,
+						    layout_qualifier);
 
       /* See if we already have an identically qualified type.  */
       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),
@@ -13365,7 +13695,8 @@  c_build_qualified_type (tree type, int t
                   TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1;
                 }
               TYPE_CANONICAL (t)
-                = c_build_qualified_type (unqualified_canon, type_quals);
+                = c_build_qualified_type_1 (unqualified_canon, type_quals,
+		                            layout_qualifier);
             }
           else
             TYPE_CANONICAL (t) = t;
@@ -13384,7 +13715,7 @@  c_build_qualified_type (tree type, int t
       type_quals &= ~TYPE_QUAL_RESTRICT;
     }
 
-  tree var_type = build_qualified_type (type, type_quals);
+  tree var_type = build_qualified_type_1 (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))
Index: gcc/c/c-upc-gasp.c
===================================================================
--- gcc/c/c-upc-gasp.c	(.../trunk)	(revision 0)
+++ gcc/c/c-upc-gasp.c	(.../branches/gupc)	(revision 231080)
@@ -0,0 +1,130 @@ 
+/* c-upc-gasp.c: UPC GASP (GAS Performance) instrumentation support
+   Copyright (C) 2005-2015 Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original Implementation by Adam Leko <leko@hcs.ufl.edu>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "stringpool.h"
+#include "c-tree.h"
+#include "tree-iterator.h"
+#include "c-upc-gasp.h"
+#include "c-upc-rts-names.h"
+
+static tree build_string_ref (const char *string);
+
+/* Build a reference to a literal string.
+   (cribbed from mf_build_string in tree-mudflap.c) */
+
+static tree
+build_string_ref (const char *string)
+{
+  size_t len = strlen (string);
+  tree result = build_string (len + 1, string);
+  TREE_TYPE (result) = build_array_type
+    (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
+  TREE_CONSTANT (result) = 1;
+  TREE_READONLY (result) = 1;
+  TREE_STATIC (result) = 1;
+  result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
+  return result;
+}
+
+/* Add source args to the argument list.  */
+
+tree
+upc_gasp_add_src_args (tree args, const char *filename, int lineno)
+{
+  return chainon (args,
+		  tree_cons (NULL_TREE, build_string_ref (filename),
+			     tree_cons (NULL_TREE,
+					build_int_cst (NULL_TREE, lineno),
+					NULL_TREE)));
+}
+
+/* Instrument `upc_forall' statement begin/end.
+   Return a call to the profiling function.  */
+
+tree
+upc_instrument_forall (location_t loc, int start)
+{
+  const char *filename = LOCATION_FILE (loc);
+  const int lineno = LOCATION_LINE (loc);
+  tree pfunc;
+
+  pfunc = lookup_name (get_identifier (UPC_INSTRUMENT_FORALL));
+  if (!pfunc)
+    internal_error ("UPC profiling function `%s' not found",
+		    UPC_INSTRUMENT_FORALL);
+
+  return build_call_expr (pfunc, 3,
+			  build_int_cst (NULL_TREE, start),
+			  build_string_ref (filename),
+			  build_int_cst (NULL_TREE, lineno));
+}
+
+/* If UPC function profiling has been enabled, rewrite the
+   body of FNDECL so that the GASP instrumentation function
+   is called before the body of the function is executed,
+   and then after it is executed (as a TRY_FINALLY_EXPR).  */
+
+void
+upc_instrument_func (tree fndecl)
+{
+  tree tf, x, pfunc, bind;
+  const char *filename, *funcname;
+  int lineno;
+
+  /* Skip, if profiling disabled via #pragma pupc.  */
+  if (!get_upc_pupc_mode ())
+    return;
+
+  pfunc = lookup_name (get_identifier (UPC_INSTRUMENT_FUNC));
+  if (!pfunc)
+    internal_error ("UPC profiling function `%s' not found",
+		    UPC_INSTRUMENT_FUNC);
+  funcname = "<unknown>";
+  if (DECL_NAME (fndecl))
+    funcname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
+  lineno = DECL_SOURCE_LINE (fndecl);
+  filename = DECL_SOURCE_FILE (fndecl);
+  tf = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
+  TREE_SIDE_EFFECTS (tf) = 1;
+  x = DECL_SAVED_TREE (fndecl);
+  append_to_statement_list (x, &TREE_OPERAND (tf, 0));
+  x = build_call_expr (pfunc, 4, integer_zero_node,	/* start == 0 */
+		       build_string_ref (funcname),
+		       build_string_ref (filename),
+		       build_int_cst (NULL_TREE, lineno));
+  append_to_statement_list (x, &TREE_OPERAND (tf, 1));
+
+  bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+  TREE_SIDE_EFFECTS (bind) = 1;
+  x = build_call_expr (pfunc, 4, integer_one_node,	/* start == 1 */
+		       build_string_ref (funcname),
+		       build_string_ref (filename),
+		       build_int_cst (NULL_TREE, lineno));
+  append_to_statement_list (x, &BIND_EXPR_BODY (bind));
+  append_to_statement_list (tf, &BIND_EXPR_BODY (bind));
+
+  DECL_SAVED_TREE (fndecl) = bind;
+
+}
Index: gcc/c/c-upc-gasp.h
===================================================================
--- gcc/c/c-upc-gasp.h	(.../trunk)	(revision 0)
+++ gcc/c/c-upc-gasp.h	(.../branches/gupc)	(revision 231080)
@@ -0,0 +1,32 @@ 
+/* c-upc-gasp.h: GASP instrumentation API.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_C_UPC_GASP_H
+#define GCC_C_UPC_GASP_H 1
+
+extern int disable_pupc_mode(void);
+extern int get_upc_pupc_mode(void);
+extern tree upc_gasp_add_src_args (tree, const char *, int);
+extern tree upc_instrument_forall (location_t, int);
+extern void set_pupc_mode(int);
+extern void upc_instrument_func (tree);
+
+#endif /* !GCC_C_UPC_GASP_H */
Index: gcc/c/c-upc.c
===================================================================
--- gcc/c/c-upc.c	(.../trunk)	(revision 0)
+++ gcc/c/c-upc.c	(.../branches/gupc)	(revision 231080)
@@ -0,0 +1,798 @@ 
+/* c-upc.c: implement UPC-related actions
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original implementation
+     by Jesse M. Draper <jdraper@super.org>
+     and William W. Carlson <wwc@super.org>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "c-family/c-common.h"
+#include "langhooks.h"
+#include "tree.h"
+#include "alias.h"
+#include "fold-const.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "output.h"
+#include "attribs.h"
+#include "target.h"
+#include "varasm.h"
+#include "c-upc.h"
+#include "c-family/c-upc-pts.h"
+#include "c-upc-pts-ops.h"
+#include "c-upc-rts-names.h"
+
+
+static int recursive_count_upc_threads_refs (tree);
+static int upc_sizeof_type_check (const char *, tree);
+
+
+/* Return a UPC pointer-to-shared type with target type, TO_TYPE.
+   If the UPC pointer-to-shared representation has a "register mode",
+   then build a pointer type with that mode.  If the UPC pointer-to-shared
+   representation type has BLKmode, then calculate its size based
+   upon the representation type.  */
+
+tree
+upc_build_pointer_type (tree to_type)
+{
+  machine_mode pointer_mode;
+  tree ptr_type;
+  if (to_type == NULL_TREE || TREE_CODE (to_type) == ERROR_MARK)
+    return error_mark_node;
+  pointer_mode = TYPE_MODE (upc_pts_rep_type_node);
+  ptr_type = build_pointer_type_for_mode (to_type, pointer_mode, false);
+  if (!integer_zerop (TYPE_SIZE (ptr_type)))
+    return ptr_type;
+  /* If the UPC pointer-to-shared representation has a size of zero,
+     then it must have BLKmode.  In that case, calculate the sizes
+     and alignment from the underlying representation type.  This
+     situation may arise when the 'struct PTS' representation is
+     configured on targets that do not assign TImode to aligned
+     128 bit structs.  */
+  gcc_assert (pointer_mode == BLKmode);
+  TYPE_SIZE (ptr_type)      = TYPE_SIZE (upc_pts_rep_type_node);
+  TYPE_SIZE_UNIT (ptr_type) = TYPE_SIZE_UNIT (upc_pts_rep_type_node);
+  TYPE_ALIGN (ptr_type)     = TYPE_ALIGN (upc_pts_rep_type_node);
+  TYPE_UNSIGNED (ptr_type)  = TYPE_UNSIGNED (upc_pts_rep_type_node);
+  TYPE_PRECISION (ptr_type) = TYPE_PRECISION (upc_pts_rep_type_node);
+  return ptr_type;
+}
+
+/* Check the type of the operand passed to a
+   upc_*sizeof () operator.
+   
+   The type must *not* be:
+   - an error mark node
+   - an incomplete type
+   - a function type
+   - a void type
+
+   The type *must* be a UPC 'shared' type.
+
+   UPC defines the following flavors of sizeof operators:
+   upc_blocksizeof, upc_elemsizeof, and upc_localsizeof.
+   These operations have similar syntax and constraints
+   as the "C" language sizeof operator.  */
+
+static int
+upc_sizeof_type_check (const char *op_name, tree type)
+{
+  enum tree_code code = TREE_CODE (type);
+  if (code == ERROR_MARK)
+    {
+      return 0;
+    }
+  else if (!COMPLETE_TYPE_P (type))
+    {
+      lang_hooks.types.incomplete_type_error (NULL_TREE, type);
+      return 0;
+    }
+  else if (code == FUNCTION_TYPE)
+    {
+      error ("UPC operator %s applied to a function type", op_name);
+      return 0;
+    }
+  else if (code == VOID_TYPE)
+    {
+      error ("UPC operator %s applied to a void type", op_name);
+      return 0;
+    }
+  else if (!SHARED_TYPE_P (type))
+    {
+      error ("UPC operator %s applied to a non-shared type", op_name);
+      return 0;
+    }
+  return 1;
+}
+
+/* Compute the value of the `upc_blocksizeof' operator.
+   The UPC block size is the value of UPC's "layout qualifier".
+   For example:
+
+   Declaration				upc_blocksizeof()
+   ----------- 				----------------
+   shared int A[5*THREADS];     	1 (default) 
+   shared [5] int A[5*THREADS];    	5
+   shared [] int A[5*100];      	0 (indefinite)
+   shared [*] int A[5*THREADS];     	5 (distributed by compiler) */
+
+tree
+upc_blocksizeof (location_t ARG_UNUSED (loc), tree type)
+{
+  tree block_factor = size_one_node;
+  if (!type || TREE_CODE (type) == ERROR_MARK)
+    return error_mark_node;
+  if (upc_sizeof_type_check ("upc_blocksizeof", type))
+    block_factor = get_block_factor (type);
+  return block_factor;
+}
+
+/* Compute the value of the `upc_elemsizeof' operator.  */
+
+tree
+upc_elemsizeof (location_t loc, tree type)
+{
+  tree elem_size;
+
+  if (!(type && upc_sizeof_type_check ("upc_elemsizeof", type)))
+    return size_int (1);
+  elem_size = c_sizeof (loc, strip_array_types (type));
+  return elem_size;
+}
+
+/* Compute the value of the `upc_localsizeof' operator.
+   Per the language spec:
+   The upc_localsizeof operator returns the size, in bytes, of the
+   local portion of its operand, which may be a shared object or a
+   shared-qualified type.  It returns the same value on all threads; the
+   value is an upper bound of the size allocated with affinity to any
+   single thread and may include an unspecified amount of padding.
+   The result of upc_localsizeof is an integer constant.  */
+
+tree
+upc_localsizeof (location_t loc, tree type)
+{
+  tree block_factor, local_size, total_size;
+
+  if (!(type && upc_sizeof_type_check ("upc_localsizeof", type)))
+    return size_one_node;
+
+  /* for scalars, return sizeof */
+
+  if (TREE_CODE (type) != ARRAY_TYPE)
+    return c_sizeof (loc, type);
+
+  block_factor = upc_blocksizeof (loc, type);
+  block_factor = convert (bitsizetype, block_factor);
+  total_size = TYPE_SIZE (type);
+
+  if (integer_zerop (block_factor))
+    {
+      /* local size is total size, because the entire
+         object lives on a single thread.  This is the
+	 case for declarations of types with an "indefinite"
+	 layout qualifier.  For example, given:
+	   shared [] int A[100];
+         the value returned for upc_localsizeof (A)
+	 will be: 100 * sizeof (int).  */
+      local_size = total_size;
+    }
+  else
+    {
+      tree elt_type, elt_size, n_elts;
+      tree t_factor, n_full_blocks;
+      tree n_full_blocks_per_thread, n_elts_in_full_blocks;
+      tree n_rem_elts, n_local_elts;
+      elt_type = strip_array_types (type);
+      if (!elt_type || TREE_CODE (elt_type) == ERROR_MARK)
+	return size_one_node;
+      elt_size = TYPE_SIZE (elt_type);
+      n_elts = size_binop (EXACT_DIV_EXPR, total_size, elt_size);
+      /* Use the worst case size, if compiling in a dynamic
+         threads environment.  The worst case size can
+         be derived by setting T_FACTOR to 1 in the calculations
+         that follow.  Otherwise T_FACTOR is equal to THREADS.  */
+      t_factor = flag_upc_threads ? upc_num_threads () : size_one_node;
+      t_factor = convert (bitsizetype, t_factor);
+      n_full_blocks = size_binop (FLOOR_DIV_EXPR, n_elts, block_factor);
+      n_full_blocks_per_thread = size_binop (FLOOR_DIV_EXPR,
+					     n_full_blocks, t_factor);
+      n_elts_in_full_blocks = size_binop (MULT_EXPR,
+					  size_binop (MULT_EXPR,
+					       n_full_blocks_per_thread,
+					       t_factor),
+					  block_factor);
+      n_rem_elts = size_binop (MINUS_EXPR, n_elts, n_elts_in_full_blocks);
+      n_local_elts = size_binop (MULT_EXPR,
+				 n_full_blocks_per_thread, block_factor);
+      /* If any elements remain, add a full block size.  */
+      if (!integer_zerop (n_rem_elts))
+	n_local_elts = size_binop (PLUS_EXPR, n_local_elts, block_factor);
+      local_size = size_binop (MULT_EXPR, n_local_elts, elt_size);
+    }
+
+  /* Convert local size into bytes, and return result.  */
+
+  local_size = convert (sizetype, local_size);
+  local_size = size_binop (CEIL_DIV_EXPR, local_size,
+			   size_int (BITS_PER_UNIT));
+  return local_size;
+}
+
+/* Traverse the expression and return the number of times
+   THREADS is referenced.  This is used to check the restriction
+   on UPC shared array declarations, that the predefined THREADS
+   variable can be mentioned only once.  */
+
+static int
+recursive_count_upc_threads_refs (tree expr)
+{
+  enum tree_code code;
+  int i;
+  int count = 0;
+  if (expr == NULL_TREE)
+    return 0;
+  code = TREE_CODE (expr);
+  switch (TREE_CODE_CLASS (code))
+    {
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_statement:
+      for (i = 0; i < TREE_CODE_LENGTH (code); i++)
+	count += recursive_count_upc_threads_refs (TREE_OPERAND (expr, i));
+      break;
+    case tcc_declaration:
+      if (expr == lookup_name (get_identifier ("THREADS")))
+	count = 1;
+      break;
+    default:
+      break;
+    }
+  return count;
+}
+
+/* Count the number of references to THREADS inside `expr'.  */
+
+int
+count_upc_threads_refs (tree expr)
+{
+  return recursive_count_upc_threads_refs (expr);
+}
+
+/* Test that EXPR is an expression tree where THREADS appears on
+   the left or the right hand side of a multiply, in a series
+   of zero or more multiplies.  For proper operation, the caller
+   should ensure that THREADS is referenced only once,
+   by calling count_upc_threads_refs () prior to calling this routine.  */
+
+int
+is_multiple_of_upc_threads (tree expr)
+{
+  enum tree_code code;
+  if (expr == NULL_TREE)
+    return 0;
+  if (expr == lookup_name (get_identifier ("THREADS")))
+    return 1;
+  code = TREE_CODE (expr);
+  if (code == MULT_EXPR)
+    return is_multiple_of_upc_threads (TREE_OPERAND (expr, 0))
+      | is_multiple_of_upc_threads (TREE_OPERAND (expr, 1));
+  if ((code == NOP_EXPR) || (code == NON_LVALUE_EXPR)
+      || (code == CONVERT_EXPR))
+    return is_multiple_of_upc_threads (TREE_OPERAND (expr, 0));
+  return 0;
+}
+
+/* Find all references to THREADS and change them into the constant `1'.
+   This is done so that fold () when applied to the dimension of a
+   UPC shared array will yield the local size of the array.  */
+
+void
+set_upc_threads_refs_to_one (tree *expr)
+{
+  enum tree_code code;
+  int i;
+  if (*expr == NULL_TREE)
+    return;
+  code = TREE_CODE (*expr);
+  switch (TREE_CODE_CLASS (code))
+    {
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_statement:
+      for (i = 0; i < TREE_CODE_LENGTH (code); i++)
+	set_upc_threads_refs_to_one (&TREE_OPERAND (*expr, i));
+      break;
+    case tcc_declaration:
+      if (*expr == lookup_name (get_identifier ("THREADS")))
+	*expr = integer_one_node;
+      break;
+    default:
+      break;
+    }
+  return;
+}
+
+/* As part of declaration processing, for a particular kind
+   of declaration, DECL_KIND, and a given LAYOUT_QUALIFIER, calculate
+   the resulting blocking factor and return it.  Issue an error
+   diagnostic if the LAYOUT_QUALIFIER specification is invalid.
+   For array types, the TYPE parameter may be the MAIN_VARIANT,
+   and not shared qualified; in that case - ELEM_BLOCK_FACTOR
+   is the blocking factor derived from the original element type.
+   If LAYOUT_QUALIFIER is NULL and ELEM_BLOCK_FACTOR is non-null,
+   then the ELEM_BLOCK_FACTOR will be used.  This situation occurs
+   when the element type is a typedef, for example.  If both
+   LAYOUT_QUALIFIER and ELEM_BLOCK_FACTOR are non-NULL, then they
+   must be equal.  */
+
+tree
+upc_grok_layout_qualifier (location_t loc, const enum tree_code decl_kind,
+	                   tree type, tree elem_block_factor,
+			   tree layout_qualifier)
+{
+  tree block_factor = NULL_TREE;
+
+  if (!type || (TREE_CODE (type) == ERROR_MARK))
+    return error_mark_node;
+
+  if (TREE_CODE (type) == VOID_TYPE)
+    {
+      error_at (loc, "UPC layout qualifier cannot be applied to a void type");
+      return NULL_TREE;
+    }
+
+  /* If no explicit layout qualifier was supplied, then
+     use the blocking factor derived from the element type.  */
+  if (!layout_qualifier && elem_block_factor)
+    return elem_block_factor;
+
+  /* The layout qualifier is given as the subscript operand
+     of an array ref.  */
+  gcc_assert (layout_qualifier);
+  gcc_assert (TREE_CODE (layout_qualifier) == ARRAY_REF);
+  layout_qualifier = TREE_OPERAND (layout_qualifier, 1);
+
+  if (layout_qualifier == NULL_TREE)
+    {
+      /* The layout qualifier is [], which is
+         equivalent to specifying [0].  */
+      block_factor = size_zero_node;
+    }
+  else if ((TREE_CODE (layout_qualifier) == INDIRECT_REF)
+	   && ((TREE_OPERAND (layout_qualifier, 0)) == NULL_TREE))
+    {
+      tree elt_size, elt_type, n_threads;
+      /* The layout qualifier is [*].  The compiler must calculate
+         a blocking factor that evenly distributes the array's
+	 elements over all the UPC threads.  */
+      if (!COMPLETE_TYPE_P (type))
+	{
+	  error_at (loc, "UPC layout qualifier of the form [*] cannot be "
+	                 "applied to an incomplete type");
+	  return NULL_TREE;
+	}
+      if (decl_kind == POINTER_TYPE)
+	{
+	  error_at (loc, "UPC [*] qualifier may not be used in "
+	                 "declaration of pointers");
+	  return NULL_TREE;
+	}
+      /* The blocking factor is given by this expression:
+         (sizeof (a) / upc_elemsizeof (a) + (THREADS - 1)) / THREADS,
+         where 'a' is the array being distributed.  */
+      elt_type = strip_array_types (type);
+      elt_size = TYPE_SIZE (elt_type);
+      if (TYPE_HAS_THREADS_FACTOR (type))
+	block_factor =
+	  size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type), elt_size);
+      else
+	{
+	  n_threads = convert (bitsizetype, upc_num_threads ());
+	  if (TREE_CODE (n_threads) != INTEGER_CST)
+	    {
+	      error_at (loc, "a UPC layout qualifier of '[*]' requires that "
+		             "the array size is either an integral constant "
+		             "or an integral multiple of THREADS");
+	      block_factor = size_one_node;
+	    }
+	  else
+	    {
+	      block_factor = size_binop (CEIL_DIV_EXPR,
+				 size_binop (FLOOR_DIV_EXPR,
+					     TYPE_SIZE (type),
+					     elt_size),
+				 n_threads);
+	    }
+	}
+    }
+  else
+    {
+      STRIP_NOPS (layout_qualifier);
+      if (TREE_CODE (layout_qualifier) != INTEGER_CST)
+        {
+	  error_at (loc, "UPC layout qualifier is not an integral constant");
+          block_factor = size_one_node;
+	}
+      else if (tree_to_shwi (layout_qualifier) < 0)
+        {
+	  error_at (loc, "UPC layout qualifier must be a non-negative "
+	                 "integral constant");
+          block_factor = size_one_node;
+	}
+      else
+	block_factor = fold (layout_qualifier);
+    }
+
+  if (TREE_OVERFLOW_P (block_factor)
+      || tree_to_shwi (block_factor) > UPC_MAX_BLOCK_SIZE)
+    {
+      error_at (loc, "the maximum UPC block size in this implementation "
+                     "is %ld", (long int) UPC_MAX_BLOCK_SIZE);
+      return NULL_TREE;
+    }
+
+  if (tree_int_cst_compare (block_factor, integer_zero_node) < 0)
+    {
+      error_at (loc, "UPC layout qualifier must be a "
+                     "non-negative integral constant");
+      return NULL_TREE;
+    }
+
+  /* Make sure that the UPC blocking factors are of type
+     'size_t' so that a compare of the tree pointers
+     is sufficient to match block sizes.  */
+  if (block_factor)
+    block_factor = convert (sizetype, block_factor);
+
+  if ((block_factor && elem_block_factor)
+      && block_factor != elem_block_factor)
+    {
+       error_at (loc, "UPC layout qualifier is incompatible with "
+		      "the referenced type");
+       return elem_block_factor;
+    }
+
+  /* A block size of [1] is the same as specifying no
+     block size at all.  */
+  if (block_factor == size_one_node)
+    block_factor = NULL_TREE;
+
+  return block_factor;
+}
+
+/* If DECL is a UPC shared variable, make sure that it ends up
+   in the executable file.  */
+
+void
+upc_check_decl (tree decl)
+{
+  if (decl
+      && TREE_CODE (decl) == VAR_DECL
+      && TREE_TYPE (decl) && SHARED_TYPE_P (TREE_TYPE (decl)))
+    {
+      TREE_USED (decl) = 1;
+      TREE_ADDRESSABLE (decl) = 1;
+      TREE_STATIC (decl) = 1;
+      /* Work-around a problem where the front-end doesn't
+         properly process the used flags set above, on
+         static variables when flag_unit_at_a_time isn't set.  */
+      if ((TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+	  && !flag_unit_at_a_time
+	  && !lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+	{
+	  tree used_id = get_identifier ("used");
+	  tree used_attrib = tree_cons (used_id, NULL_TREE, NULL_TREE);
+	  decl_attributes (&decl, used_attrib, 0);
+	}
+    }
+}
+
+/* Return TRUE if TYPE contains any references to UPC pointers-to-shared.  */
+
+int
+upc_contains_pts_refs_p (tree type)
+{
+  switch (TREE_CODE (type))
+    {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      return SHARED_TYPE_P (TREE_TYPE (type));
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      {
+	tree fields;
+	/* For a type that has fields, see if the fields have pointers.  */
+	for (fields = TYPE_FIELDS (type); fields;
+	     fields = TREE_CHAIN (fields))
+	  if (TREE_CODE (fields) == FIELD_DECL
+	      && upc_contains_pts_refs_p (TREE_TYPE (fields)))
+	    return 1;
+	return 0;
+      }
+
+    case ARRAY_TYPE:
+      /* An array type contains pointers if its element type does.  */
+      return upc_contains_pts_refs_p (TREE_TYPE (type));
+
+    default:
+      return 0;
+    }
+}
+
+/* Assign DECL to a specific linker section, if required.
+   UPC 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.  */
+
+void
+upc_set_decl_section (tree decl)
+{
+  if (TREE_SHARED (decl)
+      && targetm.upc.shared_section_name ())
+    {
+      /* UPC shared variables are placed in their own shared section */
+      set_decl_section_name (decl, targetm.upc.shared_section_name ());
+    }
+  else if (flag_upc_pthreads
+	   && ((TREE_STATIC (decl)
+	        && (DECL_SECTION_NAME (decl) == NULL))
+	            || DECL_EXTERNAL (decl)))
+    {
+      /* If we're compiling with -fupc-pthreads-model-tls asserted
+         and this is a regular "C" static scoped object which
+         is either not declared in a system header file,
+         or is being compiled in a UPC setting,
+         then assign the object to the thread local storage
+	 (TLS) section.  */
+      if (flag_upc && (c_header_level <= 0))
+	{
+	  if (upc_pthreads_model == upc_pthreads_tls_model)
+	    {
+	      set_decl_tls_model (decl, decl_default_tls_model (decl));
+	      DECL_COMMON (decl) = 0;
+	    }
+	  else
+	    /* Only the TLS model is currently implemented.  */
+	    gcc_unreachable ();
+	}
+    }
+}
+
+/* Return an external reference to an integer variable maintained
+   by the compiler and runtime to track the dynamic nesting
+   of 'upc_forall' statements.  The variable's name is given by
+   UPC_FORALL_DEPTH_NAME.  */
+
+tree
+upc_rts_forall_depth_var (void)
+{
+  tree upc_forall_depth = lookup_name (
+                                  get_identifier (UPC_FORALL_DEPTH_NAME));
+  if (upc_forall_depth == NULL_TREE)
+    internal_error ("the UPC runtime variable '" UPC_FORALL_DEPTH_NAME "' "
+		    "cannot be located; this variable should be defined "
+		    "in a compiler-supplied include file");
+  assemble_external (upc_forall_depth);
+  TREE_USED (upc_forall_depth) = 1;
+  return upc_forall_depth;
+}
+
+/* Diagnose instances of UPC statements that were
+   defined in very early UPC language specifications and that
+   have since been deprecated.  */
+
+int
+upc_diagnose_deprecated_stmt (location_t loc, tree id)
+{
+  const char *name = IDENTIFIER_POINTER (id);
+  struct deprecated_stmt_entry
+  {
+    const char *deprecated_id;
+    const char *correct_id;
+  };
+  static const struct deprecated_stmt_entry deprecated_stmts[] =
+    { {"barrier", "upc_barrier"},
+      {"barrier_wait", "upc_wait"},
+      {"barrier_notify", "upc_notify"},
+      {"fence", "upc_fence"},
+      {"forall", "upc_forall"} };
+  const int n_deprecated_stmts = sizeof (deprecated_stmts)
+    / sizeof (struct deprecated_stmt_entry);
+  int i;
+  for (i = 0; i < n_deprecated_stmts; ++i)
+    {
+      if (!strcmp (name, deprecated_stmts[i].deprecated_id))
+	{
+	  error_at (loc, "%qs was supported in version 1.0 of the UPC "
+		    "specification, it has been deprecated, "
+		    "use %qs instead",
+		    name, deprecated_stmts[i].correct_id);
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+/* Expand the pre/post increment/decrement of UPC pointer-to-shared
+   into its equivalent expression tree.  */
+
+tree
+upc_pts_increment (location_t location ATTRIBUTE_UNUSED,
+		   enum tree_code code, tree arg)
+{
+  /* The result type is a pointer of the same type as the argument
+     type after dropping the shared qualifier (for PTS's that happen
+     to live in shared memory).  */
+  tree stable_arg = stabilize_reference (arg);
+  tree val = (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+    ? stable_arg : save_expr (stable_arg);
+  enum tree_code incr_op = (code == PREINCREMENT_EXPR
+			    || code == POSTINCREMENT_EXPR)
+    ? PLUS_EXPR : MINUS_EXPR;
+  tree incr_val, result;
+  incr_val = upc_pts_int_sum (location, incr_op, val, integer_one_node);
+  TREE_SIDE_EFFECTS (incr_val) = 1;
+  result = build_modify_expr (location, arg, NULL_TREE, NOP_EXPR,
+			      location, incr_val, NULL_TREE);
+  if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+    result = build2 (COMPOUND_EXPR, TREE_TYPE (incr_val), result, val);
+  return result;
+}
+
+/* Return an expression that calculates the sum of a UPC
+   pointer-to-shared value and an integer value.  The sum
+   operator may be PLUS_EXPR or MINUS_EXPR.  The result is a
+   POINTER_PLUS_EXPR with a properly scaled integer operand.
+   This POINTER_PLUS_EXPR will be translated by the UPC lowering
+   pass into the sequence of operations dictated both by the
+   properties of the UPC pointer-to-shared type, and the UPC
+   pointer-to-shared representation.  */
+
+tree
+upc_pts_int_sum (location_t loc,
+		 enum tree_code resultcode, tree ptrop, tree intop)
+{
+
+  /* The result type is a pointer of the same type that is being added,
+     after dropping the UPC shared qualifier.  For example, this would
+     apply to UPC pointers-to-shared that happen to live in shared memory;
+     the result of the expression must not be UPC shared qualified.  */
+
+  const tree ttype = TREE_TYPE (ptrop);
+  const int shared_quals =
+    (TYPE_QUAL_SHARED | TYPE_QUAL_STRICT | TYPE_QUAL_RELAXED);
+  const int quals_minus_shared = TYPE_QUALS (ttype) & ~shared_quals;
+  const tree result_type = c_build_qualified_type (ttype, quals_minus_shared);
+  const tree result_targ_type = TREE_TYPE (result_type);
+  const tree base_type = strip_array_types (result_targ_type);
+  tree result;
+
+  if (TREE_CODE (result_targ_type) == VOID_TYPE)
+    error_at (loc, "UPC does not allow a pointer of type %<shared void *%> "
+	      "to be used in arithmetic");
+
+  /* We have a pointer to a UPC shared object.  For pointers to
+     simple objects, just build a "resultcode" tree with the intop and
+     let upc_genericize() handle the arithmetic correctly.  For pointers to
+     arrays, compute the number of elements represented by the intop
+     and build a "resultcode" tree with the ptrop and that number.  */
+
+  if (result_targ_type != base_type)
+    {
+      tree elt_cnt;
+      gcc_assert (TREE_CODE (result_targ_type) == ARRAY_TYPE);
+      if (TREE_CODE (TYPE_SIZE (result_targ_type)) == INTEGER_CST)
+	{
+	  tree n_threads = convert (sizetype, upc_num_threads ());
+	  int size = TREE_INT_CST_LOW (TYPE_SIZE (result_targ_type));
+	  int elt_size = TREE_INT_CST_LOW (TYPE_SIZE (base_type));
+	  elt_cnt = size_int (size / elt_size);
+	  if (TYPE_HAS_THREADS_FACTOR (result_targ_type))
+	    elt_cnt = size_binop (MULT_EXPR, n_threads, elt_cnt);
+	}
+      else
+	{
+	  tree size = TYPE_SIZE (result_targ_type);
+	  tree elt_size = TYPE_SIZE (base_type);
+	  elt_cnt = build2 (EXACT_DIV_EXPR, sizetype, size, elt_size);
+	}
+      intop = convert (sizetype, intop);
+      intop = size_binop (MULT_EXPR, intop, elt_cnt);
+    }
+  gcc_assert (resultcode == PLUS_EXPR || resultcode == MINUS_EXPR);
+  if (resultcode == MINUS_EXPR)
+    intop = build1 (NEGATE_EXPR, TREE_TYPE (intop), intop);
+  intop = fold (intop);
+
+  /* POINTER_PLUS expects the operand to be sizetype, which
+     is potentially unsigned.  This will have to be dealt
+     with later, when expanding the UPC pointer-to-shared arithmetic.  */
+
+  intop = convert (sizetype, intop);
+  result = build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
+
+  /* Although there may be some specific cases where the
+     addition of a constant integer to a UPC pointer-to-shared can
+     be calculated at compile-time, in the more general
+     cases the calculation must be made at runtime, so
+     we mark the resulting sum as non-constant.  This will
+     avoid situations where the compiler attempts to convert
+     things like &A[14] where A is a shared array into a
+     compile-time constant.  */
+
+  TREE_CONSTANT (result) = 0;
+  return result;
+}
+
+/* Return an expression that calculates the difference between
+   two UPC pointers-to-shared values.  */
+
+tree
+upc_pts_diff (tree op0, tree op1)
+{
+  const tree target_type = TREE_TYPE (TREE_TYPE (op0));
+  tree result;
+
+  /* The two pointers must both point to shared objects.  */
+
+  if ((SHARED_TYPE_P (target_type)
+       && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (op1))))
+      || (SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))
+	  && !SHARED_TYPE_P (target_type)))
+    {
+      error ("attempt to take the difference of a UPC pointer-to-shared "
+	     "and a local pointer");
+      return size_one_node;
+    }
+  result = build2 (MINUS_EXPR, ptrdiff_type_node, op0, op1);
+  return result;
+}
+
+/* Return TRUE if EXP is a null UPC pointer-to-shared value.
+   (Call the representation-specific hook routine to
+   perform the check.)  */
+
+int
+upc_is_null_pts_p (tree exp)
+{
+  return upc_pts_is_null_p (exp);
+}
+
+/* Return TRUE if the type of EXP is a UPC pointer-to-shared type.  */
+
+int
+upc_pts_is_valid_p (tree exp)
+{
+  tree type = TREE_TYPE (exp);
+  return (TREE_CODE (type) == POINTER_TYPE)
+    && SHARED_TYPE_P (TREE_TYPE (type));
+}
Index: gcc/c/c-upc.h
===================================================================
--- gcc/c/c-upc.h	(.../trunk)	(revision 0)
+++ gcc/c/c-upc.h	(.../branches/gupc)	(revision 231080)
@@ -0,0 +1,50 @@ 
+/* Definitions of UPC front-end entry points used for C and C++.
+   that are called from within the C front end.
+   respectively.
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#ifndef GCC_C_UPC_H
+#define GCC_C_UPC_H
+
+/* UPC-related functions called by the C front-end.  */
+
+extern int count_upc_threads_refs (tree);
+extern int is_multiple_of_upc_threads (tree);
+extern void set_upc_threads_refs_to_one (tree *);
+extern tree upc_build_pointer_type (tree);
+extern tree upc_blocksizeof (location_t, tree);
+extern void upc_check_decl (tree);
+extern int upc_contains_pts_refs_p (tree);
+extern int upc_diagnose_deprecated_stmt (location_t, tree);
+extern tree upc_elemsizeof (location_t, tree);
+extern tree upc_grok_layout_qualifier (location_t, enum tree_code,
+				       tree, tree, tree);
+extern int upc_is_null_pts_p (tree);
+extern tree upc_localsizeof (location_t, tree);
+extern tree upc_pts_diff (tree, tree);
+extern tree upc_pts_increment (location_t, enum tree_code, tree);
+extern tree upc_pts_int_sum (location_t, enum tree_code, tree, tree);
+extern int upc_pts_is_valid_p (tree);
+extern tree upc_rts_forall_depth_var (void);
+extern void upc_set_decl_section (tree);
+
+#endif /* ! GCC_C_UPC_H */