xref: /llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp (revision 7d2ea6c422d3f5712b7253407005e1a465a76946)
11ee1f493SJulie Hockett //===--- StaticallyConstructedObjectsCheck.cpp - clang-tidy----------------===//
21ee1f493SJulie Hockett //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61ee1f493SJulie Hockett //
71ee1f493SJulie Hockett //===----------------------------------------------------------------------===//
81ee1f493SJulie Hockett 
91ee1f493SJulie Hockett #include "StaticallyConstructedObjectsCheck.h"
101ee1f493SJulie Hockett 
111ee1f493SJulie Hockett using namespace clang::ast_matchers;
121ee1f493SJulie Hockett 
13*7d2ea6c4SCarlos Galvez namespace clang::tidy::fuchsia {
141ee1f493SJulie Hockett 
15f8c99297SBenjamin Kramer namespace {
AST_MATCHER(Expr,isConstantInitializer)161ee1f493SJulie Hockett AST_MATCHER(Expr, isConstantInitializer) {
171ee1f493SJulie Hockett   return Node.isConstantInitializer(Finder->getASTContext(), false);
181ee1f493SJulie Hockett }
191ee1f493SJulie Hockett 
AST_MATCHER(VarDecl,isGlobalStatic)201ee1f493SJulie Hockett AST_MATCHER(VarDecl, isGlobalStatic) {
211ee1f493SJulie Hockett   return Node.getStorageDuration() == SD_Static && !Node.isLocalVarDecl();
221ee1f493SJulie Hockett }
23f8c99297SBenjamin Kramer } // namespace
241ee1f493SJulie Hockett 
registerMatchers(MatchFinder * Finder)251ee1f493SJulie Hockett void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) {
261ee1f493SJulie Hockett   // Constructing global, non-trivial objects with static storage is
271ee1f493SJulie Hockett   // disallowed, unless the object is statically initialized with a constexpr
281ee1f493SJulie Hockett   // constructor or has no explicit constructor.
29a72307c3SStephen Kelly   Finder->addMatcher(
30027899daSAlexander Kornienko       traverse(TK_AsIs,
31a72307c3SStephen Kelly                varDecl(
321ee1f493SJulie Hockett                    // Match global, statically stored objects...
331ee1f493SJulie Hockett                    isGlobalStatic(),
341ee1f493SJulie Hockett                    // ... that have C++ constructors...
351ee1f493SJulie Hockett                    hasDescendant(cxxConstructExpr(unless(allOf(
361ee1f493SJulie Hockett                        // ... unless it is constexpr ...
371ee1f493SJulie Hockett                        hasDeclaration(cxxConstructorDecl(isConstexpr())),
381ee1f493SJulie Hockett                        // ... and is statically initialized.
39976e0c07SAlexander Kornienko                        isConstantInitializer())))))
40a72307c3SStephen Kelly                    .bind("decl")),
411ee1f493SJulie Hockett       this);
421ee1f493SJulie Hockett }
431ee1f493SJulie Hockett 
check(const MatchFinder::MatchResult & Result)441ee1f493SJulie Hockett void StaticallyConstructedObjectsCheck::check(
451ee1f493SJulie Hockett     const MatchFinder::MatchResult &Result) {
461ee1f493SJulie Hockett   if (const auto *D = Result.Nodes.getNodeAs<VarDecl>("decl"))
4743465bf3SStephen Kelly     diag(D->getBeginLoc(), "static objects are disallowed; if possible, use a "
481ee1f493SJulie Hockett                            "constexpr constructor instead");
491ee1f493SJulie Hockett }
501ee1f493SJulie Hockett 
51*7d2ea6c4SCarlos Galvez } // namespace clang::tidy::fuchsia
52