| //===--- StaticallyConstructedObjectsCheck.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 "StaticallyConstructedObjectsCheck.h" |
| |
| using namespace clang::ast_matchers; |
| |
| namespace clang { |
| namespace tidy { |
| namespace fuchsia { |
| |
| namespace { |
| AST_MATCHER(Expr, isConstantInitializer) { |
| return Node.isConstantInitializer(Finder->getASTContext(), false); |
| } |
| |
| AST_MATCHER(VarDecl, isGlobalStatic) { |
| return Node.getStorageDuration() == SD_Static && !Node.isLocalVarDecl(); |
| } |
| } // namespace |
| |
| void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) { |
| // Constructing global, non-trivial objects with static storage is |
| // disallowed, unless the object is statically initialized with a constexpr |
| // constructor or has no explicit constructor. |
| Finder->addMatcher( |
| traverse(TK_AsIs, |
| varDecl( |
| // Match global, statically stored objects... |
| isGlobalStatic(), |
| // ... that have C++ constructors... |
| hasDescendant(cxxConstructExpr(unless(allOf( |
| // ... unless it is constexpr ... |
| hasDeclaration(cxxConstructorDecl(isConstexpr())), |
| // ... and is statically initialized. |
| isConstantInitializer()))))) |
| .bind("decl")), |
| this); |
| } |
| |
| void StaticallyConstructedObjectsCheck::check( |
| const MatchFinder::MatchResult &Result) { |
| if (const auto *D = Result.Nodes.getNodeAs<VarDecl>("decl")) |
| diag(D->getBeginLoc(), "static objects are disallowed; if possible, use a " |
| "constexpr constructor instead"); |
| } |
| |
| } // namespace fuchsia |
| } // namespace tidy |
| } // namespace clang |