forked from OSchip/llvm-project
[clang-tidy] Adding Fuchsia checker for statically constructed objects
Adds a check to the Fuchsia module to warn if statically-stored objects are created, unless constructed with `constexpr`. See https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md for reference. Differential Revision: https://reviews.llvm.org/D41546 llvm-svn: 322310
This commit is contained in:
parent
d423f0d290
commit
1ee1f49393
|
@ -4,6 +4,7 @@ add_clang_library(clangTidyFuchsiaModule
|
|||
DefaultArgumentsCheck.cpp
|
||||
FuchsiaTidyModule.cpp
|
||||
OverloadedOperatorCheck.cpp
|
||||
StaticallyConstructedObjectsCheck.cpp
|
||||
VirtualInheritanceCheck.cpp
|
||||
|
||||
LINK_LIBS
|
||||
|
|
|
@ -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 @@ public:
|
|||
"fuchsia-default-arguments");
|
||||
CheckFactories.registerCheck<OverloadedOperatorCheck>(
|
||||
"fuchsia-overloaded-operator");
|
||||
CheckFactories.registerCheck<StaticallyConstructedObjectsCheck>(
|
||||
"fuchsia-statically-constructed-objects");
|
||||
CheckFactories.registerCheck<VirtualInheritanceCheck>(
|
||||
"fuchsia-virtual-inheritance");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//===--- 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 {
|
||||
|
||||
AST_MATCHER(Expr, isConstantInitializer) {
|
||||
return Node.isConstantInitializer(Finder->getASTContext(), false);
|
||||
}
|
||||
|
||||
AST_MATCHER(VarDecl, isGlobalStatic) {
|
||||
return Node.getStorageDuration() == SD_Static && !Node.isLocalVarDecl();
|
||||
}
|
||||
|
||||
void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) {
|
||||
// Constructing global, non-trivial objects with static storage is
|
||||
// disallowed, unless the object is statically initialized with a constexpr
|
||||
// constructor or has no explicit constructor.
|
||||
|
||||
// Constexpr requires C++11 or later.
|
||||
if (!getLangOpts().CPlusPlus11)
|
||||
return;
|
||||
|
||||
Finder->addMatcher(
|
||||
varDecl(allOf(
|
||||
// Match global, statically stored objects...
|
||||
isGlobalStatic(),
|
||||
// ... that have C++ constructors...
|
||||
hasDescendant(cxxConstructExpr(unless(allOf(
|
||||
// ... unless it is constexpr ...
|
||||
hasDeclaration(cxxConstructorDecl(isConstexpr())),
|
||||
// ... and is statically initialized.
|
||||
isConstantInitializer()))))))
|
||||
.bind("decl"),
|
||||
this);
|
||||
}
|
||||
|
||||
void StaticallyConstructedObjectsCheck::check(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
if (const auto *D = Result.Nodes.getNodeAs<VarDecl>("decl"))
|
||||
diag(D->getLocStart(), "static objects are disallowed; if possible, use a "
|
||||
"constexpr constructor instead");
|
||||
}
|
||||
|
||||
} // namespace fuchsia
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,37 @@
|
|||
//===--- 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 global, non-trivial objects with static storage is
|
||||
/// disallowed, unless the object is statically initialized with a constexpr
|
||||
/// constructor or has no explicit constructor.
|
||||
///
|
||||
/// 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
|
|
@ -57,7 +57,12 @@ The improvements are...
|
|||
Improvements to clang-tidy
|
||||
--------------------------
|
||||
|
||||
- ...
|
||||
- New `fuchsia-statically-constructed-objects
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-statically-constructed-objects.html>`_ check
|
||||
|
||||
Warns if global, non-trivial objects with static storage are constructed, unless the
|
||||
object is statically initialized with a ``constexpr`` constructor or has no
|
||||
explicit constructor.
|
||||
|
||||
Improvements to include-fixer
|
||||
-----------------------------
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
.. title:: clang-tidy - fuchsia-statically-constructed-objects
|
||||
|
||||
fuchsia-statically-constructed-objects
|
||||
======================================
|
||||
|
||||
Warns if global, non-trivial objects with static storage are constructed, unless
|
||||
the object is statically initialized with a ``constexpr`` constructor or has no
|
||||
explicit constructor.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class A {};
|
||||
|
||||
class B {
|
||||
public:
|
||||
B(int Val) : Val(Val) {}
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
class C {
|
||||
public:
|
||||
C(int Val) : Val(Val) {}
|
||||
constexpr C() : Val(0) {}
|
||||
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
static A a; // No warning, as there is no explicit constructor
|
||||
static C c(0); // No warning, as constructor is constexpr
|
||||
|
||||
static B b(0); // Warning, as constructor is not constexpr
|
||||
static C c2(0, 1); // Warning, as constructor is not constexpr
|
||||
|
||||
static int i; // No warning, as it is trivial
|
||||
|
||||
extern int get_i();
|
||||
static C(get_i()) // Warning, as the constructor is dynamically initialized
|
||||
|
||||
See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
|
|
@ -70,6 +70,7 @@ Clang-Tidy Checks
|
|||
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
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// RUN: %check_clang_tidy %s fuchsia-statically-constructed-objects %t
|
||||
|
||||
// Trivial static is fine
|
||||
static int i;
|
||||
|
||||
class ClassWithNoCtor {};
|
||||
|
||||
class ClassWithCtor {
|
||||
public:
|
||||
ClassWithCtor(int Val) : Val(Val) {}
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
class ClassWithConstexpr {
|
||||
public:
|
||||
ClassWithConstexpr(int Val1, int Val2) : Val(Val1) {}
|
||||
constexpr ClassWithConstexpr(int Val) : Val(Val) {}
|
||||
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
ClassWithNoCtor A;
|
||||
ClassWithConstexpr C(0);
|
||||
ClassWithConstexpr E(0, 1);
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: ClassWithConstexpr E(0, 1);
|
||||
ClassWithCtor G(0);
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: ClassWithCtor G(0);
|
||||
|
||||
static ClassWithNoCtor A2;
|
||||
static ClassWithConstexpr C2(0);
|
||||
static ClassWithConstexpr E2(0, 1);
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: static ClassWithConstexpr E2(0, 1);
|
||||
static ClassWithCtor G2(0);
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: static ClassWithCtor G2(0);
|
||||
|
||||
struct StructWithConstexpr { constexpr StructWithConstexpr(int Val) {} };
|
||||
struct StructWithNoCtor {};
|
||||
struct StructWithCtor { StructWithCtor(); };
|
||||
|
||||
StructWithNoCtor SNoCtor;
|
||||
StructWithConstexpr SConstexpr(0);
|
||||
StructWithCtor SCtor;
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: StructWithCtor SCtor;
|
||||
|
||||
static StructWithConstexpr SConstexpr2(0);
|
||||
static StructWithNoCtor SNoCtor2;
|
||||
static StructWithCtor SCtor2;
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: static StructWithCtor SCtor2;
|
||||
|
||||
extern StructWithCtor SCtor3;
|
||||
|
||||
class ClassWithStaticMember {
|
||||
private:
|
||||
static StructWithNoCtor S;
|
||||
};
|
||||
|
||||
ClassWithStaticMember Z();
|
||||
|
||||
class S {
|
||||
int Val;
|
||||
public:
|
||||
constexpr S(int i) : Val(100 / i) {}
|
||||
int getVal() const { return Val; }
|
||||
};
|
||||
|
||||
static S s1(1);
|
||||
static S s2(0);
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: static S s2(0);
|
||||
|
||||
extern int get_i();
|
||||
static S s3(get_i());
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
|
||||
// CHECK-MESSAGES-NEXT: static S s3(get_i());
|
||||
|
||||
void f() {
|
||||
// Locally static is fine
|
||||
static int i;
|
||||
static ClassWithNoCtor A2;
|
||||
static ClassWithConstexpr C2(0);
|
||||
static ClassWithConstexpr E2(0, 1);
|
||||
static ClassWithCtor G2(0);
|
||||
}
|
Loading…
Reference in New Issue