Bug 19948

Summary: [4.0 Regression] ICE: tree check: expected class 'declaration', have 'exceptional' (error_mark) in pushtag, at cp/name-lookup.c:4658
Product: gcc Reporter: David Fang <fang>
Component: c++Assignee: Kriang Lerdsuwanakij <lerdsuwa>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, lerdsuwa
Priority: P2 Keywords: ice-on-valid-code, rejects-valid
Version: 4.0.0   
Target Milestone: 4.0.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2005-03-13 14:25:34
Bug Depends on:    
Bug Blocks: 16995    

Description David Fang 2005-02-14 07:37:59 UTC
ICE: tree check: expected class 'declaration', have 'exceptional' (error_mark) in pushtag, at cp/name-
lookup.c:4658

g++ is very confused about forward-declared classes and friend classes.  
--------------------------------------------------
GCC version info:

Using built-in specs.
Configured with: ../configure --prefix=/sw --prefix=/sw/lib/gcc4 --enable-
languages=c,c++,objc,f95,java --infodir=/share/info --with-gmp=/sw --with-as=/sw/lib/odcctools/
bin/as --with-ld=/sw/lib/odcctools/bin/ld --with-included-gettext --host=powerpc-apple-darwin
Thread model: posix
gcc version 4.0.0 20050130 (experimental)
 /sw/lib/gcc4/libexec/gcc/powerpc-apple-darwin/4.0.0/cc1plus -E -quiet -v -D__DYNAMIC__ 
-D__APPLE_CC__=1 gcc4death.cc -fPIC -fpch-preprocess -o gcc4death.ii
ignoring nonexistent directory "/sw/lib/gcc4/lib/gcc/powerpc-apple-darwin/4.0.0/../../../../powerpc-
apple-darwin/include"
#include "..." search starts here:
#include <...> search starts here:
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin/4.0.0/../../../../include/c++/4.0.0
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin/4.0.0/../../../../include/c++/4.0.0/powerpc-apple-
darwin
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin/4.0.0/../../../../include/c++/4.0.0/backward
 /usr/local/include
 /sw/lib/gcc4/include
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin/4.0.0/include
 /usr/include
 /System/Library/Frameworks
 /Library/Frameworks
End of search list.
 /sw/lib/gcc4/libexec/gcc/powerpc-apple-darwin/4.0.0/cc1plus -fpreprocessed gcc4death.ii -fPIC 
-quiet -dumpbase gcc4death.cc -auxbase gcc4death -version -o gcc4death.s
GNU C++ version 4.0.0 20050130 (experimental) (powerpc-apple-darwin)
        compiled by GNU C version 3.3 20030304 (Apple Computer, Inc. build 1640).
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096

------------------------------------------
command to reproduce:

g++-4.0 -c gcc4death.cc -o gcc4death.o

------------------------------------------
gcc error feedback:

util/persistent_object_manager_gcc4death.h: In instantiation of 'util::persistent_traits<whatever>':
gcc4death.cc:7:   instantiated from here
util/persistent_object_manager_gcc4death.h:480: error: use of 'persistent_object_manager' is 
ambiguous
util/persistent_object_manager_gcc4death.h:67: error:   first declared as 'class util::
persistent_object_manager' here
util/persistent_object_manager_gcc4death.h:28: error:   also declared as 'struct util::memory::
persistent_object_manager' here
util/persistent_object_manager_gcc4death.h:480: error: conflicting declaration 'struct util::
persistent_object_manager'
util/persistent_object_manager_gcc4death.h:67: error: 'class util::persistent_object_manager' has a 
previous declaration as 'class util::persistent_object_manager'
util/persistent_object_manager_gcc4death.h:480: internal compiler error: tree check: expected class 
'declaration', have 'exceptional' (error_mark) in pushtag, at cp/name-lookup.c:4658
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.


=============== "gcc4death.ii" ================
# 1 "gcc4death.cc"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "gcc4death.cc"

# 1 "util/persistent_object_manager_gcc4death.h" 1
# 24 "util/persistent_object_manager_gcc4death.h"
namespace util {
class persistent_object_manager;
namespace memory {
class pointer_manipulator {
friend class persistent_object_manager;
};
}
}
# 45 "util/persistent_object_manager_gcc4death.h"
namespace util {
# 58 "util/persistent_object_manager_gcc4death.h"
using namespace memory;
# 67 "util/persistent_object_manager_gcc4death.h"
class persistent_object_manager {
# 467 "util/persistent_object_manager_gcc4death.h"
};
# 479 "util/persistent_object_manager_gcc4death.h"
template <class T>
class persistent_traits {
friend class persistent_object_manager;
# 525 "util/persistent_object_manager_gcc4death.h"
};


}
# 3 "gcc4death.cc" 2

