1 //===--- StaticallyConstructedObjectsCheck.cpp - clang-tidy----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "StaticallyConstructedObjectsCheck.h" 11 12 using namespace clang::ast_matchers; 13 14 namespace clang { 15 namespace tidy { 16 namespace fuchsia { 17 18 namespace { 19 AST_MATCHER(Expr, isConstantInitializer) { 20 return Node.isConstantInitializer(Finder->getASTContext(), false); 21 } 22 23 AST_MATCHER(VarDecl, isGlobalStatic) { 24 return Node.getStorageDuration() == SD_Static && !Node.isLocalVarDecl(); 25 } 26 } // namespace 27 28 void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) { 29 // Constructing global, non-trivial objects with static storage is 30 // disallowed, unless the object is statically initialized with a constexpr 31 // constructor or has no explicit constructor. 32 33 // Constexpr requires C++11 or later. 34 if (!getLangOpts().CPlusPlus11) 35 return; 36 37 Finder->addMatcher( 38 varDecl(allOf( 39 // Match global, statically stored objects... 40 isGlobalStatic(), 41 // ... that have C++ constructors... 42 hasDescendant(cxxConstructExpr(unless(allOf( spgistBuildCallback(Relation index,ItemPointer tid,Datum * values,bool * isnull,bool tupleIsAlive,void * state)43 // ... unless it is constexpr ... 44 hasDeclaration(cxxConstructorDecl(isConstexpr())), 45 // ... and is statically initialized. 46 isConstantInitializer())))))) 47 .bind("decl"), 48 this); 49 } 50 51 void StaticallyConstructedObjectsCheck::check( 52 const MatchFinder::MatchResult &Result) { 53 if (const auto *D = Result.Nodes.getNodeAs<VarDecl>("decl")) 54 diag(D->getLocStart(), "static objects are disallowed; if possible, use a " 55 "constexpr constructor instead"); 56 } 57 58 } // namespace fuchsia 59 } // namespace tidy 60 } // namespace clang 61