Bogus-looking syntax error when compiled -O2; no error if not. Expansion files (.ii) differ with/without too.
Created attachment 5531 [details] Compiler output (-v -save-temps) *with no -O2*
Created attachment 5532 [details] Compiler output (-v -save-temps) *with -O2*
Created attachment 5533 [details] Source code (-save-temps) *with no -O2*
Created attachment 5534 [details] Source code (-save-temps) *with -O2*
I need a good C++ person here but the difference happens only with -funit-at-a-time, looks like unit at a time is instainating different templates.
Here is a reduced testcase: --------------------------- template <typename T> struct X { virtual void foo() const { T::foo(1); } }; template<typename T> void bar(T v) { throw X<T>(); } inline void bar() { bar(1); } --------------------------------- The testcase is illegal, since there is no int::foo function, but we get this: g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc -funit-at-a-time x.cc: In member function `void X<T>::foo() const [with T = int]': x.cc:13: instantiated from here x.cc:3: error: `foo' is not a member of `int' In other words, with -funit-at-a-time, gcc tries to lay down a copy of bar(), where it doesn't do that without that flag. Since there is no reason to do that, this is a bug, I guess. W.
Mark, I think bug should be closed as will not fix as the code is invalid but compiling without -funit-at-a-time does not reject unless you want to keep it open for that in which case this is not a regression at all.
Beg pardon, but code is *not* invalid. Standard clearly states that unused template functions are not compiled and may be invalid for particular template arguments. In the reduced example the template function is invoked from a non-inline function, but in the original the template is invoked from another template that is not itself instantiated. I think :-) Even in the reduced - what's the point of "inline" if it causes unused template intantiations to clutter the executable with template bodies that cannot be called? If the standard required that the template be syntax checked just because it appears in an (uncalled) inline, then syntax check it - but don't instantiate it and clutter the executable.
(In reply to comment #8) > Beg pardon, but code is *not* invalid. Standard clearly states that unused template functions are not compiled and may be invalid for particular template arguments. In the reduced example the template function is invoked from a non-inline function, but in the original the template is invoked from another template that is not itself instantiated. I think :-) The above is correct but note the the function is virtual. > Even in the reduced - what's the point of "inline" if it causes unused template intantiations to clutter the executable with template bodies that cannot be called? If the standard required that the template be syntax checked just because it appears in an (uncalled) inline, then syntax check it - but don't instantiate it and clutter the executable. I could not find any where in my reading of the standard which says that inline functions are just syntax checked and not done the full name lookup and such. Note nothing ever gets emitted for code that is corrected.
I think the validity of the test is immaterial -- the testcase shows a deficiency in the implementation of -funit-at-a-time. This is certainly not a big deal, but it's a bug that we should eventually get around to fixing. I concede that it should be lower priority than most of our bugs, and shouldn't block a release. W.
*** Bug 13942 has been marked as a duplicate of this bug. ***
With -funit-at-a-time, the C++ front-end (decl2.c:maybe_emit_vtables) emits the vtable for struct X, while it doesn't do so without -funit-at-a-time. The difference in the behaviour boils down to this macro in cp-tree.h: /* DECL_NEEDED_P holds of a declaration when we need to emit its definition. This is true when the back-end tells us that the symbol has been referenced in the generated code. If, however, we are not generating code, then it is also true when a symbol has just been used somewhere, even if it's not really needed. We need anything that isn't comdat, but we don't know for sure whether or not something is comdat until end-of-file. */ #define DECL_NEEDED_P(DECL) \ ((at_eof && TREE_PUBLIC (DECL) && !DECL_COMDAT (DECL)) \ || (DECL_ASSEMBLER_NAME_SET_P (DECL) \ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \ || (((flag_syntax_only || flag_unit_at_a_time) && TREE_USED (DECL)))) According to the comment, it seems that -funit-at-a-time behaves like -fsyntax-only, that is it may emit DECLs that are not really needed.
The code is indeed invalid. When a complete object of type X<int> is created, the compiler is allowed to emit the vtable for X, and that permits instantiating the virtual functions. However, this is an optimization deficiency in -funit-at-a-time. I've therefore assigned the bug to Jan.
Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > ------- Additional Comments From mmitchel at gcc dot gnu dot org 2004-02-03 09:25 ------- > The code is indeed invalid. > > When a complete object of type X<int> is created, the compiler is allowed to > emit the vtable for X, and that permits instantiating the virtual functions. > > However, this is an optimization deficiency in -funit-at-a-time. Yes, the problem is that all dependencies are resolved before optimization is done. I am planning to address this by doing early pass of tree-ssa optimization before inlining and cgraph construction. That way we should catch majority of cases. I also plan to deffer output of datastrctures to the very end of compilation and use information about what was really used by backend. Honza > > I've therefore assigned the bug to Jan. > > -- > What |Removed |Added > ---------------------------------------------------------------------------- > AssignedTo|unassigned at gcc dot gnu |jh at suse dot cz > |dot org | > Status|NEW |ASSIGNED > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768 > > ------- You are receiving this mail because: ------- > You are on the CC list for the bug, or are watching someone who is.
Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function hubicka at ucw dot cz wrote: >------- Additional Comments From hubicka at ucw dot cz 2004-02-03 11:00 ------- >Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > > >>------- Additional Comments From mmitchel at gcc dot gnu dot org 2004-02-03 09:25 ------- >>The code is indeed invalid. >> >>When a complete object of type X<int> is created, the compiler is allowed to >>emit the vtable for X, and that permits instantiating the virtual functions. >> >>However, this is an optimization deficiency in -funit-at-a-time. >> >> > >Yes, the problem is that all dependencies are resolved before >optimization is done. I am planning to address this by doing early pass >of tree-ssa optimization before inlining and cgraph construction. That >way we should catch majority of cases. >I also plan to deffer output of datastrctures to the very end of >compilation and use information about what was really used by backend. > >Honza > What do you suggest, if anything, for GCC 3.4? (This is potentially a regression with respect to the size of the generated code. There is lots of code with trivial constructors that, after inlining, will be eliminated.)
Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > ------- Additional Comments From mark at codesourcery dot com 2004-02-03 15:46 ------- > Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles > unused inline function > > hubicka at ucw dot cz wrote: > > >------- Additional Comments From hubicka at ucw dot cz 2004-02-03 11:00 ------- > >Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > > > > > > >>------- Additional Comments From mmitchel at gcc dot gnu dot org 2004-02-03 09:25 ------- > >>The code is indeed invalid. > >> > >>When a complete object of type X<int> is created, the compiler is allowed to > >>emit the vtable for X, and that permits instantiating the virtual functions. > >> > >>However, this is an optimization deficiency in -funit-at-a-time. > >> > >> > > > >Yes, the problem is that all dependencies are resolved before > >optimization is done. I am planning to address this by doing early pass > >of tree-ssa optimization before inlining and cgraph construction. That > >way we should catch majority of cases. > >I also plan to deffer output of datastrctures to the very end of > >compilation and use information about what was really used by backend. > > > >Honza > > > What do you suggest, if anything, for GCC 3.4? > > (This is potentially a regression with respect to the size of the > generated code. There is lots of code with trivial constructors that, > after inlining, will be eliminated.) I think we can keep it as it is now. I did quite huge amount of measuring and the unit-at-a-time is a win for majority of C++ programs, so I think the other benefits outweight it. It is quite dificult to solve with current framework, unforutnately, since we discover such facts only during RTL expansion pass and because we mix analysis and optimization, we want to order things in a way so calees are compiled first and thus we can't take them back. My CFG transparent expansion/inlining project is all about getting this chicken-egg problem broken up. Note that if the constructor get inlined to all call sites, it's out of line copy will be elliminated. We only lose in the case the constructor is not inlined for whatever reason and then the call site is removed later, for instance because the code turns out to be dead. This don't seems to be terribly common in real code from what I've seen. Another problem is that we don't have ability to elliminate static cosntructors when static variable turns out to be unnecesary. Richard did some work on this, but didn't finished it, I plan to look into it after tree-SSA merge. Honza > > > > -- > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768 > > ------- You are receiving this mail because: ------- > You are the assignee for the bug, or are watching the assignee.
Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > ------- Additional Comments From jh at suse dot cz 2004-02-03 15:53 ------- > Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > > > > ------- Additional Comments From mark at codesourcery dot com 2004-02-03 15:46 ------- > > Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles > > unused inline function > > > > hubicka at ucw dot cz wrote: > > > > >------- Additional Comments From hubicka at ucw dot cz 2004-02-03 11:00 ------- > > >Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > > > > > > > > > > >>------- Additional Comments From mmitchel at gcc dot gnu dot org 2004-02-03 09:25 ------- > > >>The code is indeed invalid. > > >> > > >>When a complete object of type X<int> is created, the compiler is allowed to > > >>emit the vtable for X, and that permits instantiating the virtual functions. > > >> > > >>However, this is an optimization deficiency in -funit-at-a-time. > > >> > > >> > > > > > >Yes, the problem is that all dependencies are resolved before > > >optimization is done. I am planning to address this by doing early pass > > >of tree-ssa optimization before inlining and cgraph construction. That > > >way we should catch majority of cases. > > >I also plan to deffer output of datastrctures to the very end of > > >compilation and use information about what was really used by backend. > > > > > >Honza > > > > > What do you suggest, if anything, for GCC 3.4? > > > > (This is potentially a regression with respect to the size of the > > generated code. There is lots of code with trivial constructors that, > > after inlining, will be eliminated.) > > I think we can keep it as it is now. I did quite huge amount of > measuring and the unit-at-a-time is a win for majority of C++ programs, > so I think the other benefits outweight it. > It is quite dificult to solve with current framework, unforutnately, > since we discover such facts only during RTL expansion pass and because > we mix analysis and optimization, we want to order things in a way so > calees are compiled first and thus we can't take them back. My CFG > transparent expansion/inlining project is all about getting this > chicken-egg problem broken up. > > Note that if the constructor get inlined to all call sites, it's out of > line copy will be elliminated. We only lose in the case the > constructor is not inlined for whatever reason and then the call site is > removed later, for instance because the code turns out to be dead. This > don't seems to be terribly common in real code from what I've seen. > > Another problem is that we don't have ability to elliminate static > cosntructors when static variable turns out to be unnecesary. Richard > did some work on this, but didn't finished it, I plan to look into it > after tree-SSA merge. Actually looking deeper into this specific testcase, I believe that if the source program was correct, unit-at-a-time would emit empty file too, since there is no entry point from where the call in question can be reached, so it just builds the program representation in memory prior optimizing it. This is because of your request to change C++ frontend that way (my initial patch didn't force instantiation of all TREE_USED templates). I think this is correct thing - GCC should error out on this testcase. Why it is considered a bug at first place? Honza > > Honza > > > > > > > > -- > > > > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768 > > > > ------- You are receiving this mail because: ------- > > You are the assignee for the bug, or are watching the assignee. > > > -- > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768 > > ------- You are receiving this mail because: ------- > You are the assignee for the bug, or are watching the assignee.
Jan believes that this is (a) hard to fix, and (b) not critical based on measurements of real code, so I've postponed this until GCC 3.5.
Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function > > ------- Additional Comments From mmitchel at gcc dot gnu dot org 2004-02-03 16:02 ------- > Jan believes that this is (a) hard to fix, and (b) not critical based on > measurements of real code, so I've postponed this until GCC 3.5. Actually I think this bugreport shall be closed (or maintained as bug about accepting illegal code in non-unit-at-a-time compilation mode), see me other mail. Honza > > -- > What |Removed |Added > ---------------------------------------------------------------------------- > Target Milestone|3.4.0 |3.5.0 > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13768 > > ------- You are receiving this mail because: ------- > You are on the CC list for the bug, or are watching someone who is.
Subject: Re: [3.4/3.5 Regression] -funit-at-a-time compiles unused inline function >Actually looking deeper into this specific testcase, I believe that if >the source program was correct, unit-at-a-time would emit empty file >too, since there is no entry point from where the call in question can >be reached, so it just builds the program representation in memory prior >optimizing it. >This is because of your request to change C++ frontend that way (my >initial patch didn't force instantiation of all TREE_USED templates). > >I think this is correct thing - GCC should error out on this testcase. >Why it is considered a bug at first place? > > If the vtable will not actually be emitted to the object file, then this is not a bug, and you can close it.
Resummizing and changing the target.
No, sorry, the code is not invalid per-se. It's just unspecified, so both the unit-at-a-time and the function-at-a-time behaviours are correct. Mark is asking if the vtable is emitted or not. If it's not emitted, then it's correct that the function is not instantiated, and the bug is invalid.
Whether it's valid, invalid or unspecified, the user's mental model of the compilation process expects that the set of syntax errors reported should not depend on the optimization level on the command line. I suggest (for general user happiness and fewer nuisance reports) that the behavior be made invariant - whatever behavior is chosen. Ivan
Making the behaviour consistent across function-at-a-time and unit-at-a-time is almost impossible in this testcase without major reorganization of function-at-a-time. I would rather vote to drop function-at-a-time on some of future releases. Honza
Fixed by: 2004-07-29 Mark Mitchell <mark@codesourcery.com> * cp-tree.h (IDENTIFIER_REPO_CHOSEN): Define. (lang_decl_flags): Narrow the width of "languages". Add repo_available_p. (DECL_NEEDED_P): Remove. (FOR_EACH_CLONE): New macro. (DECL_REPO_AVAILABLE_P): Likewise. ......