Index: lldb/trunk/include/lldb/Symbol/ClangASTContext.h =================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTContext.h +++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h @@ -275,17 +275,16 @@ 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 names; llvm::SmallVector args; + + const char * pack_name = nullptr; + std::unique_ptr packed_args; }; clang::FunctionTemplateDecl * Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile +++ lldb/trunk/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 Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py +++ lldb/trunk/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")]) Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp +++ lldb/trunk/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 struct C { + T member; + bool isSixteenThirtyTwo() { return false; } +}; + +template <> struct C { + int member; + bool isSixteenThirtyTwo() { return false; } +}; + +template <> struct C : C { + bool isSixteenThirtyTwo() { return true; } +}; + +template struct D { + T member; + bool isIntBool() { return false; } +}; + +template <> struct D { + int member; + bool isIntBool() { return false; } +}; + +template <> struct D : D { + bool isIntBool() { return true; } +}; + +int main (int argc, char const *argv[]) +{ + C myC; + C myLesserC; + myC.member = 64; + (void)C().isSixteenThirtyTwo(); + (void)C().isSixteenThirtyTwo(); + (void)(myC.member != 64); //% self.expect("expression -- myC", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"]) + //% self.expect("expression -- C().isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) + //% self.expect("expression -- C().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 myD; + D myLesserD; + myD.member = 64; + (void)D().isIntBool(); + (void)D().isIntBool(); + return myD.member != 64; //% self.expect("expression -- myD", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"]) + //% self.expect("expression -- D().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) + //% self.expect("expression -- D().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"]) +} Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile +++ lldb/trunk/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 Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py +++ lldb/trunk/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")]) Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp +++ lldb/trunk/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 int staticSizeof() { + return sizeof(T); +} + +template int staticSizeof() { + return staticSizeof() + sizeof(T1); +} + +int main (int argc, char const *argv[]) +{ + int sz = staticSizeof(); + return staticSizeof() != sz; //% self.expect("expression -- sz == staticSizeof()", "staticSizeof worked", substrs = ["true"]) + //% self.expect("expression -- sz == staticSizeof() + sizeof(char)", "staticSizeof worked", substrs = ["true"]) + //% self.expect("expression -- sz == staticSizeof() + sizeof(int) + sizeof(char)", "staticSizeof worked", substrs = ["true"]) +} Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1987,8 +1987,33 @@ .GetOpaqueDeclContext(); clang::FunctionDecl *src_function_decl = llvm::dyn_cast_or_null(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( + 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( m_ast_importer_sp->CopyDecl(m_ast_context, Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1595,24 +1595,17 @@ : 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 @@ 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 @@ 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 @@ 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 Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -1647,6 +1647,8 @@ 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: Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -610,6 +610,8 @@ 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: Index: lldb/trunk/source/Symbol/ClangASTContext.cpp =================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp +++ lldb/trunk/source/Symbol/ClangASTContext.cpp @@ -1394,6 +1394,12 @@ 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 @@ 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 @@ DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind, const TemplateParameterInfos &template_param_infos) { ASTContext *ast = getASTContext(); + llvm::SmallVector 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(