[clang-tools-extra] 605b8da - [clang-tidy] Fix false positive in cppcoreguidelines-avoid-const-or-ref-data-members when detecting templated classes with inheritance (#115180)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Nov 24 14:47:26 PST 2024
Author: Congcong Cai
Date: 2024-11-25T06:47:22+08:00
New Revision: 605b8dad5cb173ac86adb3541e9f70a824aff364
URL: https://github.com/llvm/llvm-project/commit/605b8dad5cb173ac86adb3541e9f70a824aff364
DIFF: https://github.com/llvm/llvm-project/commit/605b8dad5cb173ac86adb3541e9f70a824aff364.diff
LOG: [clang-tidy] Fix false positive in cppcoreguidelines-avoid-const-or-ref-data-members when detecting templated classes with inheritance (#115180)
`hasSimpleCopyConstructor` series of functions are not reliable when
these functions are not resolved. We need to manually resolve the status
of these functions from its base classes.
Fixes: #111985.
Added:
Modified:
clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidConstOrRefDataMembersCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-const-or-ref-data-members.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidConstOrRefDataMembersCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidConstOrRefDataMembersCheck.cpp
index 6a6e620a4387b0..f615976c7edb62 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidConstOrRefDataMembersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidConstOrRefDataMembersCheck.cpp
@@ -13,79 +13,88 @@
using namespace clang::ast_matchers;
namespace clang::tidy::cppcoreguidelines {
-namespace {
-AST_MATCHER(FieldDecl, isMemberOfLambda) {
- return Node.getParent()->isLambda();
+static bool isCopyConstructible(CXXRecordDecl const &Node) {
+ if (Node.needsOverloadResolutionForCopyConstructor() &&
+ Node.needsImplicitCopyConstructor()) {
+ // unresolved
+ for (CXXBaseSpecifier const &BS : Node.bases()) {
+ CXXRecordDecl const *BRD = BS.getType()->getAsCXXRecordDecl();
+ if (BRD != nullptr && !isCopyConstructible(*BRD))
+ return false;
+ }
+ }
+ if (Node.hasSimpleCopyConstructor())
+ return true;
+ for (CXXConstructorDecl const *Ctor : Node.ctors())
+ if (Ctor->isCopyConstructor())
+ return !Ctor->isDeleted();
+ return false;
}
-struct MemberFunctionInfo {
- bool Declared{};
- bool Deleted{};
-};
-
-struct MemberFunctionPairInfo {
- MemberFunctionInfo Copy{};
- MemberFunctionInfo Move{};
-};
-
-MemberFunctionPairInfo getConstructorsInfo(CXXRecordDecl const &Node) {
- MemberFunctionPairInfo Constructors{};
-
- for (CXXConstructorDecl const *Ctor : Node.ctors()) {
- if (Ctor->isCopyConstructor()) {
- Constructors.Copy.Declared = true;
- if (Ctor->isDeleted())
- Constructors.Copy.Deleted = true;
- }
- if (Ctor->isMoveConstructor()) {
- Constructors.Move.Declared = true;
- if (Ctor->isDeleted())
- Constructors.Move.Deleted = true;
+static bool isMoveConstructible(CXXRecordDecl const &Node) {
+ if (Node.needsOverloadResolutionForMoveConstructor() &&
+ Node.needsImplicitMoveConstructor()) {
+ // unresolved
+ for (CXXBaseSpecifier const &BS : Node.bases()) {
+ CXXRecordDecl const *BRD = BS.getType()->getAsCXXRecordDecl();
+ if (BRD != nullptr && !isMoveConstructible(*BRD))
+ return false;
}
}
-
- return Constructors;
+ if (Node.hasSimpleMoveConstructor())
+ return true;
+ for (CXXConstructorDecl const *Ctor : Node.ctors())
+ if (Ctor->isMoveConstructor())
+ return !Ctor->isDeleted();
+ return false;
}
-MemberFunctionPairInfo getAssignmentsInfo(CXXRecordDecl const &Node) {
- MemberFunctionPairInfo Assignments{};
-
- for (CXXMethodDecl const *Method : Node.methods()) {
- if (Method->isCopyAssignmentOperator()) {
- Assignments.Copy.Declared = true;
- if (Method->isDeleted())
- Assignments.Copy.Deleted = true;
+static bool isCopyAssignable(CXXRecordDecl const &Node) {
+ if (Node.needsOverloadResolutionForCopyAssignment() &&
+ Node.needsImplicitCopyAssignment()) {
+ // unresolved
+ for (CXXBaseSpecifier const &BS : Node.bases()) {
+ CXXRecordDecl const *BRD = BS.getType()->getAsCXXRecordDecl();
+ if (BRD != nullptr && !isCopyAssignable(*BRD))
+ return false;
}
+ }
+ if (Node.hasSimpleCopyAssignment())
+ return true;
+ for (CXXMethodDecl const *Method : Node.methods())
+ if (Method->isCopyAssignmentOperator())
+ return !Method->isDeleted();
+ return false;
+}
- if (Method->isMoveAssignmentOperator()) {
- Assignments.Move.Declared = true;
- if (Method->isDeleted())
- Assignments.Move.Deleted = true;
+static bool isMoveAssignable(CXXRecordDecl const &Node) {
+ if (Node.needsOverloadResolutionForMoveAssignment() &&
+ Node.needsImplicitMoveAssignment()) {
+ // unresolved
+ for (CXXBaseSpecifier const &BS : Node.bases()) {
+ CXXRecordDecl const *BRD = BS.getType()->getAsCXXRecordDecl();
+ if (BRD != nullptr && !isMoveAssignable(*BRD))
+ return false;
}
}
-
- return Assignments;
+ if (Node.hasSimpleMoveAssignment())
+ return true;
+ for (CXXMethodDecl const *Method : Node.methods())
+ if (Method->isMoveAssignmentOperator())
+ return !Method->isDeleted();
+ return false;
}
-AST_MATCHER(CXXRecordDecl, isCopyableOrMovable) {
- MemberFunctionPairInfo Constructors = getConstructorsInfo(Node);
- MemberFunctionPairInfo Assignments = getAssignmentsInfo(Node);
+namespace {
- if (Node.hasSimpleCopyConstructor() ||
- (Constructors.Copy.Declared && !Constructors.Copy.Deleted))
- return true;
- if (Node.hasSimpleMoveConstructor() ||
- (Constructors.Move.Declared && !Constructors.Move.Deleted))
- return true;
- if (Node.hasSimpleCopyAssignment() ||
- (Assignments.Copy.Declared && !Assignments.Copy.Deleted))
- return true;
- if (Node.hasSimpleMoveAssignment() ||
- (Assignments.Move.Declared && !Assignments.Move.Deleted))
- return true;
+AST_MATCHER(FieldDecl, isMemberOfLambda) {
+ return Node.getParent()->isLambda();
+}
- return false;
+AST_MATCHER(CXXRecordDecl, isCopyableOrMovable) {
+ return isCopyConstructible(Node) || isMoveConstructible(Node) ||
+ isCopyAssignable(Node) || isMoveAssignable(Node);
}
} // namespace
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 1f338f23f4e6ea..fec2c20206bc4d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -207,6 +207,10 @@ Changes in existing checks
fix false positive that floating point variable is only used in increment
expression.
+- Improved :doc:`cppcoreguidelines-avoid-const-or-ref-data-members
+ <clang-tidy/checks/cppcoreguidelines/avoid-const-or-ref-data-members>` check to
+ avoid false positives when detecting a templated class with inheritance.
+
- Improved :doc:`cppcoreguidelines-init-variables
<clang-tidy/checks/cppcoreguidelines/init-variables>` check by fixing the
insertion location for function pointers.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-const-or-ref-data-members.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-const-or-ref-data-members.cpp
index e3864be134da3c..19da88300aec46 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-const-or-ref-data-members.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-const-or-ref-data-members.cpp
@@ -285,6 +285,28 @@ struct InheritBothFromNonCopyableAndNonMovable : NonCopyable, NonMovable
int& x; // OK, non copyable nor movable
};
+template<class T> struct TemplateInheritFromNonCopyable : NonCopyable
+{
+ int& x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference
+};
+
+template<class T> struct TemplateInheritFromNonMovable : NonMovable
+{
+ int& x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference
+};
+
+template<class T> struct TemplateInheritFromNonCopyableNonMovable : NonCopyableNonMovable
+{
+ int& x; // OK, non copyable nor movable
+};
+
+template<class T> struct TemplateInheritBothFromNonCopyableAndNonMovable : NonCopyable, NonMovable
+{
+ int& x; // OK, non copyable nor movable
+};
+
// Test composition
struct ContainsNonCopyable
{
More information about the cfe-commits
mailing list