1 //===--- StaticallyConstructedObjectsCheck.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 9 #include "StaticallyConstructedObjectsCheck.h" 10 11 using namespace clang::ast_matchers; 12 13 namespace clang { 14 namespace tidy { 15 namespace fuchsia { 16 17 namespace { 18 AST_MATCHER(Expr, isConstantInitializer) { 19 return Node.isConstantInitializer(Finder->getASTContext(), false); 20 } 21 22 AST_MATCHER(VarDecl, isGlobalStatic) { 23 return Node.getStorageDuration() == SD_Static && !Node.isLocalVarDecl(); 24 } 25 } // namespace 26 27 void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) { 28 // Constructing global, non-trivial objects with static storage is 29 // disallowed, unless the object is statically initialized with a constexpr 30 // constructor or has no explicit constructor. 31 32 // Constexpr requires C++11 or later. 33 if (!getLangOpts().CPlusPlus11) 34 return; 35 36 Finder->addMatcher(varDecl( 37 // Match global, statically stored objects... 38 isGlobalStatic(), 39 // ... that have C++ constructors... 40 hasDescendant(cxxConstructExpr(unless(allOf( 41 // ... unless it is constexpr ... 42 hasDeclaration(cxxConstructorDecl(isConstexpr())), 43 // ... and is statically initialized. 44 isConstantInitializer()))))) 45 .bind("decl"), 46 this); 47 } 48 49 void StaticallyConstructedObjectsCheck::check( 50 const MatchFinder::MatchResult &Result) { 51 if (const auto *D = Result.Nodes.getNodeAs<VarDecl>("decl")) 52 diag(D->getBeginLoc(), "static objects are disallowed; if possible, use a " 53 "constexpr constructor instead"); 54 } 55 56 } // namespace fuchsia 57 } // namespace tidy 58 } // namespace clang 59