Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Re: endianness and failure with inline (http://www.velocityreviews.com/forums/t735457-re-endianness-and-failure-with-inline.html)

Seebs 10-14-2010 06:34 AM

Re: endianness and failure with inline
 
On 2010-10-14, doriangray <nospam@email.net> wrote:
> 1) Why the gcc compiler fails to compile this code?


I dunno.

> $ gcc -std=c99 file.c
> /tmp/ccKmnUPF.o: In function `main':
> file.c:(.text+0x27): undefined reference to `isLE99'
> collect2: ld returned 1 exit status


This seems to be related to the std=c99 flag.

> 2) Are these portable ways to establish whether a 32bit architecture
> is Little Endian or not?


No. There really aren't portable ways, honestly -- the question isn't
even entirely well-defined.

I have very, very, rarely seen any reason to, though -- I simply
haven't seen code that legitimately needs to know.

> inline int isLE99(void) {


Hmm. One thing is, there's at least some reserved symbols starting
with "is*" for function names -- for future expansion of ctype.h. However,
that doesn't seem to be it. If I build this program as-is with
gcc in std=c99 mode, it fails with a similar message. Changing
"inline" to "static inline" fixes it, though. So does changing it to
"extern inline". This could be a bug.

I don't really understand why you declare the "C89" and "C99" versions;
it seems very unlikely that they'll actually behave differently on
all that many targets, and the differences don't have much to do with
C99. Note that, for the level of precision you seem to be going for,
you'll do just as well to set an unsigned long to 0x12, then verify that
the first byte of it appears to be 0x12 -- the rest is all irrelevant.

I have no idea why gcc is having issues with the inline specifier.
I also don't have any idea why you put it there to begin with.

Ohhh! I think I may have found something suspicious. It seems that
inlining doesn't work without some kind of -O. Thus:

cc --std=c99 -o foo foo.c

fails, but:

cc -O --std=c99 -o foo foo.c

It's quite possible that this is a bug, or possibly a documented
limitation.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Marcin Grzegorczyk 10-14-2010 10:23 PM

Re: endianness and failure with inline
 
doriangray wrote:
> Seebs wrote:
>> On 2010-10-14, doriangray<nospam@email.net> wrote:
>>> 1) Why the gcc compiler fails to compile this code?

>>
>> I dunno.
>>
>>> $ gcc -std=c99 file.c
>>> /tmp/ccKmnUPF.o: In function `main':
>>> file.c:(.text+0x27): undefined reference to `isLE99'
>>> collect2: ld returned 1 exit status


isLE99() is declared `inline` with neither `static` nor `extern`, which
means the definition of that function is an inline definition -- which
does not provide an external definition for that function. As
optimizations are not enabled, the call to isLE99() is not actually
inlined, and thus an unresolved reference to isLE99() remains.

[snip]
> That's really strange,
> maybe I am wrong but I remember of earlier gcc versions that didn't
> complain with the specifier "inline" alone.


Earlier versions of GCC had the meaning of `inline` and `extern inline`
swapped with respect to C99. It was fixed in 4.3, AFAIK.

> Ironically, it compiles fine with just "gcc file.c", due to a compiler
> extension. Nothing on the gcc documentation makes me think that such a
> failure is expected.


N1256 section 6.7.4 paragraph 6 does ;-)

See also the GCC option -fgnu89-inline.
--
Marcin Grzegorczyk

Seebs 10-14-2010 10:26 PM

Re: endianness and failure with inline
 
On 2010-10-14, Marcin Grzegorczyk <mgrzegor@poczta.onet.pl> wrote:
>> Ironically, it compiles fine with just "gcc file.c", due to a compiler
>> extension. Nothing on the gcc documentation makes me think that such a
>> failure is expected.


> N1256 section 6.7.4 paragraph 6 does ;-)


I'm looking at that in the final standard, and I see nothing to justify
this failure. So far as I can tell, the "inline" qualifier does not authorize
a compiler to fail to translate the program. The call to isLE99() doesn't
*need* an external definition, any more than a call to something declared
"static" would.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Marcin Grzegorczyk 10-14-2010 10:41 PM

Re: endianness and failure with inline
 
Seebs wrote:
> On 2010-10-14, Marcin Grzegorczyk <mgrzegor@poczta.onet.pl> wrote:
>>> Ironically, it compiles fine with just "gcc file.c", due to a compiler
>>> extension. Nothing on the gcc documentation makes me think that such a
>>> failure is expected.

>>
>> N1256 section 6.7.4 paragraph 6 does ;-)

>
> I'm looking at that in the final standard, and I see nothing to justify
> this failure. So far as I can tell, the "inline" qualifier does not authorize
> a compiler to fail to translate the program. The call to isLE99() doesn't
> *need* an external definition, any more than a call to something declared
> "static" would.


The last sentence of that paragraph says

# It is unspecified whether a call to the
# function uses the inline definition or the external definition.

So the compiler is free to ignore the inline definition altogether, and
there is no external definition of isLE99() but it is referenced.
--
Marcin Grzegorczyk

Seebs 10-14-2010 10:43 PM

Re: endianness and failure with inline
 
On 2010-10-14, Marcin Grzegorczyk <mgrzegor@poczta.onet.pl> wrote:
> So the compiler is free to ignore the inline definition altogether, and
> there is no external definition of isLE99() but it is referenced.


Ahh! I see. That was what I'd missed -- you're required to provide an
external definition of any symbol you call, even if you *also* provide an
inline one. Since the inline one doesn't provide an external definition,
the program's behavior is not defined, but no diagnostic is required because
it's Semantics, not Constraints. (The last bit was helpfully pointed out to
me by one of the nice folks at Code Sourcery.)

So in short, the program is actually incorrect, but it happens that gcc will,
in many modes, choose a way of translating it which happens to work.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Ian Collins 10-14-2010 11:11 PM

Re: endianness and failure with inline
 
On 10/15/10 12:02 PM, Seebs wrote:
> On 2010-10-14, Ian Collins<ian-news@hotmail.com> wrote:
>> "An inline definition does not provide an external definition for the
>> function, and does not forbid an external definition in another
>> translation unit. An inline definition provides an alternative to an
>> external definition, which a translator may use to implement any call to
>> the function in the same translation unit. It is unspecified whether a
>> call to the function uses the inline definition or the external definition."

>
>> Note "An inline definition provides an alternative to an external
>> definition".

>
>> So the behaviour is only unspecified if both an external *and* inline
>> definition are present.

>
> My theory is that it's always unspecified whether you use the inline one
> or the external one. And if there isn't an external one, then the behavior
> is undefined.


It's only undefined if there are both!

Otherwise behaviour of the majority of source files with inline
functions is undefined. 6.7.4/6 is specifically discussing functions
with external linkage.

Having both inline and external version of the same function is probably
rather unusual (I've never seen it).

--
Ian Collins

Marcin Grzegorczyk 10-14-2010 11:33 PM

Re: endianness and failure with inline
 
Ian Collins wrote:
> On 10/15/10 12:02 PM, Seebs wrote:
>> On 2010-10-14, Ian Collins<ian-news@hotmail.com> wrote:
>>> "An inline definition does not provide an external definition for the
>>> function, and does not forbid an external definition in another
>>> translation unit. An inline definition provides an alternative to an
>>> external definition, which a translator may use to implement any call to
>>> the function in the same translation unit. It is unspecified whether a
>>> call to the function uses the inline definition or the external
>>> definition."
>>>
>>> Note "An inline definition provides an alternative to an external
>>> definition".
>>>
>>> So the behaviour is only unspecified if both an external *and* inline
>>> definition are present.

>>
>> My theory is that it's always unspecified whether you use the inline one
>> or the external one. And if there isn't an external one, then the
>> behavior
>> is undefined.

>
> It's only undefined if there are both!


No; if there are both it's merely unspecified which one is used. OTOH,
if the external definition is missing, the behaviour is undefined,
because the function has external linkage (6.9p5).

>[...]
> Having both inline and external version of the same function is probably
> rather unusual (I've never seen it).


They're usually "the same" definition, but one translation unit makes
that definition external (by declaring it `extern`) while in all the
other translation units it's an inline definition. See the example
under 6.7.4; ordinarily, the definitions of the inline functions would
be placed in a separate file, which would be then included as needed.
--
Marcin Grzegorczyk

Ian Collins 10-15-2010 12:06 AM

Re: endianness and failure with inline
 
On 10/15/10 12:33 PM, Marcin Grzegorczyk wrote:
> Ian Collins wrote:
>> On 10/15/10 12:02 PM, Seebs wrote:
>>> On 2010-10-14, Ian Collins<ian-news@hotmail.com> wrote:
>>>> "An inline definition does not provide an external definition for the
>>>> function, and does not forbid an external definition in another
>>>> translation unit. An inline definition provides an alternative to an
>>>> external definition, which a translator may use to implement any
>>>> call to
>>>> the function in the same translation unit. It is unspecified whether a
>>>> call to the function uses the inline definition or the external
>>>> definition."
>>>>
>>>> Note "An inline definition provides an alternative to an external
>>>> definition".
>>>>
>>>> So the behaviour is only unspecified if both an external *and* inline
>>>> definition are present.
>>>
>>> My theory is that it's always unspecified whether you use the inline one
>>> or the external one. And if there isn't an external one, then the
>>> behavior
>>> is undefined.

>>
>> It's only undefined if there are both!

>
> No; if there are both it's merely unspecified which one is used. OTOH,
> if the external definition is missing, the behaviour is undefined,
> because the function has external linkage (6.9p5).


True, but only if the function has been declared with external linkage.
If the only declaration is the inline definition, all is sweet. This
was the case in the OP's example.

>> [...]
>> Having both inline and external version of the same function is probably
>> rather unusual (I've never seen it).

>
> They're usually "the same" definition, but one translation unit makes
> that definition external (by declaring it `extern`) while in all the
> other translation units it's an inline definition. See the example under
> 6.7.4; ordinarily, the definitions of the inline functions would be
> placed in a separate file, which would be then included as needed.


Which is still unusual.

--
Ian Collins

Seebs 10-15-2010 12:09 AM

Re: endianness and failure with inline
 
On 2010-10-14, Ian Collins <ian-news@hotmail.com> wrote:
> It's only undefined if there are both!


If there are both, it's *unspecified* -- but it's not undefined. You get
one or the other.

But the statement that it's unspecified which you get isn't actually qualified
by an "if there are both" -- it's just a plain statement that it's
unspecified.

Now, think about the question: How would you know whether an external one
existed? You're translating foo.c. You don't know whether bar.c has an
external function or not. You can't make your decision contingent on that
knowledge. You can just decide whether to generate a call to the external
version or to inline the inline version. Either is permitted.

> Otherwise behaviour of the majority of source files with inline
> functions is undefined. 6.7.4/6 is specifically discussing functions
> with external linkage.


I'm not sure of this.

In any event, we asked gcc maintainers, and they gave us this explanation,
so at least some gcc folks think that behavior is correct, and I'm willing to
take their word for it.

> Having both inline and external version of the same function is probably
> rather unusual (I've never seen it).


The impression I get is that if you declare something "extern inline", you
by definition get both.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Ian Collins 10-15-2010 12:41 AM

Re: endianness and failure with inline
 
On 10/15/10 01:36 PM, doriangray wrote:
> Ian Collins wrote:
> [...]
>>> No; if there are both it's merely unspecified which one is used. OTOH,
>>> if the external definition is missing, the behaviour is undefined,
>>> because the function has external linkage (6.9p5).

>>
>> True, but only if the function has been declared with external linkage.
>> If the only declaration is the inline definition, all is sweet. This was
>> the case in the OP's example.

> [...]
>
>
> Exactly. I thought that "inline" was just a hint to the compiler who
> is free to ignore hints, as it would with "register" variables.
> Why should we bother about something that the compiler is free to
> ignore? And also, isLE99() is only called in the same module where its
> defined, so I can't still understand what undefined reference means.


A compiler bug.

In your example, in terms of linkage "inline" is the same as "static".

--
Ian Collins


All times are GMT. The time now is 04:19 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.