http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48518
Summary: Inconsistent instantiation behavior depending on operator overloading Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: jyass...@gcc.gnu.org The following program instantiates wrap<Undefined>, but a very similar program that doesn't call an overloaded operator doesn't: $ cat test.ii template <class C> struct scoped_ptr { C& operator*() const { return *ptr_; } C* ptr_; }; template<class T> struct wrap { T must_be_complete; }; class Undefined; struct S { wrap<Undefined> &content() const { return *content_; } scoped_ptr<wrap<Undefined> > content_; }; $ trunk/g++ -c test.ii test.ii: In instantiation of ‘wrap<Undefined>’: test.ii:13:13: instantiated from here test.ii:8:5: error: ‘wrap<T>::must_be_complete’ has incomplete type test.ii:10:7: error: forward declaration of ‘struct Undefined’ $ However: $ cat test_works.ii template <class C> struct scoped_ptr { C& get() const { return *ptr_; } C* ptr_; }; template<class T> struct wrap { T must_be_complete; }; class Undefined; struct S { wrap<Undefined> &content() const { return content_.get(); } scoped_ptr<wrap<Undefined> > content_; }; $ ~/opensource/gcc/git/install/bin/g++ -c test_works.ii $ This was a change from gcc-4.4 to gcc-4.5. Comeau agrees with gcc here, but clang disagrees. This is confusing because the operator that makes a difference is on scoped_ptr<wrap<Undefined>>, not on wrap<Undefined>.