Clarification: dynamic threads and the constraint "when multiplied by an integer expression"

Issue #94 new
Former user created an issue

Originally reported on Google Code with ID 94

While running tests of the newly developed Clang UPC compiler, the following test case
(derived from the old GWU test, V_case5_i.upc) was initially diagnosed as an error.

#define BLOCK2 12
shared [BLOCK2] int array[THREADS*BLOCK2*10];

The reasoning behind the error is based on an interpretation of the following language
in the specification (6.5.1p2):

"When a UPC program is translated in the dynamic THREADS environment
and an array with shared-qualified elements is declared with definite blocksize the
THREADS expression shall occur exactly once in one dimension of the array declarator
(including through typedefs). Further, the THREADS expression shall only occur either
alone or when multiplied by an integer constant expression."

When the expression in the index term of the array declaration is factored, it reads
as follows: (THREADS*BLOCK2)*10.  Here, we need to understand what is meant by "the
THREADS expression".  In one interpretation, the "THREADS expression" is everything
in the index (or domain) term of the declarator, this declaration violates the constraint
due to the factorization shown above.  In another interpretation (THREADS*BLOCKSIZE)
is the "THREADS expression" and thus meets the constraint.

However, given the overall context of the discussion, it seems (to me) that the first
interpretation (that this is erroneous) should prevail.  

The examples are not sufficiently complex to offer insight on this point.

Reported by gary.funck on 2012-10-05 17:03:13

