@@ -34,27 +34,6 @@ static bool isNoReturnCallStatement(const Stmt *S) {
3434 return Func->isNoReturn ();
3535}
3636
37- static bool isLiteral (const Expr *E) {
38- return isa<StringLiteral, CharacterLiteral, IntegerLiteral, FloatingLiteral,
39- CXXBoolLiteralExpr, CXXNullPtrLiteralExpr>(E);
40- }
41-
42- static bool isUnaryExprOfLiteral (const Expr *E) {
43- if (const auto *UnOp = dyn_cast<UnaryOperator>(E))
44- return isLiteral (UnOp->getSubExpr ());
45- return false ;
46- }
47-
48- static bool shouldBeDefaultMemberInitializer (const Expr *Value) {
49- if (isLiteral (Value) || isUnaryExprOfLiteral (Value))
50- return true ;
51-
52- if (const auto *DRE = dyn_cast<DeclRefExpr>(Value))
53- return isa<EnumConstantDecl>(DRE->getDecl ());
54-
55- return false ;
56- }
57-
5837namespace {
5938
6039AST_MATCHER_P (FieldDecl, indexNotLessThan, unsigned , Index) {
@@ -166,19 +145,7 @@ isAssignmentToMemberOf(const CXXRecordDecl *Rec, const Stmt *S,
166145
167146PreferMemberInitializerCheck::PreferMemberInitializerCheck (
168147 StringRef Name, ClangTidyContext *Context)
169- : ClangTidyCheck(Name, Context),
170- IsUseDefaultMemberInitEnabled (
171- Context->isCheckEnabled (" modernize-use-default-member-init" )),
172- UseAssignment(
173- Options.get(" UseAssignment" ,
174- OptionsView (" modernize-use-default-member-init" ,
175- Context->getOptions ().CheckOptions, Context)
176- .get(" UseAssignment" , false ))) {}
177-
178- void PreferMemberInitializerCheck::storeOptions (
179- ClangTidyOptions::OptionMap &Opts) {
180- Options.store (Opts, " UseAssignment" , UseAssignment);
181- }
148+ : ClangTidyCheck(Name, Context) {}
182149
183150void PreferMemberInitializerCheck::registerMatchers (MatchFinder *Finder) {
184151 Finder->addMatcher (cxxConstructorDecl (hasBody (compoundStmt ()),
@@ -230,139 +197,99 @@ void PreferMemberInitializerCheck::check(
230197 updateAssignmentLevel (Field, InitValue, Ctor, AssignedFields);
231198 if (!canAdvanceAssignment (AssignedFields[Field]))
232199 continue ;
233- const bool IsInDefaultMemberInitializer =
234- IsUseDefaultMemberInitEnabled && getLangOpts ().CPlusPlus11 &&
235- Ctor->isDefaultConstructor () &&
236- (getLangOpts ().CPlusPlus20 || !Field->isBitField ()) &&
237- !Field->hasInClassInitializer () &&
238- (!isa<RecordDecl>(Class->getDeclContext ()) ||
239- !cast<RecordDecl>(Class->getDeclContext ())->isUnion ()) &&
240- shouldBeDefaultMemberInitializer (InitValue);
241- if (IsInDefaultMemberInitializer) {
242- bool InvalidFix = false ;
243- SourceLocation FieldEnd =
244- Lexer::getLocForEndOfToken (Field->getSourceRange ().getEnd (), 0 ,
245- *Result.SourceManager , getLangOpts ());
246- InvalidFix |= FieldEnd.isInvalid () || FieldEnd.isMacroID ();
247- SourceLocation SemiColonEnd;
248- if (auto NextToken = Lexer::findNextToken (
249- S->getEndLoc (), *Result.SourceManager , getLangOpts ()))
250- SemiColonEnd = NextToken->getEndLoc ();
251- else
252- InvalidFix = true ;
253- auto Diag =
254- diag (S->getBeginLoc (), " %0 should be initialized in an in-class"
255- " default member initializer" )
256- << Field;
257- if (InvalidFix)
258- continue ;
259- CharSourceRange StmtRange =
260- CharSourceRange::getCharRange (S->getBeginLoc (), SemiColonEnd);
261200
262- SmallString<128 > Insertion (
263- {UseAssignment ? " = " : " {" ,
264- Lexer::getSourceText (Result.SourceManager ->getExpansionRange (
265- InitValue->getSourceRange ()),
266- *Result.SourceManager , getLangOpts ()),
267- UseAssignment ? " " : " }" });
268-
269- Diag << FixItHint::CreateInsertion (FieldEnd, Insertion)
270- << FixItHint::CreateRemoval (StmtRange);
271-
272- } else {
273- StringRef InsertPrefix = " " ;
274- bool HasInitAlready = false ;
275- SourceLocation InsertPos;
276- SourceRange ReplaceRange;
277- bool AddComma = false ;
278- bool InvalidFix = false ;
279- unsigned Index = Field->getFieldIndex ();
280- const CXXCtorInitializer *LastInListInit = nullptr ;
281- for (const CXXCtorInitializer *Init : Ctor->inits ()) {
282- if (!Init->isWritten () || Init->isInClassMemberInitializer ())
283- continue ;
284- if (Init->getMember () == Field) {
285- HasInitAlready = true ;
286- if (isa<ImplicitValueInitExpr>(Init->getInit ()))
287- InsertPos = Init->getRParenLoc ();
288- else {
289- ReplaceRange = Init->getInit ()->getSourceRange ();
290- }
291- break ;
292- }
293- if (Init->isMemberInitializer () &&
294- Index < Init->getMember ()->getFieldIndex ()) {
295- InsertPos = Init->getSourceLocation ();
296- // There are initializers after the one we are inserting, so add a
297- // comma after this insertion in order to not break anything.
298- AddComma = true ;
299- break ;
201+ StringRef InsertPrefix = " " ;
202+ bool HasInitAlready = false ;
203+ SourceLocation InsertPos;
204+ SourceRange ReplaceRange;
205+ bool AddComma = false ;
206+ bool InvalidFix = false ;
207+ unsigned Index = Field->getFieldIndex ();
208+ const CXXCtorInitializer *LastInListInit = nullptr ;
209+ for (const CXXCtorInitializer *Init : Ctor->inits ()) {
210+ if (!Init->isWritten () || Init->isInClassMemberInitializer ())
211+ continue ;
212+ if (Init->getMember () == Field) {
213+ HasInitAlready = true ;
214+ if (isa<ImplicitValueInitExpr>(Init->getInit ()))
215+ InsertPos = Init->getRParenLoc ();
216+ else {
217+ ReplaceRange = Init->getInit ()->getSourceRange ();
300218 }
301- LastInListInit = Init ;
219+ break ;
302220 }
303- if (HasInitAlready) {
304- if (InsertPos.isValid ())
305- InvalidFix |= InsertPos.isMacroID ();
306- else
307- InvalidFix |= ReplaceRange.getBegin ().isMacroID () ||
308- ReplaceRange.getEnd ().isMacroID ();
309- } else {
310- if (InsertPos.isInvalid ()) {
311- if (LastInListInit) {
312- InsertPos = Lexer::getLocForEndOfToken (
313- LastInListInit->getRParenLoc (), 0 , *Result.SourceManager ,
314- getLangOpts ());
315- // Inserting after the last constructor initializer, so we need a
316- // comma.
317- InsertPrefix = " , " ;
318- } else {
319- InsertPos = Lexer::getLocForEndOfToken (
320- Ctor->getTypeSourceInfo ()
321- ->getTypeLoc ()
322- .getAs <clang::FunctionTypeLoc>()
323- .getLocalRangeEnd (),
324- 0 , *Result.SourceManager , getLangOpts ());
325-
326- // If this is first time in the loop, there are no initializers so
327- // `:` declares member initialization list. If this is a
328- // subsequent pass then we have already inserted a `:` so continue
329- // with a comma.
330- InsertPrefix = FirstToCtorInits ? " : " : " , " ;
331- }
332- }
221+ if (Init->isMemberInitializer () &&
222+ Index < Init->getMember ()->getFieldIndex ()) {
223+ InsertPos = Init->getSourceLocation ();
224+ // There are initializers after the one we are inserting, so add a
225+ // comma after this insertion in order to not break anything.
226+ AddComma = true ;
227+ break ;
228+ }
229+ LastInListInit = Init;
230+ }
231+ if (HasInitAlready) {
232+ if (InsertPos.isValid ())
333233 InvalidFix |= InsertPos.isMacroID ();
234+ else
235+ InvalidFix |= ReplaceRange.getBegin ().isMacroID () ||
236+ ReplaceRange.getEnd ().isMacroID ();
237+ } else {
238+ if (InsertPos.isInvalid ()) {
239+ if (LastInListInit) {
240+ InsertPos =
241+ Lexer::getLocForEndOfToken (LastInListInit->getRParenLoc (), 0 ,
242+ *Result.SourceManager , getLangOpts ());
243+ // Inserting after the last constructor initializer, so we need a
244+ // comma.
245+ InsertPrefix = " , " ;
246+ } else {
247+ InsertPos = Lexer::getLocForEndOfToken (
248+ Ctor->getTypeSourceInfo ()
249+ ->getTypeLoc ()
250+ .getAs <clang::FunctionTypeLoc>()
251+ .getLocalRangeEnd (),
252+ 0 , *Result.SourceManager , getLangOpts ());
253+
254+ // If this is first time in the loop, there are no initializers so
255+ // `:` declares member initialization list. If this is a
256+ // subsequent pass then we have already inserted a `:` so continue
257+ // with a comma.
258+ InsertPrefix = FirstToCtorInits ? " : " : " , " ;
259+ }
334260 }
261+ InvalidFix |= InsertPos.isMacroID ();
262+ }
335263
336- SourceLocation SemiColonEnd;
337- if (auto NextToken = Lexer::findNextToken (
338- S->getEndLoc (), *Result.SourceManager , getLangOpts ()))
339- SemiColonEnd = NextToken->getEndLoc ();
264+ SourceLocation SemiColonEnd;
265+ if (auto NextToken = Lexer::findNextToken (
266+ S->getEndLoc (), *Result.SourceManager , getLangOpts ()))
267+ SemiColonEnd = NextToken->getEndLoc ();
268+ else
269+ InvalidFix = true ;
270+
271+ auto Diag = diag (S->getBeginLoc (), " %0 should be initialized in a member"
272+ " initializer of the constructor" )
273+ << Field;
274+ if (InvalidFix)
275+ continue ;
276+ StringRef NewInit = Lexer::getSourceText (
277+ Result.SourceManager ->getExpansionRange (InitValue->getSourceRange ()),
278+ *Result.SourceManager , getLangOpts ());
279+ if (HasInitAlready) {
280+ if (InsertPos.isValid ())
281+ Diag << FixItHint::CreateInsertion (InsertPos, NewInit);
340282 else
341- InvalidFix = true ;
342-
343- auto Diag = diag (S->getBeginLoc (), " %0 should be initialized in a member"
344- " initializer of the constructor" )
345- << Field;
346- if (InvalidFix)
347- continue ;
348- StringRef NewInit = Lexer::getSourceText (
349- Result.SourceManager ->getExpansionRange (InitValue->getSourceRange ()),
350- *Result.SourceManager , getLangOpts ());
351- if (HasInitAlready) {
352- if (InsertPos.isValid ())
353- Diag << FixItHint::CreateInsertion (InsertPos, NewInit);
354- else
355- Diag << FixItHint::CreateReplacement (ReplaceRange, NewInit);
356- } else {
357- SmallString<128 > Insertion ({InsertPrefix, Field->getName (), " (" ,
358- NewInit, AddComma ? " ), " : " )" });
359- Diag << FixItHint::CreateInsertion (InsertPos, Insertion,
360- FirstToCtorInits);
361- FirstToCtorInits = areDiagsSelfContained ();
362- }
363- Diag << FixItHint::CreateRemoval (
364- CharSourceRange::getCharRange (S->getBeginLoc (), SemiColonEnd));
283+ Diag << FixItHint::CreateReplacement (ReplaceRange, NewInit);
284+ } else {
285+ SmallString<128 > Insertion ({InsertPrefix, Field->getName (), " (" , NewInit,
286+ AddComma ? " ), " : " )" });
287+ Diag << FixItHint::CreateInsertion (InsertPos, Insertion,
288+ FirstToCtorInits);
289+ FirstToCtorInits = areDiagsSelfContained ();
365290 }
291+ Diag << FixItHint::CreateRemoval (
292+ CharSourceRange::getCharRange (S->getBeginLoc (), SemiColonEnd));
366293 }
367294}
368295
0 commit comments