Clarify interaction of shared with effective type for accesses

Issue #110 new
Former user created an issue

Originally reported on Google Code with ID 110

In the process of researching some related issues, I discovered a small but significant
"hole" in UPC's current type system. In a nutshell:

  shared int x;
  int main() {
    if (MYTHREAD == 0) {
      int *p = (int *)&x;
      *p = *p + 1; // permitted?
    }
    return 0;
  }

I suspect everyone agrees this should be permitted, and I believe that all current
implementations consider this fully correct and permissible.
The problem is that by a careful reading of C99 6.5, these accesses are prohibited:

6.5-6
  The effective type of an object for an access to its stored value is the declared
type of the
  object, if any

=> This implies the "effective" type of x is (shared int)

6.5-7
  An object shall have its stored value accessed only by an lvalue expression that
has one of
  the following types:
  ..
  - a type compatible with the effective type of the object,  
  - a qualified version of a type compatible with the effective type of the object,

=> This access falls under the first case, which requires the type of *p to be compatible
with the "effective" type of x which is (shared int). 
   But the type of *p is (int).

6.2.7
  Two types have compatible type if their types are the same. Additional rules for
  determining whether two types are compatible are described in 6.7.2 for type specifiers,
  in 6.7.3 for type qualifiers, and in 6.7.5 for declarators.46
6.7.3-9
  For two qualified types to be compatible, both shall have the identically qualified
version
  of a compatible type; the order of type qualifiers within a list of specifiers or
qualifiers
  does not affect the specified type.

=> This implies that (shared int) and (int) are not compatible types.

This problem has existed since the inception of UPC. It basically arises because we
define shared as a type qualifier for syntactic convenience, whereas semantically it's
really more of a storage-class specifier. Because shared is defined as a qualifier,
it inherits the C99 details of how qualifiers affect type compatibility, and the resulting
impact on access restrictions. In the case of the C99 qualifiers (const, restrict,
volatile), these restrictions "make sense" and prohibit illegal accesses that attempt
to bypass qualifiers. But in the case of "shared", the resulting restriction is "too
strong" and prohibits accesses that we wish to permit.

The same issue also affects code like the following:

   shared [10] int A[10*THREADS];
   shared [] int *q = (shared [] int *)&(A[0]);
   *q = *q + 1;

The effective type of A[0] here is (shared [10] int), and the type of the lvalue *q
is (shared [] int).   
However by UPC 6.5.1.1-13: The block size is a part of the type compatibility
So the access is also prohibited by C99 6.5-7.

In general, the shared qualifier still needs to be a part of type compatibility (especially
as related to compatibility of pointers). However I believe we need to clarify how
shared interacts with the access restriction in 6.5-7. 

Initial proposal: 
---------------------------------------
Add a new paragraph to UPC 6.5.1.1 Semantics:

    The {\it effective type} of a shared object is the type as determined
    by [ISO/IEC00 Sec. 6.5], with the shared qualifier removed.
    \footnote{For example, in this declaration:
                 shared [10] int A[10*THREADS];
     The effective type of the object A[0] is "int".
     This implies the following lvalue expressions are all permitted for accessing
the object:
                 int x1 = A[0];
                 int x2 = *(int *)&(A[0]); // valid only for MYTHREAD==0
                 int x3 = *(shared [] int *)&(A[0]); 
    }
---------------------------------------

This fixes the problem by removing the shared qualifier from the effective type of
a shared object being accessed. Consequently, C99 6.5-7 will allow access via an lvalue
expression that either lacks a shared qualifier, or has a shared qualifier with any
blocksize.

I don't know whether this belongs in 1.3 or a later revision, but either way I believe
it should have NO impact on existing implementations or applications. We're just clarifying
the spec details to reflect the implicit understanding that I believe we've had all
along. 

Reported by danbonachea on 2013-03-15 12:51:09

