[clang] [clang] Implement statement printer for EmbedExpr (PR #117770)

via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 27 04:41:09 PST 2024


https://github.com/circl-lastname updated https://github.com/llvm/llvm-project/pull/117770

>From 184359e8be9eab570ef01810d5d3a6ba4a48afe9 Mon Sep 17 00:00:00 2001
From: circl <circl.lastname at gmail.com>
Date: Tue, 26 Nov 2024 18:52:19 +0100
Subject: [PATCH 1/2] [clang] Store filename in EmbedExpr

---
 clang/include/clang/AST/Expr.h         | 9 +++++++--
 clang/include/clang/Lex/Preprocessor.h | 5 ++++-
 clang/include/clang/Sema/Sema.h        | 4 ++--
 clang/lib/AST/Expr.cpp                 | 8 ++++----
 clang/lib/Lex/PPDirectives.cpp         | 9 ++++++---
 clang/lib/Parse/ParseInit.cpp          | 3 ++-
 clang/lib/Sema/SemaExpr.cpp            | 5 +++--
 clang/lib/Sema/SemaInit.cpp            | 6 +++---
 8 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 708c8656decbe0..95d341957c59a2 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4917,19 +4917,24 @@ class EmbedExpr final : public Expr {
   SourceLocation EmbedKeywordLoc;
   IntegerLiteral *FakeChildNode = nullptr;
   const ASTContext *Ctx = nullptr;
+  StringRef Filename;
+  bool IsAngled;
   EmbedDataStorage *Data;
   unsigned Begin = 0;
   unsigned NumOfElements;
 
 public:
-  EmbedExpr(const ASTContext &Ctx, SourceLocation Loc, EmbedDataStorage *Data,
-            unsigned Begin, unsigned NumOfElements);
+  EmbedExpr(const ASTContext &Ctx, SourceLocation Loc, StringRef Filename,
+            bool IsAngled, EmbedDataStorage *Data, unsigned Begin,
+            unsigned NumOfElements);
   explicit EmbedExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}
 
   SourceLocation getLocation() const { return EmbedKeywordLoc; }
   SourceLocation getBeginLoc() const { return EmbedKeywordLoc; }
   SourceLocation getEndLoc() const { return EmbedKeywordLoc; }
 
+  StringRef getFilename() const { return Filename; }
+  bool getIsAngled() const { return IsAngled; }
   StringLiteral *getDataStringLiteral() const { return Data->BinaryData; }
   EmbedDataStorage *getData() const { return Data; }
 
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 3312d4ed1d798d..0a4ca35224497c 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -2761,7 +2761,8 @@ class Preprocessor {
   // Binary data inclusion
   void HandleEmbedDirective(SourceLocation HashLoc, Token &Tok,
                             const FileEntry *LookupFromFile = nullptr);
-  void HandleEmbedDirectiveImpl(SourceLocation HashLoc,
+  void HandleEmbedDirectiveImpl(SourceLocation HashLoc, StringRef Filename,
+                                bool IsAngled,
                                 const LexEmbedParametersResult &Params,
                                 StringRef BinaryContents);
 
@@ -3066,6 +3067,8 @@ class EmptylineHandler {
 /// Helper class to shuttle information about #embed directives from the
 /// preprocessor to the parser through an annotation token.
 struct EmbedAnnotationData {
+  std::string Filename;
+  bool IsAngled;
   StringRef BinaryData;
 };
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 24abd5d95dd844..435bc4d4807bc4 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7086,8 +7086,8 @@ class Sema final : public SemaBase {
                                 SourceLocation RPLoc);
 
   // #embed
-  ExprResult ActOnEmbedExpr(SourceLocation EmbedKeywordLoc,
-                            StringLiteral *BinaryData);
+  ExprResult ActOnEmbedExpr(SourceLocation EmbedKeywordLoc, StringRef Filename,
+                            bool IsAngled, StringLiteral *BinaryData);
 
   // Build a potentially resolved SourceLocExpr.
   ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a4fb4d5a1f2ec4..eeea6da07d304f 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2383,11 +2383,11 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
 }
 
 EmbedExpr::EmbedExpr(const ASTContext &Ctx, SourceLocation Loc,
-                     EmbedDataStorage *Data, unsigned Begin,
-                     unsigned NumOfElements)
+                     StringRef Filename, bool IsAngled, EmbedDataStorage *Data,
+                     unsigned Begin, unsigned NumOfElements)
     : Expr(EmbedExprClass, Ctx.IntTy, VK_PRValue, OK_Ordinary),
-      EmbedKeywordLoc(Loc), Ctx(&Ctx), Data(Data), Begin(Begin),
-      NumOfElements(NumOfElements) {
+      EmbedKeywordLoc(Loc), Ctx(&Ctx), Filename(Filename), IsAngled(IsAngled),
+      Data(Data), Begin(Begin), NumOfElements(NumOfElements) {
   setDependence(ExprDependence::None);
   FakeChildNode = IntegerLiteral::Create(
       Ctx, llvm::APInt::getZero(Ctx.getTypeSize(getType())), getType(), Loc);
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index a23ad40884f249..62eda8401636c4 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -3871,8 +3871,8 @@ Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) {
 }
 
 void Preprocessor::HandleEmbedDirectiveImpl(
-    SourceLocation HashLoc, const LexEmbedParametersResult &Params,
-    StringRef BinaryContents) {
+    SourceLocation HashLoc, StringRef Filename, bool IsAngled,
+    const LexEmbedParametersResult &Params, StringRef BinaryContents) {
   if (BinaryContents.empty()) {
     // If we have no binary contents, the only thing we need to emit are the
     // if_empty tokens, if any.
@@ -3902,6 +3902,8 @@ void Preprocessor::HandleEmbedDirectiveImpl(
   }
 
   EmbedAnnotationData *Data = new (BP) EmbedAnnotationData;
+  Data->Filename = Filename;
+  Data->IsAngled = IsAngled;
   Data->BinaryData = BinaryContents;
 
   Toks[CurIdx].startToken();
@@ -4006,5 +4008,6 @@ void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok,
   if (Callbacks)
     Callbacks->EmbedDirective(HashLoc, Filename, isAngled, MaybeFileRef,
                               *Params);
-  HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents);
+  HandleEmbedDirectiveImpl(HashLoc, Filename, isAngled, *Params,
+                           BinaryContents);
 }
diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp
index 63b1d7bd9db53e..06ced273a65e92 100644
--- a/clang/lib/Parse/ParseInit.cpp
+++ b/clang/lib/Parse/ParseInit.cpp
@@ -451,7 +451,8 @@ ExprResult Parser::createEmbedExpr() {
 
     StringLiteral *BinaryDataArg = CreateStringLiteralFromStringRef(
         Data->BinaryData, Context.UnsignedCharTy);
-    Res = Actions.ActOnEmbedExpr(StartLoc, BinaryDataArg);
+    Res = Actions.ActOnEmbedExpr(StartLoc, Data->Filename, Data->IsAngled,
+                                 BinaryDataArg);
   }
   return Res;
 }
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c9d7444d5865a5..f5deacf709d606 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16770,12 +16770,13 @@ ExprResult Sema::BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
 }
 
 ExprResult Sema::ActOnEmbedExpr(SourceLocation EmbedKeywordLoc,
+                                StringRef Filename, bool IsAngled,
                                 StringLiteral *BinaryData) {
   EmbedDataStorage *Data = new (Context) EmbedDataStorage;
   Data->BinaryData = BinaryData;
   return new (Context)
-      EmbedExpr(Context, EmbedKeywordLoc, Data, /*NumOfElements=*/0,
-                Data->getDataElementCount());
+      EmbedExpr(Context, EmbedKeywordLoc, Filename, IsAngled, Data,
+                /*NumOfElements=*/0, Data->getDataElementCount());
 }
 
 static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 7c03a12e812809..609ca34a8c1d20 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -525,9 +525,9 @@ class InitListChecker {
       }
     }
 
