DynamicStaticInitializersCheck.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. //===--- DynamicStaticInitializersCheck.cpp - clang-tidy ------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "DynamicStaticInitializersCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. using namespace clang::ast_matchers;
  12. namespace clang::tidy::bugprone {
  13. AST_MATCHER(clang::VarDecl, hasConstantDeclaration) {
  14. const Expr *Init = Node.getInit();
  15. if (Init && !Init->isValueDependent()) {
  16. if (Node.isConstexpr())
  17. return true;
  18. return Node.evaluateValue();
  19. }
  20. return false;
  21. }
  22. DynamicStaticInitializersCheck::DynamicStaticInitializersCheck(StringRef Name,
  23. ClangTidyContext *Context)
  24. : ClangTidyCheck(Name, Context),
  25. RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
  26. "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
  27. if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
  28. HeaderFileExtensions,
  29. utils::defaultFileExtensionDelimiters())) {
  30. this->configurationDiag("Invalid header file extension: '%0'")
  31. << RawStringHeaderFileExtensions;
  32. }
  33. }
  34. void DynamicStaticInitializersCheck::storeOptions(
  35. ClangTidyOptions::OptionMap &Opts) {
  36. Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
  37. }
  38. void DynamicStaticInitializersCheck::registerMatchers(MatchFinder *Finder) {
  39. Finder->addMatcher(
  40. varDecl(hasGlobalStorage(), unless(hasConstantDeclaration())).bind("var"),
  41. this);
  42. }
  43. void DynamicStaticInitializersCheck::check(const MatchFinder::MatchResult &Result) {
  44. const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var");
  45. SourceLocation Loc = Var->getLocation();
  46. if (!Loc.isValid() || !utils::isPresumedLocInHeaderFile(Loc, *Result.SourceManager,
  47. HeaderFileExtensions))
  48. return;
  49. // If the initializer is a constant expression, then the compiler
  50. // doesn't have to dynamically initialize it.
  51. diag(Loc, "static variable %0 may be dynamically initialized in this header file")
  52. << Var;
  53. }
  54. } // namespace clang::tidy::bugprone