forked from OSchip/llvm-project
[clang-tidy] Add Zircon module to clang-tidy
Adding a Zircon module to clang-tidy for checks specific to the Zircon kernel, and adding a checker to fuchsia-zx (for zircon) to flag instances where specific objects are temporarily created. Differential Revision: https://reviews.llvm.org/D44346 llvm-svn: 327590
This commit is contained in:
parent
9407bb5f54
commit
b6f7c934ac
|
@ -46,3 +46,4 @@ add_subdirectory(portability)
|
|||
add_subdirectory(readability)
|
||||
add_subdirectory(tool)
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(zircon)
|
||||
|
|
|
@ -34,6 +34,7 @@ target_link_libraries(clang-tidy
|
|||
clangTidyPerformanceModule
|
||||
clangTidyPortabilityModule
|
||||
clangTidyReadabilityModule
|
||||
clangTidyZirconModule
|
||||
clangTooling
|
||||
clangToolingCore
|
||||
)
|
||||
|
|
|
@ -579,6 +579,11 @@ extern volatile int HICPPModuleAnchorSource;
|
|||
static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination =
|
||||
HICPPModuleAnchorSource;
|
||||
|
||||
// This anchor is used to force the linker to link the ZirconModule.
|
||||
extern volatile int ZirconModuleAnchorSource;
|
||||
static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination =
|
||||
ZirconModuleAnchorSource;
|
||||
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
add_clang_library(clangTidyZirconModule
|
||||
TemporaryObjectsCheck.cpp
|
||||
ZirconTidyModule.cpp
|
||||
|
||||
LINK_LIBS
|
||||
clangAST
|
||||
clangASTMatchers
|
||||
clangBasic
|
||||
clangLex
|
||||
clangTidy
|
||||
clangTidyUtils
|
||||
)
|
|
@ -0,0 +1,60 @@
|
|||
//===--- TemporaryObjectsCheck.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 "TemporaryObjectsCheck.h"
|
||||
#include "../utils/OptionsUtils.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <string>
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace zircon {
|
||||
|
||||
AST_MATCHER_P(CXXRecordDecl, matchesAnyName, ArrayRef<std::string>, Names) {
|
||||
std::string QualifiedName = Node.getQualifiedNameAsString();
|
||||
return llvm::any_of(Names,
|
||||
[&](StringRef Name) { return QualifiedName == Name; });
|
||||
}
|
||||
|
||||
void TemporaryObjectsCheck::registerMatchers(MatchFinder *Finder) {
|
||||
// Matcher for default constructors.
|
||||
Finder->addMatcher(
|
||||
cxxTemporaryObjectExpr(hasDeclaration(cxxConstructorDecl(hasParent(
|
||||
cxxRecordDecl(matchesAnyName(Names))))))
|
||||
.bind("temps"),
|
||||
this);
|
||||
|
||||
// Matcher for user-defined constructors.
|
||||
Finder->addMatcher(
|
||||
cxxConstructExpr(allOf(hasParent(cxxFunctionalCastExpr()),
|
||||
hasDeclaration(cxxConstructorDecl(hasParent(
|
||||
cxxRecordDecl(matchesAnyName(Names)))))))
|
||||
.bind("temps"),
|
||||
this);
|
||||
}
|
||||
|
||||
void TemporaryObjectsCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
if (const auto *D = Result.Nodes.getNodeAs<CXXConstructExpr>("temps"))
|
||||
diag(D->getLocation(),
|
||||
"creating a temporary object of type %q0 is prohibited")
|
||||
<< D->getConstructor()->getParent();
|
||||
}
|
||||
|
||||
void TemporaryObjectsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
||||
Options.store(Opts, "Names", utils::options::serializeStringList(Names));
|
||||
}
|
||||
|
||||
} // namespace zircon
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,42 @@
|
|||
//===--- TemporaryObjectsCheck.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_ZIRCON_TEMPORARYOBJECTSCHECK_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_TEMPORARYOBJECTSCHECK_H
|
||||
|
||||
#include "../ClangTidy.h"
|
||||
#include "../utils/OptionsUtils.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace zircon {
|
||||
|
||||
/// Construction of specific temporary objects in the Zircon kernel is
|
||||
/// discouraged.
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/zircon-temporary-objects.html
|
||||
class TemporaryObjectsCheck : public ClangTidyCheck {
|
||||
public:
|
||||
TemporaryObjectsCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context),
|
||||
Names(utils::options::parseStringList(Options.get("Names", ""))) {}
|
||||
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
|
||||
private:
|
||||
std::vector<std::string> Names;
|
||||
};
|
||||
|
||||
} // namespace zircon
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_TEMPORARYOBJECTSCHECK_H
|
|
@ -0,0 +1,40 @@
|
|||
//===--- ZirconTidyModule.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 "../ClangTidy.h"
|
||||
#include "../ClangTidyModule.h"
|
||||
#include "../ClangTidyModuleRegistry.h"
|
||||
#include "TemporaryObjectsCheck.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace zircon {
|
||||
|
||||
/// This module is for Zircon-specific checks.
|
||||
class ZirconModule : public ClangTidyModule {
|
||||
public:
|
||||
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
|
||||
CheckFactories.registerCheck<TemporaryObjectsCheck>(
|
||||
"zircon-temporary-objects");
|
||||
}
|
||||
};
|
||||
|
||||
// Register the ZirconTidyModule using this statically initialized variable.
|
||||
static ClangTidyModuleRegistry::Add<ZirconModule>
|
||||
X("zircon-module", "Adds Zircon kernel checks.");
|
||||
} // namespace zircon
|
||||
|
||||
// This anchor is used to force the linker to link in the generated object file
|
||||
// and thus register the ZirconModule.
|
||||
volatile int ZirconModuleAnchorSource = 0;
|
||||
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -59,6 +59,8 @@ Improvements to clang-tidy
|
|||
|
||||
- New module ``portability``.
|
||||
|
||||
- New module ``zircon`` for checks related to Fuchsia's Zircon kernel.
|
||||
|
||||
- New `bugprone-throw-keyword-missing
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/bugprone-throw-keyword-missing.html>`_ check
|
||||
|
||||
|
@ -159,6 +161,11 @@ Improvements to clang-tidy
|
|||
- The 'misc-undelegated-constructor' check was renamed to `bugprone-undelegated-constructor
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/bugprone-undelegated-constructor.html>`_
|
||||
|
||||
- New `zircon-temporary-objects
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/zircon-temporary-objects.html>`_ check
|
||||
|
||||
Warns on construction of specific temporary objects in the Zircon kernel.
|
||||
|
||||
Improvements to include-fixer
|
||||
-----------------------------
|
||||
|
||||
|
|
|
@ -225,3 +225,4 @@ Clang-Tidy Checks
|
|||
readability-static-definition-in-anonymous-namespace
|
||||
readability-string-compare
|
||||
readability-uniqueptr-delete-release
|
||||
zircon-temporary-objects
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
.. title:: clang-tidy - zircon-temporary-objects
|
||||
|
||||
zircon-temporary-objects
|
||||
========================
|
||||
|
||||
Warns on construction of specific temporary objects in the Zircon kernel.
|
||||
If the object should be flagged, If the object should be flagged, the fully
|
||||
qualified type name must be explicitly passed to the check.
|
||||
|
||||
For example, given the list of classes "Foo" and "NS::Bar", all of the
|
||||
following will trigger the warning:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
Foo();
|
||||
Foo F = Foo();
|
||||
func(Foo());
|
||||
|
||||
namespace NS {
|
||||
|
||||
Bar();
|
||||
|
||||
}
|
||||
|
||||
With the same list, the following will not trigger the warning:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
Foo F; // Non-temporary construction okay
|
||||
Foo F(param); // Non-temporary construction okay
|
||||
Foo *F = new Foo(); // New construction okay
|
||||
|
||||
Bar(); // Not NS::Bar, so okay
|
||||
NS::Bar B; // Non-temporary construction okay
|
||||
|
||||
Note that objects must be explicitly specified in order to be flagged,
|
||||
and so objects that inherit a specified object will not be flagged.
|
||||
|
||||
This check matches temporary objects without regard for inheritance and so a
|
||||
prohibited base class type does not similarly prohibit derived class types.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class Derived : Foo {} // Derived is not explicitly disallowed
|
||||
Derived(); // and so temporary construction is okay
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
.. option:: Names
|
||||
|
||||
A semi-colon-separated list of fully-qualified names of C++ classes that
|
||||
should not be constructed as temporaries. Default is empty.
|
|
@ -75,6 +75,7 @@ Name prefix Description
|
|||
relate to any particular coding style.
|
||||
``readability-`` Checks that target readability-related issues that don't
|
||||
relate to any particular coding style.
|
||||
``zircon-`` Checks related to Zircon kernel coding conventions.
|
||||
====================== =========================================================
|
||||
|
||||
Clang diagnostics are treated in a similar way as check diagnostics. Clang
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
// RUN: %check_clang_tidy %s zircon-temporary-objects %t -- \
|
||||
// RUN: -config="{CheckOptions: [{key: zircon-temporary-objects.Names, value: 'Foo;NS::Bar'}]}" \
|
||||
// RUN: -header-filter=.* \
|
||||
// RUN: -- -std=c++11
|
||||
|
||||
// Should flag instances of Foo, NS::Bar.
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
Foo() = default;
|
||||
Foo(int Val) : Val(Val){};
|
||||
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
namespace NS {
|
||||
|
||||
class Bar {
|
||||
public:
|
||||
Bar() = default;
|
||||
Bar(int Val) : Val(Val){};
|
||||
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
} // namespace NS
|
||||
|
||||
class Bar {
|
||||
public:
|
||||
Bar() = default;
|
||||
Bar(int Val) : Val(Val){};
|
||||
|
||||
private:
|
||||
int Val;
|
||||
};
|
||||
|
||||
int func(Foo F) { return 1; };
|
||||
|
||||
int main() {
|
||||
Foo F;
|
||||
Foo *F2 = new Foo();
|
||||
new Foo();
|
||||
Foo();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
Foo F3 = Foo();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
|
||||
Bar();
|
||||
NS::Bar();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
|
||||
|
||||
int A = func(Foo());
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
|
||||
Foo F4(0);
|
||||
Foo *F5 = new Foo(0);
|
||||
new Foo(0);
|
||||
Foo(0);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
Foo F6 = Foo(0);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
|
||||
Bar(0);
|
||||
NS::Bar(0);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
|
||||
|
||||
int B = func(Foo(0));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
}
|
||||
|
||||
namespace NS {
|
||||
|
||||
void f() {
|
||||
Bar();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
|
||||
Bar(0);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
|
||||
}
|
||||
|
||||
} // namespace NS
|
||||
|
||||
template <typename Ty>
|
||||
Ty make_ty() { return Ty(); }
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: creating a temporary object of type 'Foo' is prohibited
|
||||
// CHECK-MESSAGES: :[[@LINE-2]]:23: warning: creating a temporary object of type 'NS::Bar' is prohibited
|
||||
|
||||
void ty_func() {
|
||||
make_ty<Bar>();
|
||||
make_ty<NS::Bar>();
|
||||
make_ty<Foo>();
|
||||
}
|
||||
|
||||
// Inheriting the disallowed class does not trigger the check.
|
||||
|
||||
class Bingo : NS::Bar {}; // Not explicitly disallowed
|
||||
|
||||
void f2() {
|
||||
Bingo();
|
||||
}
|
||||
|
||||
template <typename Ty>
|
||||
class Quux : Ty {};
|
||||
|
||||
void f3() {
|
||||
Quux<NS::Bar>();
|
||||
Quux<Bar>();
|
||||
}
|
Loading…
Reference in New Issue