Created
May 8, 2017 15:36
-
-
Save MaxKellermann/758ed94d66cc744fe163bee0f854352d to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* | |
* 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