Skip to content

Commit 433c05f

Browse files
philnik777Ferdinand Lemaire
authored and
Ferdinand Lemaire
committed
[libc++] Reject standard attributes which are extensions in libcpp-uglify-attributes
This adds a list of attributes which can be pretty to be able to reject attributes which were introduced in a later C++ standard. Fixes llvm#61196 Reviewed By: Mordante, #libc Spies: mikhail.ramalho, jdoerfert, libcxx-commits Differential Revision: https://reviews.llvm.org/D145508
1 parent 67bc920 commit 433c05f

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

libcxx/include/__config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
879879
# endif
880880

881881
# if __has_cpp_attribute(nodiscard)
882-
# define _LIBCPP_NODISCARD [[nodiscard]]
882+
# define _LIBCPP_NODISCARD [[__nodiscard__]]
883883
# else
884884
// We can't use GCC's [[gnu::warn_unused_result]] and
885885
// __attribute__((warn_unused_result)), because GCC does not silence them via
@@ -1198,7 +1198,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
11981198
// [[msvc::no_unique_address]], this should be preferred though.
11991199
# define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
12001200
# elif __has_cpp_attribute(no_unique_address)
1201-
# define _LIBCPP_NO_UNIQUE_ADDRESS [[no_unique_address]]
1201+
# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
12021202
# else
12031203
# define _LIBCPP_NO_UNIQUE_ADDRESS /* nothing */
12041204
// Note that this can be replaced by #error as soon as clang-cl

libcxx/include/barrier

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public:
135135
__expected_adjustment_(0), __completion_(std::move(__completion)), __phase_(0)
136136
{
137137
}
138-
[[nodiscard]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
138+
[[__nodiscard__]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
139139
arrival_token arrive(ptrdiff_t __update)
140140
{
141141
auto const __old_phase = __phase_.load(memory_order_relaxed);
@@ -305,7 +305,7 @@ public:
305305
barrier(barrier const&) = delete;
306306
barrier& operator=(barrier const&) = delete;
307307

308-
[[nodiscard]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
308+
[[__nodiscard__]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
309309
arrival_token arrive(ptrdiff_t __update = 1)
310310
{
311311
return __b_.arrive(__update);

libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "uglify_attributes.hpp"
1313

1414
#include <algorithm>
15+
#include <array>
16+
#include <span>
1517
#include <string_view>
1618

1719
namespace {
@@ -23,25 +25,51 @@ bool isUgly(std::string_view str) {
2325
return str.find("__") != std::string_view::npos;
2426
}
2527

28+
std::vector<const char*> get_standard_attributes(const clang::LangOptions& lang_opts) {
29+
std::vector<const char*> attributes = {"noreturn", "carries_dependency"};
30+
31+
if (lang_opts.CPlusPlus14)
32+
attributes.emplace_back("deprecated");
33+
34+
if (lang_opts.CPlusPlus17) {
35+
attributes.emplace_back("fallthrough");
36+
attributes.emplace_back("nodiscard");
37+
attributes.emplace_back("maybe_unused");
38+
}
39+
40+
if (lang_opts.CPlusPlus20) {
41+
attributes.emplace_back("likely");
42+
attributes.emplace_back("unlikely");
43+
attributes.emplace_back("no_unique_address");
44+
}
45+
46+
if (lang_opts.CPlusPlus2b) {
47+
attributes.emplace_back("assume");
48+
}
49+
50+
return attributes;
51+
}
52+
2653
AST_MATCHER(clang::Attr, isPretty) {
2754
if (Node.isKeywordAttribute())
2855
return false;
29-
if (Node.isCXX11Attribute() && !Node.hasScope()) // TODO: reject standard attributes that are version extensions
30-
return false;
56+
if (Node.isCXX11Attribute() && !Node.hasScope()) {
57+
if (isUgly(Node.getAttrName()->getName()))
58+
return false;
59+
return !llvm::is_contained(
60+
get_standard_attributes(Finder->getASTContext().getLangOpts()), Node.getAttrName()->getName());
61+
}
3162
if (Node.hasScope())
3263
if (!isUgly(Node.getScopeName()->getName()))
3364
return true;
34-
3565
if (Node.getAttrName())
3666
return !isUgly(Node.getAttrName()->getName());
3767

3868
return false;
3969
}
4070

4171
std::optional<std::string> getUglyfiedCXX11Attr(const clang::Attr& attr) {
42-
// Don't try to fix attributes with `using` in them.
43-
if (std::ranges::search(std::string_view(attr.getSpelling()), std::string_view("::")).empty())
44-
return std::nullopt;
72+
// TODO: Don't emit FixItHints for attributes with `using` in them or emit correct fixes.
4573

4674
std::string attr_string;
4775
if (attr.isClangScope())
@@ -84,11 +112,11 @@ void uglify_attributes::registerMatchers(clang::ast_matchers::MatchFinder* finde
84112
}
85113

86114
void uglify_attributes::check(const clang::ast_matchers::MatchFinder::MatchResult& result) {
87-
if (const auto* call = result.Nodes.getNodeAs<clang::Attr>("normal_attribute"); call != nullptr) {
88-
auto diagnostic = diag(call->getLoc(), "Non-standard attributes should use the _Ugly spelling");
89-
auto uglified = getUglified(*call);
115+
if (const auto* attr = result.Nodes.getNodeAs<clang::Attr>("normal_attribute"); attr != nullptr) {
116+
auto diagnostic = diag(attr->getLoc(), "Non-standard attributes should use the _Ugly spelling");
117+
auto uglified = getUglified(*attr);
90118
if (uglified.has_value()) {
91-
diagnostic << clang::FixItHint::CreateReplacement(call->getRange(), *uglified);
119+
diagnostic << clang::FixItHint::CreateReplacement(attr->getRange(), *uglified);
92120
}
93121
}
94122
}

0 commit comments

Comments
 (0)