diff options
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index a106ce1..356e785 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -8051,6 +8051,71 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, return false; } +TypeResult Parser::ParseTypeFromString(StringRef TypeStr, StringRef Context, + SourceLocation IncludeLoc) { + // Consume (unexpanded) tokens up to the end-of-directive. + SmallVector<Token, 4> Tokens; + { + // Create a new buffer from which we will parse the type. + auto &SourceMgr = PP.getSourceManager(); + FileID FID = SourceMgr.createFileID( + llvm::MemoryBuffer::getMemBufferCopy(TypeStr, Context), SrcMgr::C_User, + 0, 0, IncludeLoc); + + // Form a new lexer that references the buffer. + Lexer L(FID, SourceMgr.getBufferOrFake(FID), PP); + L.setParsingPreprocessorDirective(true); + + // Lex the tokens from that buffer. + Token Tok; + do { + L.Lex(Tok); + Tokens.push_back(Tok); + } while (Tok.isNot(tok::eod)); + } + + // Replace the "eod" token with an "eof" token identifying the end of + // the provided string. + Token &EndToken = Tokens.back(); + EndToken.startToken(); + EndToken.setKind(tok::eof); + EndToken.setLocation(Tok.getLocation()); + EndToken.setEofData(TypeStr.data()); + + // Add the current token back. + Tokens.push_back(Tok); + + // Enter the tokens into the token stream. + PP.EnterTokenStream(Tokens, /*DisableMacroExpansion=*/false, + /*IsReinject=*/false); + + // Consume the current token so that we'll start parsing the tokens we + // added to the stream. + ConsumeAnyToken(); + + // Enter a new scope. + ParseScope LocalScope(this, 0); + + // Parse the type. + TypeResult Result = ParseTypeName(nullptr); + + // Check if we parsed the whole thing. + if (Result.isUsable() && + (Tok.isNot(tok::eof) || Tok.getEofData() != TypeStr.data())) { + Diag(Tok.getLocation(), diag::err_type_unparsed); + } + + // There could be leftover tokens (e.g. because of an error). + // Skip through until we reach the 'end of directive' token. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + // Consume the end token. + if (Tok.is(tok::eof) && Tok.getEofData() == TypeStr.data()) + ConsumeAnyToken(); + return Result; +} + void Parser::DiagnoseBitIntUse(const Token &Tok) { // If the token is for _ExtInt, diagnose it as being deprecated. Otherwise, // the token is about _BitInt and gets (potentially) diagnosed as use of an |