zaimoni@zaimoni.com | My Groups | My Account
comp.lang.c
Vaporware C99 preprocessor: string literal corner cases
  6 messages - Collapse all
zaimoni@zaimoni.com    More options Nov 5, 2:51 pm
Newsgroups: comp.lang.c
From: zaimoni@zaimoni.com
Date: Wed, 5 Nov 2008 12:51:52 -0800 (PST)
Local: Wed, Nov 5 2008 2:51 pm
Subject: Vaporware C99 preprocessor: string literal corner cases
I've already calculated that the following are valid and should not
error, as both just end up with the character literal 'A' being their
control expression.  The unspecified value of the char* pointing to
the string literal is eliminated during evaluation, so the fact it is
unknowable doesn't matter.  ('A' is assumed not be to mapped to NUL.)
[GCC 4.2.1 accepts the first, and inconsistently considers *"A" to be
an invalid control expression.]

#if "A"[0]
#else
#error "A"[0] is false
#endif

#if *"A"
#else
#error *"A"[0] is false
#endif

C99 6.4.4.1 does not clearly state that an integer literal is an
object, so this should be invalid as the requirements of the address-
of operator & are imposed even though neither * nor & are evaluated.

#if *&0
#error *&0 is true
#endif

C99 6.4.5p5 goes into some detail regarding the exact layout of a
string literal, so it is clear that a string literal points to an
object -- at conceptual translation phase 7, three conceptual stages
after preprocessing (conceptual stage 4).  Does an implementation have
license to assume said layout during preprocessing?  Alternately, is
the following required to be invalid even though **&"A" must be
accepted at compile-time? :

#if **&"A"
#else
#error **&"A" is false
#endif

If an implementation has license to accept the above example, is there
some way to infer that it is actually required to accept the above
example?


Ben Pfaff    More options Nov 5, 3:09 pm
Newsgroups: comp.lang.c
From: Ben Pfaff <b...@cs.stanford.edu>
Date: Wed, 05 Nov 2008 13:09:03 -0800
Local: Wed, Nov 5 2008 3:09 pm
Subject: Re: Vaporware C99 preprocessor: string literal corner cases

zaimoni@zaimoni.com writes:
> #if "A"[0]
> #else
> #error "A"[0] is false
> #endif

String literals are not permitted in integer constant
expressions, see C99 6.6:

6    An integer constant expression96) shall have integer type and
     shall only have operands that are integer constants,
     enumeration constants, character constants, sizeof
     expressions whose results are integer constants, and
     floating constants that are the immediate operands of
     casts. Cast operators in an integer constant expression
     shall only convert arithmetic types to integer types, except
     as part of an operand to the sizeof operator.

     96) An integer constant expression is used to specify the
         size of a bit-field member of a structure, the value of
         an enumeration constant, the size of an array, or the
         value of a case constant. Further constraints that apply
         to the integer constant expressions used in
         conditional-inclusion preprocessing directives are
         discussed in 6.10.1.

--
"The lusers I know are so clueless, that if they were dipped in clue
 musk and dropped in the middle of pack of horny clues, on clue prom
 night during clue happy hour, they still couldn't get a clue."
--Michael Girdwood, in the monastery


Keith Thompson    More options Nov 5, 3:13 pm
Newsgroups: comp.lang.c
From: Keith Thompson <ks...@mib.org>
Date: Wed, 05 Nov 2008 13:13:43 -0800
Local: Wed, Nov 5 2008 3:13 pm
Subject: Re: Vaporware C99 preprocessor: string literal corner cases

zaimoni@zaimoni.com writes:
> I've already calculated that the following are valid and should not
> error, as both just end up with the character literal 'A' being their
> control expression.  The unspecified value of the char* pointing to
> the string literal is eliminated during evaluation, so the fact it is
> unknowable doesn't matter.  ('A' is assumed not be to mapped to NUL.)

'A' cannot be equal to 0 (NUL) in a conforming implementation.

> [GCC 4.2.1 accepts the first, and inconsistently considers *"A" to be
> an invalid control expression.]

gcc 3.4.4 and 4.2.4 reject all of your examples.

> #if "A"[0]
> #else
> #error "A"[0] is false
> #endif

> #if *"A"
> #else
> #error *"A"[0] is false
> #endif

Both of these are constraint violations, requiring diagnostics.

C99 6.10.1p1:

    The expression that controls conditional inclusion shall be an
    integer constant expression except that [...]

This is a constraint, so violating it requires a diagnostic.

C99 6.6p6 defines "integer constant expression"; it may not contain a
string literal.

> C99 6.4.4.1 does not clearly state that an integer literal is an
> object, so this should be invalid as the requirements of the address-
> of operator & are imposed even though neither * nor & are evaluated.

> #if *&0
> #error *&0 is true
> #endif

An integer constant is not an lvalue, so &0 is a constraint violation.

> C99 6.4.5p5 goes into some detail regarding the exact layout of a
> string literal, so it is clear that a string literal points to an
> object

No, a string literal does not point to an object.  If it did,
    sizeof "hello"
would yield sizeof(char*); instead, it yields 6, the size of the array
object that corresponds to the string literal.

>        -- at conceptual translation phase 7, three conceptual stages
> after preprocessing (conceptual stage 4).  Does an implementation have
> license to assume said layout during preprocessing?  Alternately, is
> the following required to be invalid even though **&"A" must be
> accepted at compile-time? :

> #if **&"A"
> #else
> #error **&"A" is false
> #endif

> If an implementation has license to accept the above example, is there
> some way to infer that it is actually required to accept the above
> example?

As above, the example violates a constraint by attempting to use a
string literal as part of an expression in a context that requires an
integer constant expression.  A conforming compiler must issue a
diagnostic.  Once it's done so, it may, but is not required to,
continue to process the translation unit.

--
Keith Thompson (The_Other_Keith) ks...@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"


Ben Pfaff    More options Nov 5, 3:18 pm
Newsgroups: comp.lang.c
From: Ben Pfaff <b...@cs.stanford.edu>
Date: Wed, 05 Nov 2008 13:18:28 -0800
Local: Wed, Nov 5 2008 3:18 pm
Subject: Re: Vaporware C99 preprocessor: string literal corner cases

Keith Thompson <ks...@mib.org> writes:
> zaimoni@zaimoni.com writes:
>> #if "A"[0]
>> #else
>> #error "A"[0] is false
>> #endif

> C99 6.10.1p1:

>     The expression that controls conditional inclusion shall be an
>     integer constant expression except that [...]

> This is a constraint, so violating it requires a diagnostic.

Ordinarily I would agree, but C99 6.6p10 says, "An implementation
may accept other forms of constant expressions."  For me, at
least, this muddies the water a bit.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6} ,*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}

Keith Thompson    More options Nov 5, 3:29 pm
Newsgroups: comp.lang.c
From: Keith Thompson <ks...@mib.org>
Date: Wed, 05 Nov 2008 13:29:56 -0800
Local: Wed, Nov 5 2008 3:29 pm
Subject: Re: Vaporware C99 preprocessor: string literal corner cases

Good point.

Hmm.  Would additional forms of constant expressions be considered an
"extension", and thus have to be documented?

In any case, it's certainly non-portable.

--
Keith Thompson (The_Other_Keith) ks...@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"


zaimoni@zaimoni.com    More options Nov 5, 4:09 pm
Newsgroups: comp.lang.c
From: zaimoni@zaimoni.com
Date: Wed, 5 Nov 2008 14:09:18 -0800 (PST)
Local: Wed, Nov 5 2008 4:09 pm
Subject: Re: Vaporware C99 preprocessor: string literal corner cases
On Nov 5, 3:13 pm, Keith Thompson <ks...@mib.org> wrote:

> zaimoni@zaimoni.com writes:
> > I've already calculated that the following are valid and should not
> > error, as both just end up with the character literal 'A' being their
> > control expression.  The unspecified value of the char* pointing to
> > the string literal is eliminated during evaluation, so the fact it is
> > unknowable doesn't matter.  ....

> > [GCC 4.2.1 accepts the first, and inconsistently considers *"A" to be
> > an invalid control expression.]

> gcc 3.4.4 and 4.2.4 reject all of your examples.

Rechecked...yes for 4.2.1.

I have some test cases to move out of the C99 conformance suite
elsewhere, then.  (Looking elsewhere in-thread: "default" rather than
"default.nonconforming" should be the correct subdirectory, thanks to
C99 6.6p10.)

> > C99 6.4.5p5 goes into some detail regarding the exact layout of a
> > string literal, so it is clear that a string literal points to an
> > object

> No, a string literal does not point to an object.  If it did,
>     sizeof "hello"
> would yield sizeof(char*); instead, it yields 6, the size of the array
> object that corresponds to the string literal.

Ok.  (Not sure how that slipped through, as I've been exploiting that
compile-time strlen sleight-of-hand fairly intensively for this.)

End of messages

- Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google