public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-07 10:46 igusarov
  0 siblings, 0 replies; 9+ messages in thread
From: igusarov @ 2003-04-07 10:46 UTC (permalink / raw)
  To: gcc-gnats


>Number:         10332
>Category:       c++
>Synopsis:       Template classes are not instantiated correctly in presense of #pragma pack()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Apr 07 10:46:02 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Akella corp.
>Release:        3.2
>Organization:
>Environment:
System: FreeBSD gate.studio1001.akella.ru 4.4-RELEASE FreeBSD 4.4-RELEASE #11: Thu Jun 6 12:58:54
host: i386-unknown-freebsd4.4
build: i386-unknown-freebsd4.4
target: i386-unknown-freebsd4.4
configured with: /usr/src/gcc-3.2/configure --prefix=/usr
>Description:
The packing size used for class template instantiation is set by the #pragma pack directive which is in effect at the point of template instantiation (whether implicit or explicit), rather then by the #pragma pack directive which was in effect at the point of class template definition.

This is not a correct behaviour, because in a complex program it's hard to control the point of implicit instantiation of any given template class. And the wrong packing size is leading to incorrect code generation if a given template class was instantiadet with different packing sizes in different translation units. Consider the code examples in Howtorepeat section.

Related problem reports: other/4957
>How-To-Repeat:
1. Try to compile and run the following example (all code examples in this report could be compiled with "g++ file.cpp", no special command-line options are required)

//---------------------------- begin example
#include <stdio.h>

#pragma pack(4)

template <typename X >
struct T
{
    char      x1;   /* Usually 3 padding bytes are added after x1 member. */
    int       x2;
};

#pragma pack(1)
template T<int>;   /* T<int> is instantiated here */

#pragma pack(4)
template T<float>; /* T<float> is instantiated here */

int main()
{
 printf("sizeof T<int>   = %d\n", sizeof(T<int>));
 printf("sizeof T<float> = %d\n", sizeof(T<float>));
}
//---------------------------- end example

(parameter types 'int' and 'float' are not used in any way, they are required just to separate two template instances)

The output is:
sizeof T<int>   = 5
sizeof T<float> = 8
Which shows that the size (and member offsets) of the template class depends on the #pragma pack at place of instantiation.

2. There is a more complicated example which shows how to trigger this bug accidently.
Unpack the attached archive and compile two sample translation units (tu01.cpp and tu02.cpp) in alignment_bug/case_02 directory. The only difference between these translation units is the order of #include directives which causes different implicit instantiation of the same template class (include guards are skipped in such simple case). This test case repeats the behaviour reported in other/4957.
>Fix:
Do not rely on implicit instantiation. Instantiate all desired template classes explicitly (sic!).
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: application/x-compressed; name="alignment_bug_02.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="alignment_bug_02.tgz"

H4sIAGdSkT4AA+1ZXWvbMBTNs3/FJWWQlJFa8hcsXWHsuWywFvYwKIqtJGb+wpa7eqX/fVe2kziJ
s4zNdVir85BE0tW9cq7Psa7FAn8RhTwSd7N8cTF4FoCpO5YFAwDiWER+I/T6u26AY5smNR3LsdCM
Og4dgPU8y9lGngmWAgz8RZ6xNL4/ZPdjyXnQx4L6BdvKv8syfqeTju+DP8+/RQhx0Mwkjq7y3wfa
888fWJgEfOImSQcxiK5jcg/n37acFf8x7xTNbJMYA9A7iH0Urzz/Z37kBrnH4TITnh9Plleadpak
bBEySJj7fWSONU1wvBuYQCNRJDxiIYevcKVlIs1dATfaoybT6C7lHynxQKb4eXEOt1nOgqAAA315
nh8tYFYIngFLOWAH94DNBU9xAoQ8nPF0AucXpTM/EvXd8UCn2tN0Z1VkvFnUzSUaX9URqwb4GXrA
zEbCRxMPlhwjouu9a2t4mQcxk35KL1XjsB+5vpD50Wgsrz5JsT0fDTP/J4/nq0UAvIc33rdo+Baq
gVE1MB5PW6bUEfenVANy0pPWef7b+E9Pqf+UlPpvm0r/+0B7/kWuk47Ef3Bc/6ltrPOPpmhmWSZR
+t8HWvR/3TUMCzdgWTZZDrVGr09kR6NNdwzCIhYolJu5vxPL0XXxSVp/lNbjPfnbGi0lsHsNfM04
yH96Iv4TWvLfcBT/+8Df8J/u8J8o/v+3aOf/OvGdxDjGf2Kt+a9TYsj6T7ctxf8+0FbarSu766Lk
3U59h9XdVokmC7StcWNn3KwKuFNfqkILDvG/qeD/GuMY/8Gma/4TU77/cwgxFf/7wIbqm+esBu8g
yWeB764UoHxtgTKgaPzS0M5/uaXrLsZR/lvr9z+6I3+jCOjq+d8LcG8e+BHX7mPf0+ZxPGoyHj6k
C7llV5vuF4sD/Kd98p8a5ob/Rnn+56j6vx/snqqUWz587H/GNve+lJuDev/fOOAB8OoioHFQg51Y
Cax6papUvdvO9gUGHp/KAmHv2OnU/42CgoKCgsJLxS9RufPqACgAAA==


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-15 13:46 Igor A. Goussarov
  0 siblings, 0 replies; 9+ messages in thread
