Skip to content

Commit 4432d32

Browse files
committed
Refactor integer argument parsing and add corresponding test cases
1 parent b1c73a1 commit 4432d32

File tree

2 files changed

+130
-39
lines changed

2 files changed

+130
-39
lines changed

clang/lib/AST/CommentParser.cpp

Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -108,69 +108,112 @@ class TextTokenRetokenizer {
108108
}
109109
}
110110

111+
bool continueInt(SmallString<32> &NextToken) {
112+
return NextToken.ends_with(StringRef("char")) ||
113+
NextToken.ends_with(StringRef("int")) ||
114+
NextToken.ends_with(StringRef("char*")) ||
115+
NextToken.ends_with(StringRef("int*")) ||
116+
NextToken.ends_with(StringRef("char&")) ||
117+
NextToken.ends_with(StringRef("int&"));
118+
}
119+
120+
bool lexInt(SmallString<32> &WordText, SmallString<32> &NextToken) {
121+
unsigned LongCounter = (WordText.ends_with(StringRef("long"))) ? 1 : 0;
122+
bool complete = false;
123+
124+
while (!isEnd()) {
125+
const char C = peek();
126+
if (!isWhitespace(C)) {
127+
WordText.push_back(C);
128+
consumeChar();
129+
} else {
130+
131+
NextToken.clear();
132+
peekNextToken(NextToken);
133+
134+
if (WordText.ends_with(StringRef("long"))) {
135+
LongCounter++;
136+
if (continueInt(NextToken)) {
137+
WordText.push_back(C);
138+
consumeChar();
139+
complete = true;
140+
continue;
141+
} else {
142+
if (LongCounter == 2) {
143+
return true;
144+
}
145+
}
146+
} else {
147+
148+
if (complete || continueInt(WordText)) {
149+
return true;
150+
}
151+
}
152+
153+
if (NextToken.ends_with(StringRef("long"))) {
154+
WordText.push_back(C);
155+
consumeChar();
156+
} else {
157+
return true;
158+
}
159+
}
160+
}
161+
162+
return false;
163+
}
164+
111165
/// Extract a template type
112-
bool lexTemplateType(SmallString<32> &WordText) {
166+
bool lexTemplate(SmallString<32> &WordText) {
113167
unsigned IncrementCounter = 0;
114168
while (!isEnd()) {
115169
const char C = peek();
116170
WordText.push_back(C);
117171
consumeChar();
118172
switch (C) {
119-
default:
120-
break;
121173
case '<': {
122174
IncrementCounter++;
123-
} break;
175+
break;
176+
}
124177
case '>': {
125178
IncrementCounter--;
126179
if (!IncrementCounter)
127180
return true;
128-
} break;
181+
break;
182+
}
183+
default:
184+
break;
129185
}
130186
}
131187
return false;
132188
}
133189

