diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/TestCompletionCrash2.py b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/TestCompletionCrash2.py deleted file mode 100644 --- a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/TestCompletionCrash2.py +++ /dev/null @@ -1,4 +0,0 @@ -from lldbsuite.test import lldbinline -from lldbsuite.test import decorators - -lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIf(bugnumber="rdar://53754063")]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/regression-access-function-template-in-record/TestRegressionAccessFunctionTemplateInRecord.py b/lldb/packages/Python/lldbsuite/test/commands/expression/regression-access-function-template-in-record/TestRegressionAccessFunctionTemplateInRecord.py new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/regression-access-function-template-in-record/TestRegressionAccessFunctionTemplateInRecord.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), []) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/regression-access-function-template-in-record/main.cpp rename from lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/main.cpp rename to lldb/packages/Python/lldbsuite/test/commands/expression/regression-access-function-template-in-record/main.cpp diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -1340,6 +1340,11 @@ // TODO: verify which decl context we should put template_param_decls into.. template_param_decls[i]->setDeclContext(func_decl); } + // Function templates inside a record need to have an access specifier. + // It doesn't matter what access specifier we give the template as LLDB + // anyway allows accessing everything inside a record. + if (decl_ctx->isRecord()) + func_tmpl_decl->setAccess(clang::AccessSpecifier::AS_public); return func_tmpl_decl; } diff --git a/lldb/unittests/Symbol/TestClangASTContext.cpp b/lldb/unittests/Symbol/TestClangASTContext.cpp --- a/lldb/unittests/Symbol/TestClangASTContext.cpp +++ b/lldb/unittests/Symbol/TestClangASTContext.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "TestingSupport/SubsystemRAII.h" +#include "TestingSupport/Symbol/ClangTestUtils.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ClangASTContext.h" @@ -471,3 +472,51 @@ QualType t = ctxt.getTypeOfType(t_base); EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr())); } + +TEST_F(TestClangASTContext, TestFunctionTemplateConstruction) { + // Tests creating a function template. + + CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); + clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); + + // Prepare the declarations/types we need for the template. + CompilerType clang_type = + m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); + FunctionDecl *func = + m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false); + ClangASTContext::TemplateParameterInfos empty_params; + + // Create the actual function template. + clang::FunctionTemplateDecl *func_template = + m_ast->CreateFunctionTemplateDecl(TU, func, "foo", empty_params); + + EXPECT_EQ(TU, func_template->getDeclContext()); + EXPECT_EQ("foo", func_template->getName()); + EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess()); +} + +TEST_F(TestClangASTContext, TestFunctionTemplateInRecordConstruction) { + // Tests creating a function template inside a record. + + CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); + + // Create a record we can put the function template int. + CompilerType record_type = + clang_utils::createRecordWithField(*m_ast, "record", int_type, "field"); + clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type); + + // Prepare the declarations/types we need for the template. + CompilerType clang_type = + m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); + FunctionDecl *func = + m_ast->CreateFunctionDeclaration(record, "foo", clang_type, 0, false); + ClangASTContext::TemplateParameterInfos empty_params; + + // Create the actual function template. + clang::FunctionTemplateDecl *func_template = + m_ast->CreateFunctionTemplateDecl(record, func, "foo", empty_params); + + EXPECT_EQ(record, func_template->getDeclContext()); + EXPECT_EQ("foo", func_template->getName()); + EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess()); +}