From: Igor A. Goussarov @ 2003-04-15 13:46 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: "Igor A. Goussarov" <igusarov@akella.com>
To: rittle@labs.mot.com
Cc: velco@fadata.bg, ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org,
   gcc-prs@gcc.gnu.org, nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c++/10332: Template classes are not instantiated correctly in
 presense of #pragma pack()
Date: Tue, 15 Apr 2003 17:39:08 +0400

 Loren James Rittle wrote:
  > The proper fix is to either (a) document what is happening,
  > only available if no external spec says we are doing something wrong,
  > or (b) retain the global flag but capture it's value and bind it for
  > use when the C++ template is actually instantiated.
 
     The whole realm of #pragma is out of scope of the C++ standard. And 
 I don't know which other documents could be considered relyable external 
 specs...
     I can suggest examining the behaviour of other compilers (to keep 
 the behaviour consistent) or taking this question of the correct 
 behaviour to the trusted expert or community.
 
 Best Regards,
 Igor
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-14 23:46 Loren James Rittle
  0 siblings, 0 replies; 9+ messages in thread
From: Loren James Rittle @ 2003-04-14 23:46 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: Loren James Rittle <rittle@latour.rsch.comm.mot.com>
To: igusarov@akella.com
Cc: velco@fadata.bg, ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org,
   gcc-prs@gcc.gnu.org, nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
