12
12
#include " uglify_attributes.hpp"
13
13
14
14
#include < algorithm>
15
+ #include < array>
16
+ #include < span>
15
17
#include < string_view>
16
18
17
19
namespace {
@@ -23,25 +25,51 @@ bool isUgly(std::string_view str) {
23
25
return str.find (" __" ) != std::string_view::npos;
24
26
}
25
27
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
+
26
53
AST_MATCHER (clang::Attr, isPretty) {
27
54
if (Node.isKeywordAttribute ())
28
55
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
+ }
31
62
if (Node.hasScope ())
32
63
if (!isUgly (Node.getScopeName ()->getName ()))
33
64
return true ;
34
-
35
65
if (Node.getAttrName ())
36
66
return !isUgly (Node.getAttrName ()->getName ());
37
67
38
68
return false ;
39
69
}
40
70
41
71
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.
45
73
46
74
std::string attr_string;
47
75
if (attr.isClangScope ())
@@ -84,11 +112,11 @@ void uglify_attributes::registerMatchers(clang::ast_matchers::MatchFinder* finde
84
112
}
85
113
86
114
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 );
90
118
if (uglified.has_value ()) {
91
- diagnostic << clang::FixItHint::CreateReplacement (call ->getRange (), *uglified);
119
+ diagnostic << clang::FixItHint::CreateReplacement (attr ->getRange (), *uglified);
92
120
}
93
121
}
94
122
}
0 commit comments