Skip to content

Commit 60c4873

Browse files
committed
[clang-tidy] Fix misplaced fix-its in modernize-use-override
1 parent 1ae9575 commit 60c4873

File tree

4 files changed

+34
-74
lines changed

4 files changed

+34
-74
lines changed

clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp

Lines changed: 9 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -141,90 +141,28 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
141141
if (!FileRange.isValid())
142142
return;
143143

144-
// FIXME: Instead of re-lexing and looking for specific macros such as
145-
// 'ABSTRACT', properly store the location of 'virtual' and '= 0' in each
146-
// FunctionDecl.
144+
// FIXME: Instead of re-lexing and looking for the 'virtual' token,
145+
// store the location of 'virtual' in each FunctionDecl.
147146
SmallVector<Token, 16> Tokens = parseTokens(FileRange, Result);
148147

149148
// Add 'override' on inline declarations that don't already have it.
150149
if (!HasFinal && !HasOverride) {
151-
SourceLocation InsertLoc;
152-
std::string ReplacementText = (OverrideSpelling + " ").str();
153-
const SourceLocation MethodLoc = Method->getLocation();
154-
155-
for (const Token T : Tokens) {
156-
if (T.is(tok::kw___attribute) &&
157-
!Sources.isBeforeInTranslationUnit(T.getLocation(), MethodLoc)) {
158-
InsertLoc = T.getLocation();
159-
break;
160-
}
161-
}
162-
163-
if (Method->hasAttrs()) {
164-
for (const clang::Attr *A : Method->getAttrs()) {
165-
if (!A->isImplicit() && !A->isInherited()) {
166-
const SourceLocation Loc =
167-
Sources.getExpansionLoc(A->getRange().getBegin());
168-
if ((!InsertLoc.isValid() ||
169-
Sources.isBeforeInTranslationUnit(Loc, InsertLoc)) &&
170-
!Sources.isBeforeInTranslationUnit(Loc, MethodLoc))
171-
InsertLoc = Loc;
172-
}
173-
}
174-
}
175-
176-
if (InsertLoc.isInvalid() && Method->doesThisDeclarationHaveABody() &&
177-
Method->getBody() && !Method->isDefaulted()) {
178-
// For methods with inline definition, add the override keyword at the
179-
// end of the declaration of the function, but prefer to put it on the
180-
// same line as the declaration if the beginning brace for the start of
181-
// the body falls on the next line.
182-
ReplacementText = (" " + OverrideSpelling).str();
183-
auto *LastTokenIter = std::prev(Tokens.end());
184-
// When try statement is used instead of compound statement as
185-
// method body - insert override keyword before it.
186-
if (LastTokenIter->is(tok::kw_try))
187-
LastTokenIter = std::prev(LastTokenIter);
188-
InsertLoc = LastTokenIter->getEndLoc();
189-
}
190-
191-
if (!InsertLoc.isValid()) {
192-
// For declarations marked with "= 0" or "= [default|delete]", the end
193-
// location will point until after those markings. Therefore, the override
194-
// keyword shouldn't be inserted at the end, but before the '='.
195-
if (Tokens.size() > 2 &&
196-
(getText(Tokens.back(), Sources) == "0" ||
197-
Tokens.back().is(tok::kw_default) ||
198-
Tokens.back().is(tok::kw_delete)) &&
199-
getText(Tokens[Tokens.size() - 2], Sources) == "=") {
200-
InsertLoc = Tokens[Tokens.size() - 2].getLocation();
201-
// Check if we need to insert a space.
202-
if ((Tokens[Tokens.size() - 2].getFlags() & Token::LeadingSpace) == 0)
203-
ReplacementText = (" " + OverrideSpelling + " ").str();
204-
} else if (getText(Tokens.back(), Sources) == "ABSTRACT")
205-
InsertLoc = Tokens.back().getLocation();
206-
}
207-
208-
if (!InsertLoc.isValid()) {
209-
InsertLoc = FileRange.getEnd();
210-
ReplacementText = (" " + OverrideSpelling).str();
211-
}
212-
213150
// If the override macro has been specified just ensure it exists,
214151
// if not don't apply a fixit but keep the warning.
215152
if (OverrideSpelling != "override" &&
216153
!Context.Idents.get(OverrideSpelling).hasMacroDefinition())
217154
return;
218155

219-
Diag << FixItHint::CreateInsertion(InsertLoc, ReplacementText);
156+
Diag << FixItHint::CreateInsertion(
157+
Lexer::getLocForEndOfToken(
158+
Method->getTypeSourceInfo()->getTypeLoc().getEndLoc(), 0, Sources,
159+
getLangOpts()),
160+
(" " + OverrideSpelling).str());
220161
}
221162

