How to print the forward declaration of an object visited through RecursiveASTVisitor ?

Hi,

I am writing a tool that has to generate forward declarations of the classes, functions and templates.

So, if it encounters,

class Foo {
};

The output should be:

class Foo;

I am just trying to consider a specific case first by overriding VisitCXXRecordDecl .

The print method of the declaration seems to print the whole definition.
Declaration->print(llvm::outs(),clang::PrintingPolicy(clang::LangOptions()));

Is there a general way of doing this?

Or should I try to generate declaration in an adhoc way?

Something like…

llvm::outs()<< GET TYPE << GET NAME << ATTRIBUTES ;

As a follow up to this question, I am now generating the (forward)declarations manually, not having found anything in the API to do it.

The only thing that I can’t get working is the way to get the type name of a non-type template parameter.
If I have:
template<typename T, typename U, int V> class foo
{};

From where do I get the string “int” when overriding VisitClassTemplateDecl ?

I can get the names of the identifiers T, U, V as:

clang::TemplateParameterList* tl=Declaration->getTemplateParameters();
for(auto it=tl->begin();it!=tl->end();++it) {
p->getName();
}

But I can’t find any obvious way to get its type as a string.
p->getDeclKindName() only returns “TemplateTypeParm” or “NonTypeTemplateParm”

If the NamedDecl* is a NonTypeTemplateParmDecl* then it has a
getType() member function (inherited from ValueDecl) returning a
QualType. You might need to be careful in case
NonTypeTemplateParmDecl::isParameterPack() is true; I don't know what
getType() returns for a parameter pack (though it clearly wouldn't be
hard to check).

-- James

Thanks, that was it.

The code is hairy though.

I’d be helpful if there was some function for this.

bool VisitClassTemplateDecl(clang::ClassTemplateDecl* Declaration) {

if(Declaration->getName().startswith(“_”)

Declaration->getName().size()==0)
return true;

std::vector scope;
clang::DeclContext* c=Declaration->getTemplatedDecl()->getEnclosingNamespaceContext();
while(c->isNamespace()) {
clang::NamespaceDecl* n=llvm::castclang::NamespaceDecl(c);
scope.emplace_back(n->getNameAsString());
c=c->getParent();
}

llvm::outs()<<“template <”;
clang::TemplateParameterList* tl=Declaration->getTemplateParameters();
for(auto it=tl->begin();it!=tl->end();++it) {
if(llvm::isaclang::NonTypeTemplateParmDecl(it)) {
clang::NonTypeTemplateParmDecl
td=llvm::castclang::NonTypeTemplateParmDecl(*it);
llvm::outs()<getType().getAsString();
}
else llvm::outs()<<“typename”;
llvm::outs()<<" “<<(*it)->getName();
if((it+1)!=tl->end())
llvm::outs()<<”, “;
}
llvm::outs()<<”> class "
<< Declaration->getName() << “;\n”;

return false;
}

Using dump or print prints the whole body, but I have to display only what is necessary for a forward declaration.