Search code examples
c++includeforward-declarationclang++xerces

Error with both include and forward declaration


I am working on a huge codebase that uses Apache Xerces. I am building the code with clang++ and it gave an error.

In a particular .h file a.h, header for a.cpp, there is both forward declaration and include of header file of the class Attributes as follows -

#include <xercesc/sax2/Attributes.hpp>

and

namespace XERCES_CPP_NAMESPACE{
    class Attributes;
}

The file xercesc/sax2/Attributes.hpp has the code

XERCES_CPP_NAMESPACE_BEGIN
...<some code>...
class SAX2_EXPORT Attributes {
    ...<some code>... 
}
...<some code>...
XERCES_CPP_NAMESPACE_END

The error here while building the code with clang is

a.cpp:45:39: error: member access into incomplete type 'const obixercesc_2_8::Attributes'
a.h:20:10: forward declaration of 'obixercesc_2_8::obixercesc_2_8::Attributes'
    class Attributes;

This is the corresponding line from a.cpp which raises the error

void f(const XERCES_CPP_NAMESPACE::Attributes& attrs) {
 /* this line ---> */ const XMLCh * pAppName = attrs.getValue(X("appName"));

But this compiles perfectly fine when I comment out the forward declaration and include only the Attributes header in a.h. The code is also building when I use g++ instead of clang++.

I don't understand few things -

1) Why is it not building with clang++ when there are both forward declaration and include?

2) Why is error pointing to obixercesc_2_8::Attributes, but not XERCES_CPP_NAMESPACE::Attributes, the actual namespace of class Attributes?

3) Why is the code compiling with g++?


Solution

  • This is more a hypothesis than a solution, but anyway, here is a thought.

    For some reason you are forward-declaring Attributes erroneously in nested namespace obixercesc_2_8::obixercesc_2_8, and when you are referring to obixercesc_2_8::Attributes, CLang chooses your forward declaration over the implementation from Xerces because they are not in the same namespace (maybe because of a using namespace statement?). From its point-of-view you have two declarations of Attributes, one in obixercesc_2_8 and one in obixercesc_2_8::obixercesc_2_8. XERCES_CPP_NAMESPACE seems to be a macro that expands to obixercesc_2_8.