summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-09-23 21:05:52 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-09-23 21:05:52 +0000
commitbdf54a21b5e3392b431b6569007cb61689c76a3c (patch)
tree13c81be40bfacfa0fec584244b9b57b9529601d6
parent6dbbbc28b0fd9f7a6f4f1eb5a5a875d8d8cf074a (diff)
downloadbcm5719-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
-rw-r--r--clang/include/clang/Lex/Preprocessor.h1
-rw-r--r--clang/lib/Lex/PPLexerChange.cpp19
-rw-r--r--clang/test/Parser/cxx-template-argument.cpp5
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())> *);
+}
OpenPOWER on IntegriCloud