Created
May 28, 2013 18:24
-
-
Save johnbartholomew/5664925 to your computer and use it in GitHub Desktop.
A Clang plugin to generate warnings for non-const global variables.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -Wglobals Clang plugin | |
// | |
// Based on example plugins and searching Clang's API documentation. | |
// BEWARE! This is my first ever attempt at a Clang plugin. | |
// Makefile | |
#if 0 | |
warnglobals.so: WarnGlobals.cpp | |
clang++ -std=c++98 -shared -fPIC $$(llvm-config --cflags --libs support mc) -o "$@" $^ -L/usr/lib/llvm/ -lclang | |
.PHONY: run | |
run: warnglobals.so | |
clang++ -fsyntax-only -Xclang -load -Xclang ./warnglobals.so -Xclang -plugin -Xclang warn-globals test.cpp | |
.PHONY: clean | |
clean: | |
rm -f warnglobals.so | |
#endif | |
// TEST FILE -- copy out to test.cpp | |
#if 0 | |
#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; | |
} | |
#endif | |
#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"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment