Skip to content

[Clang][Comments] Add argument parsing for @throw @throws @exception #84726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jun 10, 2024
6 changes: 3 additions & 3 deletions clang/include/clang/AST/CommentCommands.td
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
// HeaderDoc command for template parameter documentation.
def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }

def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; }
def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; }
def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; }
def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; let NumArgs = 1; }
def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; let NumArgs = 1; }
def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; let NumArgs = 1;}

def Deprecated : BlockCommand<"deprecated"> {
let IsEmptyParagraphAllowed = 1;
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/CommentParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class Parser {
ArrayRef<Comment::Argument>
parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);

/// Parse arguments for \throws command supported args are in form of class
/// or template.
ArrayRef<Comment::Argument>
parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);

BlockCommandComment *parseBlockCommand();
InlineCommandComment *parseInlineCommand();

Expand Down
93 changes: 93 additions & 0 deletions clang/lib/AST/CommentParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,31 @@ class TextTokenRetokenizer {
}
}

/// Extract a template type
bool lexTemplate(SmallString<32> &WordText) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work okay for simple (most) cases, but we should have tests showing the boundaries, e.g., Foo<(1 > 0)> or a typo like Foo<Bar<T> etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some more test cases that check this edge case behavior, like unequal numbers of opening and closing brackets as well as some other unusual edge cases.

unsigned BracketCount = 0;
while (!isEnd()) {
const char C = peek();
WordText.push_back(C);
consumeChar();
Comment on lines +96 to +98
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to modify consumeChar to return the consumed char

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to do that as a separate refactor PR, I think it's outside the scope of this change.

switch (C) {
case '<': {
BracketCount++;
break;
}
case '>': {
BracketCount--;
if (!BracketCount)
return true;
break;
}
default:
break;
}
}
return false;
}

/// Add a token.
/// Returns true on success, false if there are no interesting tokens to
/// fetch from lexer.
Expand Down Expand Up @@ -149,6 +174,54 @@ class TextTokenRetokenizer {
addToken();
}

/// Extract a type argument
bool lexType(Token &Tok) {
if (isEnd())
return false;

// Save current position in case we need to rollback because the type is
// empty.
Position SavedPos = Pos;

// Consume any leading whitespace.
consumeWhitespace();
SmallString<32> WordText;
const char *WordBegin = Pos.BufferPtr;
SourceLocation Loc = getSourceLocation();

while (!isEnd()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments wouldn't hurt...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as part of the latest commit, along with some light refactoring to make it more readable. No doubt it is a complex piece of code

const char C = peek();
// For non-whitespace characters we check if it's a template or otherwise
// continue reading the text into a word.
if (!isWhitespace(C)) {
if (C == '<') {
if (!lexTemplate(WordText))
return false;
} else {
WordText.push_back(C);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this treat any non-whitespace character (other than <) as being part of a name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the code stands now, yes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which I think is fine, we are just trying to find a boundary

consumeChar();
}
} else {
consumeChar();
break;
}
}

const unsigned Length = WordText.size();
if (Length == 0) {
Pos = SavedPos;
return false;
}

char *TextPtr = Allocator.Allocate<char>(Length + 1);

memcpy(TextPtr, WordText.c_str(), Length + 1);
StringRef Text = StringRef(TextPtr, Length);

formTokenWithChars(Tok, Loc, WordBegin, Length, Text);
Comment on lines +216 to +221
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see that extracted in a separate function (and replace the few places where we do the exact same thing)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, I would prefer to do that as a separate refactor PR, I think it's outside the scope of this change.

return true;
}

/// Extract a word -- sequence of non-whitespace characters.
bool lexWord(Token &Tok) {
if (isEnd())
Expand Down Expand Up @@ -304,6 +377,23 @@ Parser::parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs) {
return llvm::ArrayRef(Args, ParsedArgs);
}

ArrayRef<Comment::Argument>
Parser::parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer,
unsigned NumArgs) {
auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))
Comment::Argument[NumArgs];
unsigned ParsedArgs = 0;
Token Arg;

while (ParsedArgs < NumArgs && Retokenizer.lexType(Arg)) {
Args[ParsedArgs] = Comment::Argument{
SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()};
ParsedArgs++;
}

return llvm::ArrayRef(Args, ParsedArgs);
}

BlockCommandComment *Parser::parseBlockCommand() {
assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));

Expand Down Expand Up @@ -356,6 +446,9 @@ BlockCommandComment *Parser::parseBlockCommand() {
parseParamCommandArgs(PC, Retokenizer);
else if (TPC)
parseTParamCommandArgs(TPC, Retokenizer);
else if (Info->IsThrowsCommand)
S.actOnBlockCommandArgs(
BC, parseThrowCommandArgs(Retokenizer, Info->NumArgs));
else
S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs));

Expand Down
34 changes: 23 additions & 11 deletions clang/lib/Index/CommentToXML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ class CommentASTToXMLConverter :
void visitParagraphComment(const ParagraphComment *C);

void appendParagraphCommentWithKind(const ParagraphComment *C,
StringRef Kind);
StringRef ParagraphKind,
StringRef PrependBodyText);

void visitBlockCommandComment(const BlockCommandComment *C);
void visitParamCommandComment(const ParamCommandComment *C);
Expand Down Expand Up @@ -680,24 +681,27 @@ CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
Result << ">&lt;/" << C->getTagName() << "&gt;</rawHTML>";
}

void
CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
appendParagraphCommentWithKind(C, StringRef());
void CommentASTToXMLConverter::visitParagraphComment(
const ParagraphComment *C) {
appendParagraphCommentWithKind(C, StringRef(), StringRef());
}

void CommentASTToXMLConverter::appendParagraphCommentWithKind(
const ParagraphComment *C,
StringRef ParagraphKind) {
if (C->isWhitespace())
const ParagraphComment *C, StringRef ParagraphKind,
StringRef PrependBodyText) {
if (C->isWhitespace() && PrependBodyText.empty())
return;

if (ParagraphKind.empty())
Result << "<Para>";
else
Result << "<Para kind=\"" << ParagraphKind << "\">";

for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I) {
if (!PrependBodyText.empty())
Result << PrependBodyText << " ";

for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E;
++I) {
visit(*I);
}
Result << "</Para>";
Expand All @@ -706,8 +710,15 @@ void CommentASTToXMLConverter::appendParagraphCommentWithKind(
void CommentASTToXMLConverter::visitBlockCommandComment(
const BlockCommandComment *C) {
StringRef ParagraphKind;
StringRef ExceptionType;

switch (C->getCommandID()) {
const unsigned CommandID = C->getCommandID();
const CommandInfo *Info = Traits.getCommandInfo(CommandID);
if (Info->IsThrowsCommand && C->getNumArgs() > 0) {
ExceptionType = C->getArgText(0);
}

switch (CommandID) {
case CommandTraits::KCI_attention:
case CommandTraits::KCI_author:
case CommandTraits::KCI_authors:
Expand All @@ -732,7 +743,8 @@ void CommentASTToXMLConverter::visitBlockCommandComment(
break;
}

appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind);
appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind,
ExceptionType);
}

void CommentASTToXMLConverter::visitParamCommandComment(
Expand Down
79 changes: 49 additions & 30 deletions clang/test/Index/comment-to-html-xml-conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1046,82 +1046,101 @@ void comment_to_xml_conversion_todo_4();
/// Aaa.
/// \throws Bbb.
void comment_to_xml_conversion_exceptions_1();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_1:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_1</Name><USR>c:@F@comment_to_xml_conversion_exceptions_1#</USR><Declaration>void comment_to_xml_conversion_exceptions_1()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para> Bbb.</Para></Exceptions></Function>]
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_1:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_1</Name><USR>c:@F@comment_to_xml_conversion_exceptions_1#</USR><Declaration>void comment_to_xml_conversion_exceptions_1()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb. </Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Bbb.]))))]
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Bbb.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace)))]

