[clang] 031d3ec - [clang-format] Fix a crash (assertion) in qualifier alignment when matching template closer is null
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 6 11:45:47 PST 2022
Author: mydeveloperday
Date: 2022-01-06T19:40:39Z
New Revision: 031d3ece3f2eb6bd785dcf7484e88cc6a306db94
URL: https://github.com/llvm/llvm-project/commit/031d3ece3f2eb6bd785dcf7484e88cc6a306db94
DIFF: https://github.com/llvm/llvm-project/commit/031d3ece3f2eb6bd785dcf7484e88cc6a306db94.diff
LOG: [clang-format] Fix a crash (assertion) in qualifier alignment when matching template closer is null
https://github.com/llvm/llvm-project/issues/53008
```
template <class Id> using A = quantity /**/<kind<Id>, 1>;
```
the presence of the comment between identifier and template opener seems to be causing the qualifier alignment to fail
Reviewed By: curdeius
Fixes: #53008
Differential Revision: https://reviews.llvm.org/D116726
Added:
Modified:
clang/lib/Format/QualifierAlignmentFixer.cpp
clang/lib/Format/QualifierAlignmentFixer.h
clang/unittests/Format/QualifierFixerTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp
index 5a89225c7fc86..ec19a38537683 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -204,9 +204,9 @@ static void rotateTokens(const SourceManager &SourceMgr,
replaceToken(SourceMgr, Fixes, Range, NewText);
}
-FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
+const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
- tooling::Replacements &Fixes, FormatToken *Tok,
+ tooling::Replacements &Fixes, const FormatToken *Tok,
const std::string &Qualifier, tok::TokenKind QualifierType) {
// We only need to think about streams that begin with a qualifier.
if (!Tok->is(QualifierType))
@@ -281,16 +281,16 @@ FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
return Tok;
}
-FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
+const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
- tooling::Replacements &Fixes, FormatToken *Tok,
+ tooling::Replacements &Fixes, const FormatToken *Tok,
const std::string &Qualifier, tok::TokenKind QualifierType) {
// if Tok is an identifier and possibly a macro then don't convert.
if (LeftRightQualifierAlignmentFixer::isPossibleMacro(Tok))
return Tok;
- FormatToken *Qual = Tok;
- FormatToken *LastQual = Qual;
+ const FormatToken *Qual = Tok;
+ const FormatToken *LastQual = Qual;
while (Qual && isQualifierOrType(Qual, ConfiguredQualifierTokens)) {
LastQual = Qual;
Qual = Qual->Next;
@@ -326,7 +326,7 @@ FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
Tok->Previous->isOneOf(tok::star, tok::ampamp, tok::amp)) {
return Tok;
}
- FormatToken *Next = Tok->Next;
+ const FormatToken *Next = Tok->Next;
// The case `std::Foo<T> const` -> `const std::Foo<T> &&`
while (Next && Next->isOneOf(tok::identifier, tok::coloncolon))
Next = Next->Next;
@@ -334,6 +334,8 @@ FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
Next->Previous->startsSequence(tok::identifier, TT_TemplateOpener)) {
// Read from to the end of the TemplateOpener to
// TemplateCloser const ArrayRef<int> a; const ArrayRef<int> &a;
+ if (Next->is(tok::comment) && Next->getNextNonComment())
+ Next = Next->getNextNonComment();
assert(Next->MatchingParen && "Missing template closer");
Next = Next->MatchingParen->Next;
@@ -398,7 +400,8 @@ LeftRightQualifierAlignmentFixer::analyze(
FormatToken *First = AnnotatedLines[I]->First;
const auto *Last = AnnotatedLines[I]->Last;
- for (auto *Tok = First; Tok && Tok != Last && Tok->Next; Tok = Tok->Next) {
+ for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;
+ Tok = Tok->Next) {
if (Tok->is(tok::comment))
continue;
if (RightAlign)
diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h
index 7abd25687564b..30ef96b8b0a7c 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.h
+++ b/clang/lib/Format/QualifierAlignmentFixer.h
@@ -72,17 +72,19 @@ class LeftRightQualifierAlignmentFixer : public TokenAnalyzer {
static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier);
- FormatToken *analyzeRight(const SourceManager &SourceMgr,
- const AdditionalKeywords &Keywords,
- tooling::Replacements &Fixes, FormatToken *Tok,
- const std::string &Qualifier,
- tok::TokenKind QualifierType);
-
- FormatToken *analyzeLeft(const SourceManager &SourceMgr,
- const AdditionalKeywords &Keywords,
- tooling::Replacements &Fixes, FormatToken *Tok,
- const std::string &Qualifier,
- tok::TokenKind QualifierType);
+ const FormatToken *analyzeRight(const SourceManager &SourceMgr,
+ const AdditionalKeywords &Keywords,
+ tooling::Replacements &Fixes,
+ const FormatToken *Tok,
+ const std::string &Qualifier,
+ tok::TokenKind QualifierType);
+
+ const FormatToken *analyzeLeft(const SourceManager &SourceMgr,
+ const AdditionalKeywords &Keywords,
+ tooling::Replacements &Fixes,
+ const FormatToken *Tok,
+ const std::string &Qualifier,
+ tok::TokenKind QualifierType);
// is the Token a simple or qualifier type
static bool isQualifierOrType(const FormatToken *Tok,
diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp
index e3d0a9a0e2607..0517de2820d9d 100755
--- a/clang/unittests/Format/QualifierFixerTest.cpp
+++ b/clang/unittests/Format/QualifierFixerTest.cpp
@@ -818,5 +818,45 @@ TEST_F(QualifierFixerTest, NoOpQualifierReplacements) {
EXPECT_EQ(ReplacementCount, 0);
}
+TEST_F(QualifierFixerTest, QualifierTemplates) {
+ FormatStyle Style = getLLVMStyle();
+ Style.QualifierAlignment = FormatStyle::QAS_Custom;
+ Style.QualifierOrder = {"static", "const", "type"};
+
+ ReplacementCount = 0;
+ EXPECT_EQ(ReplacementCount, 0);
+ verifyFormat("using A = B<>;", Style);
+ verifyFormat("using A = B /**/<>;", Style);
+ verifyFormat("template <class C> using A = B<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /**/<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /* */<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /*foo*/<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /**/ /**/<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B<Foo</**/ C>, 1>;", Style);
+ verifyFormat("template <class C> using A = /**/ B<Foo<C>, 1>;", Style);
+ EXPECT_EQ(ReplacementCount, 0);
+ verifyFormat("template <class C>\n"
+ "using A = B // foo\n"
+ " <Foo<C>, 1>;",
+ Style);
+
+ ReplacementCount = 0;
+ Style.QualifierOrder = {"type", "static", "const"};
+ verifyFormat("using A = B<>;", Style);
+ verifyFormat("using A = B /**/<>;", Style);
+ verifyFormat("template <class C> using A = B<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /**/<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /* */<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /*foo*/<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B /**/ /**/<Foo<C>, 1>;", Style);
+ verifyFormat("template <class C> using A = B<Foo</**/ C>, 1>;", Style);
+ verifyFormat("template <class C> using A = /**/ B<Foo<C>, 1>;", Style);
+ EXPECT_EQ(ReplacementCount, 0);
+ verifyFormat("template <class C>\n"
+ "using A = B // foo\n"
+ " <Foo<C>, 1>;",
+ Style);
+}
+
} // namespace format
} // namespace clang
More information about the cfe-commits
mailing list