diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/CommentParser.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/CommentParser.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/CommentParser.cpp b/contrib/llvm-project/clang/lib/AST/CommentParser.cpp index 8adfd85d0160..d5e5bb27ceba 100644 --- a/contrib/llvm-project/clang/lib/AST/CommentParser.cpp +++ b/contrib/llvm-project/clang/lib/AST/CommentParser.cpp @@ -89,6 +89,31 @@ class TextTokenRetokenizer { } } + /// Extract a template type + bool lexTemplate(SmallString<32> &WordText) { + unsigned BracketCount = 0; + while (!isEnd()) { + const char C = peek(); + WordText.push_back(C); + consumeChar(); + 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. @@ -149,6 +174,111 @@ public: 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()) { + 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); + 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); + return true; + } + + // Check if this line starts with @par or \par + bool startsWithParCommand() { + unsigned Offset = 1; + + // Skip all whitespace characters at the beginning. + // This needs to backtrack because Pos has already advanced past the + // actual \par or @par command by the time this function is called. + while (isWhitespace(*(Pos.BufferPtr - Offset))) + Offset++; + + // Once we've reached the whitespace, backtrack and check if the previous + // four characters are \par or @par. + llvm::StringRef LineStart(Pos.BufferPtr - Offset - 3, 4); + return LineStart.starts_with("\\par") || LineStart.starts_with("@par"); + } + + /// Extract a par command argument-header. + bool lexParHeading(Token &Tok) { + if (isEnd()) + return false; + + Position SavedPos = Pos; + + consumeWhitespace(); + SmallString<32> WordText; + const char *WordBegin = Pos.BufferPtr; + SourceLocation Loc = getSourceLocation(); + + if (!startsWithParCommand()) + return false; + + // Read until the end of this token, which is effectively the end of the + // line. This gets us the content of the par header, if there is one. + while (!isEnd()) { + WordText.push_back(peek()); + if (Pos.BufferPtr + 1 == Pos.BufferEnd) { + consumeChar(); + break; + } + consumeChar(); + } + + 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); + return true; + } + /// Extract a word -- sequence of non-whitespace characters. bool lexWord(Token &Tok) { if (isEnd()) @@ -304,6 +434,41 @@ 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); +} + +ArrayRef<Comment::Argument> +Parser::parseParCommandArgs(TextTokenRetokenizer &Retokenizer, + unsigned NumArgs) { + assert(NumArgs > 0); + auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs)) + Comment::Argument[NumArgs]; + unsigned ParsedArgs = 0; + Token Arg; + + while (ParsedArgs < NumArgs && Retokenizer.lexParHeading(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)); @@ -356,6 +521,12 @@ BlockCommandComment *Parser::parseBlockCommand() { parseParamCommandArgs(PC, Retokenizer); else if (TPC) parseTParamCommandArgs(TPC, Retokenizer); + else if (Info->IsThrowsCommand) + S.actOnBlockCommandArgs( + BC, parseThrowCommandArgs(Retokenizer, Info->NumArgs)); + else if (Info->IsParCommand) + S.actOnBlockCommandArgs(BC, + parseParCommandArgs(Retokenizer, Info->NumArgs)); else S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs)); |