[libcxx-commits] [libcxx] c8eff95 - [libc++] Add a clang-tidy check to make sure we use _Uglyfied attribute names

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Wed Feb 1 09:57:13 PST 2023


Author: Nikolas Klauser
Date: 2023-02-01T18:57:06+01:00
New Revision: c8eff9560fc1d2462a60bccb560a9ef87a4ba5bb

URL: https://github.com/llvm/llvm-project/commit/c8eff9560fc1d2462a60bccb560a9ef87a4ba5bb
DIFF: https://github.com/llvm/llvm-project/commit/c8eff9560fc1d2462a60bccb560a9ef87a4ba5bb.diff

LOG: [libc++] Add a clang-tidy check to make sure we use _Uglyfied attribute names

Reviewed By: ldionne, #libc

Spies: krytarowski, jdoerfert, libcxx-commits

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

Added: 
    libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp
    libcxx/test/tools/clang_tidy_checks/uglify_attributes.hpp

Modified: 
    libcxx/include/__config
    libcxx/include/__memory/shared_ptr.h
    libcxx/include/__memory/unique_ptr.h
    libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
    libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__config b/libcxx/include/__config
index 40c9deb622951..a4af3f176ec37 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -767,9 +767,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
 // Deprecations warnings are always enabled, except when users explicitly opt-out
 // by defining _LIBCPP_DISABLE_DEPRECATION_WARNINGS.
 #  if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)
-#    if __has_attribute(deprecated)
-#      define _LIBCPP_DEPRECATED __attribute__((deprecated))
-#      define _LIBCPP_DEPRECATED_(m) __attribute__((deprecated(m)))
+#    if __has_attribute(__deprecated__)
+#      define _LIBCPP_DEPRECATED __attribute__((__deprecated__))
+#      define _LIBCPP_DEPRECATED_(m) __attribute__((__deprecated__(m)))
 #    elif _LIBCPP_STD_VER > 11
 #      define _LIBCPP_DEPRECATED [[deprecated]]
 #      define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]]

diff  --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 6bb9ca968dfad..f990612c2c946 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -404,7 +404,7 @@ struct __shared_ptr_deleter_ctor_reqs
 };
 
 #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI)
-#  define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((trivial_abi))
+#  define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__))
 #else
 #  define _LIBCPP_SHARED_PTR_TRIVIAL_ABI
 #endif

diff  --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 9cdbda8eba409..c50ac4cad4ba7 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -115,7 +115,7 @@ struct __unique_ptr_deleter_sfinae<_Deleter&> {
 };
 
 #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI)
-#  define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi))
+#  define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__))
 #else
 #  define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI
 #endif

