Index: clang-tidy/CMakeLists.txt =================================================================== --- clang-tidy/CMakeLists.txt +++ clang-tidy/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(bugprone) add_subdirectory(cert) add_subdirectory(cppcoreguidelines) +add_subdirectory(fuchsia) add_subdirectory(google) add_subdirectory(hicpp) add_subdirectory(llvm) Index: clang-tidy/fuchsia/CMakeLists.txt =================================================================== --- /dev/null +++ clang-tidy/fuchsia/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangTidyFuchsiaModule + DefaultArgumentsCheck.cpp + FuchsiaTidyModule.cpp + + LINK_LIBS + clangAST + clangASTMatchers + clangBasic + clangLex + clangTidy + clangTidyUtils + ) Index: clang-tidy/fuchsia/DefaultArgumentsCheck.h =================================================================== --- /dev/null +++ clang-tidy/fuchsia/DefaultArgumentsCheck.h @@ -0,0 +1,35 @@ +//===--- DefaultArgumentsCheck.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_DEFAULT_ARGUMENTS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_DEFAULT_ARGUMENTS_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace fuchsia { + +/// Default arguments are not allowed in declared or called functions. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-default-arguments.html +class DefaultArgumentsCheck : public ClangTidyCheck { +public: + DefaultArgumentsCheck(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_DEFAULT_ARGUMENTS_H Index: clang-tidy/fuchsia/DefaultArgumentsCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/fuchsia/DefaultArgumentsCheck.cpp @@ -0,0 +1,64 @@ +//===--- DefaultArgumentsCheck.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 "DefaultArgumentsCheck.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace fuchsia { + +void DefaultArgumentsCheck::registerMatchers(MatchFinder *Finder) { + // Calling a function which uses default arguments is disallowed. + Finder->addMatcher(cxxDefaultArgExpr().bind("stmt"), this); + // Declaring default parameters is disallowed. + Finder->addMatcher(parmVarDecl(hasDefaultArgument()).bind("decl"), this); +} + +void DefaultArgumentsCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *S = + Result.Nodes.getNodeAs("stmt")) { + diag(S->getUsedLocation(), + "calling a function that uses a default argument is disallowed"); + diag(S->getParam()->getLocStart(), + "default parameter was declared here", + DiagnosticIDs::Note); + } else if (const ParmVarDecl *D = + Result.Nodes.getNodeAs("decl")) { + SourceRange DefaultArgRange = D->getDefaultArgRange(); + + if (DefaultArgRange.getEnd() != D->getLocEnd()) { + return; + } else if (DefaultArgRange.getBegin().isMacroID()) { + diag(D->getLocStart(), + "declaring a parameter with a default argument is disallowed"); + } else { + SourceLocation StartLocation = D->getName().empty() ? + D->getLocStart() : D->getLocation(); + + SourceRange RemovalRange(Lexer::getLocForEndOfToken( + StartLocation, 0, + *Result.SourceManager, + Result.Context->getLangOpts() + ), + DefaultArgRange.getEnd() + ); + + diag(D->getLocStart(), + "declaring a parameter with a default argument is disallowed") + << D + << FixItHint::CreateRemoval(RemovalRange); + } + } +} + +} // namespace fuchsia +} // namespace tidy +} // namespace clang Index: clang-tidy/fuchsia/FuchsiaTidyModule.cpp =================================================================== --- /dev/null +++ clang-tidy/fuchsia/FuchsiaTidyModule.cpp @@ -0,0 +1,39 @@ +//===--- FuchsiaTidyModule.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 "DefaultArgumentsCheck.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace fuchsia { + +/// This module is for Fuchsia specific checks. +class FuchsiaModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "fuchsia-default-arguments"); + } +}; +// Register the FuchsiaTidyModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add + X("fuchsia-module", "Adds Fuchsia platform checks."); +} // namespace fuchsia + +// This anchor is used to force the linker to link in the generated object file +// and thus register the FuchsiaModule. +volatile int FuchsiaModuleAnchorSource = 0; + +} // namespace tidy +} // namespace clang Index: clang-tidy/tool/CMakeLists.txt =================================================================== --- clang-tidy/tool/CMakeLists.txt +++ clang-tidy/tool/CMakeLists.txt @@ -21,6 +21,7 @@ clangTidyBugproneModule clangTidyCERTModule clangTidyCppCoreGuidelinesModule + clangTidyFuchsiaModule clangTidyGoogleModule clangTidyHICPPModule clangTidyLLVMModule Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -482,6 +482,11 @@ static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination = CppCoreGuidelinesModuleAnchorSource; +// This anchor is used to force the linker to link the GoogleModule. +extern volatile int FuchsiaModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination = + FuchsiaModuleAnchorSource; + // This anchor is used to force the linker to link the GoogleModule. extern volatile int GoogleModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination = Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -57,6 +57,11 @@ Improvements to clang-tidy -------------------------- +- New `fuchsia-default-arguments + `_ check + + Warns if a function or method is declared or called with default arguments. + - New `google-avoid-throwing-objc-exception `_ check Index: docs/clang-tidy/checks/fuchsia-default-arguments.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/fuchsia-default-arguments.rst @@ -0,0 +1,24 @@ +.. title:: clang-tidy - fuchsia-default-arguments + +fuchsia-default-arguments +========================= + +Warns if a function is declared or called with default arguments. + +For example, the declaration: + +.. code-block:: c++ + + int foo(int value = 5) { return value; } + +will cause a warning. + +A function call expression that uses a default argument will be diagnosed. +Calling it without defaults will not cause a warning: + +.. code-block:: c++ + + foo(); // warning + foo(0); // no warning + +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 @@ -55,6 +55,7 @@ cppcoreguidelines-pro-type-vararg cppcoreguidelines-slicing cppcoreguidelines-special-member-functions + fuchsia-default-arguments google-build-explicit-make-pair google-build-namespaces google-build-using-namespace Index: docs/clang-tidy/index.rst =================================================================== --- docs/clang-tidy/index.rst +++ docs/clang-tidy/index.rst @@ -61,6 +61,7 @@ ``cert-`` Checks related to CERT Secure Coding Guidelines. ``cppcoreguidelines-`` Checks related to C++ Core Guidelines. ``clang-analyzer-`` Clang Static Analyzer checks. +``fuchsia-`` Checks related to Fuchsia coding conventions. ``google-`` Checks related to Google coding conventions. ``hicpp-`` Checks related to High Integrity C++ Coding Standard. ``llvm-`` Checks related to the LLVM coding conventions. Index: test/clang-tidy/fuchsia-default-arguments.cpp =================================================================== --- /dev/null +++ test/clang-tidy/fuchsia-default-arguments.cpp @@ -0,0 +1,81 @@ +// RUN: %check_clang_tidy %s fuchsia-default-arguments %t + +int foo(int value = 5) { return value; } +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] +// CHECK-FIXES: int foo(int value) { return value; } + +int f() { + foo(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments] + // CHECK-NEXT: note: default parameter was declared here: + // CHECK-NEXT: int foo(int value = 5) { return value; } +} + +int bar(int value) { return value; } + +int n() { + foo(0); + bar(0); +} + +class Baz { +public: + int a(int value = 5) { return value; } + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] + // CHECK-FIXES: int a(int value) { return value; } + + int b(int value) { return value; } +}; + +class Foo { + // Fix should be suggested in declaration + int a(int value = 53); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] + // CHECK-FIXES: int a(int value); +}; + +// Fix shouldn't be suggested in implementation +int Foo::a(int value) { + return value; +} + +// Elided functions +void f(int = 5) {}; +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] +// CHECK-FIXES: void f(int) {}; + +void g(int) {}; + +// Should not suggest fix for macro-defined parameters +#define D(val) = val + +void h(int i D(5)); +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] +// CHECK-FIXES-NOT: void h(int i); + +void x(int i); +void x(int i = 12); +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] +// CHECK-FIXES: void x(int i); + +void x(int i) {} + +struct S { + void x(int i); +}; + +void S::x(int i = 12) {} +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments] +// CHECK-FIXES: void S::x(int i) {} + +int main() { + S s; + s.x(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments] + // CHECK-NEXT: note: default parameter was declared here: + // CHECK-NEXT: void S::x(int i = 12) {} + x(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments] + // CHECK-NEXT: note: default parameter was declared here: + // CHECK-NEXT: void x(int i = 12); +} \ No newline at end of file