diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/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 { + llvm::SmallSetVector 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(E->getDecl())) + NonODRUseVars.insert(VD); + } +}; +} // namespace + void CGDebugInfo::CollectRecordLambdaFields( const CXXRecordDecl *CXXDecl, SmallVectorImpl &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 *