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++?
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
.