Add a clang-tidy flag to support temporary destructor-aware analysis (workaround for bug 15599).
Reviewers: alexfh Subscribers: jordan_rose, klimek, djasper, cfe-commits Differential Revision: http://reviews.llvm.org/D3556 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@207652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
2e1ac36c3e
Коммит
10c783a34e
|
@ -173,8 +173,9 @@ private:
|
|||
} // namespace
|
||||
|
||||
ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
|
||||
ClangTidyContext &Context)
|
||||
: Context(Context), CheckFactories(new ClangTidyCheckFactories) {
|
||||
ClangTidyContext &Context, const ClangTidyOptions &Options)
|
||||
: Context(Context), CheckFactories(new ClangTidyCheckFactories),
|
||||
Options(Options) {
|
||||
for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
|
||||
E = ClangTidyModuleRegistry::end();
|
||||
I != E; ++I) {
|
||||
|
@ -207,16 +208,21 @@ clang::ASTConsumer *ClangTidyASTConsumerFactory::CreateASTConsumer(
|
|||
if (!CheckFactories->empty())
|
||||
Consumers.push_back(Finder.newASTConsumer());
|
||||
|
||||
AnalyzerOptionsRef Options = Compiler.getAnalyzerOpts();
|
||||
Options->CheckersControlList = getCheckersControlList();
|
||||
if (!Options->CheckersControlList.empty()) {
|
||||
Options->AnalysisStoreOpt = RegionStoreModel;
|
||||
Options->AnalysisDiagOpt = PD_NONE;
|
||||
Options->AnalyzeNestedBlocks = true;
|
||||
Options->eagerlyAssumeBinOpBifurcation = true;
|
||||
AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
|
||||
// FIXME: Remove this option once clang's cfg-temporary-dtors option defaults
|
||||
// to true.
|
||||
AnalyzerOptions->Config["cfg-temporary-dtors"] =
|
||||
Options.AnalyzeTemporaryDtors ? "true" : "false";
|
||||
|
||||
AnalyzerOptions->CheckersControlList = getCheckersControlList();
|
||||
if (!AnalyzerOptions->CheckersControlList.empty()) {
|
||||
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
|
||||
AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
|
||||
AnalyzerOptions->AnalyzeNestedBlocks = true;
|
||||
AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true;
|
||||
ento::AnalysisASTConsumer *AnalysisConsumer = ento::CreateAnalysisConsumer(
|
||||
Compiler.getPreprocessor(), Compiler.getFrontendOpts().OutputFile,
|
||||
Options, Compiler.getFrontendOpts().Plugins);
|
||||
AnalyzerOptions, Compiler.getFrontendOpts().Plugins);
|
||||
AnalysisConsumer->AddDiagnosticConsumer(
|
||||
new AnalyzerDiagnosticConsumer(Context));
|
||||
Consumers.push_back(AnalysisConsumer);
|
||||
|
@ -288,7 +294,7 @@ void ClangTidyCheck::setName(StringRef Name) {
|
|||
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
|
||||
SmallVector<ClangTidyError, 8> Errors;
|
||||
clang::tidy::ClangTidyContext Context(&Errors, Options);
|
||||
ClangTidyASTConsumerFactory Factory(Context);
|
||||
ClangTidyASTConsumerFactory Factory(Context, Options);
|
||||
return Factory.getCheckNames();
|
||||
}
|
||||
|
||||
|
@ -326,7 +332,7 @@ void runClangTidy(const ClangTidyOptions &Options,
|
|||
ClangTidyASTConsumerFactory *ConsumerFactory;
|
||||
};
|
||||
|
||||
Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context)));
|
||||
Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context, Options)));
|
||||
}
|
||||
|
||||
void handleErrors(SmallVectorImpl<ClangTidyError> &Errors, bool Fix) {
|
||||
|
|
|
@ -94,7 +94,8 @@ class ClangTidyCheckFactories;
|
|||
|
||||
class ClangTidyASTConsumerFactory {
|
||||
public:
|
||||
ClangTidyASTConsumerFactory(ClangTidyContext &Context);
|
||||
ClangTidyASTConsumerFactory(ClangTidyContext &Context,
|
||||
const ClangTidyOptions &Options);
|
||||
~ClangTidyASTConsumerFactory();
|
||||
|
||||
/// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
|
||||
|
@ -112,6 +113,7 @@ private:
|
|||
ClangTidyContext &Context;
|
||||
ast_matchers::MatchFinder Finder;
|
||||
std::unique_ptr<ClangTidyCheckFactories> CheckFactories;
|
||||
ClangTidyOptions Options;
|
||||
};
|
||||
|
||||
/// \brief Fills the list of check names that are enabled when the provided
|
||||
|
|
|
@ -18,6 +18,7 @@ struct ClangTidyOptions {
|
|||
ClangTidyOptions() : EnableChecksRegex(".*") {}
|
||||
std::string EnableChecksRegex;
|
||||
std::string DisableChecksRegex;
|
||||
bool AnalyzeTemporaryDtors;
|
||||
};
|
||||
|
||||
} // end namespace tidy
|
||||
|
|
|
@ -46,12 +46,20 @@ static cl::opt<bool> ListChecks("list-checks",
|
|||
cl::desc("List all enabled checks and exit."),
|
||||
cl::init(false), cl::cat(ClangTidyCategory));
|
||||
|
||||
static cl::opt<bool> AnalyzeTemporaryDtors(
|
||||
"analyze-temporary-dtors",
|
||||
cl::desc("Enable temporary destructor-aware analysis in clang-analyzer- "
|
||||
"checks."),
|
||||
cl::init(false),
|
||||
cl::cat(ClangTidyCategory));
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory);
|
||||
|
||||
clang::tidy::ClangTidyOptions Options;
|
||||
Options.EnableChecksRegex = Checks;
|
||||
Options.DisableChecksRegex = DisableChecks;
|
||||
Options.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors;
|
||||
|
||||
// FIXME: Allow using --list-checks without positional arguments.
|
||||
if (ListChecks) {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// RUN: clang-tidy -checks=clang-analyzer-core.NullDereference -disable-checks='' -analyze-temporary-dtors %s -- > %t.log
|
||||
// FileCheck complains if the input file is empty, so add a dummy line.
|
||||
// RUN: echo foo >> %t.log
|
||||
// RUN: FileCheck %s < %t.log
|
||||
|
||||
struct NoReturnDtor {
|
||||
~NoReturnDtor() __attribute__((noreturn));
|
||||
};
|
||||
|
||||
extern bool check(const NoReturnDtor &);
|
||||
|
||||
// CHECK-NOT: warning
|
||||
void testNullPointerDereferencePositive() {
|
||||
int *value = 0;
|
||||
// CHECK: [[@LINE+1]]:10: warning: Dereference of null pointer (loaded from variable 'value') [clang-analyzer-core.NullDereference]
|
||||
*value = 1;
|
||||
}
|
||||
|
||||
// CHECK-NOT: warning
|
||||
void testNullPointerDereference() {
|
||||
int *value = 0;
|
||||
if (check(NoReturnDtor())) {
|
||||
// This unreachable code causes a warning if we don't run with -analyze-temporary-dtors
|
||||
*value = 1;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче