Skip to content

Commit b1c73a1

Browse files
committed
Support more qualifiers, such as volatile
1 parent ea7b933 commit b1c73a1

File tree

2 files changed

+162
-23
lines changed

2 files changed

+162
-23
lines changed

clang/lib/AST/CommentParser.cpp

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,48 @@ class TextTokenRetokenizer {
131131
return false;
132132
}
133133

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;
166+
}
167+
168+
bool isScopeResolutionOperator(SmallString<32> &WordText) {
169+
return WordText.ends_with(StringRef("::"));
170+
}
171+
172+
bool continueParsing(SmallString<32> &WordText) {
173+
return isDataTypeQualifier(WordText) || isScopeResolutionOperator(WordText);
174+
}
175+
134176
/// Add a token.
135177
/// Returns true on success, false if there are no interesting tokens to
136178
/// fetch from lexer.
@@ -192,7 +234,7 @@ class TextTokenRetokenizer {
192234
}
193235

194236
/// Extract a type argument
195-
bool lexDataType(Token &Tok) {
237+
bool lexType(Token &Tok) {
196238
if (isEnd())
197239
return false;
198240
Position SavedPos = Pos;
@@ -202,6 +244,8 @@ class TextTokenRetokenizer {
202244
const char *WordBegin = Pos.BufferPtr;
203245
SourceLocation Loc = getSourceLocation();
204246
StringRef ConstVal = StringRef("const");
247+
StringRef PointerVal = StringRef("*");
248+
StringRef ReferenceVal = StringRef("&");
205249
bool ConstPointer = false;
206250

207251
while (!isEnd()) {
@@ -215,32 +259,41 @@ class TextTokenRetokenizer {
215259
consumeChar();
216260
}
217261
} else {
218-
if (WordText.equals(ConstVal)) {
219-
WordText.push_back(C);
262+
if (ConstPointer) {
220263
consumeChar();
221-
} else if (WordText.ends_with(StringRef("*")) ||
222-
WordText.ends_with(StringRef("&"))) {
223-
NextToken.clear();
224-
peekNextToken(NextToken);
225-
if (NextToken.equals(ConstVal)) {
226-
ConstPointer = true;
227-
WordText.push_back(C);
228-
consumeChar();
229-
} else {
230-
consumeChar();
231-
break;
232-
}
264+
break;
233265
} else {
234-
NextToken.clear();
235-
peekNextToken(NextToken);
236-
if ((NextToken.ends_with(StringRef("*")) ||
237-
NextToken.ends_with(StringRef("&"))) &&
238-
!ConstPointer) {
266+
if (continueParsing(WordText)) {
239267
WordText.push_back(C);
240268
consumeChar();
241269
} else {
242-
consumeChar();
243-
break;
270+
NextToken.clear();
271+
peekNextToken(NextToken);
272+
if (WordText.ends_with(PointerVal) ||
273+
WordText.ends_with(ReferenceVal)) {
274+
if (NextToken.equals(ConstVal)) {
275+
ConstPointer = true;
276+
WordText.push_back(C);
277+
consumeChar();
278+
} else {
279+
consumeChar();
280+
break;
281+
}
282+
} else {
283+
if ((NextToken.ends_with(PointerVal) ||
284+
NextToken.ends_with(ReferenceVal))) {
285+
WordText.push_back(C);
286+
consumeChar();
287+
} else {
288+
if (continueParsing(NextToken)) {
289+
WordText.push_back(C);
290+
consumeChar();
291+
} else {
292+
consumeChar();
293+
break;
294+
}
295+
}
296+
}
244297
}
245298
}
246299
}
@@ -425,7 +478,7 @@ Parser::parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer,
425478
unsigned ParsedArgs = 0;
426479
Token Arg;
427480

428-
while (ParsedArgs < NumArgs && Retokenizer.lexDataType(Arg)) {
481+
while (ParsedArgs < NumArgs && Retokenizer.lexType(Arg)) {
429482
Args[ParsedArgs] = Comment::Argument{
430483
SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()};
431484
ParsedArgs++;

clang/unittests/AST/CommentParser.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,6 +1661,92 @@ TEST_F(CommentParserTest, ThrowsCommandHasArg9) {
16611661
}
16621662
}
16631663

1664+
TEST_F(CommentParserTest, ThrowsCommandHasArg10) {
1665+
const char *Sources[] = {
1666+
"/// @throws const std::map<int, std::string> * pointer to a const map",
1667+
};
1668+
1669+
for (size_t i = 0, e = std::size(Sources); i != e; i++) {
1670+
FullComment *FC = parseString(Sources[i]);
1671+
ASSERT_TRUE(HasChildCount(FC, 2));
1672+
1673+
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1674+
{
1675+
BlockCommandComment *BCC;
1676+
ParagraphComment *PC;
1677+
ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "throws", PC));
1678+
ASSERT_TRUE(HasChildCount(PC, 1));
1679+
ASSERT_TRUE(BCC->getNumArgs() == 1);
1680+
ASSERT_TRUE(BCC->getArgText(0) == "const std::map<int, std::string> *");
1681+
}
1682+
}
1683+
}
1684+
1685+
TEST_F(CommentParserTest, ThrowsCommandHasArg11) {
1686+
const char *Sources[] = {
1687+
"/// @throws const std :: map<int, std :: string> * pointer to a "
1688+
"const map with spaces",
1689+
};
1690+
1691+
for (size_t i = 0, e = std::size(Sources); i != e; i++) {
1692+
FullComment *FC = parseString(Sources[i]);
1693+
ASSERT_TRUE(HasChildCount(FC, 2));
1694+
1695+
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1696+
{
1697+
BlockCommandComment *BCC;
1698+
ParagraphComment *PC;
1699+
ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "throws", PC));
1700+
ASSERT_TRUE(HasChildCount(PC, 1));
1701+
ASSERT_TRUE(BCC->getNumArgs() == 1);
1702+
ASSERT_TRUE(BCC->getArgText(0) ==
1703+
"const std :: map<int, std :: string> *");
1704+
}
1705+
}
1706+
}
1707+
1708+
TEST_F(CommentParserTest, ThrowsCommandHasArg12) {
1709+
const char *Sources[] = {
1710+
"/// @throws volatile int a volatile integer",
1711+
};
1712+
1713+
for (size_t i = 0, e = std::size(Sources); i != e; i++) {
1714+
FullComment *FC = parseString(Sources[i]);
1715+
ASSERT_TRUE(HasChildCount(FC, 2));
1716+
1717+
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1718+
{
1719+
BlockCommandComment *BCC;
1720+
ParagraphComment *PC;
1721+
ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "throws", PC));
1722+
ASSERT_TRUE(HasChildCount(PC, 1));
1723+
ASSERT_TRUE(BCC->getNumArgs() == 1);
1724+
ASSERT_TRUE(BCC->getArgText(0) == "volatile int");
1725+
}
1726+
}
1727+
}
1728+
1729+
TEST_F(CommentParserTest, ThrowsCommandHasArg13) {
1730+
const char *Sources[] = {
1731+
"/// @throws volatile double * volatile pointer to a double",
1732+
};
1733+
1734+
for (size_t i = 0, e = std::size(Sources); i != e; i++) {
1735+
FullComment *FC = parseString(Sources[i]);
1736+
ASSERT_TRUE(HasChildCount(FC, 2));
1737+
1738+
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1739+
{
1740+
BlockCommandComment *BCC;
1741+
ParagraphComment *PC;
1742+
ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "throws", PC));
1743+
ASSERT_TRUE(HasChildCount(PC, 1));
1744+
ASSERT_TRUE(BCC->getNumArgs() == 1);
1745+
ASSERT_TRUE(BCC->getArgText(0) == "volatile double *");
1746+
}
1747+
}
1748+
}
1749+
16641750
} // unnamed namespace
16651751

16661752
} // end namespace comments

0 commit comments

Comments
 (0)