/// Aaa.
/// \throw Bbb.
void comment_to_xml_conversion_exceptions_2();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_2:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_2</Name><USR>c:@F@comment_to_xml_conversion_exceptions_2#</USR><Declaration>void comment_to_xml_conversion_exceptions_2()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para> Bbb.</Para></Exceptions></Function>]
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_2:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_2</Name><USR>c:@F@comment_to_xml_conversion_exceptions_2#</USR><Declaration>void comment_to_xml_conversion_exceptions_2()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb. </Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throw]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Bbb.]))))]
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throw] Arg[0]=Bbb.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace)))]

/// Aaa.
/// \exception Bbb.
void comment_to_xml_conversion_exceptions_3();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_3:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_3</Name><USR>c:@F@comment_to_xml_conversion_exceptions_3#</USR><Declaration>void comment_to_xml_conversion_exceptions_3()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para> Bbb.</Para></Exceptions></Function>]
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_3:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_3</Name><USR>c:@F@comment_to_xml_conversion_exceptions_3#</USR><Declaration>void comment_to_xml_conversion_exceptions_3()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb. </Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[exception]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Bbb.]))))]
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[exception] Arg[0]=Bbb.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace)))]

/// Aaa.
/// \throws Bbb.
/// \throws Ccc.
/// \throws Ddd.
void comment_to_xml_conversion_exceptions_4();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_4:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_4</Name><USR>c:@F@comment_to_xml_conversion_exceptions_4#</USR><Declaration>void comment_to_xml_conversion_exceptions_4()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para> Bbb. </Para><Para> Ccc. </Para><Para> Ddd.</Para></Exceptions></Function>]
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_4:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_4</Name><USR>c:@F@comment_to_xml_conversion_exceptions_4#</USR><Declaration>void comment_to_xml_conversion_exceptions_4()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb. </Para><Para>Ccc. </Para><Para>Ddd. </Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Bbb.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Ccc.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Ddd.]))))]
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Bbb.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Ccc.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Ddd.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace)))]

/// Aaa.
/// \throws Bbb.
/// \throw Ccc.
void comment_to_xml_conversion_exceptions_5();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_5:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_5</Name><USR>c:@F@comment_to_xml_conversion_exceptions_5#</USR><Declaration>void comment_to_xml_conversion_exceptions_5()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para> Bbb. </Para><Para> Ccc.</Para></Exceptions></Function>]
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_5:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_5</Name><USR>c:@F@comment_to_xml_conversion_exceptions_5#</USR><Declaration>void comment_to_xml_conversion_exceptions_5()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb. </Para><Para>Ccc. </Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Bbb.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throw] Arg[0]=Ccc.
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace)))]

/// Aaa.
/// \throws Bbb subsequent arg text
void comment_to_xml_conversion_exceptions_6();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_6:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_6</Name><USR>c:@F@comment_to_xml_conversion_exceptions_6#</USR><Declaration>void comment_to_xml_conversion_exceptions_6()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb subsequent arg text</Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws]
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Bbb
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Bbb.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[subsequent arg text]))))]

/// Aaa.
/// \throws Bbb subsequent arg text
/// \throw Ccc subsequent arg text
void comment_to_xml_conversion_exceptions_7();
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_exceptions_7:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_exceptions_7</Name><USR>c:@F@comment_to_xml_conversion_exceptions_7#</USR><Declaration>void comment_to_xml_conversion_exceptions_7()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Exceptions><Para>Bbb subsequent arg text </Para><Para>Ccc subsequent arg text</Para></Exceptions></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throws] Arg[0]=Bbb
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[subsequent arg text] HasTrailingNewline)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throw]
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[throw] Arg[0]=Ccc
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Ccc.]))))]
// CHECK-NEXT: (CXComment_Text Text=[subsequent arg text]))))]

#endif

Loading