1212#include " uglify_attributes.hpp"
1313
1414#include < algorithm>
15+ #include < array>
16+ #include < span>
1517#include < string_view>
1618
1719namespace {
@@ -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+
2653AST_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
4171std::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
86114void 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