// Copyright 2018 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "absl/debugging/internal/demangle.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" #include "absl/debugging/internal/stack_consumption.h" #include "absl/log/log.h" #include "absl/memory/memory.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace debugging_internal { namespace { using ::testing::ContainsRegex; TEST(Demangle, FunctionTemplate) { char tmp[100]; // template // int foo(T); // // foo(5); ASSERT_TRUE(Demangle("_Z3fooIiEiT_", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionTemplateWithNesting) { char tmp[100]; // template // int foo(T); // // foo>({ .value = 5 }); ASSERT_TRUE(Demangle("_Z3fooI7WrapperIiEEiT_", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionTemplateWithNonTypeParamConstraint) { char tmp[100]; // template // int foo(T); // // foo(5); ASSERT_TRUE(Demangle("_Z3fooITkSt8integraliEiT_", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionTemplateWithFunctionRequiresClause) { char tmp[100]; // template // int foo() requires std::integral; // // foo(); ASSERT_TRUE(Demangle("_Z3fooIiEivQsr3stdE8integralIT_E", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionWithTemplateParamRequiresClause) { char tmp[100]; // template // requires std::integral // int foo(); // // foo(); ASSERT_TRUE(Demangle("_Z3fooIiQsr3stdE8integralIT_EEiv", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionWithTemplateParamAndFunctionRequiresClauses) { char tmp[100]; // template // requires std::integral // int foo() requires std::integral; // // foo(); ASSERT_TRUE(Demangle("_Z3fooIiQsr3stdE8integralIT_EEivQsr3stdE8integralIS0_E", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionTemplateBacktracksOnMalformedRequiresClause) { char tmp[100]; // template // int foo(T); // // foo(5); // Except there's an extra `Q` where the mangled requires clause would be. ASSERT_FALSE(Demangle("_Z3fooIiQEiT_", tmp, sizeof(tmp))); } TEST(Demangle, FunctionTemplateWithAutoParam) { char tmp[100]; // template // void foo(); // // foo<1>(); ASSERT_TRUE(Demangle("_Z3fooITnDaLi1EEvv", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionTemplateWithNonTypeParamPack) { char tmp[100]; // template // void foo(T); // // foo(2); ASSERT_TRUE(Demangle("_Z3fooITpTnRiJEiEvT0_", tmp, sizeof(tmp))); EXPECT_STREQ(tmp, "foo<>()"); } TEST(Demangle, FunctionTemplateTemplateParamWithConstrainedArg) { char tmp[100]; // template // concept True = true; // // template requires True // struct Fooer {}; // // template