Comments (6)

  1. Former user Account Deleted
    This issue adds a worthwhile clarification to the specification.  We have seen some
    of these type compatibility questions come up in our discussions.  The point that a
    case might be made that "shared" as used in variable declarations might better match
    aspects of a "storage specifier" in the C language is a good one, though clearly out
    of scope because it would create incompatibilities with the current UPC language definition.
    
    Given that the issue clarifications noted in this issue "should have NO impact on existing
    implementations or applications" (as Dan states), I recommend that this issue be deferred
    to Spec. version 1.4.  There are already several other clarifications to the definition
    and use of layout qualifiers that have been deferred to 1.4 for example.
    

    Reported by gary.funck on 2013-03-15 15:47:55

  2. Former user Account Deleted
    Below is an actual Latex diff proposal. 
    This version also clarifies that the top-level shared qualifier is the one removed
    when computing the effective type. 
    Specifically, for a "tricky" object like:
       shared int * shared p;
    the effective type of p is (shared int *).
    
    --- upc-language.tex    (revision 204)
    +++ upc-language.tex    (working copy)
    @@ -559,6 +568,21 @@
    
     \np For purposes of assignment compatibility, generic pointers-to-shared
         behave as if they always have a compatible block size.
    +
    +\np \xadded[id=DB]{110}{
    +    The {\it effective type} of a shared object 
    +    is the type as determined by [ISO/IEC00 Sec. 6.5], 
    +    with the top-level (rightmost) shared qualifier removed.%
    +      \truefootnote{For example, in the file-scope declaration {\tt shared [10] int
    A[10*THREADS];}
    +       the effective type of the object {\tt A[0]} is {\tt int}.
    +       This implies the following lvalue expressions are all permitted for accessing
    the object:
    +       \begin{quote}
    +       {\tt int x1 = A[0];}\\
    +       {\tt int x2 = *(int *)\&(A[0]); // valid only for MYTHREAD==0}\\
    +       {\tt int x3 = *(shared [] int *)\&(A[0]); }
    +       \end{quote}
    +    }
    +    }
    
     \np If the layout qualifier is of the form `{\bf [ * ]}',
         the shared object is distributed as if it had a block size of
    

    Reported by danbonachea on 2013-03-15 17:45:31

  3. Former user Account Deleted
    > Given that the issue clarifications noted in this issue "should have NO impact on
    existing 
    > implementations or applications" (as Dan states), I recommend that this issue be
    deferred to Spec. 
    > version 1.4.  There are already several other clarifications to the definition and
    use of 
    > layout qualifiers that have been deferred to 1.4 for example.
    
    It's worth noting that while it has "no impact" on existing applications, most non-trivial
    applications are nonetheless very heavily reliant upon the implicit understanding of
    the core concept being clarified here. This is in contrast to issues like issue 69
    which are merely a corner case of the type system where we can get away with saying
    "just don't do that" because the ambiguity is easily avoided in user code. One can
    make a convincing case that without this clarification, most real UPC applications
    are relying upon undefined behavior.
    

    Reported by danbonachea on 2013-03-15 17:49:38 - Labels added: Priority-Critical - Labels removed: Priority-High

  4. Former user Account Deleted
    In the 3/15/13 telecon, we decided that we should try to resolve this issue in spec
    1.3.
    
    Official change proposal mailed 3/15/13:
    
    Proposed Change:
    -------------------------
    --- upc-language.tex    (revision 204)
    +++ upc-language.tex    (working copy)
    @@ -559,6 +568,22 @@
    
     \np For purposes of assignment compatibility, generic pointers-to-shared
         behave as if they always have a compatible block size.
    +
    +\np \xadded[id=DB]{110}{
    +    The {\it effective type} of a shared object
    +    is the type as determined by [ISO/IEC00 Sec. 6.5],
    +    with the top-level (rightmost) shared qualifier removed.%
    +      \truefootnote{For example, in the file-scope declaration {\tt shared [10] int
    A[10*THREADS];}
    +       the effective type of the object {\tt A[0]} is {\tt int}.
    +       This implies the following lvalue expressions are all permitted for accessing
    the object:
    +       % DOB: would like to use verbatim environment here, but Latex does not allow
    it in a footnote
    +       \begin{quote}
    +       {\tt int x1 = A[0];}\\
    +       {\tt int x2 = *(int *)\&(A[0]); // valid only for MYTHREAD==0}\\
    +       {\tt int x3 = *(shared [] int *)\&(A[0]); }
    +       \end{quote}
    +    }
    +    }
    
     \np If the layout qualifier is of the form `{\bf [ * ]}',
         the shared object is distributed as if it had a block size of
    

    Reported by danbonachea on 2013-03-16 01:31:49 - Status changed: PendingApproval

  5. Former user Account Deleted
    Committed as SVN r212
    

    Reported by danbonachea on 2013-04-30 18:34:45 - Status changed: Fixed

  6. Former user Account Deleted
    Ratified in the 5/22 telecon.
    

    Reported by danbonachea on 2013-08-03 03:55:37 - Status changed: Ratified

  7. Log in to comment