[libcxx-commits] [libcxx] [libc++] Clang-tidy operator& hijacker. (PR #128366)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Apr 5 07:03:22 PDT 2025


https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/128366

>From 3f892227df166d56f408b9f502233a3670619e2d Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sun, 16 Feb 2025 12:07:44 +0100
Subject: [PATCH 1/3] [libc++] Clang-tidy operator& hijacker.

Guards against introducing new places where operator& depends on a
template type.
---
 .../tools/clang_tidy_checks/CMakeLists.txt    |  1 +
 .../tools/clang_tidy_checks/libcpp_module.cpp |  3 ++
 .../robust_against_operator_ampersand.cpp     | 47 +++++++++++++++++++
 .../robust_against_operator_ampersand.hpp     | 24 ++++++++++
 4 files changed, 75 insertions(+)
 create mode 100644 libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
 create mode 100644 libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp

diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
index f8b523ec0ba93..c02f54a703e1b 100644
--- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
+++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
@@ -95,6 +95,7 @@ set(SOURCES
     nodebug_on_aliases.cpp
     proper_version_checks.cpp
     robust_against_adl.cpp
+    robust_against_operator_ampersand.cpp
     uglify_attributes.cpp
 
     libcpp_module.cpp
diff --git a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
index 32a33dddad632..2cf39e2b626f8 100644
--- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
+++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
@@ -16,6 +16,7 @@
 #include "nodebug_on_aliases.hpp"
 #include "proper_version_checks.hpp"
 #include "robust_against_adl.hpp"
+#include "robust_against_operator_ampersand.hpp"
 #include "uglify_attributes.hpp"
 
 namespace {
@@ -29,6 +30,8 @@ class LibcxxTestModule : public clang::tidy::ClangTidyModule {
     check_factories.registerCheck<libcpp::nodebug_on_aliases>("libcpp-nodebug-on-aliases");
     check_factories.registerCheck<libcpp::proper_version_checks>("libcpp-cpp-version-check");
     check_factories.registerCheck<libcpp::robust_against_adl_check>("libcpp-robust-against-adl");
+    check_factories.registerCheck<libcpp::robust_against_operator_ampersand>(
+        "libcpp-robust-against-operator-ampersand");
     check_factories.registerCheck<libcpp::uglify_attributes>("libcpp-uglify-attributes");
   }
 };
diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
new file mode 100644
index 0000000000000..3d3e7d516be9a
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "clang-tidy/ClangTidyCheck.h"
+#include "clang-tidy/ClangTidyModuleRegistry.h"
+#include "clang/Tooling/FixIt.h"
+
+#include "robust_against_operator_ampersand.hpp"
+
+// This clang-tidy check ensures that we don't use operator& on dependant
+// types. If the type is user supplied it may call the type's operator&.
+// Instead use std::addressof.
+
+namespace libcpp {
+robust_against_operator_ampersand::robust_against_operator_ampersand(
+    llvm::StringRef name, clang::tidy::ClangTidyContext* context)
+    : clang::tidy::ClangTidyCheck(name, context), disabled_(!context->getLangOpts().CPlusPlus11) {}
+
+void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) {
+  if (disabled_)
+    return;
+
+  using namespace clang::ast_matchers;
+  finder->addMatcher(
+      cxxOperatorCallExpr(allOf(hasOperatorName("&"), argumentCountIs(1), isTypeDependent()),
+                          unless(hasUnaryOperand(dependentScopeDeclRefExpr())))
+          .bind("match"),
+      this);
+}
+
+void robust_against_operator_ampersand::check(const clang::ast_matchers::MatchFinder::MatchResult& result) {
+  if (const auto* call = result.Nodes.getNodeAs< clang::CXXOperatorCallExpr >("match"); call != nullptr) {
+    diag(call->getBeginLoc(), "Guard against user provided operator& for dependent types.")
+        << clang::FixItHint::CreateReplacement(
+               call->getSourceRange(),
+               (llvm::Twine(
+                    "std::addressof(" + clang::tooling::fixit::getText(*call->getArg(0), *result.Context) + ")"))
+                   .str());
+  }
+}
+
+} // namespace libcpp
diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp
new file mode 100644
index 0000000000000..e7010de02685c
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "clang-tidy/ClangTidyCheck.h"
+
+namespace libcpp {
+class robust_against_operator_ampersand : public clang::tidy::ClangTidyCheck {
+  // At the moment libc++ is phasing out development on C++03.
+  // To avoid testing in C++03, this test is automatically disabled in C++03
+  // mode. (Doing this from the tests is a lot harder.)
+  // TODO Remove after dropping C++03 support.
+  bool disabled_;
+
+public:
+  robust_against_operator_ampersand(llvm::StringRef, clang::tidy::ClangTidyContext*);
+  void registerMatchers(clang::ast_matchers::MatchFinder*) override;
+  void check(const clang::ast_matchers::MatchFinder::MatchResult&) override;
+};
+} // namespace libcpp

>From bc68ee10bf7f6109bb3a8fd850365eafbd4d29ac Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Tue, 18 Mar 2025 18:20:23 +0100
Subject: [PATCH 2/3] Addresses review comments.

---
 libcxx/test/libcxx/clang_tidy.gen.py                        | 4 ++++
 .../clang_tidy_checks/robust_against_operator_ampersand.cpp | 5 +----
 .../clang_tidy_checks/robust_against_operator_ampersand.hpp | 6 ------
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/libcxx/test/libcxx/clang_tidy.gen.py b/libcxx/test/libcxx/clang_tidy.gen.py
index f1135749febe4..dbab2875e3126 100644
--- a/libcxx/test/libcxx/clang_tidy.gen.py
+++ b/libcxx/test/libcxx/clang_tidy.gen.py
@@ -6,6 +6,7 @@
 #
 # ===----------------------------------------------------------------------===##
 
+
 # Run our custom libc++ clang-tidy checks on all public headers.
 
 # RUN: %{python} %s %{libcxx-dir}/utils
@@ -23,6 +24,9 @@
 
 // REQUIRES: has-clang-tidy
 
+// The frozen headers should not be updated to the latest libc++ style, so don't test.
+// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
+
 // The GCC compiler flags are not always compatible with clang-tidy.
 // UNSUPPORTED: gcc
 
diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
index 3d3e7d516be9a..8361e0c3eee88 100644
--- a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
+++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
@@ -19,12 +19,9 @@
 namespace libcpp {
 robust_against_operator_ampersand::robust_against_operator_ampersand(
     llvm::StringRef name, clang::tidy::ClangTidyContext* context)
-    : clang::tidy::ClangTidyCheck(name, context), disabled_(!context->getLangOpts().CPlusPlus11) {}
+    : clang::tidy::ClangTidyCheck(name, context) {}
 
 void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) {
-  if (disabled_)
-    return;
-
   using namespace clang::ast_matchers;
   finder->addMatcher(
       cxxOperatorCallExpr(allOf(hasOperatorName("&"), argumentCountIs(1), isTypeDependent()),
diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp
index e7010de02685c..5cdc0baca5c23 100644
--- a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp
+++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp
@@ -10,12 +10,6 @@
 
 namespace libcpp {
 class robust_against_operator_ampersand : public clang::tidy::ClangTidyCheck {
-  // At the moment libc++ is phasing out development on C++03.
-  // To avoid testing in C++03, this test is automatically disabled in C++03
-  // mode. (Doing this from the tests is a lot harder.)
-  // TODO Remove after dropping C++03 support.
-  bool disabled_;
-
 public:
   robust_against_operator_ampersand(llvm::StringRef, clang::tidy::ClangTidyContext*);
   void registerMatchers(clang::ast_matchers::MatchFinder*) override;

>From b8432daa6ff81dc7b4f3ce18234278d22d0a446c Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sat, 5 Apr 2025 16:02:48 +0200
Subject: [PATCH 3/3] Try to fix CI and address review comment.

---
 .../clang_tidy_checks/robust_against_operator_ampersand.cpp   | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
index 8361e0c3eee88..bb83c86275561 100644
--- a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
+++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp
@@ -8,6 +8,7 @@
 
 #include "clang-tidy/ClangTidyCheck.h"
 #include "clang-tidy/ClangTidyModuleRegistry.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
 
 #include "robust_against_operator_ampersand.hpp"
@@ -15,6 +16,9 @@
 // This clang-tidy check ensures that we don't use operator& on dependant
 // types. If the type is user supplied it may call the type's operator&.
 // Instead use std::addressof.
+//
+// This is part of libc++'s policy
+// https://libcxx.llvm.org/CodingGuidelines.html#don-t-use-argument-dependent-lookup-unless-required-by-the-standard
 
 namespace libcpp {
 robust_against_operator_ampersand::robust_against_operator_ampersand(



More information about the libcxx-commits mailing list