Skip to content

Instantly share code, notes, and snippets.

@MaxKellermann
Created May 8, 2017 15:36
Show Gist options
  • Save MaxKellermann/758ed94d66cc744fe163bee0f854352d to your computer and use it in GitHub Desktop.
Save MaxKellermann/758ed94d66cc744fe163bee0f854352d to your computer and use it in GitHub Desktop.
/*
* clang plugin which emits warnings for functions which should have a
* "noexcept" specification.
*
* Author: Max Kellermann <[email protected]>
*
* This file is distributed under the University of Illinois Open Source
* License.
*/
#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"
#include "clang/Sema/Sema.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
namespace {
bool
IsPure(const Decl &d)
{
return d.hasAttr<PureAttr>() || d.hasAttr<ConstAttr>();
}
bool
IsNoexcept(const FunctionType &t)
{
if (const auto *p = dyn_cast<FunctionProtoType>(&t))
return isNoexceptExceptionSpec(p->getExceptionSpecType());
return false;
}
bool
IsNoexcept(const QualType &qt)
{
const auto *t = qt.getTypePtr();
if (const auto *ft = dyn_cast<FunctionType>(t))
return IsNoexcept(*ft);
return false;
}
bool
IsNoexcept(const ValueDecl &d)
{
return IsNoexcept(d.getType());
}
class PureNoexceptConsumer : public ASTConsumer {
CompilerInstance &Instance;
public:
explicit PureNoexceptConsumer(CompilerInstance &Instance)
: Instance(Instance) {}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
auto &diag = Instance.getDiagnostics();
for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
const Decl *D = *i;
if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D))
if (IsPure(*ND) && !IsNoexcept(*ND)) {
const auto ID = diag.getCustomDiagID(clang::DiagnosticsEngine::Warning,
"'pure' function without 'noexcept'");
diag.Report(ND->getLocation(), ID);
}
}
return true;
}
};
class PureNoexceptAction : public PluginASTAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef) override {
return llvm::make_unique<PureNoexceptConsumer>(CI);
}
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string> &args) override {
if (!args.empty()) {
llvm::errs() << "This plugin has no arguments\n";
return false;
}
return true;
}
};
}
static FrontendPluginRegistry::Add<PureNoexceptAction>
X("pure-noexcept", "Show missing 'noexcept' attributes for 'pure' and 'const' functions");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment