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