14
14
#include " clang/ASTMatchers/ASTMatchFinder.h"
15
15
#include " clang/ASTMatchers/ASTMatchers.h"
16
16
#include " clang/ASTMatchers/ASTMatchersMacros.h"
17
- #include < algorithm >
18
- #include < iterator >
19
- #include < vector >
17
+ #include " clang/Basic/Diagnostic.h "
18
+ #include " clang/Lex/Lexer.h "
19
+ #include " clang/Tooling/DesignatedInitializers.h "
20
20
21
21
using namespace clang ::ast_matchers;
22
22
@@ -29,15 +29,6 @@ static const bool IgnoreSingleElementAggregatesDefault = true;
29
29
static const char *RestrictToPODTypesName = " RestrictToPODTypes" ;
30
30
static const bool RestrictToPODTypesDefault = false ;
31
31
32
- static std::vector<Stmt *>
33
- getUndesignatedComponents (const InitListExpr *SyntacticInitList) {
34
- std::vector<Stmt *> Result;
35
- std::copy_if (SyntacticInitList->begin (), SyntacticInitList->end (),
36
- std::back_inserter (Result),
37
- [](auto S) { return !isa<DesignatedInitExpr>(S); });
38
- return Result;
39
- }
40
-
41
32
UseDesignatedInitializersCheck::UseDesignatedInitializersCheck (
42
33
StringRef Name, ClangTidyContext *Context)
43
34
: ClangTidyCheck(Name, Context), IgnoreSingleElementAggregates(Options.get(
@@ -51,7 +42,9 @@ AST_MATCHER(CXXRecordDecl, isAggregate) { return Node.isAggregate(); }
51
42
AST_MATCHER (CXXRecordDecl, isPOD) { return Node.isPOD (); }
52
43
53
44
AST_MATCHER (InitListExpr, isFullyDesignated) {
54
- return getUndesignatedComponents (&Node).empty ();
45
+ return std::all_of (Node.begin (), Node.end (), [](auto *InitExpr) {
46
+ return isa<DesignatedInitExpr>(InitExpr);
47
+ });
55
48
}
56
49
57
50
AST_MATCHER (InitListExpr, hasSingleElement) { return Node.getNumInits () == 1 ; }
@@ -82,31 +75,43 @@ void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) {
82
75
this );
83
76
}
84
77
78
+ static bool isFullyUndesignated (const InitListExpr *SyntacticInitList) {
79
+ return std::all_of (
80
+ SyntacticInitList->begin (), SyntacticInitList->end (),
81
+ [](auto *InitExpr) { return !isa<DesignatedInitExpr>(InitExpr); });
82
+ }
83
+
85
84
void UseDesignatedInitializersCheck::check (
86
85
const MatchFinder::MatchResult &Result) {
87
86
const auto *InitList = Result.Nodes .getNodeAs <InitListExpr>(" init" );
88
87
const auto *Type = Result.Nodes .getNodeAs <CXXRecordDecl>(" type" );
89
88
if (!Type || !InitList)
90
89
return ;
91
90
if (const auto *SyntacticInitList = InitList->getSyntacticForm ()) {
92
- const auto UndesignatedComponents =
93
- getUndesignatedComponents (SyntacticInitList);
94
- if (UndesignatedComponents.size () == SyntacticInitList->getNumInits ()) {
95
- diag (InitList->getLBraceLoc (), " use designated initializer list" );
96
- return ;
97
- }
98
- const auto FieldIterator = Type->fields ().begin ();
99
- for (const auto *InitExpr : *SyntacticInitList) {
100
- const auto Field = std::next (FieldIterator);
101
- if (std::find (UndesignatedComponents.begin (),
102
- UndesignatedComponents.end (),
103
- InitExpr) == UndesignatedComponents.end ())
104
- continue ;
105
- if (const auto *FieldID = Field->getIdentifier ()) {
106
- const auto FieldName = FieldID->getName ();
107
- diag (InitExpr->getBeginLoc (), " use designated init expression" )
108
- << FixItHint::CreateInsertion (InitExpr->getBeginLoc (),
109
- " ." + FieldName.str () + " =" );
91
+ const llvm::DenseMap<clang::SourceLocation, std::string> Designators =
92
+ clang::tooling::getDesignators (SyntacticInitList);
93
+ if (isFullyUndesignated (SyntacticInitList)) {
94
+ std::string NewList = " {" ;
95
+ for (const Stmt *InitExpr : *SyntacticInitList) {
96
+ if (InitExpr != *SyntacticInitList->begin ())
97
+ NewList += " , " ;
98
+ NewList += Designators.at (InitExpr->getBeginLoc ());
99
+ NewList += " =" ;
100
+ NewList += Lexer::getSourceText (
101
+ CharSourceRange::getTokenRange (InitExpr->getSourceRange ()),
102
+ *Result.SourceManager , getLangOpts ());
103
+ }
104
+ NewList += " }" ;
105
+ diag (InitList->getLBraceLoc (), " use designated initializer list" )
106
+ << FixItHint::CreateReplacement (InitList->getSourceRange (), NewList);
107
+ } else {
108
+ for (const auto *InitExpr : *SyntacticInitList) {
109
+ if (!isa<DesignatedInitExpr>(InitExpr)) {
110
+ diag (InitExpr->getBeginLoc (), " use designated init expression" )
111
+ << FixItHint::CreateInsertion (
112
+ InitExpr->getBeginLoc (),
113
+ Designators.at (InitExpr->getBeginLoc ()) + " =" );
114
+ }
110
115
}
111
116
}
112
117
}
0 commit comments