diff options
12 files changed, 211 insertions, 36 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index ef165915969..9d0a08414e9 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -275,17 +275,16 @@ public: bool IsValid() const { if (args.empty()) return false; - return args.size() == names.size(); - } - - size_t GetSize() const { - if (IsValid()) - return args.size(); - return 0; + return args.size() == names.size() && + ((bool)pack_name == (bool)packed_args) && + (!packed_args || !packed_args->packed_args); } llvm::SmallVector<const char *, 2> names; llvm::SmallVector<clang::TemplateArgument, 2> args; + + const char * pack_name = nullptr; + std::unique_ptr<TemplateParameterInfos> packed_args; }; clang::FunctionTemplateDecl * diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile b/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile new file mode 100644 index 00000000000..99bfa7e03b4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py b/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py new file mode 100644 index 00000000000..af362f5be5d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py @@ -0,0 +1,7 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.expectedFailureAll( + oslist=["windows"], bugnumber="llvm.org/pr24764")]) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp new file mode 100644 index 00000000000..90e63b40f41 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp @@ -0,0 +1,61 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LIDENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +template <class T, int... Args> struct C { + T member; + bool isSixteenThirtyTwo() { return false; } +}; + +template <> struct C<int, 16> { + int member; + bool isSixteenThirtyTwo() { return false; } +}; + +template <> struct C<int, 16, 32> : C<int, 16> { + bool isSixteenThirtyTwo() { return true; } +}; + +template <class T, typename... Args> struct D { + T member; + bool isIntBool() { return false; } +}; + +template <> struct D<int, int> { + int member; + bool isIntBool() { return false; } +}; + +template <> struct D<int, int, bool> : D<int, int> { + bool isIntBool() { return true; } +}; + +int main (int argc, char const *argv[]) +{ + C<int,16,32> myC; + C<int,16> myLesserC; + myC.member = 64; + (void)C<int,16,32>().isSixteenThirtyTwo(); + (void)C<int,16>().isSixteenThirtyTwo(); + (void)(myC.member != 64); //% self.expect("expression -- myC", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"]) + //% self.expect("expression -- C<int, 16>().isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) + //% self.expect("expression -- C<int, 16, 32>().isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"]) + //% self.expect("expression -- myLesserC.isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) + //% self.expect("expression -- myC.isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"]) + + D<int,int,bool> myD; + D<int,int> myLesserD; + myD.member = 64; + (void)D<int,int,bool>().isIntBool(); + (void)D<int,int>().isIntBool(); + return myD.member != 64; //% self.expect("expression -- myD", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"]) + //% self.expect("expression -- D<int, int>().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) + //% self.expect("expression -- D<int, int, bool>().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"]) + //% self.expect("expression -- myLesserD.isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) + //% self.expect("expression -- myD.isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"]) +} diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile b/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile new file mode 100644 index 00000000000..99bfa7e03b4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py b/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py new file mode 100644 index 00000000000..810aefee0f0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.expectedFailureAll(bugnumber="rdar://problem/32096064")]) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp new file mode 100644 index 00000000000..e802d40e5f8 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp @@ -0,0 +1,24 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LIDENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +template <class T> int staticSizeof() { + return sizeof(T); +} + +template <class T1, class T2, class... Ts> int staticSizeof() { + return staticSizeof<T2, Ts...>() + sizeof(T1); +} + +int main (int argc, char const *argv[]) +{ + int sz = staticSizeof<long, int, char>(); + return staticSizeof<long, int, char>() != sz; //% self.expect("expression -- sz == staticSizeof<long, int, char>()", "staticSizeof<long, int, char> worked", substrs = ["true"]) + //% self.expect("expression -- sz == staticSizeof<long, int>() + sizeof(char)", "staticSizeof<long, int> worked", substrs = ["true"]) + //% self.expect("expression -- sz == staticSizeof<long>() + sizeof(int) + sizeof(char)", "staticSizeof<long> worked", substrs = ["true"]) +} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 1f78fb96bc3..a3cdfa9d5f1 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1987,8 +1987,33 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, .GetOpaqueDeclContext(); clang::FunctionDecl *src_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(src_decl_context); - - if (src_function_decl) { + if (src_function_decl && + src_function_decl->getTemplateSpecializationInfo()) { + clang::FunctionTemplateDecl *function_template = + src_function_decl->getTemplateSpecializationInfo()->getTemplate(); + clang::FunctionTemplateDecl *copied_function_template = + llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>( + m_ast_importer_sp->CopyDecl(m_ast_context, + src_ast->getASTContext(), + function_template)); + if (copied_function_template) { + if (log) { + ASTDumper ast_dumper((clang::Decl *)copied_function_template); + + StreamString ss; + + function->DumpSymbolContext(&ss); + + log->Printf(" CEDM::FEVD[%u] Imported decl for function template" + " %s (description %s), returned %s", + current_id, + copied_function_template->getNameAsString().c_str(), + ss.GetData(), ast_dumper.GetCString()); + } + + context.AddNamedDecl(copied_function_template); + } + } else if (src_function_decl) { if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( m_ast_importer_sp->CopyDecl(m_ast_context, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 8aec35d09ce..cb00e840673 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1595,24 +1595,17 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, : containing_decl_ctx, type_name_cstr, clang_type, storage, is_inline); - // if (template_param_infos.GetSize() > - // 0) - // { - // clang::FunctionTemplateDecl - // *func_template_decl = - // CreateFunctionTemplateDecl - // (containing_decl_ctx, - // function_decl, - // type_name_cstr, - // template_param_infos); - // - // CreateFunctionTemplateSpecializationInfo - // (function_decl, - // func_template_decl, - // template_param_infos); - // } - // Add the decl to our DIE to decl context map - + if (has_template_params) { + ClangASTContext::TemplateParameterInfos template_param_infos; + ParseTemplateParameterInfos(die, template_param_infos); + clang::FunctionTemplateDecl *func_template_decl = + m_ast.CreateFunctionTemplateDecl( + containing_decl_ctx, function_decl, type_name_cstr, + template_param_infos); + m_ast.CreateFunctionTemplateSpecializationInfo( + function_decl, func_template_decl, template_param_infos); + } + lldbassert(function_decl); if (function_decl) { @@ -1951,6 +1944,19 @@ bool DWARFASTParserClang::ParseTemplateDIE( const dw_tag_t tag = die.Tag(); switch (tag) { + case DW_TAG_GNU_template_parameter_pack: { + template_param_infos.packed_args.reset( + new ClangASTContext::TemplateParameterInfos); + for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); + child_die = child_die.GetSibling()) { + if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args)) + return false; + } + if (const char *name = die.GetName()) { + template_param_infos.pack_name = name; + } + return true; + } case DW_TAG_template_type_parameter: case DW_TAG_template_value_parameter: { DWARFAttributes attributes; @@ -2040,6 +2046,7 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos( switch (tag) { case DW_TAG_template_type_parameter: case DW_TAG_template_value_parameter: + case DW_TAG_GNU_template_parameter_pack: ParseTemplateDIE(die, template_param_infos); break; @@ -3450,6 +3457,7 @@ size_t DWARFASTParserClang::ParseChildParameters( case DW_TAG_template_type_parameter: case DW_TAG_template_value_parameter: + case DW_TAG_GNU_template_parameter_pack: // The one caller of this was never using the template_param_infos, // and the local variable was taking up a large amount of stack space // in SymbolFileDWARF::ParseType() so this was removed. If we ever need diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index e00eda4f35c..022ce5523a0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -1647,6 +1647,8 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, break; case DW_TAG_template_value_parameter: break; + case DW_TAG_GNU_template_parameter_pack: + break; case DW_TAG_thrown_type: break; case DW_TAG_try_block: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp index f0d66720c55..2ff0fe3aac4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -610,6 +610,8 @@ DW_TAG_CategoryEnum get_tag_category(uint16_t tag) { return TagCategoryType; case DW_TAG_template_value_parameter: return TagCategoryType; + case DW_TAG_GNU_template_parameter_pack: + return TagCategoryType; case DW_TAG_thrown_type: return TagCategoryType; case DW_TAG_try_block: diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 8e2576aaec9..d03c5a684a1 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -1394,6 +1394,12 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx, return CompilerType(); } +namespace { + bool IsValueParam(const clang::TemplateArgument &argument) { + return argument.getKind() == TemplateArgument::Integral; + } +} + static TemplateParameterList *CreateTemplateParameterList( ASTContext *ast, const ClangASTContext::TemplateParameterInfos &template_param_infos, @@ -1401,31 +1407,51 @@ static TemplateParameterList *CreateTemplateParameterList( const bool parameter_pack = false; const bool is_typename = false; const unsigned depth = 0; - const size_t num_template_params = template_param_infos.GetSize(); + const size_t num_template_params = template_param_infos.args.size(); + DeclContext *const decl_context = + ast->getTranslationUnitDecl(); // Is this the right decl context?, for (size_t i = 0; i < num_template_params; ++i) { const char *name = template_param_infos.names[i]; IdentifierInfo *identifier_info = nullptr; if (name && name[0]) identifier_info = &ast->Idents.get(name); - if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) { + if (IsValueParam(template_param_infos.args[i])) { template_param_decls.push_back(NonTypeTemplateParmDecl::Create( - *ast, - ast->getTranslationUnitDecl(), // Is this the right decl context?, - // SourceLocation StartLoc, + *ast, decl_context, SourceLocation(), SourceLocation(), depth, i, identifier_info, template_param_infos.args[i].getIntegralType(), parameter_pack, nullptr)); } else { template_param_decls.push_back(TemplateTypeParmDecl::Create( - *ast, - ast->getTranslationUnitDecl(), // Is this the right decl context? + *ast, decl_context, SourceLocation(), SourceLocation(), depth, i, identifier_info, is_typename, parameter_pack)); } } - + + if (template_param_infos.packed_args && + template_param_infos.packed_args->args.size()) { + IdentifierInfo *identifier_info = nullptr; + if (template_param_infos.pack_name && template_param_infos.pack_name[0]) + identifier_info = &ast->Idents.get(template_param_infos.pack_name); + const bool parameter_pack_true = true; + if (IsValueParam(template_param_infos.packed_args->args[0])) { + template_param_decls.push_back(NonTypeTemplateParmDecl::Create( + *ast, decl_context, + SourceLocation(), SourceLocation(), depth, num_template_params, + identifier_info, + template_param_infos.packed_args->args[0].getIntegralType(), + parameter_pack_true, nullptr)); + } else { + template_param_decls.push_back(TemplateTypeParmDecl::Create( + *ast, decl_context, + SourceLocation(), SourceLocation(), depth, num_template_params, + identifier_info, + is_typename, parameter_pack_true)); + } + } clang::Expr *const requires_clause = nullptr; // TODO: Concepts TemplateParameterList *template_param_list = TemplateParameterList::Create( *ast, SourceLocation(), SourceLocation(), template_param_decls, @@ -1535,10 +1561,19 @@ ClangASTContext::CreateClassTemplateSpecializationDecl( DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind, const TemplateParameterInfos &template_param_infos) { ASTContext *ast = getASTContext(); + llvm::SmallVector<clang::TemplateArgument, 2> args( + template_param_infos.args.size() + + (template_param_infos.packed_args ? 1 : 0)); + std::copy(template_param_infos.args.begin(), template_param_infos.args.end(), + args.begin()); + if (template_param_infos.packed_args) { + args[args.size() - 1] = TemplateArgument::CreatePackCopy( + *ast, template_param_infos.packed_args->args); + } ClassTemplateSpecializationDecl *class_template_specialization_decl = ClassTemplateSpecializationDecl::Create( *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), - SourceLocation(), class_template_decl, template_param_infos.args, + SourceLocation(), class_template_decl, args, nullptr); class_template_specialization_decl->setSpecializationKind( |