From 012096290352438668d8f4bb7a97179952a87a3a Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Sat, 18 Nov 2023 00:20:05 +0000 Subject: [PATCH] [clang][DebugInfo] Create evaluateConstantInitializer helper function This patch extracts the logic to evaluate a C++ static data-member's constant initializer such that it can be used by an upcoming patch. It also makes the check for whether we are dealing with a constant initializer more robust/idiomatic, which revealed a bug in the `debug-info-static-inline-member` test. --- clang/lib/CodeGen/CGDebugInfo.cpp | 28 ++++++++++++++++--- .../debug-info-static-inline-member.cpp | 9 ------ .../CodeGenCXX/debug-info-static-member.cpp | 14 +++++----- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0b52d99ad07f16..4c7c7d68b4271e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -69,6 +69,29 @@ static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) { return D->hasAttr() ? D->getMaxAlignment() : 0; } +/// Given a VarDecl corresponding to either the definition or +/// declaration of a C++ static data member, if it has a constant +/// initializer and is evaluatable, return the evaluated value. +/// Returns std::nullopt otherwise. +static std::optional +evaluateConstantInitializer(const clang::VarDecl *VD, + const clang::ASTContext &Ctx) { + assert(VD != nullptr); + + if (!VD->isStaticDataMember()) + return std::nullopt; + + if (!VD->isUsableInConstantExpressions(Ctx)) + return std::nullopt; + + auto const *InitExpr = VD->getAnyInitializer(); + Expr::EvalResult Result; + if (!InitExpr->EvaluateAsConstantExpr(Result, Ctx)) + return std::nullopt; + + return Result.Val; +} + CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs), @@ -5596,14 +5619,11 @@ void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) { if (VD->hasAttr()) return; - if (!VD->hasInit()) - return; - const auto CacheIt = DeclCache.find(VD); if (CacheIt != DeclCache.end()) return; - auto const *InitVal = VD->evaluateValue(); + const auto InitVal = evaluateConstantInitializer(VD, CGM.getContext()); if (!InitVal) return; diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp index f2d4d9408a8297..6ba98373d33ada 100644 --- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp +++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp @@ -67,10 +67,6 @@ int main() { // CHECK-SAME: flags: DIFlagStaticMember // CHECK-NOT: extraData: -// CHECK: ![[IENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "inline_enum", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-NOT: extraData: - // CHECK: ![[EMPTY_TEMPLATED_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "empty_templated", // CHECK-SAME: flags: DIFlagStaticMember // CHECK-NOT: extraData: @@ -98,11 +94,6 @@ int main() { // CHECK-NOT: linkageName: // CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]]) -// CHECK: !DIGlobalVariableExpression(var: ![[IENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) -// CHECK: ![[IENUM_VAR]] = distinct !DIGlobalVariable(name: "inline_enum" -// CHECK-NOT: linkageName: -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[IENUM_DECL]]) - // CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_TEMPLATED_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value)) // CHECK: ![[EMPTY_TEMPLATED_VAR]] = distinct !DIGlobalVariable(name: "empty_templated" // CHECK-NOT: linkageName: diff --git a/clang/test/CodeGenCXX/debug-info-static-member.cpp b/clang/test/CodeGenCXX/debug-info-static-member.cpp index a2d25e98ed1cb6..519c971e1fbf1b 100644 --- a/clang/test/CodeGenCXX/debug-info-static-member.cpp +++ b/clang/test/CodeGenCXX/debug-info-static-member.cpp @@ -1,8 +1,8 @@ -// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11,NOT-MS %s // RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++98 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s -// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s -// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-5 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF5 %s -// RUN: %clangxx -target x86_64-windows-msvc -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4 %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11,NOT-MS %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-5 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF5,CPP11 %s +// RUN: %clangxx -target x86_64-windows-msvc -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11 %s // PR14471 // CHECK: @{{.*}}a{{.*}} = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]] @@ -171,9 +171,9 @@ int y::z; // CHECK: ![[CONST_A_VAR]] = distinct !DIGlobalVariable(name: "const_a" // CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_A_DECL]]) -// CHECK: !DIGlobalVariableExpression(var: ![[CONST_B_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) -// CHECK: ![[CONST_B_VAR]] = distinct !DIGlobalVariable(name: "const_b" -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_B_DECL]]) +// CPP11: !DIGlobalVariableExpression(var: ![[CONST_B_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) +// CPP11: ![[CONST_B_VAR]] = distinct !DIGlobalVariable(name: "const_b" +// CPP11-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_B_DECL]]) // CHECK: !DIGlobalVariableExpression(var: ![[CONST_C_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18, DW_OP_stack_value)) // CHECK: ![[CONST_C_VAR]] = distinct !DIGlobalVariable(name: "const_c"