Hi again,
I'm still plodding away at my SWIG alternative. As I said in my previous email, typedefs that are declared within templates but which do not depend on any of the template arguments are held in the AST as children of a CXXRecordDecl ignorant of the fact that it should be a template and what its arguments should be. This is a problem for me because it means that I can't print a properly scoped name to identify the type for c++ code. I have managed to work around this by adding a check for whether a typedef is a child of a CXXRecordDecl but should really be a child of a template. The code I'm using appears to work, but I'd like to double-check that it is appropriate:
bool shouldBeTemplate(clang::DeclContext const* context) {
if(context->getDeclKind() == clang::Decl::CXXRecord) {
auto record = llvm::cast<clang::CXXRecordDecl>(context);
auto dname = record->getDeclName();
// there will always be a parent
auto cursor = context->getParent()->lookup(dname);
for(auto named : cursor) {
if(llvm::isa<clang::ClassTemplateDecl>(named)) {
return true;
}
}
}
return false;
}
Another issue is that, while it is safe to handle values that are pointers to incomplete structure types, it is illegal to call a function that takes an argument value or returns a result value that is an incomplete type. My first attempt was to check for RecordTypes and call CXXRecordDecl::getDefinition(), but for some (but confusingly to me, not all) template types getDefinition() returns NULL even though the type isn't incomplete, is this expected? The code that I'm using is below, I also wonder whether getCanonicalDecl() is overkill here:
bool isIncompleteType(clang::QualType inType) {
if(inType->isRecordType()) {
auto realType = inType->getAs<clang::RecordType>();`
auto decl = realType->getDecl()->getCanonicalDecl();
if(decl->getDefinition() ||
llvm::isa<clang::ClassTemplateSpecializationDecl>(decl)) {
return false;
}
else {
return true;
}
}
return false;
}
I've also discovered that parsing code that calls a builtin function causes a no-argument, returns-int declaration to be inserted. It's been a while, but as I remember, in C this kind of declaration actually means that the function takes an unspecified number of arguments, but each one passed should be promoted to the size of an int (did they update this since pointers became much larger than ints?). In C++ it means something rather different. It seems a bit odd to me that builtin functions don't have the correct declaration inserted, since the compiler must have them on hand somewhere.
Finally, I need to generate the list of base classes that a derived class can be implicitly converted to. I have an intuitive understanding of when it should work, but when I try to think of an algorithm to sort out arbitrarily-evil trees combining virtual and normal inheritance I go a bit cross-eyed. Can anyone point me at something that will help me figure this out?