[cfe-dev] Further AST spelunking
Peter Stirling
peter at pjstirling.plus.com
Wed Oct 8 06:02:29 PDT 2014
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?
More information about the cfe-dev
mailing list