134-
bool isDataTypeQualifier(SmallString<32> &WordText) {
135-
if (WordText.ends_with(StringRef("const")))
136-
return true;
137-
if (WordText.ends_with(StringRef("volatile")))
138-
return true;
139-
if (WordText.ends_with(StringRef("unsigned")))
140-
return true;
141-
if (WordText.ends_with(StringRef("signed")))
142-
return true;
143-
if (WordText.ends_with(StringRef("long")))
144-
return true;
145-
if (WordText.ends_with(StringRef("short")))
146-
return true;
147-
if (WordText.ends_with(StringRef("restrict")))
148-
return true;
149-
if (WordText.ends_with(StringRef("auto")))
150-
return true;
151-
if (WordText.ends_with(StringRef("register")))
152-
return true;
153-
if (WordText.ends_with(StringRef("static")))
154-
return true;
155-
if (WordText.ends_with(StringRef("extern")))
156-
return true;
157-
if (WordText.ends_with(StringRef("struct")))
158-
return true;
159-
if (WordText.ends_with(StringRef("typedef")))
160-
return true;
161-
if (WordText.ends_with(StringRef("union")))
162-
return true;
163-
if (WordText.ends_with(StringRef("void")))
164-
return true;
165-
return false;
190+
bool isTypeQualifier(SmallString<32> &WordText) {
191+
return WordText.ends_with(StringRef("const")) ||
192+
WordText.ends_with(StringRef("volatile")) ||
193+
WordText.ends_with(StringRef("short")) ||
194+
WordText.ends_with(StringRef("restrict")) ||
195+
WordText.ends_with(StringRef("auto")) ||
196+
WordText.ends_with(StringRef("register")) ||
197+
WordText.ends_with(StringRef("static")) ||
198+
WordText.ends_with(StringRef("extern")) ||
199+
WordText.ends_with(StringRef("struct")) ||
200+
WordText.ends_with(StringRef("typedef")) ||
201+
WordText.ends_with(StringRef("union")) ||
202+
WordText.ends_with(StringRef("void"));
166203
}
167204

168205
bool isScopeResolutionOperator(SmallString<32> &WordText) {
169206
return WordText.ends_with(StringRef("::"));
170207
}
171208

209+
bool isInt(SmallString<32> &WordText) {
210+
return WordText.ends_with(StringRef("unsigned")) ||
211+
WordText.ends_with(StringRef("long")) ||
212+
WordText.ends_with(StringRef("signed"));
213+
}
214+
172215
bool continueParsing(SmallString<32> &WordText) {
173-
return isDataTypeQualifier(WordText) || isScopeResolutionOperator(WordText);
216+
return isTypeQualifier(WordText) || isScopeResolutionOperator(WordText);
174217
}
175218

176219
/// Add a token.
@@ -252,7 +295,7 @@ class TextTokenRetokenizer {
252295
const char C = peek();
253296
if (!isWhitespace(C)) {
254297
if (C == '<') {
255-
if (!lexTemplateType(WordText))
298+
if (!lexTemplate(WordText))
256299
return false;
257300
} else {
258301
WordText.push_back(C);
@@ -263,6 +306,12 @@ class TextTokenRetokenizer {
263306
consumeChar();
264307
break;
265308
} else {
309+
if (isInt(WordText)) {
310+
WordText.push_back(C);
311+
consumeChar();
312+
if (!lexInt(WordText, NextToken))
313+
return false;
314+
}
266315
if (continueParsing(WordText)) {
267316
WordText.push_back(C);
268317
consumeChar();

clang/unittests/AST/CommentParser.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,48 @@ TEST_F(CommentParserTest, ThrowsCommandHasArg13) {
17471747
}
17481748
}
17491749

1750+
TEST_F(CommentParserTest, ThrowsCommandHasArg14) {
1751+
const char *Sources[] = {
1752+
"/// @throws unsigned long at least a 32-bit integer",
1753+
};
1754+
1755+
for (size_t i = 0, e = std::size(Sources); i != e; i++) {
1756+
FullComment *FC = parseString(Sources[i]);
1757+
ASSERT_TRUE(HasChildCount(FC, 2));
1758+
1759+
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1760+
{
1761+
BlockCommandComment *BCC;
1762+
ParagraphComment *PC;
1763+
ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "throws", PC));
1764+
ASSERT_TRUE(HasChildCount(PC, 1));
1765+
ASSERT_TRUE(BCC->getNumArgs() == 1);
1766+
ASSERT_TRUE(BCC->getArgText(0) == "unsigned long");
1767+
}
1768+
}
1769+
}
1770+
1771+
TEST_F(CommentParserTest, ThrowsCommandHasArg15) {
1772+
const char *Sources[] = {
1773+
"/// @throws unsigned long long at least a 64-bit integer",
1774+
};
1775+
1776+
for (size_t i = 0, e = std::size(Sources); i != e; i++) {
1777+
FullComment *FC = parseString(Sources[i]);
1778+
ASSERT_TRUE(HasChildCount(FC, 2));
1779+
1780+
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1781+
{
1782+
BlockCommandComment *BCC;
1783+
ParagraphComment *PC;
1784+
ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "throws", PC));
1785+
ASSERT_TRUE(HasChildCount(PC, 1));
1786+
ASSERT_TRUE(BCC->getNumArgs() == 1);
1787+
ASSERT_TRUE(BCC->getArgText(0) == "unsigned long long");
1788+
}
1789+
}
1790+
}
1791+
17501792
} // unnamed namespace
17511793

17521794
} // end namespace comments

0 commit comments

Comments
 (0)