222-
if (HasFinal && HasOverride && !AllowOverrideAndFinal) {
223-
const SourceLocation OverrideLoc =
224-
Method->getAttr<OverrideAttr>()->getLocation();
163+
if (HasFinal && HasOverride && !AllowOverrideAndFinal)
225164
Diag << FixItHint::CreateRemoval(
226-
CharSourceRange::getTokenRange(OverrideLoc, OverrideLoc));
227-
}
165+
Method->getAttr<OverrideAttr>()->getLocation());
228166

229167
if (HasVirtual) {
230168
for (const Token Tok : Tokens) {

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,11 @@ Changes in existing checks
508508
on Windows when the check was enabled with a 32-bit :program:`clang-tidy`
509509
binary.
510510

511+
- Improved :doc:`modernize-use-override
512+
<clang-tidy/checks/modernize/use-override>` by fixing an issue where
513+
the check would sometimes suggest inserting ``override`` in an invalid
514+
place.
515+
511516
- Improved :doc:`modernize-use-scoped-lock
512517
<clang-tidy/checks/modernize/use-scoped-lock>` check by fixing a crash
513518
on malformed code (common when using :program:`clang-tidy` through
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %check_clang_tidy -std=c++26-or-later %s modernize-use-override,cppcoreguidelines-explicit-virtual-functions %t
2+
3+
struct Base {
4+
virtual void f() = delete("");
5+
};
6+
7+
struct Derived : Base {
8+
virtual void f() = delete("");
9+
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual'
10+
// CHECK-FIXES: void f() override = delete("");
11+
};

clang-tools-extra/test/clang-tidy/checkers/modernize/use-override.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ struct Base {
4848
virtual void t() throw();
4949

5050
virtual void il(IntPair);
51+
52+
virtual void u(int x __attribute__((unused))) {}
5153
};
5254

5355
struct SimpleCases : public Base {
@@ -82,11 +84,11 @@ struct SimpleCases : public Base {
8284

8385
virtual void f()=0;
8486
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
85-
// CHECK-FIXES: void f() override =0;
87+
// CHECK-FIXES: void f() override=0;
8688

8789
virtual void f2() const=0;
8890
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
89-
// CHECK-FIXES: void f2() const override =0;
91+
// CHECK-FIXES: void f2() const override=0;
9092

9193
virtual void g() ABSTRACT;
9294
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
@@ -132,6 +134,10 @@ struct SimpleCases : public Base {
132134
virtual /* */ void g2();
133135
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual'
134136
// CHECK-FIXES: /* */ void g2() override;
137+
138+
virtual void u(int x __attribute__((unused)));
139+
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual'
140+
// CHECK-FIXES: void u(int x __attribute__((unused))) override;
135141
};
136142

137143
// CHECK-MESSAGES-NOT: warning:
@@ -308,7 +314,7 @@ struct MembersOfSpecializations : public Base2 {
308314
// CHECK-FIXES: void a() override;
309315
};
310316
template <> void MembersOfSpecializations<3>::a() {}
311-
void ff() { MembersOfSpecializations<3>().a(); };
317+
void ff() { MembersOfSpecializations<3>().a(); }
312318

313319
// In case try statement is used as a method body,
314320
// make sure that override fix is placed before try keyword.

0 commit comments

Comments
 (0)