Topic: Can a conforming implementation define inline member functions ??for standard containers?


Author: usenet@mkarcher.dialup.fu-berlin.de (Michael Karcher)
Date: Fri, 26 Jun 2009 23:09:43 CST
Raw View
Joshua Maurice <joshuamaurice@gmail.com> wrote:
> >         unsigned char * testptr = (unsigned char*)&test;
> [snip]
> Casting a "pointer to function" to "pointer to unsigned char" and
> using it after is undefined behavior (according to the C++ standard).
> The statement made was that you could not tell the difference between
> if the standard library function was declared inline or not for a
> conforming program, and your program is not conforming (to the C++
> standard) because of that cast.

I know, and Alf Steinbach was right, I should have provided more context in
that posting. I assumed that the reader was still in the context of the
thread, which was like this:

1) Original Question: May vector functions be inlined?
2) Me: I don't think you can write a conforming program that can tell
        the difference, although it probably is possible to write a
        program that does tell the difference on a specific platform.
        Of course this program - which has (amongst other things) -
        a code-to-data-pointer conversion will not be conforming,
        because it has expressions with unspecified or undefined
        behaviour.
3) James Kanze: I don't see how you can do that. (Quoting only a
        part of my statement)
4) Me: Here is a program that supports the claim that you can write
        a non-conforming program that can tell the difference.

Regards,
   Michael Karcher

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: usenet@mkarcher.dialup.fu-berlin.de (Michael Karcher)
Date: Sun, 28 Jun 2009 17:39:57 CST
Raw View
Hello,

first, I want to make clear again that I think we all agree on that
a *conforming* program can not find out whether functions of the vector
class are declared inline or not. This subthread is about the claim
that a *non-conforming* program can analyze itself to find out at least
whether the some vector functions are inlined in a specific case.

James Kanze <james.kanze@gmail.com> wrote:
> >         unsigned char * testptr = (unsigned char*)&test;
> The above line is not legal C++, and requires a compiler
> diagnostic.  It won't compile with a conforming compiler.
OK, that might be. I expected it to be just undefined behaviour.

> And regardless: if you have an inline function, and you take its
> address, the compiler is required to generate an out of line
> copy somewhere.
So what? If I understood the original question correctly, the question
was about whether the vector functions might be declared inline, not
whether they are inlined all the time.

> >         while(*testptr != 0xc3 /* return */)
> >         {
> >                 if(*testptr == 0xE8)
> >                 {
> >                          calls++; /* call near */
> >                          testptr += 4;
> >                 }
> >                 if(*testptr >= 0x70 && *testptr <=0x7f)
> >                         inlined = 1; /* conditional jump */
> >                 testptr++;
> >         }
> >         if(inlined || calls != 3) /* constructor, reserve, destructor */
> >                 cout << "was inlined\n";
> > }
>
> > (works on x86. Outputs nothing with "gcc", outputs "was
> > inlined" with "gcc -O")

> Sounds like a bug in the compiler---the code shouldn't compile,
> according to the standard.
Huh? The standard says anything about whether code should compile?
As far as I know, in some cases a diagnostic is required, but it
does not state whether compilation must be aborted after issuing
such a diagnostic, although behaviour of the compiled program is
undefined.


> And I still don't see where it's relevant in any way to whether
> the library can define the functions "inline" or not---at best,
> it might indicate that the compiler hasn't included an out of
> line copy, or that it's simply generating the code differently
> than you expect.
I am not searching for out-of-line-copies in that code. I try to
analyze just the assembly code of the function test, which should
call three functions: The vector constructor, the reserve function
and the vector destructor. If the compiler inlines any of them, I
will see something different than the three calls.

As that program was a 5 minute hackup, it might very well fail to
work as intended on your machine. It was just a reply on how to
write a non-conforming program that can find out whether vector
functions are inlined.

> The very fact that you are getting different
> results depending on optimization rather proves, in fact, that
> you're not testing whether the function was declared inline or
> not.
gcc does no inlining without optimization. Yes, you are right: I don't
test whether vector functions are *declared* inline, but whether they
were compiled as inlines in this particular case. As modern optimizing
compilers might also inline functions not declared as inline or the
other way around, the output of the program is really not related to
the declaration.

> On my Linux box, your code says "was inlined" regardless
> of the optimization level, or whether I compiled with or without
> debugging.
If you get "was inlined" without optimization, that indicates that
the primitive logic of the program is unreliable. It might be a false
positive induced by operand bytes treated as opcodes.

> If I examine the sources, however, the function
> reserve is NOT inlined.
While that might be the case, the constructor and destructor definitely
*are* declared inline in the standard library as supplied by g++,
version 4.3.2.

Regards,
   Michael Karcher

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Mon, 29 Jun 2009 10:43:18 CST
Raw View
On Jun 29, 1:39 am, use...@mkarcher.dialup.fu-berlin.de (Michael
Karcher) wrote:
> first, I want to make clear again that I think we all agree on
> that a *conforming* program can not find out whether functions
> of the vector class are declared inline or not. This subthread
> is about the claim that a *non-conforming* program can analyze
> itself to find out at least whether the some vector functions
> are inlined in a specific case.

OK.  And a non-conforming program can use compiler extensions.
Including the relatively frequent one of converting a function
pointer to a data pointer.

> James Kanze <james.ka...@gmail.com> wrote:
> > >         unsigned char * testptr = (unsigned char*)&test;
> > The above line is not legal C++, and requires a compiler
> > diagnostic.  It won't compile with a conforming compiler.

> OK, that might be. I expected it to be just undefined
> behaviour.

Of course, if you don't do something like -std=c++98 (with g++),
it will compile without even a warning.

> > And regardless: if you have an inline function, and you take
> > its address, the compiler is required to generate an out of
> > line copy somewhere.

> So what? If I understood the original question correctly, the
> question was about whether the vector functions might be
> declared inline, not whether they are inlined all the time.

Which I addressed later.  But yes, I'd not fully understood what
you were doing when I read that.

> > >         while(*testptr != 0xc3 /* return */)
> > >         {
> > >                 if(*testptr == 0xE8)
> > >                 {
> > >                          calls++; /* call near */
> > >                          testptr += 4;
> > >                 }
> > >                 if(*testptr >= 0x70 && *testptr <=0x7f)
> > >                         inlined = 1; /* conditional jump */
> > >                 testptr++;
> > >         }
> > >         if(inlined || calls != 3) /* constructor, reserve, destructor */
> > >                 cout << "was inlined\n";
> > > }

> > > (works on x86. Outputs nothing with "gcc", outputs "was
> > > inlined" with "gcc -O")
> > Sounds like a bug in the compiler---the code shouldn't compile,
> > according to the standard.

> Huh? The standard says anything about whether code should
> compile?  As far as I know, in some cases a diagnostic is
> required, but it does not state whether compilation must be
> aborted after issuing such a diagnostic, although behaviour of
> the compiled program is undefined.

Point taken.  In fact, with g++ -std=c++98, it does compile.
After the diagnostic.

> > And I still don't see where it's relevant in any way to
> > whether the library can define the functions "inline" or
> > not---at best, it might indicate that the compiler hasn't
> > included an out of line copy, or that it's simply generating
> > the code differently than you expect.

> I am not searching for out-of-line-copies in that code. I try
> to analyze just the assembly code of the function test, which
> should call three functions: The vector constructor, the
> reserve function and the vector destructor. If the compiler
> inlines any of them, I will see something different than the
> three calls.

I understood that later.  It can easily fail, however, because:

  -- some data part of the instruction containing a 0xC3 (which
     can be avoided by disassembling the targetted function
     completely), or

  -- if the inlined code happens to contain just the right number
     of calls---if the constructor of std::vector is inline, for
     example, but it calls the constructor of a base class (which
     might or might not be inlined---I haven't checked) and other
     compilers have been known to generate calls to check for
     stack overflow, or to set up exception handling, or

  -- simply whether the compiler feals like inlining the function
     or not---g++ will often inline even if the function isn't
     declared inline, and in other cases, will not inline even if
     it is declared inline (and I think this holds for all other
     compilers.

> As that program was a 5 minute hackup, it might very well fail
> to work as intended on your machine. It was just a reply on
> how to write a non-conforming program that can find out
> whether vector functions are inlined.

> > The very fact that you are getting different results
> > depending on optimization rather proves, in fact, that
> > you're not testing whether the function was declared inline
> > or not.

> gcc does no inlining without optimization.

> Yes, you are right:
> I don't test whether vector functions are *declared* inline,
> but whether they were compiled as inlines in this particular
> case. As modern optimizing compilers might also inline
> functions not declared as inline or the other way around, the
> output of the program is really not related to the
> declaration.

> > On my Linux box, your code says "was inlined" regardless of
> > the optimization level, or whether I compiled with or
> > without debugging.

> If you get "was inlined" without optimization, that indicates
> that the primitive logic of the program is unreliable. It
> might be a false positive induced by operand bytes treated as
> opcodes.

It may be because my aliases to compile without optimization
also request debugging mode.  Looking at the assembler output,
the line for the constructor contains three calls, however, when
compiled without optimizing (and none when compiled with)---the
code constructs a temporary allocator, which is passed to the
constructor of vector, and there is a call to both the
constructor and the destructor of this allocator.  If I suppress
the debugging checks, the calls to the constructor and the
destructor of the allocator disappear (perhaps these functions
are trivial in the non-debug version, but non-trivial in the
debug version).

> > If I examine the sources, however, the function reserve is
> > NOT inlined.

> While that might be the case, the constructor and destructor
> definitely *are* declared inline in the standard library as
> supplied by g++, version 4.3.2.

Yes, but the inline version calls a base class constructor,
which itself may or may not be declared inline.  (I haven't
looked.)

Anyway, depending on the options chosen, I get 0, 1 or three
call instructions for the first line of your function test.
Which was really my point---you can't tell from code how a
function was declared, because the compiler can do a lot of odd
things with it.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]