diff  --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
index adceee2d8b3c7..2ef102419e2fd 100644
--- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
+++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
@@ -8,8 +8,9 @@ find_package(Clang 16)
 set(SOURCES
     abi_tag_on_virtual.cpp
     hide_from_abi.cpp
-    robust_against_adl.cpp
     qualify_declval.cpp
+    robust_against_adl.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 f1dfbf563959e..685d34a86b54a 100644
--- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
+++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
@@ -13,6 +13,7 @@
 #include "hide_from_abi.hpp"
 #include "robust_against_adl.hpp"
 #include "qualify_declval.hpp"
+#include "uglify_attributes.hpp"
 
 namespace {
 class LibcxxTestModule : public clang::tidy::ClangTidyModule {
@@ -21,6 +22,7 @@ class LibcxxTestModule : public clang::tidy::ClangTidyModule {
     check_factories.registerCheck<libcpp::abi_tag_on_virtual>("libcpp-avoid-abi-tag-on-virtual");
     check_factories.registerCheck<libcpp::hide_from_abi>("libcpp-hide-from-abi");
     check_factories.registerCheck<libcpp::robust_against_adl_check>("libcpp-robust-against-adl");
+    check_factories.registerCheck<libcpp::uglify_attributes>("libcpp-uglify-attributes");
     check_factories.registerCheck<libcpp::qualify_declval>("libcpp-qualify-declval");
   }
 };

diff  --git a/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp b/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp
new file mode 100644
index 0000000000000..03b9fe5e4d0f6
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "uglify_attributes.hpp"
+
+#include <algorithm>
+#include <string_view>
+
+namespace {
+bool isUgly(std::string_view str) {
+  if (str.size() < 2)
+    return false;
+  if (str[0] == '_' && str[1] >= 'A' && str[1] <= 'Z')
+    return true;
+  return str.find("__") != std::string_view::npos;
+}
+
+AST_MATCHER(clang::Attr, isPretty) {
+  if (Node.isKeywordAttribute())
+    return false;
+  if (Node.isCXX11Attribute() && !Node.hasScope()) // TODO: reject standard attributes that are version extensions
+    return false;
+  if (Node.hasScope())
+    if (!isUgly(Node.getScopeName()->getName()))
+      return true;
+
+  if (Node.getAttrName())
+    return !isUgly(Node.getAttrName()->getName());
+
+  return false;
+}
+
+std::optional<std::string> getUglyfiedCXX11Attr(const clang::Attr& attr) {
+  // Don't try to fix attributes with `using` in them.
+  if (std::ranges::search(std::string_view(attr.getSpelling()), std::string_view("::")).empty())
+    return std::nullopt;
+
+  std::string attr_string;
+  if (attr.isClangScope())
+    attr_string += "_Clang::";
+  else if (attr.isGNUScope())
+    attr_string += "__gnu__::";
+
+  if (!attr.getAttrName()->getName().starts_with("__")) {
+    attr_string += "__";
+    attr_string += attr.getAttrName()->getName();
+    attr_string += "__";
+  } else {
+    attr_string += attr.getAttrName()->getName();
+  }
+  return std::move(attr_string);
+}
+
+std::optional<std::string> getUglyfiedGNUAttr(const clang::Attr& attr) {
+  return "__" + attr.getAttrName()->getName().str() + "__";
+}
+
+std::optional<std::string> getUglified(const clang::Attr& attr) {
+  if (attr.isCXX11Attribute()) {
+    return getUglyfiedCXX11Attr(attr);
+  } else if (attr.isGNUAttribute()) {
+    return getUglyfiedGNUAttr(attr);
+  }
+
+  return std::nullopt;
+}
+} // namespace
+
+namespace libcpp {
+uglify_attributes::uglify_attributes(llvm::StringRef name, clang::tidy::ClangTidyContext* context)
+    : clang::tidy::ClangTidyCheck(name, context) {}
+
+void uglify_attributes::registerMatchers(clang::ast_matchers::MatchFinder* finder) {
+  using namespace clang::ast_matchers;
+  finder->addMatcher(attr(isPretty()).bind("normal_attribute"), this);
+}
+
+void uglify_attributes::check(const clang::ast_matchers::MatchFinder::MatchResult& result) {
+  if (const auto* call = result.Nodes.getNodeAs<clang::Attr>("normal_attribute"); call != nullptr) {
+    auto diagnostic = diag(call->getLoc(), "Non-standard attributes should use the _Ugly spelling");
+    auto uglified   = getUglified(*call);
+    if (uglified.has_value()) {
+      diagnostic << clang::FixItHint::CreateReplacement(call->getRange(), *uglified);
+    }
+  }
+}
+} // namespace libcpp

diff  --git a/libcxx/test/tools/clang_tidy_checks/uglify_attributes.hpp b/libcxx/test/tools/clang_tidy_checks/uglify_attributes.hpp
new file mode 100644
index 0000000000000..a3a06e6703dc5
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/uglify_attributes.hpp
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 uglify_attributes : public clang::tidy::ClangTidyCheck {
+public:
+  uglify_attributes(llvm::StringRef, clang::tidy::ClangTidyContext*);
+  void registerMatchers(clang::ast_matchers::MatchFinder*) override;
+  void check(const clang::ast_matchers::MatchFinder::MatchResult&) override;
+};
+} // namespace libcpp


        


More information about the libcxx-commits mailing list