Skip to content

Commit e10c34b

Browse files
committed
[lldb][DWARFASTParserClang] Handle pointer-to-member non-type template parameters in MakeAPValue
1 parent e3bb71c commit e10c34b

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,21 +2015,32 @@ static std::optional<clang::APValue> MakeAPValue(const clang::ASTContext &ast,
20152015
return std::nullopt;
20162016

20172017
bool is_signed = false;
2018-
const bool is_integral = clang_type.IsIntegerOrEnumerationType(is_signed);
2018+
const bool is_integral =
2019+
clang_type.IsIntegerOrEnumerationType(is_signed) ||
2020+
clang_type.IsPointerType() || clang_type.IsMemberFunctionPointerType() ||
2021+
clang_type.IsNullPtrType() || clang_type.IsReferenceType();
20192022

20202023
llvm::APSInt apint(*bit_width, !is_signed);
20212024
apint = value;
20222025

20232026
if (is_integral)
20242027
return clang::APValue(apint);
20252028

2029+
if (clang_type.IsRealFloatingPointType()) {
2030+
return clang::APValue(llvm::APFloat(
2031+
ast.getFloatTypeSemantics(ClangUtil::GetQualType(clang_type)), apint));
2032+
}
2033+
20262034
// FIXME: we currently support a limited set of floating point types.
20272035
// E.g., 16-bit floats are not supported.
2028-
if (!clang_type.IsRealFloatingPointType())
2029-
return std::nullopt;
20302036

2031-
return clang::APValue(llvm::APFloat(
2032-
ast.getFloatTypeSemantics(ClangUtil::GetQualType(clang_type)), apint));
2037+
LLDB_LOG(GetLog(LLDBLog::Types),
2038+
"MakeAPValue: Unsupported NTTP type class: {0}",
2039+
clang_type.GetTypeClass());
2040+
2041+
lldbassert(false && "Unsupported type for non-type template parameter");
2042+
2043+
return std::nullopt;
20332044
}
20342045

20352046
bool DWARFASTParserClang::ParseTemplateDIE(
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
3+
include Makefile.rules
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
Test that LLDB correctly distinguishes template specializations
3+
with different pointer-to-member non-type template parameter values.
4+
"""
5+
6+
import lldb
7+
from lldbsuite.test.decorators import *
8+
from lldbsuite.test.lldbtest import *
9+
from lldbsuite.test import lldbutil
10+
11+
12+
class TestCase(TestBase):
13+
@no_debug_info_test
14+
def test(self):
15+
self.build()
16+
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
17+
18+
# Both Data<&S::x> and Data<&S::y> should be resolvable as
19+
# distinct specializations. Without the fix, the second
20+
# specialization is rejected as a duplicate and dy is
21+
# unresolvable.
22+
self.expect_expr("dx", result_type="Data<0>")
23+
self.expect_expr("dy", result_type="Data<4>")
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Test that LLDB correctly distinguishes template specializations with
2+
// different pointer-to-member non-type template parameter values.
3+
//
4+
// When a template takes a pointer-to-member as a non-type parameter
5+
// (e.g., template <int S::*P>), DWARF encodes each instantiation's
6+
// member as a DW_AT_const_value (the byte offset of the member).
7+
// LLDB must treat these as distinct values so that each specialization
8+
// (e.g., Data<&S::x> vs Data<&S::y>) gets its own type in the AST.
9+
//
10+
// Without the fix, MakeAPValue rejects pointer-to-member types,
11+
// causing both specializations to produce identical TemplateArguments.
12+
// findSpecialization then treats the second as a duplicate, so only
13+
// one specialization exists and the other variable becomes unresolvable.
14+
15+
struct S {
16+
int x;
17+
int y;
18+
};
19+
20+
template <int S::*P> struct Data {
21+
int get(S &s) { return s.*P; }
22+
};
23+
24+
Data<&S::x> dx;
25+
Data<&S::y> dy;
26+
27+
int main() {
28+
S s{1, 2};
29+
return dx.get(s) + dy.get(s);
30+
}

0 commit comments

Comments
 (0)