-    Result = new (SemaRef.Context)
-        EmbedExpr(SemaRef.Context, Embed->getLocation(), Embed->getData(),
-                  CurEmbedIndex, ElsCount);
+    Result = new (SemaRef.Context) EmbedExpr(
+        SemaRef.Context, Embed->getLocation(), Embed->getFilename(),
+        Embed->getIsAngled(), Embed->getData(), CurEmbedIndex, ElsCount);
     CurEmbedIndex += ElsCount;
     if (CurEmbedIndex >= Embed->getDataElementCount()) {
       CurEmbed = nullptr;

>From c175f5ca83bd5e6a4c676ce7d36e2c8bdc73b701 Mon Sep 17 00:00:00 2001
From: circl <circl.lastname at gmail.com>
Date: Tue, 26 Nov 2024 19:44:27 +0100
Subject: [PATCH 2/2] [clang] Implement statement printer for EmbedExpr

---
 clang/docs/ReleaseNotes.rst   | 1 +
 clang/lib/AST/StmtPrinter.cpp | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6c40e48e2f49b3..95ae2b52d80598 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -334,6 +334,7 @@ C23 Feature Support
 - Clang now officially supports `N3030 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3030.htm>`_ Enhancements to Enumerations. Clang already supported it as an extension, so there were no changes to compiler behavior.
 - Fixed the value of ``BOOL_WIDTH`` in ``<limits.h>`` to return ``1``
   explicitly, as mandated by the standard. Fixes #GH117348
+- Initial support for pretty printing ``#embed`` directives, which no longer crash clangd when hovered.
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index c8677d11b64e8d..2ab9e9a1df4819 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1202,7 +1202,11 @@ void StmtPrinter::VisitSourceLocExpr(SourceLocExpr *Node) {
 }
 
 void StmtPrinter::VisitEmbedExpr(EmbedExpr *Node) {
-  llvm::report_fatal_error("Not implemented");
+  // FIXME: This doesn't handle offsets, prefixes, and if_empty yet
+  OS << NL << "#embed ";
+  OS << (Node->getIsAngled() ? '<' : '"');
+  OS << Node->getFilename();
+  OS << (Node->getIsAngled() ? '>' : '"') << NL;
 }
 
 void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {



More information about the cfe-commits mailing list