compiler bug or language feature?

Hi,

I don't know if I encountered a compiler bug in clang 3.3 or if this is one of the many subtle c++ exceptional cases:

When I try to compile the attached file (using: clang++ -std=c++11 test.cpp) I receive a compiler error:

"test.cpp:15:42: error: identifier 'SmartPtrType' in object destruction expression does not name a type
  ~SmartUnion() {m_sptr.SmartPtrType<T>::~SmartPtrType(); }"

g++ compiles the file without problem.

clang compiles it, too, if I explicitly introduce a typedef for SmartPtrType<T> and call this typedef name instead:

typedef SmartPtrType<T> smartptr_type;
~SmartUnion() {m_sptr.smartptr_type::~smartptr_type(); }

Is this a subtle language feature or a compiler bug?

Daniel

test.cpp (621 Bytes)

Hi,

I don't know if I encountered a compiler bug in clang 3.3 or if this is
one of the many subtle c++ exceptional cases:

When I try to compile the attached file (using: clang++ -std=c++11
test.cpp) I receive a compiler error:

"test.cpp:15:42: error: identifier 'SmartPtrType' in object destruction
expression does not name a type
~SmartUnion() {m_sptr.SmartPtrType<T>::~**SmartPtrType(); }"

g++ compiles the file without problem.

clang compiles it, too, if I explicitly introduce a typedef for
SmartPtrType<T> and call this typedef name instead:

typedef SmartPtrType<T> smartptr_type;
~SmartUnion() {m_sptr.smartptr_type::~**smartptr_type(); }

Is this a subtle language feature or a compiler bug?

I believe this is a language feature because the expression is ambiguous if
m_sptr is type dependent (which I assume it is)

The other solution, rather than introducing a typedef, is to use the
'template' keyword:

~SmartUnion() {m_sptr.template SmartPtrType<T>::~**SmartPtrType(); }

When I add the 'template' keyword as suggested clang gives me the very same error. g++ still eats it without problem.

You need to write

m_sptr.SmartPtrType::~SmartPtrType****();

Hmm, if I do this it gives me another error:

test.cpp:15:42: error: 'SmartPtrType' following the 'template' keyword does not refer to a template
  ~SmartUnion() {m_sptr.SmartPtrType<T>::~SmartPtrType<T>(); }

Again, g++ takes it without complaining.

Since I noticed that my original attachment got scrubbed I am pasting the modified test program directly. Perhaps the context will help to sort things out:

#include <memory>
#include <string>
using namespace std;

//comment this in to see the compiler error
#define show_compiler_error 1

template<typename T, template<class> class SmartPtrType = shared_ptr>
struct SmartUnion
{
     SmartUnion() {new(&m_sptr) SmartPtrType<T>();}

#ifdef show_compiler_error
  ~SmartUnion() {m_sptr.SmartPtrType<T>::~SmartPtrType<T>(); }
#else
  typedef SmartPtrType<T> smartptr_type;
   ~SmartUnion() {m_sptr.smartptr_type::~smartptr_type(); }
#endif

  union {
      SmartPtrType<T> m_sptr;
      T * m_ptr;
  };

};

using namespace std;
int main()
{
     SmartUnion<string,shared_ptr> smu;

     return 0;
}

Hmm, if I do this it gives me another error:

test.cpp:15:42: error: 'SmartPtrType' following the 'template' keyword
does not refer to a template
~SmartUnion() {m_sptr.SmartPtrType<T>::~SmartPtrType<T>(); }

This is a bug. (Also, there's no 'template' keyword here, so the diagnostic
is simultaneously wrong in two different ways.)

Again, g++ takes it without complaining.

Since I noticed that my original attachment got scrubbed I am pasting the
modified test program directly. Perhaps the context will help to sort
things out:

Thanks, this helped.

Thank you all for your help. I filed now a bug report ( http://llvm.org/bugs/show_bug.cgi?id=17528) for this issue.