class whatever { };

static const
util::persistent_traits<whatever> __blah__;
=================== end-of-file =================

other comments:
The above code should produce the following error as reported by gcc-3.3 and gcc-3.4.

gcc4death.cc:7: error: uninitialized const `__blah__'
Comment 1 Andrew Pinski 2005-02-14 15:02:02 UTC
Confirmed, here is a testcase which is valid code (yes I checked to make sure that it is valid):

namespace util
{
  class persistent_object_manager;
  namespace memory
  {
    class pointer_manipulator
    {
      friend class persistent_object_manager;
    };
  }
}
namespace util
{
  using namespace memory;
  
  class persistent_object_manager
  {
  };
  
  template <class T>  class persistent_traits
  {
    friend class persistent_object_manager;
  };
}

static util::persistent_traits<int> __blah__;
: Search converges between 2004-11-25-014001-trunk (#656) and 2004-11-25-161001-trunk 
(#657).

I think this is very related to PR 4403 (it might be fixed by that patch too).  And related to PR 19403.
Comment 2 David Fang 2005-02-27 06:25:36 UTC
1) Has anyone figured out a workaround to this yet?  I suppose I could remove some using 
namespace declarations and prefix type names with namespaces...  I'll keep tinkering around.  

2) New and perhaps closely related bug?
g++-4.0 is also rejecting-valid the following code, tweaked from Andrew's example to reproduce 
something else I'm doing in my project: (using same version info as reported here)

//-------------- snip ---------------
namespace util
{
  class persistent_object_manager;
  namespace memory
  {
    class pointer_manipulator
    {
      friend class persistent_object_manager;
    };
  }
}
namespace util
{
  using namespace memory;

  class persistent_object_manager
  {
        static const int foo;
  };
}

namespace util {
        const int
        persistent_object_manager::foo = 666;
}
//--------------- end snip ----------------
g++-4.0 -c blah.cc -o blah.o
reports:
blah.cc:24: error: 'persistent_object_manager' has not been declared

whereas 3.3 and 3.4 accept the code.  
Removing the friend declaration on line 8 allows g++-4.0 to compile.  
Removing the using namespace memory line 14 also allows g++-4.0 to compile.  

It was difficult to find a bug in the bugzilla database with the same characteristics.  
Should I file a separate bug report for this one or just tack it on to this one because it's probably closely 
related?  

-- David
Comment 3 David Fang 2005-02-27 06:53:05 UTC
Workaround discovered (shortly after I asked for one, fancy that!)

Declaring:

        using util::persistent_object_manager;

inside the 'memory' namespace before the first friend declaration (after line 5) results in correct output 
for the examples listed above.  The using declaration prevents (I think) injection of the friend class 
declaration into the 'memory' namespace and further confusion.  Not a bad idea in practice, actually.  
Comment 4 Giovanni Bajo 2005-02-27 08:49:50 UTC
Please, always fill a different bugreport for different testcases, unless you 
can prove it is exactly the same problem (and here you surely cannot). Then 
add references forth and back.
Comment 5 Kriang Lerdsuwanakij 2005-02-28 06:22:51 UTC
If you want a work around, simply use this in the first 'friend'
declaration:

  friend class util::persistent_object_manager;

There is still uncertainty about whether name from 'using' 
declaration/directive is allowed (DR138) so your workaround 
may not work in the future.
Comment 6 Kriang Lerdsuwanakij 2005-03-13 14:25:33 UTC
Look like caused by my changes to pushtag.
Comment 7 Kriang Lerdsuwanakij 2005-03-16 14:14:38 UTC
Mainline is fixed.  No error message is produced which is
the correct behavior.  Will recheck 4.0 branch.
Comment 8 Kriang Lerdsuwanakij 2005-03-16 16:05:43 UTC
Cannot reproduce it now on 4.0.  I think it's already fixed.
Comment 9 Kriang Lerdsuwanakij 2005-03-16 16:09:32 UTC
ICE no longer reproducible.