summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Dino Radakovic <dinor@google.com>2024-02-07 07:26:02 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2024-02-07 07:27:17 -0800
commite22f9c1fdd00f2ad3cfdd1dd7a67145eadc3b21c (patch)
tree698b11b97dffb06cbaada007a0606f0d356875a4
parent563c86a80c06ffbbfaa2ea792a9c255a5c258cf0 (diff)
`demangle`: Implement parsing for simplest constrained template arguments
C++20 introduced constraints, where concepts such as `std::integral` can be used to restrict template parameters: ``` template <std::integral T> int foo(T t); // Only accepts integral types. ``` Clang mangles these starting with a prefix `Tk`, followed by the concept name, which mangles as a type. For example, compare `foo` and `bar` here: https://godbolt.org/z/Kzbrrchde Note that this implementation doesn't cover the more complex case where the concept is templated too. See [llvm's implementation](https://github.com/llvm/llvm-project/commit/4b163e343cfa54c8d55c9da73c70d58f55ea9df2) and its tests for a thorough version. PiperOrigin-RevId: 604976260 Change-Id: Ic116c5f6f27c3f7714638bdee8de11dce871f0be
-rw-r--r--absl/debugging/internal/demangle.cc9
-rw-r--r--absl/debugging/internal/demangle_test.cc33
2 files changed, 42 insertions, 0 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 381a2b50..3ef21581 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1461,6 +1461,9 @@ static bool ParseTemplateArgs(State *state) {
// ::= <expr-primary>
// ::= J <template-arg>* E # argument pack
// ::= X <expression> E
+// ::= Tk <type> <type> # constraint
+//
+// TODO(b/323420445): Support templated constraints.
static bool ParseTemplateArg(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
@@ -1560,6 +1563,12 @@ static bool ParseTemplateArg(State *state) {
return true;
}
state->parse_state = copy;
+
+ if (ParseTwoCharToken(state, "Tk") && ParseType(state) && ParseType(state)) {
+ return true;
+ }
+ state->parse_state = copy;
+
return false;
}
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index a16ab75e..c1b61253 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -31,6 +31,39 @@ namespace {
using ::testing::ContainsRegex;
+TEST(Demangle, FunctionTemplate) {
+ char tmp[100];
+
+ // template <typename T>
+ // int foo(T);
+ //
+ // foo<int>(5);
+ ASSERT_TRUE(Demangle("_Z3fooIiEiT_", tmp, sizeof(tmp)));
+ EXPECT_STREQ(tmp, "foo<>()");
+}
+
+TEST(Demangle, FunctionTemplateWithNesting) {
+ char tmp[100];
+
+ // template <typename T>
+ // int foo(T);
+ //
+ // foo<Wrapper<int>>({ .value = 5 });
+ ASSERT_TRUE(Demangle("_Z3fooI7WrapperIiEEiT_", tmp, sizeof(tmp)));
+ EXPECT_STREQ(tmp, "foo<>()");
+}
+
+TEST(Demangle, FunctionTemplateWithConstraint) {
+ char tmp[100];
+
+ // template <std::integral T>
+ // int foo(T);
+ //
+ // foo<Wrapper<int>(5);
+ ASSERT_TRUE(Demangle("_Z3fooITkSt8integraliEiT_", tmp, sizeof(tmp)));
+ EXPECT_STREQ(tmp, "foo<>()");
+}
+
// Test corner cases of boundary conditions.
TEST(Demangle, CornerCases) {
char tmp[10];