Index: clang-tidy/fuchsia/CMakeLists.txt =================================================================== --- clang-tidy/fuchsia/CMakeLists.txt +++ clang-tidy/fuchsia/CMakeLists.txt @@ -4,6 +4,7 @@ DefaultArgumentsCheck.cpp FuchsiaTidyModule.cpp OverloadedOperatorCheck.cpp + StaticallyConstructedObjectsCheck.cpp VirtualInheritanceCheck.cpp LINK_LIBS Index: clang-tidy/fuchsia/FuchsiaTidyModule.cpp =================================================================== --- clang-tidy/fuchsia/FuchsiaTidyModule.cpp +++ clang-tidy/fuchsia/FuchsiaTidyModule.cpp @@ -12,6 +12,7 @@ #include "../ClangTidyModuleRegistry.h" #include "DefaultArgumentsCheck.h" #include "OverloadedOperatorCheck.h" +#include "StaticallyConstructedObjectsCheck.h" #include "VirtualInheritanceCheck.h" using namespace clang::ast_matchers; @@ -28,6 +29,8 @@ "fuchsia-default-arguments"); CheckFactories.registerCheck( "fuchsia-overloaded-operator"); + CheckFactories.registerCheck( + "fuchsia-statically-constructed-objects"); CheckFactories.registerCheck( "fuchsia-virtual-inheritance"); } Index: clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h =================================================================== --- /dev/null +++ clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h @@ -0,0 +1,35 @@ +//===--- StaticallyConstructedObjectsCheck.h - clang-tidy--------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace fuchsia { + +/// Constructing objects which are statically stored is disallowed. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-statically-constructed-objects.html +class StaticallyConstructedObjectsCheck : public ClangTidyCheck { +public: + StaticallyConstructedObjectsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace fuchsia +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H Index: clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp @@ -0,0 +1,43 @@ +//===--- StaticallyConstructedObjectsCheck.cpp - clang-tidy----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "StaticallyConstructedObjectsCheck.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace fuchsia { + +void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) { + // Constructing objects which are stored statically is disallowed. + Finder->addMatcher( + varDecl(allOf( + // Match statically stored objects... + hasStaticStorageDuration(), + // ... which have C++ constructors... + hasDescendant(cxxConstructExpr(unless( + // ... that are not constexpr. + hasDeclaration(cxxConstructorDecl(isConstexpr()))))))) + .bind("decl"), + this); +} + +void StaticallyConstructedObjectsCheck::check( + const MatchFinder::MatchResult &Result) { + if (const auto *D = Result.Nodes.getNodeAs("decl")) { + diag(D->getLocStart(), "statically constructed objects are disallowed"); + diag(D->getLocStart(), "if possible, use a constexpr constructor instead", + DiagnosticIDs::Note); + } +} + +} // namespace fuchsia +} // namespace tidy +} // namespace clang Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -140,6 +140,11 @@ Warns if an operator is overloaded, except for the assignment (copy and move) operators. +- New `fuchsia-statically-constructed-objects + `_ check + + Warns if statically-stored objects are created, unless constructed with `constexpr`. + - New `fuchsia-virtual-inheritance `_ check Index: docs/clang-tidy/checks/fuchsia-statically-constructed-objects.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/fuchsia-statically-constructed-objects.rst @@ -0,0 +1,32 @@ +.. title:: clang-tidy - fuchsia-statically-constructed-objects + +fuchsia-statically-constructed-objects +====================================== + +Warns if statically-stored objects are created, unless constructed with +`constexpr`. + +For example, creating static classes or structs is not allowed: + +.. code-block:: c++ + + class AdderClass { + public: + AdderClass(int Value1, int Value2) : Val(Value1 + Value2) {} + constexpr AdderClass(int Value) : Val(Value) {} + + private: + int Val; + }; + + // Will cause warning + static AdderClass A(1, 2); + +But creation of static objects using `constexpr` constructors is allowed: + +.. code-block:: c++ + + // No warning + static AdderClass B(0); + +See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -70,6 +70,7 @@ cppcoreguidelines-special-member-functions fuchsia-default-arguments fuchsia-overloaded-operator + fuchsia-statically-constructed-objects fuchsia-virtual-inheritance google-build-explicit-make-pair google-build-namespaces Index: test/clang-tidy/fuchsia-statically-constructed-objects.cpp =================================================================== --- /dev/null +++ test/clang-tidy/fuchsia-statically-constructed-objects.cpp @@ -0,0 +1,46 @@ +// RUN: %check_clang_tidy %s fuchsia-statically-constructed-objects %t + +class AdderClass { +public: + AdderClass(int Value1, int Value2) : Val(Value1 + Value2) {} + constexpr AdderClass(int Value) : Val(Value) {} + +private: + int Val; +}; + +struct Simple_Struct { + int a; +}; + +struct Struct_With_Method { + int A; + void StructMethod() { A++; } +}; + +struct Static_Struct_Container { + int A; + static int B; + static struct Simple_Struct C; +}; + +int main() { + + static AdderClass A(1, 2); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: statically constructed objects are disallowed [fuchsia-statically-constructed-objects] + // CHECK-MESSAGES-NEXT: static AdderClass A(1, 2); + + // Allowed, as it uses the constexpr constructor. + static AdderClass B(0); + + static struct Simple_Struct C; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: statically constructed objects are disallowed [fuchsia-statically-constructed-objects] + // CHECK-MESSAGES-NEXT: static struct Simple_Struct C; + + static struct Struct_With_Method D; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: statically constructed objects are disallowed [fuchsia-statically-constructed-objects] + // CHECK-MESSAGES-NEXT: static struct Struct_With_Method D; + + static int E; + struct Static_Struct_Container F; +}