UPC pointers-to-shared arithmetics

Issue #11 new
Former user created an issue

Originally reported on Google Code with ID 11 ``` 1) Is arithmetic on (void *) and (shared void *) an error? Some implementations of UPC currently define arithmetic on (shared void *) as erroneous. BUPC thinks it is ... and GCC/UPC has now followed suit, but what does C99 say?

2) Is conversion from a pointer−to−shared to an integer allowed? BUPC thinks it is and does something, GCC/UPC issues an error. If it is defined in the language, what is the definition? (Note that on 32−bit targets, a shared pointer might be 64 bits, and 128 bits on a 64−bit target.)

```

Reported by `yzheng@lbl.gov` on 2012-04-29 01:20:59

Comments (9)

  1. Former user Account Deleted

    ``` To try to address (1), here are a few excerpts from the C99 Standard:

    6.5.6.1: For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)

    6.2.5.1: [...] Types are partitioned into object types (types that fully describe objects), function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).

    6.2.5.19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

    From these three, it would seem that addition on (void *) is not defined in C99. For reference, the C11 wording is slightly different, but effectively the same. ```

    Reported by `nspark.work` on 2012-05-03 20:52:13

  2. Former user Account Deleted

    ``` 1) Note that while the standard doesn't define it, nearly every C compiler has an extension to support void pointer arithmetic with semantics equivalent to char pointer arithmetic, as it is very popular. Perhaps a notice in the standard that states that it is undefined, with a note to implementers that treating it as a (shared) char * is a common extension that should be supported if possible?

    2) See 6.3.2.3 paragraph 6:

    "Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type."

    From this, I conclude it should always be allowed, but the results are at best implementation defined--and then only if the implementation-defined integer value for the pointer fits in the range of the integer the programmer is trying to stuff it into. Otherwise the behavior of the resulting program is undefined. ```

    Reported by `sdvormwa@cray.com` on 2012-05-11 16:55:12

  3. Former user Account Deleted

    ``` On (1), I think it's important that a standard define the rules for writing portable programs. Anyone who is relying on void* arithmetic is writing nonportable programs. For an implementation like BUPC that can use different back-end compilers, the ability to support this as an extension might even depend on which compiler is being used as the back-end.

    On (2), does this overlap with the rules of when it's valid to cast shared to local? If the shared pointer is a pointer to local shared data, one can cast away the shared qualifier and then cast the local pointer to an integer. Seems like this case has a good definition. The other case could be either undefined or erroneous if we interpret it as casting a shared pointer that is non-local to a local pointer. ```

    Reported by `james.dinan` on 2012-05-11 18:42:48

  4. Former user Account Deleted

    ``` 1) I agree w/ Jim's point that the UPC spec says what correct/portable programs do and isn't required to call out what happens with non-portable code. So, I vote that the compilers that want to do PTS arithmetic as if sizeof(void)==1 may continue to do so, but that the UPC spec should leave this behavior unspecified. Warnings from the void-has-size-1 compilers about the non-portable construct would be nice, but the UPC spec should not require such a diagnostic.

    2) Steven's quotation of 6.3.2.3 paragraph 6 seems conclusive to me: PTS-to-integer conversion is ALLOWED but the result is implementation defined. I would NOT go as far as Jim has by suggesting that int i = (int)pointer_to_shared and int i = (int)(void*)pointer_to_shared MUST behave the same. However, if the community wanted to specify that, then I'd be more than happy to ensure BUPC implements it (I am 99% sure we do). ```

    Reported by `phhargrove@lbl.gov` on 2012-05-22 00:38:17

  5. Former user Account Deleted

    ``` I agree with leaving unspecified the behavior of pointer arithmetic on shared void *.

    I disagree with making

    (int)pointer_to_shared

    the same as

    (int)(void*)pointer_to_shared

    Two reasons: 1. It might be useful for, say, a 64-bit pointer-to-shared representation to be cast to a 64-bit integer. (Although you can get the bits via *(long*)(&p), so that's not such a big deal.

    2. (void*)pointer_to_shared is only defined where upc_threadof(pointer_to_shared) == MYTHREAD. If there is to be a definition of the integer cast, it seems to me it should be defined for all threads.

    I don't see a strong reason to impose a definition in the language, but I would find

    int i = (int)upc_addrfield(pointer_to_shared)

    more acceptable. ```

    Reported by `brian.wibecan` on 2012-05-22 22:41:48

  6. Former user Account Deleted

    ``` As mentioned in comment #1, arithmetic on (void *) is very clearly erroneous by the C99 sections quoted by Nicholas. Specifically "one operand shall be a pointer to an object type" and void is elsewhere defined as an incomplete (non-object) type. Therefore arithmetic on (void *) is a violation of a "shall" constraint on C99 semantics, making the program erroneous and the behavior undefined. In spec-eze (shared void *) is a "qualified" version of (void *) and the exact same rules apply, as intended.

    I see no reason why the UPC spec should advocate relaxing this C99 constraint, especially since arithmetic on (shared void *) has the potential to deviate even further from user expectations in the presence of distributed arrays. Arithmetic on (void *) is a programmer error and should remain that way - there is always a more correct and less sloppy way to write your arithmetic using pointers with complete referent types.

    I also agree that (2) should remain permitted but have implementation-defined behavior, as provided by C99 6.3.2.3. Specifically there are no guarantees whatsoever about the value resulting from casting a pointer-to-shared to an integral type. Questions about whether it should or should not equal another cast expression are meaningless because the value is explicitly undefined. Users writing portable code should never do this.

    There seems to be agreement that this issue is resolved with no changes required to the spec.

    ```

    Reported by `danbonachea` on 2012-05-31 08:33:04

  7. Former user Account Deleted

    ``` Regarding point 1 (arithmetic on (shared void *) is an illegal and therefore should result in a translation error), I agree, and Nick's comment #1 provides support.

    I will note however, that GCC at least appears rather permissive on the issue of arithmetic on "(void *)". I don't recall if -std=c99 will cause GCC to at least issue a warning, or -Wpedantic might do so. I mention this only to note that some programmers may have a (faulty) expectation that arithmetic on (void *) is defined and therefore arithmetic on (shared void *) should be defined.

    ```

    Reported by `gary.funck` on 2012-05-31 15:17:19

  8. Former user Account Deleted

    ``` From the discussion, it seems that we have reached consensus on the answers to the original questions. I propose to close this issue.

    To recapitulate:

    1) Is arithmetic on (void *) and (shared void *) an error? Some implementations of UPC currently define arithmetic on (shared void *) as erroneous. BUPC thinks it is ... and GCC/UPC has now followed suit, but what does C99 say?

    Answer: Yes, this is an error.

    2) Is conversion from a pointer−to−shared to an integer allowed? BUPC thinks it is and does something, GCC/UPC issues an error. If it is defined in the language, what is the definition? (Note that on 32−bit targets, a shared pointer might be 64 bits, and 128 bits on a 64−bit target.)

    Answer: Conversion from a pointer−to−shared to an integer is allowed but the result is implementation-defined.

    ```

    Reported by `yzheng@lbl.gov` on 2012-06-14 18:19:46 - Status changed: `Done` - Labels added: Milestone-Spec-1.3

  9. Former user Account Deleted

    ``` Mass update to closed issue status ```

    Reported by `danbonachea` on 2012-06-15 18:42:19 - Status changed: `NoChange`

  10. Log in to comment