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