[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