Skip to content

Instantly share code, notes, and snippets.

@sgielen
Last active November 23, 2023 01:09
Show Gist options
  • Save sgielen/8685438 to your computer and use it in GitHub Desktop.
Save sgielen/8685438 to your computer and use it in GitHub Desktop.
Clang plugin by John Bartholomew for finding globals and non-const static variables, unpacked
warnglobals.so
// -Wglobals Clang plugin
//
// Based on example plugins and searching Clang's API documentation.
// BEWARE! This is my first ever attempt at a Clang plugin.
//
// Written by John Bartholomew <jpa.bartholomew@gmail.com>
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
namespace {
class PrintGlobalsVisitor : public clang::RecursiveASTVisitor<PrintGlobalsVisitor> {
public:
explicit PrintGlobalsVisitor(clang::ASTContext *Context, clang::DiagnosticsEngine *Diagnostics)
: Context(Context), Diagnostics(Diagnostics) {}
bool VisitVarDecl(clang::VarDecl *D) {
const clang::SourceManager &SM = Context->getSourceManager();
if (D->hasGlobalStorage() && !D->getType().isConstQualified()) {
clang::FullSourceLoc loc = Context->getFullLoc(D->getLocStart());
if (!SM.isInSystemHeader(loc)) {
clang::DiagnosticsEngine &D = *Diagnostics;
unsigned int id = D.getCustomDiagID(clang::DiagnosticsEngine::Warning, "global variable");
D.Report(loc, id);
}
}
return true;
}
private:
clang::ASTContext *Context;
clang::DiagnosticsEngine *Diagnostics;
};
class PrintGlobalsConsumer : public clang::ASTConsumer {
public:
explicit PrintGlobalsConsumer(clang::ASTContext *Context, clang::DiagnosticsEngine *Diagnostics)
: Visitor(Context, Diagnostics) {}
virtual void HandleTranslationUnit(clang::ASTContext &Context) {
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
}
private:
PrintGlobalsVisitor Visitor;
};
class PrintGlobalsAction : public clang::PluginASTAction {
protected:
clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) {
return new PrintGlobalsConsumer(&CI.getASTContext(), &CI.getDiagnostics());
}
bool ParseArgs(const clang::CompilerInstance &CI,
const std::vector<std::string>& args) {
// To be written...
return true;
}
};
}
static clang::FrontendPluginRegistry::Add<PrintGlobalsAction>
X("warn-globals", "generate warnings for non-const global variables");
warnglobals.so: ClangWarnGlobals.cpp
clang++ -g -O0 -std=c++98 -shared -fPIC $$(llvm-config --cflags --ldflags --libs support mc) -o "$@" $^ -lclang
.PHONY: run
run: warnglobals.so
clang++ -Xclang -load -Xclang ./warnglobals.so -Xclang -plugin -Xclang warn-globals test.cpp
.PHONY: clean
clean:
rm -f warnglobals.so
#include <iostream>
static int s_some_global = 42;
static const int s_some_const_global = 42;
static void some_function_with_a_static() {
static int s_static_local = 42;
}
namespace some_namespace {
namespace some_sub_namespace {
int public_global = 42;
}
class some_class {
static const int static_const_member = 42;
static int static_member;
};
}
int some_namespace::some_class::static_member = 42;
int main(int argc, char **argv) {
std::cout << "global value: " << s_some_global << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment