[tidy] add new check bugprone-return-const-ref-from-parameter (#89497)
This commit is contained in:
parent
4f4ebee10e
commit
d56f08b2ba
@ -54,6 +54,7 @@
|
||||
#include "PosixReturnCheck.h"
|
||||
#include "RedundantBranchConditionCheck.h"
|
||||
#include "ReservedIdentifierCheck.h"
|
||||
#include "ReturnConstRefFromParameterCheck.h"
|
||||
#include "SharedPtrArrayMismatchCheck.h"
|
||||
#include "SignalHandlerCheck.h"
|
||||
#include "SignedCharMisuseCheck.h"
|
||||
@ -137,6 +138,8 @@ public:
|
||||
"bugprone-inaccurate-erase");
|
||||
CheckFactories.registerCheck<IncorrectEnableIfCheck>(
|
||||
"bugprone-incorrect-enable-if");
|
||||
CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>(
|
||||
"bugprone-return-const-ref-from-parameter");
|
||||
CheckFactories.registerCheck<SwitchMissingDefaultCaseCheck>(
|
||||
"bugprone-switch-missing-default-case");
|
||||
CheckFactories.registerCheck<IncDecInConditionsCheck>(
|
||||
|
@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule
|
||||
ImplicitWideningOfMultiplicationResultCheck.cpp
|
||||
InaccurateEraseCheck.cpp
|
||||
IncorrectEnableIfCheck.cpp
|
||||
ReturnConstRefFromParameterCheck.cpp
|
||||
SuspiciousStringviewDataUsageCheck.cpp
|
||||
SwitchMissingDefaultCaseCheck.cpp
|
||||
IncDecInConditionsCheck.cpp
|
||||
|
@ -0,0 +1,34 @@
|
||||
//===--- ReturnConstRefFromParameterCheck.cpp - clang-tidy ----------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ReturnConstRefFromParameterCheck.h"
|
||||
#include "../utils/Matchers.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang::tidy::bugprone {
|
||||
|
||||
void ReturnConstRefFromParameterCheck::registerMatchers(MatchFinder *Finder) {
|
||||
Finder->addMatcher(
|
||||
returnStmt(hasReturnValue(declRefExpr(to(parmVarDecl(hasType(
|
||||
hasCanonicalType(matchers::isReferenceToConst())))))))
|
||||
.bind("ret"),
|
||||
this);
|
||||
}
|
||||
|
||||
void ReturnConstRefFromParameterCheck::check(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
const auto *R = Result.Nodes.getNodeAs<ReturnStmt>("ret");
|
||||
diag(R->getRetValue()->getBeginLoc(),
|
||||
"returning a constant reference parameter may cause a use-after-free "
|
||||
"when the parameter is constructed from a temporary");
|
||||
}
|
||||
|
||||
} // namespace clang::tidy::bugprone
|
@ -0,0 +1,40 @@
|
||||
//===--- ReturnConstRefFromParameterCheck.h - clang-tidy --------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RETURNCONSTREFFROMPARAMETERCHECK_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RETURNCONSTREFFROMPARAMETERCHECK_H
|
||||
|
||||
#include "../ClangTidyCheck.h"
|
||||
|
||||
namespace clang::tidy::bugprone {
|
||||
|
||||
/// Detects return statements that return a constant reference parameter as
|
||||
/// constant reference. This may cause use-after-free errors if the caller uses
|
||||
/// xvalues as arguments.
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/return-const-ref-from-parameter.html
|
||||
class ReturnConstRefFromParameterCheck : public ClangTidyCheck {
|
||||
public:
|
||||
ReturnConstRefFromParameterCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
std::optional<TraversalKind> getCheckTraversalKind() const override {
|
||||
// Use 'AsIs' to make sure the return type is exactly the same as the
|
||||
// parameter type.
|
||||
return TK_AsIs;
|
||||
}
|
||||
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
|
||||
return LangOpts.CPlusPlus;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace clang::tidy::bugprone
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RETURNCONSTREFFROMPARAMETERCHECK_H
|
@ -117,6 +117,13 @@ New checks
|
||||
Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP
|
||||
can be constructed outside itself and the derived class.
|
||||
|
||||
- New :doc:`bugprone-return-const-ref-from-parameter
|
||||
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check.
|
||||
|
||||
Detects return statements that return a constant reference parameter as constant
|
||||
reference. This may cause use-after-free errors if the caller uses xvalues as
|
||||
arguments.
|
||||
|
||||
- New :doc:`bugprone-suspicious-stringview-data-usage
|
||||
<clang-tidy/checks/bugprone/suspicious-stringview-data-usage>` check.
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
.. title:: clang-tidy - bugprone-return-const-ref-from-parameter
|
||||
|
||||
bugprone-return-const-ref-from-parameter
|
||||
========================================
|
||||
|
||||
Detects return statements that return a constant reference parameter as constant
|
||||
reference. This may cause use-after-free errors if the caller uses xvalues as
|
||||
arguments.
|
||||
|
||||
In C++, constant reference parameters can accept xvalues which will be destructed
|
||||
after the call. When the function returns such a parameter also as constant reference,
|
||||
then the returned reference can be used after the object it refers to has been
|
||||
destroyed.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
struct S {
|
||||
int v;
|
||||
S(int);
|
||||
~S();
|
||||
};
|
||||
|
||||
const S &fn(const S &a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
const S& s = fn(S{1});
|
||||
s.v; // use after free
|
@ -120,6 +120,7 @@ Clang-Tidy Checks
|
||||
:doc:`bugprone-posix-return <bugprone/posix-return>`, "Yes"
|
||||
:doc:`bugprone-redundant-branch-condition <bugprone/redundant-branch-condition>`, "Yes"
|
||||
:doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes"
|
||||
:doc:`bugprone-return-const-ref-from-parameter <bugprone/return-const-ref-from-parameter>`
|
||||
:doc:`bugprone-shared-ptr-array-mismatch <bugprone/shared-ptr-array-mismatch>`, "Yes"
|
||||
:doc:`bugprone-signal-handler <bugprone/signal-handler>`,
|
||||
:doc:`bugprone-signed-char-misuse <bugprone/signed-char-misuse>`,
|
||||
|
@ -0,0 +1,31 @@
|
||||
// RUN: %check_clang_tidy %s bugprone-return-const-ref-from-parameter %t
|
||||
|
||||
using T = int;
|
||||
using TConst = int const;
|
||||
using TConstRef = int const&;
|
||||
|
||||
namespace invalid {
|
||||
|
||||
int const &f1(int const &a) { return a; }
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter
|
||||
|
||||
int const &f2(T const &a) { return a; }
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter
|
||||
|
||||
int const &f3(TConstRef a) { return a; }
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: returning a constant reference parameter
|
||||
|
||||
int const &f4(TConst &a) { return a; }
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
|
||||
|
||||
} // namespace invalid
|
||||
|
||||
namespace valid {
|
||||
|
||||
int const &f1(int &a) { return a; }
|
||||
|
||||
int const &f2(int &&a) { return a; }
|
||||
|
||||
int f1(int const &a) { return a; }
|
||||
|
||||
} // namespace valid
|
Loading…
x
Reference in New Issue
Block a user