Patchwork RFC: Merge the GUPC branch into the GCC 4.8 trunk (patch 02 of 16)

login
register
mail settings
Submitter Gary Funck
Date Oct. 15, 2012, 10:05 p.m.
Message ID <20121015220555.GG18153@intrepid.com>
Download mbox | patch
Permalink /patch/191673/
State New
Headers show

Comments

Gary Funck - Oct. 15, 2012, 10:05 p.m.
Attached, patch 02 of 16.

This patch set lists the small set of changes required
in the C++ and Objective C front-end to accommodate
changes needed for UPC.

gcc/c/c-decl.c is also included here, to illustrate
both the UPC front-end changes and to motivate the introduction of
c_build_qualified_type_1() which accepts an additional argument
which is the "layout qualifier" (blocking factor) that is unique to UPC.

- Gary
Other Languages (patch 02 of 16)
--------------------------------

    gcc/cp/lex.c
    gcc/cp/tree.c
    gcc/c/c-decl.c
    gcc/c/c-objc-common.h
Joseph S. Myers - Oct. 15, 2012, 10:22 p.m.
On Mon, 15 Oct 2012, Gary Funck wrote:

> Attached, patch 02 of 16.
> 
> This patch set lists the small set of changes required
> in the C++ and Objective C front-end to accommodate
> changes needed for UPC.
> 
> gcc/c/c-decl.c is also included here, to illustrate
> both the UPC front-end changes and to motivate the introduction of
> c_build_qualified_type_1() which accepts an additional argument
> which is the "layout qualifier" (blocking factor) that is unique to UPC.

Please go back to my previous comments, then post a full patch series 
*once those issues are addressed*.  Each submission needs ChangeLog 
entries and more detailed descriptions / rationale.  For example, explain 
why a lang hook change is made in c-objc-common.h.  Make sure that you 
consistently use error_at, not error, for new diagnostics, or explain in 
your rationale why a location isn't readily available.  Make sure that 
source lines do not go over 80 columns.  There are at least some other 
coding standards issues; some visible at a glance are the comment /* for 
static declarations of shared arrays */ (start with a capital letter, end 
with '.', actually say what the semantics of this variable's value are if 
it needs a comment) and a missing space in TREE_CODE(decl).

Avoid any diff lines that are solely changing trailing whitespace (you 
have at least once diff hunk in c-decl.c that appears to do nothing but 
add such whitespace).  Some indentation also looks suspicious - look at 
the @@ -8859,6 +9048,23 @@ declspecs_add_qual hunk, for example, where 
inconsistent indentation reveals that you are indenting with spaces in 
some places, except for one line using a TAB (all new lines should be 
indented with TABs for every 8 spaces).

Patch

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