diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp | 67 | 
1 files changed, 57 insertions, 10 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp index 608e0dedebb7..a7957e82e495 100644 --- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp @@ -1,9 +1,8 @@  //===- TokenLexer.cpp - Lex from a token stream ---------------------------===//  // -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  //  //===----------------------------------------------------------------------===//  // @@ -54,6 +53,7 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,    Tokens = &*Macro->tokens_begin();    OwnsTokens = false;    DisableMacroExpansion = false; +  IsReinject = false;    NumTokens = Macro->tokens_end()-Macro->tokens_begin();    MacroExpansionStart = SourceLocation(); @@ -92,7 +92,9 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,  /// Create a TokenLexer for the specified token stream.  This does not  /// take ownership of the specified token vector.  void TokenLexer::Init(const Token *TokArray, unsigned NumToks, -                      bool disableMacroExpansion, bool ownsTokens) { +                      bool disableMacroExpansion, bool ownsTokens, +                      bool isReinject) { +  assert(!isReinject || disableMacroExpansion);    // If the client is reusing a TokenLexer, make sure to free any memory    // associated with it.    destroy(); @@ -102,6 +104,7 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks,    Tokens = TokArray;    OwnsTokens = ownsTokens;    DisableMacroExpansion = disableMacroExpansion; +  IsReinject = isReinject;    NumTokens = NumToks;    CurTokenIdx = 0;    ExpandLocStart = ExpandLocEnd = SourceLocation(); @@ -244,8 +247,7 @@ void TokenLexer::ExpandFunctionArguments() {    // we install the newly expanded sequence as the new 'Tokens' list.    bool MadeChange = false; -  const bool CalledWithVariadicArguments = -      ActualArgs->invokedWithVariadicArgument(Macro); +  Optional<bool> CalledWithVariadicArguments;    VAOptExpansionContext VCtx(PP); @@ -292,7 +294,12 @@ void TokenLexer::ExpandFunctionArguments() {        // this token. Note sawClosingParen() returns true only if the r_paren matches        // the closing r_paren of the __VA_OPT__.        if (!Tokens[I].is(tok::r_paren) || !VCtx.sawClosingParen()) { -        if (!CalledWithVariadicArguments) { +        // Lazily expand __VA_ARGS__ when we see the first __VA_OPT__. +        if (!CalledWithVariadicArguments.hasValue()) { +          CalledWithVariadicArguments = +              ActualArgs->invokedWithVariadicArgument(Macro, PP); +        } +        if (!*CalledWithVariadicArguments) {            // Skip this token.            continue;          } @@ -315,8 +322,8 @@ void TokenLexer::ExpandFunctionArguments() {            stringifyVAOPTContents(ResultToks, VCtx,                                   /*ClosingParenLoc*/ Tokens[I].getLocation()); -        } else if (/*No tokens within VAOPT*/ !( -            ResultToks.size() - VCtx.getNumberOfTokensPriorToVAOpt())) { +        } else if (/*No tokens within VAOPT*/ +                   ResultToks.size() == VCtx.getNumberOfTokensPriorToVAOpt()) {            // Treat VAOPT as a placemarker token.  Eat either the '##' before the            // RHS/VAOPT (if one exists, suggesting that the LHS (if any) to that            // hashhash was not a placemarker) or the '##' @@ -327,6 +334,26 @@ void TokenLexer::ExpandFunctionArguments() {            } else if ((I + 1 != E) && Tokens[I + 1].is(tok::hashhash)) {              ++I; // Skip the following hashhash.            } +        } else { +          // If there's a ## before the __VA_OPT__, we might have discovered +          // that the __VA_OPT__ begins with a placeholder. We delay action on +          // that to now to avoid messing up our stashed count of tokens before +          // __VA_OPT__. +          if (VCtx.beginsWithPlaceholder()) { +            assert(VCtx.getNumberOfTokensPriorToVAOpt() > 0 && +                   ResultToks.size() >= VCtx.getNumberOfTokensPriorToVAOpt() && +                   ResultToks[VCtx.getNumberOfTokensPriorToVAOpt() - 1].is( +                       tok::hashhash) && +                   "no token paste before __VA_OPT__"); +            ResultToks.erase(ResultToks.begin() + +                             VCtx.getNumberOfTokensPriorToVAOpt() - 1); +          } +          // If the expansion of __VA_OPT__ ends with a placeholder, eat any +          // following '##' token. +          if (VCtx.endsWithPlaceholder() && I + 1 != E && +              Tokens[I + 1].is(tok::hashhash)) { +            ++I; +          }          }          VCtx.reset();          // We processed __VA_OPT__'s closing paren (and the exit out of @@ -387,6 +414,7 @@ void TokenLexer::ExpandFunctionArguments() {        !ResultToks.empty() && ResultToks.back().is(tok::hashhash);      bool PasteBefore = I != 0 && Tokens[I-1].is(tok::hashhash);      bool PasteAfter = I+1 != E && Tokens[I+1].is(tok::hashhash); +    bool RParenAfter = I+1 != E && Tokens[I+1].is(tok::r_paren);      assert((!NonEmptyPasteBefore || PasteBefore || VCtx.isInVAOpt()) &&             "unexpected ## in ResultToks"); @@ -471,6 +499,18 @@ void TokenLexer::ExpandFunctionArguments() {                                               NextTokGetsSpace);          ResultToks[FirstResult].setFlagValue(Token::StartOfLine, false);          NextTokGetsSpace = false; +      } else { +        // We're creating a placeholder token. Usually this doesn't matter, +        // but it can affect paste behavior when at the start or end of a +        // __VA_OPT__. +        if (NonEmptyPasteBefore) { +          // We're imagining a placeholder token is inserted here. If this is +          // the first token in a __VA_OPT__ after a ##, delete the ##. +          assert(VCtx.isInVAOpt() && "should only happen inside a __VA_OPT__"); +          VCtx.hasPlaceholderAfterHashhashAtStart(); +        } +        if (RParenAfter) +          VCtx.hasPlaceholderBeforeRParen();        }        continue;      } @@ -535,6 +575,9 @@ void TokenLexer::ExpandFunctionArguments() {        continue;      } +    if (RParenAfter) +      VCtx.hasPlaceholderBeforeRParen(); +      // If this is on the RHS of a paste operator, we've already copied the      // paste operator to the ResultToks list, unless the LHS was empty too.      // Remove it. @@ -548,6 +591,8 @@ void TokenLexer::ExpandFunctionArguments() {        if (!VCtx.isInVAOpt() ||            ResultToks.size() > VCtx.getNumberOfTokensPriorToVAOpt())          ResultToks.pop_back(); +      else +        VCtx.hasPlaceholderAfterHashhashAtStart();      }      // If this is the __VA_ARGS__ token, and if the argument wasn't provided, @@ -606,6 +651,8 @@ bool TokenLexer::Lex(Token &Tok) {    // Get the next token to return.    Tok = Tokens[CurTokenIdx++]; +  if (IsReinject) +    Tok.setFlag(Token::IsReinjected);    bool TokenIsFromPaste = false;  | 
