diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-09-23 21:05:52 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-09-23 21:05:52 +0000 |
commit | bdf54a21b5e3392b431b6569007cb61689c76a3c (patch) | |
tree | 13c81be40bfacfa0fec584244b9b57b9529601d6 /clang | |
parent | 6dbbbc28b0fd9f7a6f4f1eb5a5a875d8d8cf074a (diff) | |
download | bcm5719-llvm-bdf54a21b5e3392b431b6569007cb61689c76a3c.tar.gz bcm5719-llvm-bdf54a21b5e3392b431b6569007cb61689c76a3c.zip |
PR18793: If we try to EnterTokenStream when our current lexer is a caching
lexer, add the token buffer underneath the caching lexer where possible and
push the tokens directly into the caching lexer otherwise. We previously
put the lexer into a corrupted state where we could not guarantee to provide
the tokens in the right order and would sometimes assert.
llvm-svn: 218333
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Lex/Preprocessor.h | 1 | ||||
-rw-r--r-- | clang/lib/Lex/PPLexerChange.cpp | 19 | ||||
-rw-r--r-- | clang/test/Parser/cxx-template-argument.cpp | 5 |
3 files changed, 25 insertions, 0 deletions
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index e08c07bd20d..4d2994feb33 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1361,6 +1361,7 @@ public: private: void PushIncludeMacroStack() { + assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); IncludeMacroStack.push_back(IncludeStackInfo( CurLexerKind, CurSubmodule, std::move(CurLexer), std::move(CurPTHLexer), CurPPLexer, std::move(CurTokenLexer), CurDirLookup)); diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 1ce3796aa79..f0d3d67acae 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -190,6 +190,25 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd, void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks, bool DisableMacroExpansion, bool OwnsTokens) { + if (CurLexerKind == CLK_CachingLexer) { + if (CachedLexPos < CachedTokens.size()) { + // We're entering tokens into the middle of our cached token stream. We + // can't represent that, so just insert the tokens into the buffer. + CachedTokens.insert(CachedTokens.begin() + CachedLexPos, + Toks, Toks + NumToks); + if (OwnsTokens) + delete [] Toks; + return; + } + + // New tokens are at the end of the cached token sequnece; insert the + // token stream underneath the caching lexer. + ExitCachingLexMode(); + EnterTokenStream(Toks, NumToks, DisableMacroExpansion, OwnsTokens); + EnterCachingLexMode(); + return; + } + // Create a macro expander to expand from the specified token stream. std::unique_ptr<TokenLexer> TokLexer; if (NumCachedTokenLexers == 0) { diff --git a/clang/test/Parser/cxx-template-argument.cpp b/clang/test/Parser/cxx-template-argument.cpp index bbd53b2bdd6..c9cc6b80790 100644 --- a/clang/test/Parser/cxx-template-argument.cpp +++ b/clang/test/Parser/cxx-template-argument.cpp @@ -106,3 +106,8 @@ namespace pr16225add { { }; } + +namespace PR18793 { + template<typename T, T> struct S {}; + template<typename T> int g(S<T, (T())> *); +} |