Skip to content

Commit b018450

Browse files
committed
[clang-format] Recognize TableGen paste operator on separate line
Formatting this piece of code made the program crash. ``` class TypedVecListRegOperand<RegisterClass Reg, int lanes, string eltsize> : RegisterOperand<Reg, "printTypedVectorList<" # lanes # ", '" # eltsize # "'>">; ``` The line starting with the `#` was treated as a separate preprocessor directive line. Then the code dereferenced a null pointer when it tried to continue parsing the first line that did not end in a semicolon. Now the 2 problems are fixed.
1 parent 0794d5c commit b018450

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,8 @@ class AnnotatingParser {
949949
HashTok->setType(TT_Unknown);
950950
if (!parseTableGenValue(ParseNameMode))
951951
return false;
952+
if (!CurrentToken)
953+
return true;
952954
}
953955
// In name mode, '{' is regarded as the end of the value.
954956
// See TGParser::ParseValue in TGParser.cpp

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4853,9 +4853,16 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
48534853
PreviousWasComment = FormatTok->is(tok::comment);
48544854

48554855
while (!Line->InPPDirective && FormatTok->is(tok::hash) &&
4856-
(!Style.isVerilog() ||
4857-
Keywords.isVerilogPPDirective(*Tokens->peekNextToken())) &&
48584856
FirstNonCommentOnLine) {
4857+
// In Verilog, the backtick is used for macro invocations. In TableGen,
4858+
// the single hash is used for the paste operator.
4859+
const FormatToken *Next = Tokens->peekNextToken();
4860+
assert(Next); // There is an EOF token at the end.
4861+
if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*Next)) ||
4862+
(Style.isTableGen() &&
4863+
!Next->isOneOf(tok::pp_define, tok::pp_ifdef, tok::pp_ifndef))) {
4864+
break;
4865+
}
48594866
distributeComments(Comments, FormatTok);
48604867
Comments.clear();
48614868
// If there is an unfinished unwrapped line, we flush the preprocessor

clang/unittests/Format/FormatTestTableGen.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ TEST_F(FormatTestTableGen, PasteOperator) {
218218
" string Z = [\"Traring\", \"Paste\", \"Traring\", \"Paste\",\n"
219219
" \"Traring\", \"Paste\"]#;\n"
220220
"}");
221+
verifyFormat("def x#x {}", "def x\n"
222+
"#x {}");
223+
verifyFormat("def x#x {}", "def x\n"
224+
"#\n"
225+
"x {}");
226+
verifyFormat("def x#x");
221227
}
222228

223229
TEST_F(FormatTestTableGen, ClassDefinition) {

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,6 +2832,23 @@ TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) {
28322832
Tokens = Annotate("!cond");
28332833
EXPECT_TOKEN(Tokens[0], tok::identifier, TT_TableGenCondOperator);
28342834

2835+
// The paste operator should not be treated as a preprocessor directive even
2836+
// if it is on a separate line.
2837+
Tokens = Annotate("def x\n"
2838+
"#embed {}");
2839+
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
2840+
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_StartOfName);
2841+
EXPECT_TOKEN(Tokens[2], tok::hash, TT_Unknown);
2842+
EXPECT_EQ(Tokens[1]->Next, Tokens[2]);
2843+
Tokens = Annotate("def x\n"
2844+
"#define x\n"
2845+
"#embed {}");
2846+
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
2847+
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_StartOfName);
2848+
EXPECT_TOKEN(Tokens[2], tok::hash, TT_Unknown);
2849+
EXPECT_TOKEN(Tokens[5], tok::hash, TT_Unknown);
2850+
EXPECT_EQ(Tokens[1]->Next, Tokens[5]);
2851+
28352852
auto AnnotateValue = [this, &Style](StringRef Code) {
28362853
// Values are annotated only in specific context.
28372854
auto Result = annotate(("def X { let V = " + Code + "; }").str(), Style);

0 commit comments

Comments
 (0)