diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1944,8 +1944,6 @@ break; } } - if (template_param_infos.args.empty()) - return false; return template_param_infos.args.size() == template_param_infos.names.size(); } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -332,10 +332,11 @@ class TemplateParameterInfos { public: bool IsValid() const { - if (args.empty()) + // Having a pack name but no packed args doesn't make sense, so mark + // these template parameters as invalid. + if (pack_name && !packed_args) return false; return args.size() == names.size() && - ((bool)pack_name == (bool)packed_args) && (!packed_args || !packed_args->packed_args); } diff --git a/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/Makefile b/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/TestClassTemplateNonTypeParameterPack.py b/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/TestClassTemplateNonTypeParameterPack.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/TestClassTemplateNonTypeParameterPack.py @@ -0,0 +1,76 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test(self): + self.build() + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + + self.expect_expr("emptyNonTypePack", result_type="NonTypePack<>", + result_children=[ValueCheck(name="a", type="int")]) + self.expect_expr("oneElemNonTypePack", result_type="NonTypePack<1>", + result_children=[ValueCheck(name="a", type="int")]) + self.expect_expr("twoElemNonTypePack", result_type="NonTypePack<1, 2>", + result_children=[ValueCheck(name="a", type="int")]) + + + self.expect_expr("emptyAnonNonTypePack", result_type="AnonNonTypePack<>", + result_children=[ValueCheck(name="b", type="int")]) + self.expect_expr("oneElemAnonNonTypePack", result_type="AnonNonTypePack<1>", + result_children=[ValueCheck(name="b", type="int")]) + self.expect_expr("twoElemAnonNonTypePack", result_type="AnonNonTypePack<1, 2>", + result_children=[ValueCheck(name="b", type="int")]) + + + self.expect_expr("emptyAnonNonTypePackAfterTypeParam", result_type="AnonNonTypePackAfterTypeParam", + result_children=[ValueCheck(name="c", type="int")]) + self.expect_expr("oneElemAnonNonTypePackAfterTypeParam", result_type="AnonNonTypePackAfterTypeParam", + result_children=[ValueCheck(name="c", type="int")]) + + + + self.expect_expr("emptyAnonNonTypePackAfterAnonTypeParam", result_type="AnonNonTypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="d", type="float")]) + self.expect_expr("oneElemAnonNonTypePackAfterAnonTypeParam", result_type="AnonNonTypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="d", type="float")]) + + + self.expect_expr("emptyNonTypePackAfterAnonTypeParam", result_type="NonTypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="e", type="int")]) + self.expect_expr("oneElemNonTypePackAfterAnonTypeParam", result_type="NonTypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="e", type="int")]) + + + self.expect_expr("emptyNonTypePackAfterTypeParam", result_type="NonTypePackAfterTypeParam", + result_children=[ValueCheck(name="f", type="int")]) + self.expect_expr("oneElemNonTypePackAfterTypeParam", result_type="NonTypePackAfterTypeParam", + result_children=[ValueCheck(name="f", type="int")]) + + self.expect_expr("emptyAnonNonTypePackAfterNonTypeParam", result_type="AnonNonTypePackAfterNonTypeParam<1>", + result_children=[ValueCheck(name="g", type="int")]) + self.expect_expr("oneElemAnonNonTypePackAfterNonTypeParam", result_type="AnonNonTypePackAfterNonTypeParam<1, 2>", + result_children=[ValueCheck(name="g", type="int")]) + + + self.expect_expr("emptyAnonNonTypePackAfterAnonNonTypeParam", result_type="AnonNonTypePackAfterAnonNonTypeParam<1>", + result_children=[ValueCheck(name="h", type="float")]) + self.expect_expr("oneElemAnonNonTypePackAfterAnonNonTypeParam", result_type="AnonNonTypePackAfterAnonNonTypeParam<1, 2>", + result_children=[ValueCheck(name="h", type="float")]) + + + self.expect_expr("emptyNonTypePackAfterAnonNonTypeParam", result_type="NonTypePackAfterAnonNonTypeParam<1>", + result_children=[ValueCheck(name="i", type="int")]) + self.expect_expr("oneElemNonTypePackAfterAnonNonTypeParam", result_type="NonTypePackAfterAnonNonTypeParam<1, 2>", + result_children=[ValueCheck(name="i", type="int")]) + + + self.expect_expr("emptyNonTypePackAfterNonTypeParam", result_type="NonTypePackAfterNonTypeParam<1>", + result_children=[ValueCheck(name="j", type="int")]) + self.expect_expr("oneElemNonTypePackAfterNonTypeParam", result_type="NonTypePackAfterNonTypeParam<1, 2>", + result_children=[ValueCheck(name="j", type="int")]) \ No newline at end of file diff --git a/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/main.cpp b/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/class-template-non-type-parameter-pack/main.cpp @@ -0,0 +1,69 @@ +// Named type parameter pack. +template +struct NonTypePack { int a; }; +NonTypePack<> emptyNonTypePack; +NonTypePack<1> oneElemNonTypePack; +NonTypePack<1, 2> twoElemNonTypePack; + +// Unnamed type parameter pack. +template +struct AnonNonTypePack { int b; }; +AnonNonTypePack<> emptyAnonNonTypePack; +AnonNonTypePack<1> oneElemAnonNonTypePack; +AnonNonTypePack<1, 2> twoElemAnonNonTypePack; + +// Test type parameter packs combined with non-pack type template parameters. + +// Unnamed non-type parameter pack behind a named type parameter. +template +struct AnonNonTypePackAfterTypeParam { T c; }; +AnonNonTypePackAfterTypeParam emptyAnonNonTypePackAfterTypeParam; +AnonNonTypePackAfterTypeParam oneElemAnonNonTypePackAfterTypeParam; + +// Unnamed non-type parameter pack behind an unnamed type parameter. +template +struct AnonNonTypePackAfterAnonTypeParam { float d; }; +AnonNonTypePackAfterAnonTypeParam emptyAnonNonTypePackAfterAnonTypeParam; +AnonNonTypePackAfterAnonTypeParam oneElemAnonNonTypePackAfterAnonTypeParam; + +// Named non-type parameter pack behind an unnamed type parameter. +template +struct NonTypePackAfterAnonTypeParam { int e; }; +NonTypePackAfterAnonTypeParam emptyNonTypePackAfterAnonTypeParam; +NonTypePackAfterAnonTypeParam oneElemNonTypePackAfterAnonTypeParam; + +// Named non-type parameter pack behind a named type parameter. +template +struct NonTypePackAfterTypeParam { int f; }; +NonTypePackAfterTypeParam emptyNonTypePackAfterTypeParam; +NonTypePackAfterTypeParam oneElemNonTypePackAfterTypeParam; + +// Test non-type parameter packs combined with non-pack non-type template parameters. + +// Unnamed non-type parameter pack behind a named non-type parameter. +template +struct AnonNonTypePackAfterNonTypeParam { int g; }; +AnonNonTypePackAfterNonTypeParam<1> emptyAnonNonTypePackAfterNonTypeParam; +AnonNonTypePackAfterNonTypeParam<1, 2> oneElemAnonNonTypePackAfterNonTypeParam; + +// Unnamed non-type parameter pack behind an unnamed non-type parameter. +template +struct AnonNonTypePackAfterAnonNonTypeParam { float h; }; +AnonNonTypePackAfterAnonNonTypeParam<1> emptyAnonNonTypePackAfterAnonNonTypeParam; +AnonNonTypePackAfterAnonNonTypeParam<1, 2> oneElemAnonNonTypePackAfterAnonNonTypeParam; + +// Named non-type parameter pack behind an unnamed non-type parameter. +template +struct NonTypePackAfterAnonNonTypeParam { int i; }; +NonTypePackAfterAnonNonTypeParam<1> emptyNonTypePackAfterAnonNonTypeParam; +NonTypePackAfterAnonNonTypeParam<1, 2> oneElemNonTypePackAfterAnonNonTypeParam; + +// Named non-type parameter pack behind an unnamed non-type parameter. +template +struct NonTypePackAfterNonTypeParam { int j; }; +NonTypePackAfterNonTypeParam<1> emptyNonTypePackAfterNonTypeParam; +NonTypePackAfterNonTypeParam<1, 2> oneElemNonTypePackAfterNonTypeParam; + +int main() { + return 0; // break here +} diff --git a/lldb/test/API/lang/cpp/class-template-type-parameter-pack/Makefile b/lldb/test/API/lang/cpp/class-template-type-parameter-pack/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/class-template-type-parameter-pack/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/class-template-type-parameter-pack/TestClassTemplateTypeParameterPack.py b/lldb/test/API/lang/cpp/class-template-type-parameter-pack/TestClassTemplateTypeParameterPack.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/class-template-type-parameter-pack/TestClassTemplateTypeParameterPack.py @@ -0,0 +1,76 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test(self): + self.build() + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + + self.expect_expr("emptyTypePack", result_type="TypePack<>", + result_children=[ValueCheck(name="a", type="int")]) + self.expect_expr("oneElemTypePack", result_type="TypePack", + result_children=[ValueCheck(name="a", type="int")]) + self.expect_expr("twoElemTypePack", result_type="TypePack", + result_children=[ValueCheck(name="a", type="int")]) + + + self.expect_expr("emptyAnonTypePack", result_type="AnonTypePack<>", + result_children=[ValueCheck(name="b", type="int")]) + self.expect_expr("oneElemAnonTypePack", result_type="AnonTypePack", + result_children=[ValueCheck(name="b", type="int")]) + self.expect_expr("twoElemAnonTypePack", result_type="AnonTypePack", + result_children=[ValueCheck(name="b", type="int")]) + + + self.expect_expr("emptyAnonTypePackAfterTypeParam", result_type="AnonTypePackAfterTypeParam", + result_children=[ValueCheck(name="c", type="int")]) + self.expect_expr("oneElemAnonTypePackAfterTypeParam", result_type="AnonTypePackAfterTypeParam", + result_children=[ValueCheck(name="c", type="int")]) + + + + self.expect_expr("emptyAnonTypePackAfterAnonTypeParam", result_type="AnonTypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="d", type="float")]) + self.expect_expr("oneElemAnonTypePackAfterAnonTypeParam", result_type="AnonTypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="d", type="float")]) + + + self.expect_expr("emptyTypePackAfterAnonTypeParam", result_type="TypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="e", type="int")]) + self.expect_expr("oneElemTypePackAfterAnonTypeParam", result_type="TypePackAfterAnonTypeParam", + result_children=[ValueCheck(name="e", type="int")]) + + + self.expect_expr("emptyTypePackAfterTypeParam", result_type="TypePackAfterTypeParam", + result_children=[ValueCheck(name="f", type="int")]) + self.expect_expr("oneElemTypePackAfterTypeParam", result_type="TypePackAfterTypeParam", + result_children=[ValueCheck(name="f", type="int")]) + + self.expect_expr("emptyAnonTypePackAfterNonTypeParam", result_type="AnonTypePackAfterNonTypeParam<1>", + result_children=[ValueCheck(name="g", type="int")]) + self.expect_expr("oneElemAnonTypePackAfterNonTypeParam", result_type="AnonTypePackAfterNonTypeParam<1, int>", + result_children=[ValueCheck(name="g", type="int")]) + + + self.expect_expr("emptyAnonTypePackAfterAnonNonTypeParam", result_type="AnonTypePackAfterAnonNonTypeParam<1>", + result_children=[ValueCheck(name="h", type="float")]) + self.expect_expr("oneElemAnonTypePackAfterAnonNonTypeParam", result_type="AnonTypePackAfterAnonNonTypeParam<1, int>", + result_children=[ValueCheck(name="h", type="float")]) + + + self.expect_expr("emptyTypePackAfterAnonNonTypeParam", result_type="TypePackAfterAnonNonTypeParam<1>", + result_children=[ValueCheck(name="i", type="int")]) + self.expect_expr("oneElemTypePackAfterAnonNonTypeParam", result_type="TypePackAfterAnonNonTypeParam<1, int>", + result_children=[ValueCheck(name="i", type="int")]) + + + self.expect_expr("emptyTypePackAfterNonTypeParam", result_type="TypePackAfterNonTypeParam<1>", + result_children=[ValueCheck(name="j", type="int")]) + self.expect_expr("oneElemTypePackAfterNonTypeParam", result_type="TypePackAfterNonTypeParam<1, int>", + result_children=[ValueCheck(name="j", type="int")]) \ No newline at end of file diff --git a/lldb/test/API/lang/cpp/class-template-type-parameter-pack/main.cpp b/lldb/test/API/lang/cpp/class-template-type-parameter-pack/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/class-template-type-parameter-pack/main.cpp @@ -0,0 +1,69 @@ +// Named type parameter pack. +template +struct TypePack { int a; }; +TypePack<> emptyTypePack; +TypePack oneElemTypePack; +TypePack twoElemTypePack; + +// Unnamed type parameter pack. +template +struct AnonTypePack { int b; }; +AnonTypePack<> emptyAnonTypePack; +AnonTypePack oneElemAnonTypePack; +AnonTypePack twoElemAnonTypePack; + +// Test type parameter packs combined with non-pack type template parameters. + +// Unnamed type parameter pack behind a named type parameter. +template +struct AnonTypePackAfterTypeParam { T c; }; +AnonTypePackAfterTypeParam emptyAnonTypePackAfterTypeParam; +AnonTypePackAfterTypeParam oneElemAnonTypePackAfterTypeParam; + +// Unnamed type parameter pack behind an unnamed type parameter. +template +struct AnonTypePackAfterAnonTypeParam { float d; }; +AnonTypePackAfterAnonTypeParam emptyAnonTypePackAfterAnonTypeParam; +AnonTypePackAfterAnonTypeParam oneElemAnonTypePackAfterAnonTypeParam; + +// Named type parameter pack behind an unnamed type parameter. +template +struct TypePackAfterAnonTypeParam { int e; }; +TypePackAfterAnonTypeParam emptyTypePackAfterAnonTypeParam; +TypePackAfterAnonTypeParam oneElemTypePackAfterAnonTypeParam; + +// Named type parameter pack behind a named type parameter. +template +struct TypePackAfterTypeParam { int f; }; +TypePackAfterTypeParam emptyTypePackAfterTypeParam; +TypePackAfterTypeParam oneElemTypePackAfterTypeParam; + +// Test type parameter packs combined with non-pack non-type template parameters. + +// Unnamed type parameter pack behind a named type parameter. +template +struct AnonTypePackAfterNonTypeParam { int g; }; +AnonTypePackAfterNonTypeParam<1> emptyAnonTypePackAfterNonTypeParam; +AnonTypePackAfterNonTypeParam<1, int> oneElemAnonTypePackAfterNonTypeParam; + +// Unnamed type parameter pack behind an unnamed type parameter. +template +struct AnonTypePackAfterAnonNonTypeParam { float h; }; +AnonTypePackAfterAnonNonTypeParam<1> emptyAnonTypePackAfterAnonNonTypeParam; +AnonTypePackAfterAnonNonTypeParam<1, int> oneElemAnonTypePackAfterAnonNonTypeParam; + +// Named type parameter pack behind an unnamed type parameter. +template +struct TypePackAfterAnonNonTypeParam { int i; }; +TypePackAfterAnonNonTypeParam<1> emptyTypePackAfterAnonNonTypeParam; +TypePackAfterAnonNonTypeParam<1, int> oneElemTypePackAfterAnonNonTypeParam; + +// Named type parameter pack behind an unnamed type parameter. +template +struct TypePackAfterNonTypeParam { int j; }; +TypePackAfterNonTypeParam<1> emptyTypePackAfterNonTypeParam; +TypePackAfterNonTypeParam<1, int> oneElemTypePackAfterNonTypeParam; + +int main() { + return 0; // break here +} diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -516,6 +516,12 @@ } } +TEST_F(TestTypeSystemClang, OnlyPackName) { + TypeSystemClang::TemplateParameterInfos infos; + infos.pack_name = "A"; + EXPECT_FALSE(infos.IsValid()); +} + static QualType makeConstInt(clang::ASTContext &ctxt) { QualType result(ctxt.IntTy); result.addConst();