diff options
| author | Yuanfang Chen <yuanfang.chen@sony.com> | 2019-08-21 20:00:01 +0000 |
|---|---|---|
| committer | Yuanfang Chen <yuanfang.chen@sony.com> | 2019-08-21 20:00:01 +0000 |
| commit | f24c1e6b515ed7aec632b5e4c6019e7dd0972efa (patch) | |
| tree | e6b14700bbf4d54dc4905e27cdaf87e43deeb1e5 /clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp | |
| parent | ed18e70c86f6de353cebe0a8faa961a341c74d27 (diff) | |
| download | bcm5719-llvm-f24c1e6b515ed7aec632b5e4c6019e7dd0972efa.tar.gz bcm5719-llvm-f24c1e6b515ed7aec632b5e4c6019e7dd0972efa.zip | |
[clang-tidy] Check for dynamically initialized statics in headers.
Finds instances where variables with static storage are initialized dynamically in header files.
Reviewed By: aaron.ballman, alexfh
Patch by Charles Zhang!
Differential Revision: https://reviews.llvm.org/D62829
llvm-svn: 369568
Diffstat (limited to 'clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp new file mode 100644 index 00000000000..2c6f3b13fa7 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp @@ -0,0 +1,68 @@ +//===--- DynamicStaticInitializersCheck.cpp - clang-tidy ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DynamicStaticInitializersCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace bugprone { + +AST_MATCHER(clang::VarDecl, hasConstantDeclaration) { + const Expr *Init = Node.getInit(); + if (Init && !Init->isValueDependent()) { + if (Node.isConstexpr()) + return true; + return Node.checkInitIsICE(); + } + return false; +} + +DynamicStaticInitializersCheck::DynamicStaticInitializersCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + RawStringHeaderFileExtensions(Options.getLocalOrGlobal( + "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { + if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions, + HeaderFileExtensions, ',')) { + llvm::errs() << "Invalid header file extension: " + << RawStringHeaderFileExtensions << "\n"; + } +} + +void DynamicStaticInitializersCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions); +} + +void DynamicStaticInitializersCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus || getLangOpts().ThreadsafeStatics) + return; + Finder->addMatcher( + varDecl(hasGlobalStorage(), unless(hasConstantDeclaration())).bind("var"), + this); +} + +void DynamicStaticInitializersCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var"); + SourceLocation Loc = Var->getLocation(); + if (!Loc.isValid() || !utils::isPresumedLocInHeaderFile(Loc, *Result.SourceManager, + HeaderFileExtensions)) + return; + // If the initializer is a constant expression, then the compiler + // doesn't have to dynamically initialize it. + diag(Loc, "static variable %0 may be dynamically initialized in this header file") + << Var; +} + +} // namespace bugprone +} // namespace tidy +} // namespace clang |