Date: Mon, 14 Apr 2003 18:42:04 -0500 (CDT)

 In article <3E9A8732.7000600@akella.com>,
 "Igor A. Goussarov" <igusarov@akella.com> writes:
 
 >>>> What is the scope of #pragma pack ? 
 Igor> Apparently, from the line it is encountered at till the end of
 Igor> translation unit or till the next #pragma pack.
 >> In that case holding it in a global variable looks appropriate, no ?
 
 >     Up to a certain degree, yes. The concept of "packing" is applied to 
 > structures, thus the packing size is a property of each structure. 
 > Holding it in a global variable is justifiable only if there's 
 > absolutely no chance that this variable could potentially be altered 
 > before it is used to create an internal compiler representation of the 
 > structure in question. I grant that C plain structures are 
 > "instantiated" immediately at the point of their definition. C++ 
 > templates are not. [...]
 
 >     By now, I'm most interested in figuring out the point of view of the 
 > gcc developers: do you tend to think that the current interference of 
 > #pragma pack and templates is an undocumented feature or an incorrect 
 > behaviour?
 
 Agreed.  The proper fix is to either (a) document what is happening,
 only available if no external spec says we are doing something wrong,
 or (b) retain the global flag but capture it's value and bind it for
 use when the C++ template is actually instantiated.
 
 I'd favor (b) unless disallowed by the spec(s) that we claim to
 implement for this pragma.  This is either an easy patch (if the
 infrastructure allows it) or a nightmare (if it doesn't).  FYI, if
 updating the documentation is not enough, this is outside my area to
 productively fix.
 
 Regards,
 Loren


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-14 10:06 Igor A. Goussarov
  0 siblings, 0 replies; 9+ messages in thread
From: Igor A. Goussarov @ 2003-04-14 10:06 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: "Igor A. Goussarov" <igusarov@akella.com>
To: Momchil Velikov <velco@fadata.bg>
Cc: ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
   nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c++/10332: Template classes are not instantiated correctly in
 presense of #pragma pack()
Date: Mon, 14 Apr 2003 14:02:26 +0400

 Momchil Velikov wrote:
  >>>>>>"Igor" == Igor A Goussarov <igusarov@akella.com> writes:
  >     Igor> Momchil Velikov wrote:
  >     >> What is the scope of #pragma pack ?
  >
  >     Igor>     Apparently, from the line it is encountered at till the 
 end of
  >     Igor> translation unit or till the next #pragma pack.
  >
  > In that case holding it in a global variable looks appropriate, no ?
 
     Up to a certain degree, yes. The concept of "packing" is applied to 
 structures, thus the packing size is a property of each structure. 
 Holding it in a global variable is justifiable only if there's 
 absolutely no chance that this variable could potentially be altered 
 before it is used to create an internal compiler representation of the 
 structure in question. I grant that C plain structures are 
 "instantiated" immediately at the point of their definition. C++ 
 templates are not.
     The compiler still have to store the last packing size in a global 
 var (or a stack, to support #pragma push/pop). But as soon as a struct 
 definition is encountered (whether a template or not), the value of that 
 global var should've been copied to that structure description. And the 
 compiler should later use the value from the structure description 
 rather then from the global var. In other words, the global var only 
 stores the current packing size and is used _solely_ to initialize the 
 packing size of each new defined struct.
     As Loren has mentioned, #pragma pack came from C compiler, and 
 probably its interference with C++ entities was not fully considered...
     By now, I'm most interested in figuring out the point of view of the 
 gcc developers: do you tend to think that the current interference of 
 #pragma pack and templates is an undocumented feature or an incorrect 
 behaviour?
 
 Best Regards,
 Igor
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-14  9:06 Momchil Velikov
  0 siblings, 0 replies; 9+ messages in thread
From: Momchil Velikov @ 2003-04-14  9:06 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: Momchil Velikov <velco@fadata.bg>
To: "Igor A. Goussarov" <igusarov@akella.com>
Cc: ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
	nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
Date: 14 Apr 2003 11:57:04 +0300

 >>>>> "Igor" == Igor A Goussarov <igusarov@akella.com> writes:
 
     Igor> Momchil Velikov wrote:
     >> What is the scope of #pragma pack ?
 
     Igor>     Apparently, from the line it is encountered at till the end of
     Igor> translation unit or till the next #pragma pack.
 
 In that case holding it in a global variable looks appropriate, no ?
 
 ~velco


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-14  8:56 Igor A. Goussarov
  0 siblings, 0 replies; 9+ messages in thread
From: Igor A. Goussarov @ 2003-04-14  8:56 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: "Igor A. Goussarov" <igusarov@akella.com>
To: Momchil Velikov <velco@fadata.bg>
Cc: ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
   nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c++/10332: Template classes are not instantiated correctly in
 presense of #pragma pack()
Date: Mon, 14 Apr 2003 12:50:28 +0400

 Momchil Velikov wrote:
 > What is the scope of #pragma pack ?
 
     Apparently, from the line it is encountered at till the end of 
 translation unit or till the next #pragma pack.
     Er... Was it one of them trick questions?
 
 Best Regards,
 Igor
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-11 13:56 Momchil Velikov
  0 siblings, 0 replies; 9+ messages in thread
From: Momchil Velikov @ 2003-04-11 13:56 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: Momchil Velikov <velco@fadata.bg>
To: "Igor A. Goussarov" <igusarov@akella.com>
Cc: ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
	nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
Date: 11 Apr 2003 16:52:55 +0300

 >>>>> "Igor" == Igor A Goussarov <igusarov@akella.com> writes:
 
     Igor>     Being a programmer myself I can see where all this comes from: it
     Igor> is likely that gcc uses some global variable for storing the current
     Igor> packing size instead of associating the packing size with each
     Igor> individual data structure. Thus, when there is a need to create an
     Igor> instance of a template class, the compiler simply uses the current
     Igor> value of that global variable.
 
 What is the scope of #pragma pack ?
 
 ~velco


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-11 11:46 Igor A. Goussarov
  0 siblings, 0 replies; 9+ messages in thread
From: Igor A. Goussarov @ 2003-04-11 11:46 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR c++/10332; it has been noted by GNATS.

From: "Igor A. Goussarov" <igusarov@akella.com>
To: ljrittle@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
   nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: c++/10332: Template classes are not instantiated correctly in
 presense of #pragma pack()
Date: Fri, 11 Apr 2003 15:46:35 +0400

 Hello Loren and the team,
 
     Thank you for taking time to examine this another report!
     Unfortunately the fix you suggested isn't very good for two reasons:
 a) __atribute__ is much less portable (compared to #pragma pack which is 
 supported at least by gcc, MSVC, BCB and CodeWarrior)
 b) the fix doesn't address the problem.
 
     I _don't_ want to have packed template classes. I want to have 
 ordinary templates, which use default packing and alignment. But: if 
 this template occasiously got instantiated at the point where "#pragma 
 pack" was set to some obscure value, then the template instance somewhy 
 become packed! This is the behaviour I object to.
 
     Let me put it in other words:
 1. I wrote a template class which doesn't need any packing.
 2. I was using this template class in many translation units all over 
 the program.
 3. One day I wrote another not-template class (or POD struct), which 
 _has_ to be packed.
 4. If the template class in question is implicitly instantiated from 
 within the said packed struct, it miraculously becomes packed.
 5. More disasters follows when several TUs are linked together...
 
     So you see, I'm not trying to apply packing to template classes 
 intentionally. Well, in a sense, packing and templates are used 
 together, since a single translation unit contains them both. But it 
 doesn't look right to me that some class affects the instantiation of a 
 previously defined template. This is kind of... not right.
     For example, imagine that the layout of vtable for polymorphic 
 classes was dependent on the use of some feature in some other place in 
 the program. This would come as a surprise to the developer of the said 
 class, because he always firmly belived that since the class was fully 
 defined nothing more can change it.
     So did I, and so was I surprised. Actually, I've called this 
 behaviour "a bug" because I get used to think that once a class was 
 defined nothing more can change it (and inherently its layout).
 
     Being a programmer myself I can see where all this comes from: it is 
 likely that gcc uses some global variable for storing the current 
 packing size instead of associating the packing size with each 
 individual data structure. Thus, when there is a need to create an 
 instance of a template class, the compiler simply uses the current value 
 of that global variable.
     If this is the case, then changing such behaviour of the compiler is 
 not easy. I mean, it looks more like design issue rather then like 
 implementation bug. Also I can see that such situation is impossible to 
 detect and thus no diagnostic message is ever possible... Pity.
 
 Best Regards,
 Igor
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: c++/10332: Template classes are not instantiated correctly in presense of #pragma pack()
@ 2003-04-11  1:16 ljrittle
  0 siblings, 0 replies; 9+ messages in thread
From: ljrittle @ 2003-04-11  1:16 UTC (permalink / raw)
  To: gcc-bugs, gcc-prs, igusarov, nobody

Synopsis: Template classes are not instantiated correctly in presense of #pragma pack()

State-Changed-From-To: open->analyzed
State-Changed-By: ljrittle
State-Changed-When: Fri Apr 11 01:16:40 2003
State-Changed-Why:
    Igor created a small test case which displays the behavior he considers a bug and included an analysis of the failure.  I will add only one comment: because a feature is hard to use in a complex program does not imply that the feature has incorrect behaviour.  In this case, #pragma pack came from a C ABI.  It is doubtful anyone ever looked at the rules as applied to C ++.  E.g. no documentation on such interactions is found in tm.texi.  One correct resolution to this PR is to update our documentation.  (I will also add another user-level fix.)

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=10332


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2003-04-15 13:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-07 10:46 c++/10332: Template classes are not instantiated correctly in presense of #pragma pack() igusarov
2003-04-11  1:16 ljrittle
2003-04-11 11:46 Igor A. Goussarov
2003-04-11 13:56 Momchil Velikov
2003-04-14  8:56 Igor A. Goussarov
2003-04-14  9:06 Momchil Velikov
2003-04-14 10:06 Igor A. Goussarov
2003-04-14 23:46 Loren James Rittle
2003-04-15 13:46 Igor A. Goussarov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).