Skip to content

Commit b2cb7e8

Browse files
Joachim PriesnerLegalizeAdulthood
authored andcommitted
[clang-tidy] cppcoreguidelines-virtual-class-destructor: Fix crash when "virtual" keyword is expanded from a macro
Check llvm::Optional before dereferencing it. Compute VirtualEndLoc differently to avoid an assertion failure in clang::SourceManager::getFileIDLoaded: Assertion `0 && "Invalid SLocOffset or bad function choice"' failed
1 parent b0d6dd3 commit b2cb7e8

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

clang-tools-extra/clang-tidy/cppcoreguidelines/VirtualClassDestructorCheck.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,17 @@ getVirtualKeywordRange(const CXXDestructorDecl &Destructor,
5454
return None;
5555

5656
SourceLocation VirtualBeginLoc = Destructor.getBeginLoc();
57-
SourceLocation VirtualEndLoc = VirtualBeginLoc.getLocWithOffset(
58-
Lexer::MeasureTokenLength(VirtualBeginLoc, SM, LangOpts));
57+
SourceLocation VirtualBeginSpellingLoc =
58+
SM.getSpellingLoc(Destructor.getBeginLoc());
59+
SourceLocation VirtualEndLoc = VirtualBeginSpellingLoc.getLocWithOffset(
60+
Lexer::MeasureTokenLength(VirtualBeginSpellingLoc, SM, LangOpts));
5961

6062
/// Range ends with \c StartOfNextToken so that any whitespace after \c
6163
/// virtual is included.
62-
SourceLocation StartOfNextToken =
63-
Lexer::findNextToken(VirtualEndLoc, SM, LangOpts)->getLocation();
64+
Optional<Token> NextToken = Lexer::findNextToken(VirtualEndLoc, SM, LangOpts);
65+
if (!NextToken)
66+
return None;
67+
SourceLocation StartOfNextToken = NextToken->getLocation();
6468

6569
return CharSourceRange::getCharRange(VirtualBeginLoc, StartOfNextToken);
6670
}

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/virtual-class-destructor.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ DerivedFromTemplateNonVirtualBaseStruct2Typedef InstantiationWithPublicNonVirtua
272272
} // namespace Bugzilla_51912
273273

274274
namespace macro_tests {
275+
#define MY_VIRTUAL virtual
275276
#define CONCAT(x, y) x##y
276277

277278
// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar1' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
@@ -317,8 +318,17 @@ class FooBar5 {
317318
protected:
318319
XMACRO(CONCAT(vir, tual), ~CONCAT(Foo, Bar5());) // no-crash, no-fixit
319320
};
321+
322+
// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar6' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
323+
// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
324+
class FooBar6 {
325+
protected:
326+
MY_VIRTUAL ~FooBar6(); // FIXME: We should have a fixit for this.
327+
};
328+
320329
#undef XMACRO
321330
#undef CONCAT
331+
#undef MY_VIRTUAL
322332
} // namespace macro_tests
323333

324334
namespace FinalClassCannotBeBaseClass {

0 commit comments

Comments
 (0)