Skip to content

Instantly share code, notes, and snippets.

@FederAndInk
Last active May 11, 2020 17:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FederAndInk/d7e0867b15fa09758e1abfb95a9e20d4 to your computer and use it in GitHub Desktop.
Save FederAndInk/d7e0867b15fa09758e1abfb95a9e20d4 to your computer and use it in GitHub Desktop.
Printing test with clang index (IndexASTConsumer)
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Index/IndexDataConsumer.h>
#include <clang/Index/IndexingAction.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
#include <llvm/ADT/DenseMap.h>
#include <llvm/ADT/DenseMapInfo.h>
#include <llvm/Support/CommandLine.h>
#include <string_view>
using namespace clang;
using namespace clang::tooling;
using namespace clang::index;
using namespace llvm;
std::string generatePointingArrowAt(unsigned int c)
{
return std::string(c - 1, ' ') + '^';
}
PrintingPolicy default_policy(ASTContext const* ctx)
{
PrintingPolicy pp(ctx->getLangOpts());
pp.AnonymousTagLocations = false;
pp.TerseOutput = true;
pp.PolishForDeclaration = true;
pp.ConstantsAsWritten = true;
pp.SuppressTagKeyword = false;
pp.SuppressUnwrittenScope = false;
pp.SuppressInitializers = false;
pp.FullyQualifiedName = false;
return pp;
}
class IndexDC : public clang::index::IndexDataConsumer
{
ASTContext* ctx = nullptr;
public:
void initialize(ASTContext& ctx) override
{
this->ctx = &ctx;
}
bool handleDeclOccurrence(const Decl* d, SymbolRoleSet roles,
ArrayRef<SymbolRelation> relations, SourceLocation loc,
ASTNodeInfo ast_node) override
{
SourceManager& sm = ctx->getSourceManager();
auto buf = sm.getBufferData(sm.getFileID(loc));
auto l = sm.getPresumedLineNumber(loc);
auto c = sm.getPresumedColumnNumber(loc);
outs() << "Presumed: " << l << ":" << c << "\n";
l = sm.getExpansionLineNumber(loc);
c = sm.getExpansionColumnNumber(loc);
outs() << "Expansion: " << l << ":" << c << "\n";
l = sm.getSpellingLineNumber(loc);
c = sm.getSpellingColumnNumber(loc);
outs() << "Spelling: " << l << ":" << c << "\n";
outs() << "Roles: ";
printSymbolRoles(roles, outs());
outs() << "\n";
outs() << "Kind: " << d->getDeclKindName() << "\n";
if (ast_node.OrigE)
{
outs() << "expr: " << ast_node.OrigE->getStmtClassName() << "\n";
}
if (auto* nd = dyn_cast<NamedDecl>(d))
{
outs() << "name: " << nd->getDeclName().getAsString() << "\n";
}
SmallVector<StringRef, 1> lines;
buf.split(lines, "\n");
outs() << l << "|" << lines[l - 1].str() << "\n";
outs() << generatePointingArrowAt(c + 1 + std::to_string(l).size()) << "\n\n";
return true;
}
};
class ASTDeclNodeLister : public ASTConsumer,
public RecursiveASTVisitor<ASTDeclNodeLister>
{
public:
ASTDeclNodeLister(raw_ostream* Out = nullptr) : Out(Out ? *Out : llvm::outs()) {}
void HandleTranslationUnit(ASTContext& Context) override
{
TraverseDecl(Context.getTranslationUnitDecl());
}
bool shouldWalkTypesOfTypeLocs() const
{
return false;
}
bool VisitNamedDecl(NamedDecl* D)
{
D->printQualifiedName(Out);
Out << '\n';
return true;
}
bool VisitCXXConstructExpr(CXXConstructExpr const* expr)
{
if (auto* nd = dyn_cast<NamedDecl>(expr->getConstructor()))
{
outs() << "name: " << nd->getDeclName().getAsString() << "\n";
}
return true;
}
private:
raw_ostream& Out;
};
class Action : public clang::ASTFrontendAction
{
IndexingOptions opts{.SystemSymbolFilter = IndexingOptions::SystemSymbolFilterKind::All,
.IndexFunctionLocals = true,
.IndexImplicitInstantiation = true,
.IndexParametersInDeclarations = true,
.IndexTemplateParameters = true};
public:
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& ci,
StringRef inFile) override
{
return createIndexingASTConsumer(std::make_shared<IndexDC>(), opts,
ci.getPreprocessorPtr());
}
};
class Action2 : public clang::ASTFrontendAction
{
public:
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& ci,
StringRef inFile) override
{
return std::make_unique<ASTDeclNodeLister>();
}
};
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static cl::OptionCategory MyToolCategory("my-tool options");
// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char** argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
auto& comp = OptionsParser.getCompilations();
ClangTool tool(comp, OptionsParser.getSourcePathList());
return tool.run(newFrontendActionFactory<Action>().get());
// clang::SyntaxOnlyAction
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment