[clang-tools-extra] r350760 - [clang-tidy] Adding a new modernize use nodiscard checker

Jonas Toth via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 9 12:50:50 PST 2019


Author: jonastoth
Date: Wed Jan  9 12:50:50 2019
New Revision: 350760

URL: http://llvm.org/viewvc/llvm-project?rev=350760&view=rev
Log:
[clang-tidy] Adding a new modernize use nodiscard checker

Summary: Adds a checker to clang-tidy to warn when a non void const member function, taking only parameters passed by value or const reference could be marked as '[[nodiscard]]'

Patch by MyDeveloperDay.

Reviewers: alexfh, stephenkelly, curdeius, aaron.ballman, hokein, JonasToth

Reviewed By: curdeius, JonasToth

Subscribers: Eugene.Zelenko, lefticus, lebedev.ri, mgorny, xazax.hun, cfe-commits

Tags: #clang-tools-extra

Differential Revision: https://reviews.llvm.org/D55433

Added:
    clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.cpp
    clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nodiscard.rst
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.h
Modified:
    clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
    clang-tools-extra/trunk/docs/ReleaseNotes.rst
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt?rev=350760&r1=350759&r2=350760&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Wed Jan  9 12:50:50 2019
@@ -26,6 +26,7 @@ add_clang_library(clangTidyModernizeModu
   UseEmplaceCheck.cpp
   UseEqualsDefaultCheck.cpp
   UseEqualsDeleteCheck.cpp
+  UseNodiscardCheck.cpp
   UseNoexceptCheck.cpp
   UseNullptrCheck.cpp
   UseOverrideCheck.cpp

Modified: clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp?rev=350760&r1=350759&r2=350760&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Wed Jan  9 12:50:50 2019
@@ -32,6 +32,7 @@
 #include "UseEmplaceCheck.h"
 #include "UseEqualsDefaultCheck.h"
 #include "UseEqualsDeleteCheck.h"
+#include "UseNodiscardCheck.h"
 #include "UseNoexceptCheck.h"
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
@@ -82,6 +83,8 @@ public:
     CheckFactories.registerCheck<UseEqualsDefaultCheck>("modernize-use-equals-default");
     CheckFactories.registerCheck<UseEqualsDeleteCheck>(
         "modernize-use-equals-delete");
+    CheckFactories.registerCheck<UseNodiscardCheck>(
+        "modernize-use-nodiscard");
     CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept");
     CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
     CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");

Added: clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,145 @@
+//===--- UseNodiscardCheck.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 "UseNodiscardCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static bool doesNoDiscardMacroExist(ASTContext &Context,
+                                    const llvm::StringRef &MacroId) {
+  // Don't check for the Macro existence if we are using an attribute
+  // either a C++17 standard attribute or pre C++17 syntax
+  if (MacroId.startswith("[[") || MacroId.startswith("__attribute__"))
+    return true;
+
+  // Otherwise look up the macro name in the context to see if its defined.
+  return Context.Idents.get(MacroId).hasMacroDefinition();
+}
+
+namespace {
+AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
+  // Don't put ``[[nodiscard]]`` in front of operators.
+  return Node.isOverloadedOperator();
+}
+AST_MATCHER(CXXMethodDecl, isConversionOperator) {
+  // Don't put ``[[nodiscard]]`` in front of a conversion decl
+  // like operator bool().
+  return isa<CXXConversionDecl>(Node);
+}
+AST_MATCHER(CXXMethodDecl, hasClassMutableFields) {
+  // Don't put ``[[nodiscard]]`` on functions on classes with
+  // mutable member variables.
+  return Node.getParent()->hasMutableFields();
+}
+AST_MATCHER(ParmVarDecl, hasParameterPack) {
+  // Don't put ``[[nodiscard]]`` on functions with parameter pack arguments.
+  return Node.isParameterPack();
+}
+AST_MATCHER(CXXMethodDecl, hasTemplateReturnType) {
+  // Don't put ``[[nodiscard]]`` in front of functions returning a template
+  // type.
+  return Node.getReturnType()->isTemplateTypeParmType() ||
+         Node.getReturnType()->isInstantiationDependentType();
+}
+AST_MATCHER(CXXMethodDecl, isDefinitionOrInline) {
+  // A function definition, with optional inline but not the declaration.
+  return !(Node.isThisDeclarationADefinition() && Node.isOutOfLine());
+}
+AST_MATCHER(QualType, isInstantiationDependentType) {
+  return Node->isInstantiationDependentType();
+}
+AST_MATCHER(QualType, isNonConstReferenceOrPointer) {
+  // If the function has any non-const-reference arguments
+  //    bool foo(A &a)
+  // or pointer arguments
+  //    bool foo(A*)
+  // then they may not care about the return value because of passing data
+  // via the arguments.
+  return (Node->isTemplateTypeParmType() || Node->isPointerType() ||
+          (Node->isReferenceType() &&
+           !Node.getNonReferenceType().isConstQualified()) ||
+          Node->isInstantiationDependentType());
+}
+} // namespace
+
+UseNodiscardCheck::UseNodiscardCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      NoDiscardMacro(Options.get("ReplacementString", "[[nodiscard]]")) {}
+
+void UseNodiscardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ReplacementString", NoDiscardMacro);
+}
+
+void UseNodiscardCheck::registerMatchers(MatchFinder *Finder) {
+  // If we use ``[[nodiscard]]`` attribute, we require at least C++17. Use a
+  // macro or ``__attribute__`` with pre c++17 compilers by using
+  // ReplacementString option.
+  if ((NoDiscardMacro == "[[nodiscard]]" && !getLangOpts().CPlusPlus17) ||
+      !getLangOpts().CPlusPlus)
+    return;
+
+  auto functionObj =
+      cxxRecordDecl(hasAnyName("::std::function", "::boost::function"));
+
+  // Find all non-void const methods which have not already been marked to
+  // warn on unused result.
+  Finder->addMatcher(
+      cxxMethodDecl(
+          allOf(isConst(), isDefinitionOrInline(),
+                unless(anyOf(
+                    returns(voidType()), isNoReturn(), isOverloadedOperator(),
+                    isVariadic(), hasTemplateReturnType(),
+                    hasClassMutableFields(), isConversionOperator(),
+                    hasAttr(clang::attr::WarnUnusedResult),
+                    hasType(isInstantiationDependentType()),
+                    hasAnyParameter(anyOf(
+                        parmVarDecl(anyOf(hasType(functionObj),
+                                          hasType(references(functionObj)))),
+                        hasType(isNonConstReferenceOrPointer()),
+                        hasParameterPack()))))))
+          .bind("no_discard"),
+      this);
+}
+
+void UseNodiscardCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("no_discard");
+  // Don't make replacements if the location is invalid or in a macro.
+  SourceLocation Loc = MatchedDecl->getLocation();
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return;
+
+  SourceLocation retLoc = MatchedDecl->getInnerLocStart();
+
+  ASTContext &Context = *Result.Context;
+
+  auto Diag = diag(retLoc, "function %0 should be marked " + NoDiscardMacro)
+              << MatchedDecl;
+
+  // Check for the existence of the keyword being used as the ``[[nodiscard]]``.
+  if (!doesNoDiscardMacroExist(Context, NoDiscardMacro))
+    return;
+
+  // Possible false positives include:
+  // 1. A const member function which returns a variable which is ignored
+  // but performs some external I/O operation and the return value could be
+  // ignored.
+  Diag << FixItHint::CreateInsertion(retLoc, NoDiscardMacro + " ");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.h?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseNodiscardCheck.h Wed Jan  9 12:50:50 2019
@@ -0,0 +1,50 @@
+//===--- UseNodiscardCheck.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_MODERNIZE_USENODISCARDCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USENODISCARDCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Add ``[[nodiscard]]`` to non-void const-member functions with no
+/// arguments or pass-by-value or pass by const-reference arguments.
+/// \code
+///    bool empty() const;
+///    bool empty(const Bar &) const;
+///    bool empty(int bar) const;
+/// \endcode
+/// Is converted to:
+/// \code
+///    [[nodiscard]] bool empty() const;
+///    [[nodiscard]] bool empty(const Bar &) const;
+///    [[nodiscard]] bool empty(int bar) const;
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nodiscard.html
+class UseNodiscardCheck : public ClangTidyCheck {
+public:
+  UseNodiscardCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const std::string NoDiscardMacro;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USENODISCARDCHECK_H

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=350760&r1=350759&r2=350760&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Jan  9 12:50:50 2019
@@ -220,6 +220,12 @@ Improvements to clang-tidy
   Detects usage of the deprecated member types of ``std::ios_base`` and replaces
   those that have a non-deprecated equivalent.
 
+- New :doc:`modernize-use-nodiscard
+  <clang-tidy/checks/modernize-use-nodiscard>` check.
+
+  Adds ``[[nodiscard]]`` attributes (introduced in C++17) to member functions
+  to highlight at compile time which return values should not be ignored.
+
 - New :doc:`readability-isolate-decl
   <clang-tidy/checks/readability-isolate-declaration>` check.
 

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=350760&r1=350759&r2=350760&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Jan  9 12:50:50 2019
@@ -207,6 +207,7 @@ Clang-Tidy Checks
    modernize-use-emplace
    modernize-use-equals-default
    modernize-use-equals-delete
+   modernize-use-nodiscard
    modernize-use-noexcept
    modernize-use-nullptr
    modernize-use-override

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nodiscard.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nodiscard.rst?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nodiscard.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nodiscard.rst Wed Jan  9 12:50:50 2019
@@ -0,0 +1,77 @@
+.. title:: clang-tidy - modernize-use-nodiscard
+
+modernize-use-nodiscard
+=======================
+
+Adds ``[[nodiscard]]`` attributes (introduced in C++17) to member functions in
+order to highlight at compile time which return values should not be ignored.
+
+Member functions need to satisfy the following conditions to be considered by
+this check:
+  - no ``[[nodiscard]]``, ``[[noreturn]]``, ``__attribute__((warn_unused_result))``, ``[[clang::warn_unused_result]]`` nor ``[[gcc::warn_unused_result]]`` attribute,
+  - non-void return type,
+  - non-template return types,
+  - const member function,
+  - non-variadic functions,
+  - no non-const reference parameters,
+  - no pointer parameters,
+  - no template parameters,
+  - no template function parameters,
+  - not be a member of a class with mutable member variables,
+  - no Lambdas,
+  - no conversion functions.
+
+Such functions have no means of altering any state or passing values other than
+via the return type. Unless the member functions are altering state via some
+external call (e.g. I/O).
+
+Example
+-------
+
+.. code-block:: c++
+
+    bool empty() const;
+    bool empty(int i) const;
+
+transforms to:
+
+.. code-block:: c++
+
+    [[nodiscard] bool empty() const;
+    [[nodiscard] bool empty(int i) const;
+
+Options
+-------
+
+.. option:: ReplacementString
+
+Specifies a macro to use instead of ``[[nodiscard]]``. This is useful when
+maintaining source code that needs to compile with a pre-C++17 compiler.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+    bool empty() const;
+    bool empty(int i) const;
+
+transforms to:
+
+.. code-block:: c++
+
+    NO_DISCARD bool empty() const;
+    NO_DISCARD bool empty(int i) const;
+
+if the :option:`ReplacementString` option is set to `NO_DISCARD`.
+
+.. note::
+
+If the :option:`ReplacementString` is not a C++ attribute, but instead a macro,
+then that macro must be defined in scope or the fix-it will not be applied.
+
+.. note::
+
+   For alternative ``__attribute__`` syntax options to mark functions as
+   ``[[nodiscard]]`` in non-c++17 source code.
+   See https://clang.llvm.org/docs/AttributeReference.html#nodiscard-warn-unused-result

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '[[clang::warn_unused_result]]'}]}" \
+// RUN: -- -std=c++11 
+
+class Foo
+{
+public:
+    bool f1() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f1() const;
+
+    bool f2(int) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f2(int) const;
+
+    bool f3(const int &) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f3(const int &) const;
+
+    bool f4(void) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f4(void) const;
+
+};
+

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '__attribute__((warn_unused_result))'}]}" \
+// RUN: -- -std=c++11 \
+
+class Foo
+{
+public:
+    bool f1() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+    // CHECK-FIXES: __attribute__((warn_unused_result)) bool f1() const;
+
+    bool f2(int) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+    // CHECK-FIXES: __attribute__((warn_unused_result)) bool f2(int) const;
+
+    bool f3(const int &) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+    // CHECK-FIXES: __attribute__((warn_unused_result)) bool f3(const int &) const;
+
+    bool f4(void) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+    // CHECK-FIXES: __attribute__((warn_unused_result)) bool f4(void) const;
+};
+

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '[[gcc::warn_unused_result]]'}]}" \
+// RUN: -- -std=c++11 
+
+class Foo
+{
+public:
+    bool f1() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f1() const;
+
+    bool f2(int) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f2(int) const;
+
+    bool f3(const int &) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f3(const int &) const;
+
+    bool f4(void) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f4(void) const;
+
+};
+

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: 'CUSTOM_NO_DISCARD'}]}" -- -std=c++11 
+
+// As if the macro was not defined.
+// #define CUSTOM_NO_DISCARD __attribute_((warn_unused_result))
+
+class Foo
+{
+public:
+    bool f1() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked CUSTOM_NO_DISCARD [modernize-use-nodiscard]
+};
+

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- -- -std=c++17 
+
+class Foo
+{
+public:
+    bool f1() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f1() const;
+
+    bool f2(int) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f2(int) const;
+
+    bool f3(const int &) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f3(const int &) const;
+
+    bool f4(void) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+    // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f4(void) const;
+
+};

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.cpp?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.cpp Wed Jan  9 12:50:50 2019
@@ -0,0 +1,256 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: 'NO_DISCARD'}]}" \
+// RUN: -- -std=c++17
+
+#include <functional>
+
+namespace boost {
+template <class>
+class function;
+}
+
+#include "modernize-use-nodiscard.h"
+
+#define BOOLEAN_FUNC bool f23() const
+
+typedef unsigned my_unsigned;
+typedef unsigned &my_unsigned_reference;
+typedef const unsigned &my_unsigned_const_reference;
+
+class Foo {
+public:
+    using size_type = unsigned;
+
+    bool f1() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f1() const;
+
+    bool f2(int) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f2(int) const;
+
+    bool f3(const int &) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f3(const int &) const;
+
+    bool f4(void) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f4(void) const;
+    
+    // negative tests
+
+    void f5() const;
+    
+    bool f6();
+    
+    bool f7(int &);
+    
+    bool f8(int &) const;
+    
+    bool f9(int *) const;
+    
+    bool f10(const int &, int &) const;
+    
+    NO_DISCARD bool f12() const;
+    
+    MUST_USE_RESULT bool f13() const;
+    
+    [[nodiscard]] bool f11() const;
+    
+    [[clang::warn_unused_result]] bool f11a() const;
+    
+    [[gnu::warn_unused_result]] bool f11b() const;
+
+    bool _f20() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function '_f20' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool _f20() const;
+    
+    NO_RETURN bool f21() const;
+    
+    ~Foo();
+    
+    bool operator+=(int) const;
+    
+    // extra keywords (virtual,inline,const) on return type
+    
+    virtual bool f14() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f14' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD virtual bool f14() const;
+    
+    const bool f15() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f15' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD const bool f15() const;
+    
+    inline const bool f16() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f16' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD inline const bool f16() const;
+
+    inline const std::string &f45() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f45' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD inline const std::string &f45() const;
+
+    inline virtual const bool f17() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f17' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD inline virtual const bool f17() const;
+
+    // inline with body
+    bool f18() const 
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f18' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f18() const 
+    {
+     return true;
+    }
+
+    bool f19() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f19' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f19() const;
+
+    BOOLEAN_FUNC;
+    
+    bool f24(size_type) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f24' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f24(size_type) const;
+    
+    bool f28(my_unsigned) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f28' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f28(my_unsigned) const;
+
+    bool f29(my_unsigned_reference) const;
+
+    bool f30(my_unsigned_const_reference) const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f30' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool f30(my_unsigned_const_reference) const;
+
+    template <class F>
+    F f37(F a, F b) const;
+
+    template <class F>
+    bool f38(F a) const;
+
+    bool f39(const std::function<bool()> &predicate) const;
+
+    bool f39a(std::function<bool()> predicate) const;
+
+    bool f39b(const std::function<bool()> predicate) const;
+
+    bool f45(const boost::function<bool()> &predicate) const;
+
+    bool f45a(boost::function<bool()> predicate) const;
+
+    bool f45b(const boost::function<bool()> predicate) const;
+
+    // Do not add ``[[nodiscard]]`` to parameter packs.
+    template <class... Args>
+    bool ParameterPack(Args... args) const;
+
+    template <typename... Targs>
+    bool ParameterPack2(Targs... Fargs) const;
+
+    // Do not add ``[[nodiscard]]`` to variadic functions.
+    bool VariadicFunctionTest(const int &, ...) const;
+
+    // Do not add ``[[nodiscard]]`` to non constant static functions.
+    static bool not_empty();
+
+    // Do not add ``[[nodiscard]]`` to conversion functions.
+    // explicit operator bool() const { return true; }
+};
+
+// Do not add ``[[nodiscard]]`` to Lambda.
+const auto nonConstReferenceType = [] {
+  return true;
+};
+
+auto lambda1 = [](int a, int b) { return a < b; };
+auto lambda1a = [](int a) { return a; };
+auto lambda1b = []()  { return true;};
+
+auto get_functor = [](bool check) {
+    return  [&](const std::string& sr)->std::string {
+        if(check){
+            return "some string";
+        }
+        return "another string";
+    };
+};
+
+// Do not add ``[[nodiscard]]`` to function definition.
+bool Foo::f19() const {
+  return true;
+}
+
+template <class T>
+class Bar {
+public:
+    using value_type = T;
+    using reference = value_type &;
+    using const_reference = const value_type &;
+
+    // Do not add ``[[nodiscard]]`` to non explicit conversion functions.
+    operator bool() const { return true; }
+
+    bool empty() const;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'empty' should be marked NO_DISCARD [modernize-use-nodiscard]
+    // CHECK-FIXES: NO_DISCARD bool empty() const;
+
+    // we cannot assume that the template parameter isn't a pointer
+    bool f25(value_type) const;
+
+    bool f27(reference) const;
+
+    typename T::value_type f35() const;
+
+    T f34() const;
+
+    bool f31(T) const;
+
+    bool f33(T &) const;
+
+    bool f26(const_reference) const;
+
+    bool f32(const T &) const;
+};
+
+template <typename _Tp, int cn>
+class Vec {
+public:
+    Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor
+
+    Vec cross(const Vec &v) const;
+
+    template <typename T2>
+    operator Vec<T2, cn>() const;
+};
+    
+template <class T>
+class Bar2 {
+public:
+  typedef T value_type;
+  typedef value_type &reference;
+  typedef const value_type &const_reference;
+
+  // we cannot assume that the template parameter isn't a pointer
+  bool f40(value_type) const;
+
+  bool f41(reference) const;
+
+  value_type f42() const;
+
+  typename T::value_type f43() const;
+
+  bool f44(const_reference) const;
+};
+
+template <class T>
+bool Bar<T>::empty() const {
+  return true;
+}
+
+// don't mark typical ``[[nodiscard]]`` candidates if the class
+// has mutable member variables
+class MutableExample {
+  mutable bool m_isempty;
+
+public:
+  bool empty() const;
+};

Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.h?rev=350760&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.h (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nodiscard.h Wed Jan  9 12:50:50 2019
@@ -0,0 +1,5 @@
+
+#define MUST_USE_RESULT __attribute__((warn_unused_result))
+#define NO_DISCARD [[nodiscard]]
+#define NO_RETURN [[noreturn]]
+




More information about the cfe-commits mailing list