mibintc created this revision.
mibintc added a reviewer: debug-info.
Herald added a project: clang.
mibintc requested review of this revision.

This is an exploratory patch, an attempt to solve 
bugs.llvm.org/show_bug.cgi?id=47400

That bug report shows a simple test case where the constexpr variable, declared 
outside the scope of the lambda but used within the lambda, is simply unknown 
in the DebugInfo.  This is different from a gcc compilation where gdb knows the 
symbol, and knows that the value is "optimized out".

The problem is constexpr variables like n_steps (see example in the bug report) 
are not captured and so do not appear in the record type. These still appear in 
the AST so if we gather them it is possible to emit static data member. As a 
proof of concept, this is prototyped here. I didn't think about exactly which 
variables should be gathered but this might be a framework.  This is a little 
hacky since the constexpr variable  is not really a static member of the lambda 
but the use is roughly correct.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87049

Files:
  clang/lib/CodeGen/CGDebugInfo.cpp


Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
@@ -1358,6 +1359,29 @@
                                    offsetInBits, flags, debugType);
 }
 
+namespace {
+/// Locate the non_odr_use constant variables in a statement.
+struct NonODRUseVarFinder final : public ConstStmtVisitor<NonODRUseVarFinder> {
+  llvm::SmallSetVector<const VarDecl *, 4> NonODRUseVars;
+
+  NonODRUseVarFinder(const Stmt *S) {
+    Visit(S);
+  }
+
+  void VisitStmt(const Stmt *S) {
+    for (const Stmt *Child : S->children())
+      if (Child)
+        Visit(Child);
+  }
+
+  void VisitDeclRefExpr(const DeclRefExpr *E) {
+    if (E->isNonOdrUse() == NOUR_Constant)
+      if (const auto *VD = dyn_cast<VarDecl>(E->getDecl()))
+        NonODRUseVars.insert(VD);
+  }
+};
+} // namespace
+
 void CGDebugInfo::CollectRecordLambdaFields(
     const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
     llvm::DIType *RecordTy) {
@@ -1397,6 +1421,13 @@
       elements.push_back(fieldType);
     }
   }
+  // constexpr variables do not need to be captured, so to view them
+  // in the debugger pretend they are const static data members.
+  CXXMethodDecl *CallOp = CXXDecl->getLambdaCallOperator();
+  assert(CallOp);
+  NonODRUseVarFinder Finder(CallOp->getBody());
+  for (const auto *VD : Finder.NonODRUseVars)
+    elements.push_back(CreateRecordStaticField(VD, RecordTy, CXXDecl));
 }
 
 llvm::DIDerivedType *


Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
@@ -1358,6 +1359,29 @@
                                    offsetInBits, flags, debugType);
 }
 
+namespace {
+/// Locate the non_odr_use constant variables in a statement.
+struct NonODRUseVarFinder final : public ConstStmtVisitor<NonODRUseVarFinder> {
+  llvm::SmallSetVector<const VarDecl *, 4> NonODRUseVars;
+
+  NonODRUseVarFinder(const Stmt *S) {
+    Visit(S);
+  }
+
+  void VisitStmt(const Stmt *S) {
+    for (const Stmt *Child : S->children())
+      if (Child)
+        Visit(Child);
+  }
+
+  void VisitDeclRefExpr(const DeclRefExpr *E) {
+    if (E->isNonOdrUse() == NOUR_Constant)
+      if (const auto *VD = dyn_cast<VarDecl>(E->getDecl()))
+        NonODRUseVars.insert(VD);
+  }
+};
+} // namespace
+
 void CGDebugInfo::CollectRecordLambdaFields(
     const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
     llvm::DIType *RecordTy) {
@@ -1397,6 +1421,13 @@
       elements.push_back(fieldType);
     }
   }
+  // constexpr variables do not need to be captured, so to view them
+  // in the debugger pretend they are const static data members.
+  CXXMethodDecl *CallOp = CXXDecl->getLambdaCallOperator();
+  assert(CallOp);
+  NonODRUseVarFinder Finder(CallOp->getBody());
+  for (const auto *VD : Finder.NonODRUseVars)
+    elements.push_back(CreateRecordStaticField(VD, RecordTy, CXXDecl));
 }
 
 llvm::DIDerivedType *
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to