[cfe-dev] Insert static data member definitions

Alfred Krohmer devkid at devkid.net
Tue Jan 22 07:47:09 PST 2013


Hi!

I'm trying to add something reflection-like to C++ via a clang plugin. 
In the test file that I want to compile I've got the following piece of 
code:

#include <iostream>

template<class T> struct reflection {};

class MyTestClass {};

int main () {
     std::cout << reflection<MyTestClass>::name << "\n";
     return 0;
}

As you can see, I expect the "reflection" class template to provide a 
static data member called "name" of the type const char*. The output 
here should obviously be "MyTestClass". I have realized this so far:

ClassTemplateSpecializationDecl *rd = instantiate(
         ctx,
         CI.getSema(),
         decl->getDeclContext(),
         reflectionDef,
{TemplateArgument(decl->getTypeForDecl()->getCanonicalTypeInternal())});

QualType charType (new BuiltinType(BuiltinType::Kind::Char_S), 0);
charType.addConst();
charType = ctx.getPointerType(charType);

auto field = VarDecl::Create(
         ctx,
         rd,
         {}, {},
         &ctx.Idents.get("name"),
         charType,
         ctx.getTrivialTypeSourceInfo(charType, SourceLocation()),
         StorageClass::SC_Static, StorageClass::SC_Static
);
CI.getSema().SetMemberAccessSpecifier(field, nullptr, 
AccessSpecifier::AS_public);
field->setConstexpr(true);
field->setInitStyle(VarDecl::InitializationStyle::CInit);
Expr *expr = StringLiteral::Create(ctx, r.name, 
StringLiteral::StringKind::Ascii, false, charType, SourceLocation());
field->setInit(expr);
rd->addDecl(field);
reflectionDef->getDeclContext()->addDecl(rd);

Where "decl" is the corresponding CXXRecordDecl for the MyTestClass, 
"reflectionDef" is the ClassTemplateDecl of the "reflection" template 
class, "r.name" contains the name of the Class ("MyTestClass") and the 
"instantiate" function is taken from this post: 
http://clang-developers.42468.n3.nabble.com/How-to-perform-template-substitution-in-the-clang-library-td4028413.html#a4028622

When I run clang over the test code with my plugin loaded, it compiles 
just fine, but the linker seems not being able to find the definition of 
the "name" data member:

/tmp/test-sLkoVj.o:../examples/test.cpp:function main: error: undefined 
reference to 'reflection<A>::name'

The relevant output of the decleration context dump:

template <class T> struct reflection {
};
class A {
};
struct reflection {
     static const char *name = "A";
};

Do I need to tell the Sema object that it has to instantiate the data 
member correctly? (And if yes, how do I do this?)

PS: I am resending this message because I first posted it via the Nabble 
interface, which seems to strip out the code I included in the message 
and I didn't get an answer yet. I hope this isn't causing any trouble.



More information about the cfe-dev mailing list