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