================
@@ -48,6 +48,59 @@ class ActionCommentHandler : public CommentHandler {
 };
 } // end anonymous namespace
 
+class Parser::TokenInjectionHandlerImpl : public sema::TokenInjectionHandler {
+  Parser &P;
+
+public:
+  explicit TokenInjectionHandlerImpl(Parser &P) : P{P} {}
+
+  ExprResult ParseAsExpression(StringRef Code,
+                               const llvm::StringMap<Token> &Replacements,
+                               SourceLocation InjectionLoc) override {
+    // Collect tokens.
+    SmallVector<Token> Tokens;
+    if (P.PP.LexTokensInString(Tokens, Code, InjectionLoc))
+      return ExprError();
+
+    for (Token &Tok : Tokens) {
+      if (Tok.is(tok::identifier)) {
+        auto It = Replacements.find(Tok.getIdentifierInfo()->getName());
+        if (It != Replacements.end())
+          Tok = It->getValue();
+      }
+    }
+
+    // Add an EOF token so we know when to stop.
+    char EofMarker{};
+    Token &EofToken = Tokens.emplace_back();
+    EofToken.startToken();
+    EofToken.setKind(tok::eof);
+    EofToken.setEofData(&EofMarker);
+
+    // Start parsing the tokens; we need to save the current token so we
+    // don't lose it, and consume it since EnterTokenStream() doesn't change
+    // the current token.
+    //
+    // Disable macro expansion since that was already done as part of the call
+    // to LexTokensInString() above; 'IsReinjected' is for phase 4 tokens, so
+    // we don't want that either here.
+    SaveAndRestore SaveCurTok{P.Tok};
+    P.PP.EnterTokenStream(Tokens, /*DisableMacroExpansion=*/true,
+                          /*IsReinjected=*/false);
+    P.ConsumeAnyToken();
+    ExprResult Res = P.ParseExpression();
+
+    // We should have parsed exactly one expression; if we still have tokens
+    // left, then there was probably an error; don't diagnose this and just
+    // skip them.
+    while (P.Tok.isNot(tok::eof))
+      P.ConsumeAnyToken();
+
+    assert(P.Tok.getEofData() == &EofMarker);
+    return Res;
----------------
cor3ntin wrote:

Not a fan of that either - The assert should be before we flush the tokens.
We are not parsing some user-provided content that could be bogus - we are 
calling an api with a payload of our own making so there should never be non 
sense tokens (assuming the expression is valid)
so `assert(P.Tok.is(tok::eof) || Res.isInvalid()` ?

But i wonder if we should have a "ParsingInjectedTokens" mode in Lexer that 
would inject EOF for us? here, maybe not but it's worth thinking about 

https://github.com/llvm/llvm-project/pull/208877
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to