Comments (20)

  1. Former user Account Deleted

    ``` I don't follow why that's erroneous. The #define BLOCK2 12 is a preprocessor macro, so the declaration is shared [12] int array[THREADS*12*10]. The 12*10 is an integer constant expression. ```

    Reported by `johnson.troy.a` on 2012-10-05 17:06:41

  2. Former user Account Deleted

    ``` Troy wrote: "I don't follow why that's erroneous. The #define BLOCK2 12 is a preprocessor macro, so the declaration is shared [12] int array[THREADS*12*10]. The 12*10 is an integer constant expression."

    If the this is an equivalent factorization, (THREADS*12)*10, then the entire array index is expression is not "the threads expression". If the expression had been written THREADS*(12*10) then clearly the threads expression is THREADS multiplied by a constant expression and this threads expression is the entire expression appearing in the index term (domain) of the array declarator.

    I will note that we have subsequently changed Clang UPC to use the more conventional, intuitive interpretation. In this report, I am just highlighting a potential ambiguity in the specification, for the purposes of discussion and possible clarification.

    ```

    Reported by `gary.funck` on 2012-10-05 17:29:21

  3. Former user Account Deleted

    ``` The issue we're dealing with here is that under dynamic threads, the shared array dimension involving THREADS needs to provably be an expression whose value is strictly linear in THREADS (and otherwise constant). However, there's a syntactic question of how "hard" the compiler should have to work to "prove" this linearity before accepting the declaration as valid.

    For example, all of the following declarations have dimensions which are technically linear in THREADS and satisfy the underlying requirement, but it's probably not reasonable to expect a UPC type checker to prove this:

    shared int x[(THREADS*10)*20]; shared int x[(THREADS*1*1*1)*20]; shared int x[(THREADS+0)*20]; shared int x[(THREADS+100-100)*20]; shared int x[(THREADS*sizeof(char)/sizeof(int8_t)*((int)66.34)-'A')*20]; shared int x[(THREADS+THREADS-THREADS)*THREADS/THREADS];

    Consequently, the specification needs to "draw the line" somewhere regarding what will be accepted, and the current text is INTENDED to state that the dimension involving THREADS has one of the following forms: [THREADS] [THREADS * (integer constant expression)] [(integer constant expression) * THREADS] Where "integer constant expression" is a very specific entity defined in C99 6.6, and is grouped as a single subexpression to the multiplication by THREADS, either explicitly (via parentheses) or implicitly (according to the operator syntax grouping defined in C99 6.5).

    To answer Gary's nitpick, the phrase "the THREADS expression" is INTENDED to mean exactly "THREADS", not "any expression containing THREADS" , as the latter would include ridiculous cases like (THREADS+THREADS) or (THREADS*clock()), which are clearly not what's intended.

    By my reading this makes the original example erroneous, because after applying the operator grouping of C syntax, the whole dimension effectively reads: [((THREADS*12)*10)] which does not conform to any of the cases above. This is a bit unintuitive, but the programmer can easily fix this by re-parenthesizing his expression. The fact the re-parenthesized expression happens to be mathematically equivalent (in this case) does not mean the type checker should be required to prove that.

    This all seems relatively clear to me in the current wording, although perhaps Gary could elaborate on the manner of clarification he's suggesting?

    ```

    Reported by `danbonachea` on 2012-10-06 20:07:54

  4. Former user Account Deleted

    ``` Is there really a decent C compiler out there that can't figure out that all of Dan's examples are constant integer expressions times THREADS? If I was using a compiler that could not figure out that "(x*sizeof(char)/sizeof(int8_t)*((int)66.34)-'A')*20" was "a*x" for some integer constant a, I would fire my C compiler and get a new one. I do not see why the same logic should not apply to a UPC compiler. ```

    Reported by `jeff.science` on 2012-10-07 21:33:02

  5. Former user Account Deleted

    ``` Jeff asks: "Is there really a decent C compiler out there that can't figure out that all of Dan's examples are constant integer expressions times THREADS?"

    For some expressions involving things like THREADS*THREADS/THREADS, it is important to keep in mind that in a dynamic threads translation environment that THREADS is either a variable or an expression that will not yield a compile-time known constant [barring something like JIT compilation unique to each thread] (and I'm not sure that the spec. says that THREADS is a constant or invariant expression, but it should). Thus, simplifying THREADS, when it appears more than once amounts to something like a symbolic mathematic substitution, and most compilers don't do that sort of optimization in the front end where language semantics are usually checked.

    Not all decent C compilers perform constant folding early in the front-end. GCC does; Clang doesn't. Clang's front-end (by design) attempts to keep the initial program AST very close to the original source program syntax. Clang in fact will track pre-processor macro references to provide better diagnostics, rather than erasing them away by substituting them in a pre-processor pass before the front-end sees them. Thus, when Clang sees THREADS*BLOCK2/10 it literally builds an AST that reads as ((THREADS*BLOCK2)/10). GCC on the other hand performs pre-processing and constant folding before implementing most semantic checks. GCC will see (THREADS*120), if we assume for the moment that THREADS is a variable identifier.

    Note that if THREADS is some expression defined by a macro, for example

    1. define THREADS upc_info->num_threads that Clang will see the pre-processor symbol THREADS and have the choice of dealing with the expression in that form or in the substituted form. Note that if GUPC or any compiler with a GCC-like processing flow ran the preprocessor first before trying to make the semantic check, its job may become more difficult. Thus, it is unlikely that THREADS will be implemented as a preproessor macro at least until after the UPC translator has had a chance to perform the language required semantic checks.

    As Dan points out there are various sound reasons for restricting the types of expressions that THREADS can appear in within the index (domain) part of an array declaration. For this reason: certainly THREADS should appear only once in the expression and then only as the left or right-hand term of a multiplication, with the other term being provably a compile-time constant. Assuming some compilers can accept more complicated forms of expressions: this would argue for making such behavior implementation-defined. Otherwise, more complicated expressions should be defined as erroneous.

    I am in favor of simplifying and making the more complicated form of expression erroneous; such as that shown in the issue summary. but that may break some existing programs.

    ```

    Reported by `gary.funck` on 2012-10-07 22:45:30

  6. Former user Account Deleted

    ``` "Is there really a decent C compiler out there that can't figure out that all of Dan's examples are constant integer expressions times THREADS?"

    It's not that any compiler wont *eventually* figure it out, indeed in many cases compilers are required to perform constant folding down to a value on integer constant expressions before code generation. The issue is that depending on compiler architecture, that may not happen until a late pass in the compilation process, whereas the typechecker generally needs to run somewhat early and decide whether a program's declarations are legal. Requiring the compiler to "prove" linearity for all the examples I gave might represent an undue implementation burden, and IMHO there's really no good motivation to require it - if the expression truly is linear in THREADS, then the programmer should be able to concisely express that in an obvious form.

    Also note that in the case of typechecking my last example:

    shared int x[(THREADS+THREADS-THREADS)*THREADS/THREADS];

    the typechecker would need not only standard constant folding, but also symbolic expression simplification, a capability which is not strictly required anywhere else in a C/UPC compiler. Here's a more extreme illustration, which is also linear in THREADS, but would require an unreasonably smart typechecker to verify:

    shared int x[(THREADS+2)*(THREADS+1)-THREADS*THREADS-2];

    Like I said, we have to draw the line somewhere :-)

    ```

    Reported by `danbonachea` on 2012-10-07 23:01:49

  7. Former user Account Deleted

    ``` Closely related to this issue, it occurred to me that we should also clarify the integer constant expression must eventually evaluate to a positive value, specifically to prohibit nonsensical dimensions like: [THREADS*(sizeof(int)-sizeof(int))] [THREADS*-14] This is not technically covered by C99 6.7.5.2 in the dynamic threads environment, because the full dimension is not an integer constant expression (due to the inclusion of THREADS). ```

    Reported by `danbonachea` on 2012-10-08 00:28:28

  8. Former user Account Deleted

    ``` I'd think that the user should be able to use *any* (positive) expression which is valid in other contexts where an integer constant is expected, multiplied by THREADS.

    Any C compiler operating in "C89 mode" (and thus NOT supporting VLA) should already be able to process the arbitrarily "messy" expressions in comment #3 if they occur as an array dimension (including the case where they occur in a typedef) *IF* an actual value were substituted for THREADS. So, I strongly suspect that enough "machinery" is present in the front-end if one is clever enough in how they approach the problem.

    When the expression is provably a constant, there is no problem to be solved. Otherwise one can the play a game with substituting THREADS=0 and subjecting the dimension expression to the compiler's "zero_p" type of test. If there is no "zero_p" provided then one can leverage the checks which are already done for array dimensions (and layout qualifiers) which must be non-negative: zero_p(expr) == (is_non_negative(expr) && is_non_negative(-expr))

    Additional checks are then required to ensure the expression is linear (can be simplified to contain exactly one instance of the THREADS identifier) as opposed to being quadratic or some rational function. Ideally one can examine the AST and determine if THREADS already occurs exactly once. If NOT, (which should be rare but seems to be the case most worrisome to Gary and Dan), then we can either use "symbolic" or "numeric" approaches to the problem.

    Given any (even limited) symbolic capabilities to simplify, one can apply the simplification before the "check AST for exactly one instance of THREADS" test before resorting to "numeric" methods. IF there are not sufficient symbolic capabilities in the compiler to prove linearity, then some more "games" substituting THREADS==1 and THREADS==2 will allow one to "support" a conclusion of linearity again using only constant folding and zero_p( expr(2) - 2*expr(1) ) That doesn't "prove" linearity in general, but if one can determine that the THREADS identifier occurs N times in the AST, then N+1 "samples" (of which THREADS==0 is one)

    • is* sufficient to prove linearity (I know this is true if expr is a polynomial, but am less sure about "f(THREADS)/g(THREADS)" sorts of cases).

    So, I'd *hope* that allowing this full generality should not impose a significant implementation burden. I am not claiming this is TRIVIAL, just that it NOT IMPOSSIBLE.

    ```

    Reported by `phhargrove@lbl.gov` on 2012-10-08 23:30:27

  9. Former user Account Deleted

    ``` Just to prove to myself that I am not delusional, I've implemented in Berkeley UPC the scheme described above to test for linearity via "zero_p" and substitutions of small integers for THREADS in the expression. It pretty much works with a couple caveats, for the cases in comment #3.

    1) The case shared int x[(THREADS*sizeof(char)/sizeof(int8_t)*((int)66.34)-'A')*20]; is mis-parenthesized and actually should be shared int x[[THREADS*sizeof(char)/sizeof(int8_t)*((int)66.34-'A'))*20]; if it is to meet the THREADS*constant constraint. Once fixed, this is one BUPC could already handle.

    2) The case shared int x[(THREADS+THREADS-THREADS)*THREADS/THREADS]; doesn't work because of the 0/0 in the evaluation throws things off. Of course "(THREADS-N)/(THREADS-N)" could appear, showing that 0 is not "special".

    However, the extra case given in comment #6: shared int x[(THREADS+2)*(THREADS+1)-THREADS*THREADS-2]; "just works" as my new code counts 4 instances of THREADS in the AST and thus evaluates the expression at THREADS=0,1,2,3,4,5,6 to prove its linearity.

    ```

    Reported by `phhargrove@lbl.gov` on 2012-10-09 02:26:24

  10. Former user Account Deleted

    ``` Paul said: "That doesn't "prove" linearity in general, but if one can determine that the THREADS identifier occurs N times in the AST, then N+1 "samples" (of which THREADS==0 is one)

    • is* sufficient to prove linearity "

    I believe your proposed zero_p test is predicated on an assumption that the dimension expression being tested is a continuous function, which is not guaranteed for invalid declarations (that must nevertheless be detected). Here's a few examples of invalid (non-linear) declarations, that I believe pass your "zero_p" test (false positives):

    ex1: shared int x[THREADS*THREADS > 10000 ? THREADS * 16 : THREADS * 15];

    Declarations similar to ex1 can be made arbitrarily complicated to defeat the use of an additional finite number of samples. Here's another where the THREADS expression only appears once:

    ex2: shared int x[THREADS == 1 ? 1 : 2]; iscontinuity that makes this expression illegal for THREADS >= 3

    It's also not sufficient to simply prohibit the conditional operator, because similar discontinuites can be created through the use of integer roundoff:

    ex3: shared int x[THREADS + (int)(THREADS/1024)]; discontinuity that makes this expression illegal only appears at THREADS >= 1024

    or with bitwise operators:

    ex4: shared int x[THREADS & 0xFF]; discontinuity that makes this expression illegal only appears at THREADS >= 256

    or with integer overflow:

    ex5: shared int x[(THREADS * (INT_MAX / 256))/(INT_MAX/256)]; this one is questionable even for a C declaration

    Here's a declaration which IS linear for all valid instances of THREADS, but I suspect triggers a false negative in your test:

    ex3: shared int x[THREADS <= 0 ? -20 : THREADS]

    Note these declarations are all fully valid in the static threads environment, but must be prohibited (and reliably rejected by any typechecker) for the dynamic threads environment. ```

    Reported by `danbonachea` on 2012-10-09 14:03:16

  11. Former user Account Deleted

    ``` This discussion has become somwhat obscure, and I think it would help to introduce some formalisms to improve the vocabulary of discourse.

    ---------------------------------------------- Assume we are typechecking an array declaration in the dynamic threads environment, which has the following form after typedef expansions:

    shared [B] T array[expr1][expr2]...[exprN]

    Further, assume B >= 1 (not indefinitely blocked)

    Define the expression DIMPROD: DIMPROD := expr1 * expr2 * ... * exprN

    ---------------------------------------------- Define the predicate CORRECTNESS-PROPERTY:

    CORRECTNESS-PROPERTY := There exists a positive integer constant LOCALSZ such that For All values of THREADS in [1,inf) (DIMPROD / THREADS) == LOCALSZ

    This is the property that we wish to guarantee the implementation. Specifically, this is the necessary and sufficient condition which enables a dynamic threads implementation that statically allocates per-thread components of all static shared objects as constant-sized symbols in the .bss segment of the executable (without overallocating by more than B*sizeof(T) per thread).

    ---------------------------------------------- Define the CURRENT-CONSTRAINT:

    In the dynamic threads environment, the typechecker shall validate that for all shared array types declared by the program, the identifier THREADS shall appear exactly once in DIMPROD, and furthermore the dimension expression (dimI) which includes THREADS has exactly one of the following forms: [THREADS] [THREADS * (integer constant expression)] [(integer constant expression) * THREADS] Where "integer constant expression" is the very specific entity defined in C99 6.6, is additionally constrainted to have positive value, and is grouped as a single subexpression to the multiplication by THREADS, either explicitly (via parentheses) or implicitly (according to the operator syntax grouping defined in C99 6.5).

    CURRENT-CONSTRAINT is the requirement that was INTENDED by the current spec wording - it's arguable whether or not the current spec phrasing makes this unambiguously clear.

    ---------------------------------------------- THEOREM 1: CURRENT-CONSTRAINT is sufficient to guarantee CORRECTNESS-PROPERTY.

    Proof: Consider the three permitted forms of THREADS in a dimension expression: Case 1, [THREADS]: For this case, DIMPROD = expr1 * expr2 * .. * THREADS * ... * exprN Case 2, [THREADS * (integer constant expression)]: For this case, DIMPROD = expr1 * expr2 * .. * THREADS * (integer constant expression)

    • ... * exprN Case 3, [(integer constant expression) * THREADS]: For this case, DIMPROD = expr1 * expr2 * .. * (integer constant expression) * THREADS
    • ... * exprN In all cases, each of the expressions expr1, expr2, ..., exprN and (integer constant expression) are required by C99 and CURRENT-CONSTRAINT to have a value that can be evaluated at compile time and results in a positive integer constant. Let: LOCALSZ = expr1 * expr2 * .. * (integer constant expression) * ... * exprN (omit "integer constant expression" for Case 1) By the rules of basic arithmetic (multiplication), the value of LOCALSZ is a positive integer constant. Furthermore, again by basic arithmetic (cancellation), for all values of THREADS the expression DIMPROD / THREADS is equivalent to the expression used to define LOCALSZ. Hence by the identity of LOCALSZ, the CORRECTNESS-PROPERTY is proven. ----------------------------------------------

    By Theorem 1, CURRENT-CONSTRAINT is *sufficient* to imply CORRECTNESS-PROPERTY, but is not *necessary* - looser constraints are possible which still satisfy CORRECTNESS-PROPERTY, but its arguable what implementation burden they impose upon the typechecker.

    Summarizing resolutions for this issue: ------------------------------------- Option 1: "No change": Agree that CURRENT-CONSTRAINT is acceptable and that the current spec wording adequately and unambiguously describes CURRENT-CONSTRAINT, so no further action is required.

    Option 2: "Clarify": Agree that CURRENT-CONSTRAINT is acceptable, but take action to clarify the current spec wording to ensure it adequately and unambiguously describes CURRENT-CONSTRAINT.

    Option 3: "Minimal Loosen": Decide to loosen CURRENT-CONSTRAINT by a minimal amount to allow examples like comment 0, and update the spec wording. For example require that dimI can be transformed into a form that satisfies CURRENT-CONSTRAINT by applying associative and commutative transformations on top-level multiplication operators in dimI. This can easily be proven to satisfy CORRECTNESS-PROPERTY, and it sounds like this is what some compilers have already implemented.

    Option 4: "Strong Loosen": Decide to loosen CURRENT-CONSTRAINT to some new predicate (yet to be formalized) which still involves only a single appearance of THREADS in DIMPROD, but allows more latitude in the dimI expression (allowing some more operators in the expression tree as a parent to THREADS), AND can still be formally proven to imply CORRECTNESS-PROPERTY. I would want to see a formal proof similar to Theorem 1 for any proposed predicate before considering this option. Also, some handwaving would be needed to argue that it doesn't impose a significant additional implementation burden for the typechecker to validate.

    Option 5: "Maximally Loosen": Similar to Option 3, but additionally allow dimI to be an arbitrary expression tree combining THREADS (or possibly multiple copies of THREADS) and integer constant expressions, provided the resulting expression behavior satisfies CORRECTNESS-PROPERTY. I have argued this constraint would in general require full symbolic manipulation by the typechecker to perform validation, which is a significant departure from the "spirit" of C's type system, and would constitute an unacceptable implementation burden.

    My 2 cents: I'm in favor of option 1 or 2, but could be convinced to accept option 3 as a usability enhancement if that is the consensus. I would be opposed to options 4 and 5 on the basis of complexity and implementation burden that provides no substantial benefit to users.

    ```

    Reported by `danbonachea` on 2012-10-09 14:07:36

  12. Former user Account Deleted

    ``` I am in favor of clarification on this issue (having had my idea in comments 8 and 9 squashed by Dan's comment 10). I agree that "CURRENT-CONSTRAINT" expresses the same thing as the current text, but feel that as written now it can be misinterpreted.

    On a related topic, should we be clear that a compiler MUST NOT accept looser forms? That would avoid a more permissive compiler from leading a user down the path of writing non-portable code. ```

    Reported by `phhargrove@lbl.gov` on 2012-10-09 17:07:51

  13. Former user Account Deleted
    "On a related topic, should we be clear that a compiler MUST NOT accept looser forms?
     That would avoid a more permissive compiler from leading a user down the path of writing
    non-portable code."
    
    The spec wording under review appears in a Constraint section, so this is already implied
    by C99 5.1.1.3:
    
    "A conforming implementation shall produce at least one diagnostic message (identified
    in an implementation-defined manner) if a preprocessing translation unit or translation
    unit contains a violation of any syntax rule or constraint, even if the behavior is
    also explicitly specified as undefined or implementation-defined."
    
    So UPC 1.2 compilers that silently accept more general dimension expressions are technically
    non-compliant. I see no need to explicitly restate that, as it applies to every constraint
    in the specification. On the other hand, there probably SHOULD be multiple tests in
    a good compiler conformance test suite that exercise all the corner cases for this
    constraint and validate that every test pass/fails compilation when it should.
    

    Reported by danbonachea on 2012-10-09 19:16:16

  14. Former user Account Deleted
    Here's a proposal to specify the clarification suggested in comment 11, option 2:
    
    Change this wording:
    "Further, the THREADS expression shall only occur either alone or when multiplied by
    an integer constant expression"
    
    to:
    "Further, the THREADS keyword shall only occur either alone or when multiplied by an
    integer constant expression (as defined in [ISO/IEC00 Sec. 6.6]) with positive value."
    
    Also, we can augment the examples appearing further in the section to demonstrate the
    implications (new entries highlighted with <<<<):
    
    EXAMPLE 1: declarations allowed in either static THREADS or dynamic THREADS translation
    environments:
    shared int x [10*THREADS];
    shared int x [THREADS*(100*20)];       <<<<
    shared [] int x [10];
    
    EXAMPLE 2: declarations allowed only in static THREADS translation environment:
    shared int x [10+THREADS];
    shared [] int x [THREADS];
    shared int x [10];
    shared int x [THREADS][4*THREADS];   <<<<
    shared int x [THREADS*THREADS];      <<<<
    shared int x [THREADS*100*20];       <<<<
    

    Reported by danbonachea on 2013-01-17 18:15:16 - Status changed: Accepted - Labels added: Consensus-Medium - Labels removed: Consensus-Low

  15. Former user Account Deleted
    Set critical priority on the unresolved technical issues slated for 1.3 which are blocking
    progress on ratification.
    

    Reported by danbonachea on 2013-01-24 07:40:02 - Labels added: Priority-Critical - Labels removed: Priority-Medium

  16. Former user Account Deleted
    I concur with the proposal in Comment 15.
    
    Note that per our telecon, that this example likely currently compiles without error
    for GCC-based front-ends, due to constant folding in the front-end:
    
    shared int x [THREADS*100*20];
    
    and this same example which used to be diagnosed as an error under Clang UPC will necessarily
    be made to fail again.  Adjustments will need to be made to various UPC compilers (probably
    some test programs, and perhaps some applications) to bring them into compliance with
    this change in the specification.
    

    Reported by gary.funck on 2013-01-28 21:39:31 - Labels added: Consensus-High - Labels removed: Consensus-Medium

  17. Former user Account Deleted
    Official proposal for issues 94&95 mailed on 2/4/13:
    
    --- upc-language.tex    (revision 199)
    +++ upc-language.tex    (working copy)
    @@ -665,18 +679,32 @@
    
     {\bf Constraints}
    
    -\np When a UPC program is translated in the {\em dynamic
    -    THREADS} environment and an array with shared-qualified elements
    -    is declared with definite blocksize, the THREADS expression shall
    -    occur exactly once in one dimension of the array declarator
    -    (including through typedefs).  Further, the THREADS expression
    +\np 
    +    When a UPC program is translated in the {\em dynamic THREADS} environment,
    +  \xreplaced[id=DB]{95}{%
    +    every {\em declarator} or {\em type-name} containing an array type with 
    +    shared-qualified elements and definite blocksize shall include the THREADS keyword
    +  }{%
    +    and an array with shared-qualified elements
    +    is declared with definite blocksize, the THREADS expression shall occur 
    +  }%
    +    exactly once in one dimension of the array declarator
    +    (including through typedefs).  
    +  \xreplaced[id=DB]{94}{%
    +    Further, the THREADS keyword shall only occur either alone 
    +    or when multiplied by an integer constant expression
    +    (as defined in [ISO/IEC00 Sec. 6.6]) with positive value.
    +  }{%
    +    Further, the THREADS expression
         shall only occur either alone or when multiplied by an integer
    -    constant expression.\footnote{In the {\em static THREADS} environment
    +    constant expression.
    +  }%
    +    \footnote{In the {\em static THREADS} environment
         THREADS is an integer constant expression, and is therefore valid in
         all dimensions.}
    
     \np \xadded[id=DB]{15}{
    -    The THREADS expression
    +    The THREADS keyword
         shall not appear anywhere in the declarator of a shared array with
         indefinite blocksize under the {\em dynamic THREADS} environment.
         }
    @@ -704,19 +732,31 @@
     \np EXAMPLE 1: declarations allowed in either {\em static THREADS} or
         {\em dynamic THREADS} translation environments:
    
    +\cbstart
     \begin{verbatim}
         shared int x [10*THREADS];
    +    shared int x [THREADS*(100*20)];  
         shared [] int x [10];
     \end{verbatim}
    +\cbend
    
     \np EXAMPLE 2: declarations allowed only in {\em static THREADS} translation
         environment:
    
    +\cbstart
     \begin{verbatim}
         shared int x [10+THREADS];
         shared [] int x [THREADS];
         shared int x [10];
    +    shared int x [THREADS][4*THREADS];
    +    shared int x [THREADS*THREADS];
    +    shared int x [THREADS*100*20];
    +    shared int (**p)[THREADS][THREADS];
    +    typedef shared int (*t)[THREADS][13][THREADS];
    +    shared void *p = (shared int (*)[THREADS][THREADS])q;  
     \end{verbatim}
    +\cbend
    +\xchangenote[id=DB]{94}{SEVEN NEW EXAMPLES ADDED ABOVE}
    
     \np EXAMPLE 3: declaration of a shared array
    

    Reported by danbonachea on 2013-02-04 17:46:53 - Status changed: PendingApproval

  18. Former user Account Deleted
    Committed as SVN r214
    

    Reported by danbonachea on 2013-04-30 20:02:27 - Status changed: Fixed

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

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

  20. Log in to comment