Changeset View
Changeset View
Standalone View
Standalone View
lldb/unittests/Symbol/TestTypeSystemClang.cpp
//===-- TestTypeSystemClang.cpp -------------------------------------------===// | //===-- TestTypeSystemClang.cpp -------------------------------------------===// | ||||
// | // | ||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
// See https://llvm.org/LICENSE.txt for license information. | // See https://llvm.org/LICENSE.txt for license information. | ||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "Plugins/ExpressionParser/Clang/ClangUtil.h" | #include "Plugins/ExpressionParser/Clang/ClangUtil.h" | ||||
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" | ||||
#include "TestingSupport/SubsystemRAII.h" | #include "TestingSupport/SubsystemRAII.h" | ||||
#include "TestingSupport/Symbol/ClangTestUtils.h" | #include "TestingSupport/Symbol/ClangTestUtils.h" | ||||
#include "lldb/Host/FileSystem.h" | #include "lldb/Host/FileSystem.h" | ||||
#include "lldb/Host/HostInfo.h" | #include "lldb/Host/HostInfo.h" | ||||
#include "lldb/Symbol/Declaration.h" | #include "lldb/Symbol/Declaration.h" | ||||
#include "clang/AST/DeclCXX.h" | #include "clang/AST/DeclCXX.h" | ||||
#include "clang/AST/DeclObjC.h" | |||||
#include "clang/AST/ExprCXX.h" | #include "clang/AST/ExprCXX.h" | ||||
#include "gtest/gtest.h" | #include "gtest/gtest.h" | ||||
using namespace clang; | using namespace clang; | ||||
using namespace lldb; | using namespace lldb; | ||||
using namespace lldb_private; | using namespace lldb_private; | ||||
class TestTypeSystemClang : public testing::Test { | class TestTypeSystemClang : public testing::Test { | ||||
▲ Show 20 Lines • Show All 228 Lines • ▼ Show 20 Lines | for (bool scoped : {true, false}) { | ||||
for (lldb::BasicType basic_type : types_to_test) { | for (lldb::BasicType basic_type : types_to_test) { | ||||
SCOPED_TRACE(std::to_string(basic_type)); | SCOPED_TRACE(std::to_string(basic_type)); | ||||
TypeSystemClang ast("enum_ast", HostInfo::GetTargetTriple()); | TypeSystemClang ast("enum_ast", HostInfo::GetTargetTriple()); | ||||
CompilerType basic_compiler_type = ast.GetBasicType(basic_type); | CompilerType basic_compiler_type = ast.GetBasicType(basic_type); | ||||
EXPECT_TRUE(basic_compiler_type.IsValid()); | EXPECT_TRUE(basic_compiler_type.IsValid()); | ||||
CompilerType enum_type = | CompilerType enum_type = | ||||
ast.CreateEnumerationType("my_enum", ast.GetTranslationUnitDecl(), | ast.CreateEnumerationType("my_enum", ast.GetTranslationUnitDecl(), 0, | ||||
Declaration(), basic_compiler_type, scoped); | Declaration(), basic_compiler_type, scoped); | ||||
CompilerType t = ast.GetEnumerationIntegerType(enum_type); | CompilerType t = ast.GetEnumerationIntegerType(enum_type); | ||||
// Check that the type we put in at the start is found again. | // Check that the type we put in at the start is found again. | ||||
EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName()); | EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName()); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
TEST_F(TestTypeSystemClang, TestOwningModule) { | |||||
TypeSystemClang ast("module_ast", HostInfo::GetTargetTriple()); | |||||
CompilerType basic_compiler_type = ast.GetBasicType(BasicType::eBasicTypeInt); | |||||
CompilerType enum_type = | |||||
ast.CreateEnumerationType("my_enum", ast.GetTranslationUnitDecl(), 100, | |||||
Declaration(), basic_compiler_type, false); | |||||
auto *ed = TypeSystemClang::GetAsEnumDecl(enum_type); | |||||
EXPECT_FALSE(!ed); | |||||
EXPECT_EQ(ed->getOwningModuleID(), 100u); | |||||
CompilerType record_type = ast.CreateRecordType( | |||||
nullptr, 200, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, | |||||
lldb::eLanguageTypeC_plus_plus, nullptr); | |||||
auto *rd = TypeSystemClang::GetAsRecordDecl(record_type); | |||||
EXPECT_FALSE(!rd); | |||||
EXPECT_EQ(rd->getOwningModuleID(), 200u); | |||||
CompilerType class_type = ast.CreateObjCClass( | |||||
"objc_class", ast.GetTranslationUnitDecl(), 300, false, false); | |||||
auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(class_type); | |||||
EXPECT_FALSE(!cd); | |||||
EXPECT_EQ(cd->getOwningModuleID(), 300u); | |||||
} | |||||
TEST_F(TestTypeSystemClang, TestIsClangType) { | TEST_F(TestTypeSystemClang, TestIsClangType) { | ||||
clang::ASTContext &context = m_ast->getASTContext(); | clang::ASTContext &context = m_ast->getASTContext(); | ||||
lldb::opaque_compiler_type_t bool_ctype = | lldb::opaque_compiler_type_t bool_ctype = | ||||
TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool); | TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool); | ||||
CompilerType bool_type(m_ast.get(), bool_ctype); | CompilerType bool_type(m_ast.get(), bool_ctype); | ||||
CompilerType record_type = m_ast->CreateRecordType( | CompilerType record_type = m_ast->CreateRecordType( | ||||
nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, | nullptr, 100, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, | ||||
lldb::eLanguageTypeC_plus_plus, nullptr); | lldb::eLanguageTypeC_plus_plus, nullptr); | ||||
// Clang builtin type and record type should pass | // Clang builtin type and record type should pass | ||||
EXPECT_TRUE(ClangUtil::IsClangType(bool_type)); | EXPECT_TRUE(ClangUtil::IsClangType(bool_type)); | ||||
EXPECT_TRUE(ClangUtil::IsClangType(record_type)); | EXPECT_TRUE(ClangUtil::IsClangType(record_type)); | ||||
// Default constructed type should fail | // Default constructed type should fail | ||||
EXPECT_FALSE(ClangUtil::IsClangType(CompilerType())); | EXPECT_FALSE(ClangUtil::IsClangType(CompilerType())); | ||||
} | } | ||||
TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) { | TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) { | ||||
CompilerType record_type = m_ast->CreateRecordType( | CompilerType record_type = m_ast->CreateRecordType( | ||||
nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, | nullptr, 0, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, | ||||
lldb::eLanguageTypeC_plus_plus, nullptr); | lldb::eLanguageTypeC_plus_plus, nullptr); | ||||
QualType qt; | QualType qt; | ||||
qt = ClangUtil::GetQualType(record_type); | qt = ClangUtil::GetQualType(record_type); | ||||
EXPECT_EQ(0u, qt.getLocalFastQualifiers()); | EXPECT_EQ(0u, qt.getLocalFastQualifiers()); | ||||
record_type = record_type.AddConstModifier(); | record_type = record_type.AddConstModifier(); | ||||
record_type = record_type.AddVolatileModifier(); | record_type = record_type.AddVolatileModifier(); | ||||
record_type = record_type.AddRestrictModifier(); | record_type = record_type.AddRestrictModifier(); | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | EXPECT_EQ(AS_none, | ||||
TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_none)); | TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_none)); | ||||
} | } | ||||
TEST_F(TestTypeSystemClang, TestRecordHasFields) { | TEST_F(TestTypeSystemClang, TestRecordHasFields) { | ||||
CompilerType int_type = m_ast->GetBasicType(eBasicTypeInt); | CompilerType int_type = m_ast->GetBasicType(eBasicTypeInt); | ||||
// Test that a record with no fields returns false | // Test that a record with no fields returns false | ||||
CompilerType empty_base = m_ast->CreateRecordType( | CompilerType empty_base = m_ast->CreateRecordType( | ||||
nullptr, lldb::eAccessPublic, "EmptyBase", clang::TTK_Struct, | nullptr, 0, lldb::eAccessPublic, "EmptyBase", clang::TTK_Struct, | ||||
lldb::eLanguageTypeC_plus_plus, nullptr); | lldb::eLanguageTypeC_plus_plus, nullptr); | ||||
TypeSystemClang::StartTagDeclarationDefinition(empty_base); | TypeSystemClang::StartTagDeclarationDefinition(empty_base); | ||||
TypeSystemClang::CompleteTagDeclarationDefinition(empty_base); | TypeSystemClang::CompleteTagDeclarationDefinition(empty_base); | ||||
RecordDecl *empty_base_decl = TypeSystemClang::GetAsRecordDecl(empty_base); | RecordDecl *empty_base_decl = TypeSystemClang::GetAsRecordDecl(empty_base); | ||||
EXPECT_NE(nullptr, empty_base_decl); | EXPECT_NE(nullptr, empty_base_decl); | ||||
EXPECT_FALSE(TypeSystemClang::RecordHasFields(empty_base_decl)); | EXPECT_FALSE(TypeSystemClang::RecordHasFields(empty_base_decl)); | ||||
// Test that a record with direct fields returns true | // Test that a record with direct fields returns true | ||||
CompilerType non_empty_base = m_ast->CreateRecordType( | CompilerType non_empty_base = m_ast->CreateRecordType( | ||||
nullptr, lldb::eAccessPublic, "NonEmptyBase", clang::TTK_Struct, | nullptr, 0, lldb::eAccessPublic, "NonEmptyBase", clang::TTK_Struct, | ||||
lldb::eLanguageTypeC_plus_plus, nullptr); | lldb::eLanguageTypeC_plus_plus, nullptr); | ||||
TypeSystemClang::StartTagDeclarationDefinition(non_empty_base); | TypeSystemClang::StartTagDeclarationDefinition(non_empty_base); | ||||
FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType( | FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType( | ||||
non_empty_base, "MyField", int_type, eAccessPublic, 0); | non_empty_base, "MyField", int_type, eAccessPublic, 0); | ||||
TypeSystemClang::CompleteTagDeclarationDefinition(non_empty_base); | TypeSystemClang::CompleteTagDeclarationDefinition(non_empty_base); | ||||
RecordDecl *non_empty_base_decl = | RecordDecl *non_empty_base_decl = | ||||
TypeSystemClang::GetAsRecordDecl(non_empty_base); | TypeSystemClang::GetAsRecordDecl(non_empty_base); | ||||
EXPECT_NE(nullptr, non_empty_base_decl); | EXPECT_NE(nullptr, non_empty_base_decl); | ||||
EXPECT_NE(nullptr, non_empty_base_field_decl); | EXPECT_NE(nullptr, non_empty_base_field_decl); | ||||
EXPECT_TRUE(TypeSystemClang::RecordHasFields(non_empty_base_decl)); | EXPECT_TRUE(TypeSystemClang::RecordHasFields(non_empty_base_decl)); | ||||
std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; | std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; | ||||
// Test that a record with no direct fields, but fields in a base returns true | // Test that a record with no direct fields, but fields in a base returns true | ||||
CompilerType empty_derived = m_ast->CreateRecordType( | CompilerType empty_derived = m_ast->CreateRecordType( | ||||
nullptr, lldb::eAccessPublic, "EmptyDerived", clang::TTK_Struct, | nullptr, 0, lldb::eAccessPublic, "EmptyDerived", clang::TTK_Struct, | ||||
lldb::eLanguageTypeC_plus_plus, nullptr); | lldb::eLanguageTypeC_plus_plus, nullptr); | ||||
TypeSystemClang::StartTagDeclarationDefinition(empty_derived); | TypeSystemClang::StartTagDeclarationDefinition(empty_derived); | ||||
std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec = | std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec = | ||||
m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(), | m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(), | ||||
lldb::eAccessPublic, false, false); | lldb::eAccessPublic, false, false); | ||||
bases.push_back(std::move(non_empty_base_spec)); | bases.push_back(std::move(non_empty_base_spec)); | ||||
bool result = m_ast->TransferBaseClasses(empty_derived.GetOpaqueQualType(), | bool result = m_ast->TransferBaseClasses(empty_derived.GetOpaqueQualType(), | ||||
std::move(bases)); | std::move(bases)); | ||||
TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived); | TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived); | ||||
EXPECT_TRUE(result); | EXPECT_TRUE(result); | ||||
CXXRecordDecl *empty_derived_non_empty_base_cxx_decl = | CXXRecordDecl *empty_derived_non_empty_base_cxx_decl = | ||||
m_ast->GetAsCXXRecordDecl(empty_derived.GetOpaqueQualType()); | m_ast->GetAsCXXRecordDecl(empty_derived.GetOpaqueQualType()); | ||||
RecordDecl *empty_derived_non_empty_base_decl = | RecordDecl *empty_derived_non_empty_base_decl = | ||||
TypeSystemClang::GetAsRecordDecl(empty_derived); | TypeSystemClang::GetAsRecordDecl(empty_derived); | ||||
EXPECT_EQ(1u, TypeSystemClang::GetNumBaseClasses( | EXPECT_EQ(1u, TypeSystemClang::GetNumBaseClasses( | ||||
empty_derived_non_empty_base_cxx_decl, false)); | empty_derived_non_empty_base_cxx_decl, false)); | ||||
EXPECT_TRUE( | EXPECT_TRUE( | ||||
TypeSystemClang::RecordHasFields(empty_derived_non_empty_base_decl)); | TypeSystemClang::RecordHasFields(empty_derived_non_empty_base_decl)); | ||||
// Test that a record with no direct fields, but fields in a virtual base | // Test that a record with no direct fields, but fields in a virtual base | ||||
// returns true | // returns true | ||||
CompilerType empty_derived2 = m_ast->CreateRecordType( | CompilerType empty_derived2 = m_ast->CreateRecordType( | ||||
nullptr, lldb::eAccessPublic, "EmptyDerived2", clang::TTK_Struct, | nullptr, 0, lldb::eAccessPublic, "EmptyDerived2", clang::TTK_Struct, | ||||
lldb::eLanguageTypeC_plus_plus, nullptr); | lldb::eLanguageTypeC_plus_plus, nullptr); | ||||
TypeSystemClang::StartTagDeclarationDefinition(empty_derived2); | TypeSystemClang::StartTagDeclarationDefinition(empty_derived2); | ||||
std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec = | std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec = | ||||
m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(), | m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(), | ||||
lldb::eAccessPublic, true, false); | lldb::eAccessPublic, true, false); | ||||
bases.push_back(std::move(non_empty_vbase_spec)); | bases.push_back(std::move(non_empty_vbase_spec)); | ||||
result = m_ast->TransferBaseClasses(empty_derived2.GetOpaqueQualType(), | result = m_ast->TransferBaseClasses(empty_derived2.GetOpaqueQualType(), | ||||
std::move(bases)); | std::move(bases)); | ||||
Show All 15 Lines | TEST_F(TestTypeSystemClang, TemplateArguments) { | ||||
infos.args.push_back(TemplateArgument(m_ast->getASTContext().IntTy)); | infos.args.push_back(TemplateArgument(m_ast->getASTContext().IntTy)); | ||||
infos.names.push_back("I"); | infos.names.push_back("I"); | ||||
llvm::APSInt arg(llvm::APInt(8, 47)); | llvm::APSInt arg(llvm::APInt(8, 47)); | ||||
infos.args.push_back(TemplateArgument(m_ast->getASTContext(), arg, | infos.args.push_back(TemplateArgument(m_ast->getASTContext(), arg, | ||||
m_ast->getASTContext().IntTy)); | m_ast->getASTContext().IntTy)); | ||||
// template<typename T, int I> struct foo; | // template<typename T, int I> struct foo; | ||||
ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl( | ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl( | ||||
m_ast->GetTranslationUnitDecl(), eAccessPublic, "foo", TTK_Struct, infos); | m_ast->GetTranslationUnitDecl(), 0, eAccessPublic, "foo", | ||||
TTK_Struct, infos); | |||||
ASSERT_NE(decl, nullptr); | ASSERT_NE(decl, nullptr); | ||||
// foo<int, 47> | // foo<int, 47> | ||||
ClassTemplateSpecializationDecl *spec_decl = | ClassTemplateSpecializationDecl *spec_decl = | ||||
m_ast->CreateClassTemplateSpecializationDecl( | m_ast->CreateClassTemplateSpecializationDecl( | ||||
m_ast->GetTranslationUnitDecl(), decl, TTK_Struct, infos); | m_ast->GetTranslationUnitDecl(), 0, decl, TTK_Struct, infos); | ||||
ASSERT_NE(spec_decl, nullptr); | ASSERT_NE(spec_decl, nullptr); | ||||
CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl); | CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl); | ||||
ASSERT_TRUE(type); | ASSERT_TRUE(type); | ||||
m_ast->StartTagDeclarationDefinition(type); | m_ast->StartTagDeclarationDefinition(type); | ||||
m_ast->CompleteTagDeclarationDefinition(type); | m_ast->CompleteTagDeclarationDefinition(type); | ||||
// typedef foo<int, 47> foo_def; | // typedef foo<int, 47> foo_def; | ||||
CompilerType typedef_type = m_ast->CreateTypedefType( | CompilerType typedef_type = m_ast->CreateTypedefType( | ||||
type, "foo_def", m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl())); | type, "foo_def", | ||||
m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), 0); | |||||
CompilerType auto_type( | CompilerType auto_type( | ||||
m_ast.get(), | m_ast.get(), | ||||
m_ast->getASTContext() | m_ast->getASTContext() | ||||
.getAutoType(ClangUtil::GetCanonicalQualType(typedef_type), | .getAutoType(ClangUtil::GetCanonicalQualType(typedef_type), | ||||
clang::AutoTypeKeyword::Auto, false) | clang::AutoTypeKeyword::Auto, false) | ||||
.getAsOpaquePtr()); | .getAsOpaquePtr()); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) { | ||||
CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); | CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); | ||||
clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); | clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); | ||||
// Prepare the declarations/types we need for the template. | // Prepare the declarations/types we need for the template. | ||||
CompilerType clang_type = | CompilerType clang_type = | ||||
m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); | m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); | ||||
FunctionDecl *func = | FunctionDecl *func = | ||||
m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false); | m_ast->CreateFunctionDeclaration(TU, 0, "foo", clang_type, 0, false); | ||||
TypeSystemClang::TemplateParameterInfos empty_params; | TypeSystemClang::TemplateParameterInfos empty_params; | ||||
// Create the actual function template. | // Create the actual function template. | ||||
clang::FunctionTemplateDecl *func_template = | clang::FunctionTemplateDecl *func_template = | ||||
m_ast->CreateFunctionTemplateDecl(TU, func, "foo", empty_params); | m_ast->CreateFunctionTemplateDecl(TU, 0, func, "foo", empty_params); | ||||
EXPECT_EQ(TU, func_template->getDeclContext()); | EXPECT_EQ(TU, func_template->getDeclContext()); | ||||
EXPECT_EQ("foo", func_template->getName()); | EXPECT_EQ("foo", func_template->getName()); | ||||
EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess()); | EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess()); | ||||
} | } | ||||
TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { | TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { | ||||
// Tests creating a function template inside a record. | // Tests creating a function template inside a record. | ||||
CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); | CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); | ||||
clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); | clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); | ||||
// Create a record we can put the function template int. | // Create a record we can put the function template int. | ||||
CompilerType record_type = | CompilerType record_type = | ||||
clang_utils::createRecordWithField(*m_ast, "record", int_type, "field"); | clang_utils::createRecordWithField(*m_ast, "record", int_type, "field"); | ||||
clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type); | clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type); | ||||
// Prepare the declarations/types we need for the template. | // Prepare the declarations/types we need for the template. | ||||
CompilerType clang_type = | CompilerType clang_type = | ||||
m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); | m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); | ||||
// We create the FunctionDecl for the template in the TU DeclContext because: | // We create the FunctionDecl for the template in the TU DeclContext because: | ||||
// 1. FunctionDecls can't be in a Record (only CXXMethodDecls can). | // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can). | ||||
// 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. | // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. | ||||
FunctionDecl *func = | FunctionDecl *func = | ||||
m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false); | m_ast->CreateFunctionDeclaration(TU, 0, "foo", clang_type, 0, false); | ||||
TypeSystemClang::TemplateParameterInfos empty_params; | TypeSystemClang::TemplateParameterInfos empty_params; | ||||
// Create the actual function template. | // Create the actual function template. | ||||
clang::FunctionTemplateDecl *func_template = | clang::FunctionTemplateDecl *func_template = | ||||
m_ast->CreateFunctionTemplateDecl(record, func, "foo", empty_params); | m_ast->CreateFunctionTemplateDecl(record, 0, func, "foo", empty_params); | ||||
EXPECT_EQ(record, func_template->getDeclContext()); | EXPECT_EQ(record, func_template->getDeclContext()); | ||||
EXPECT_EQ("foo", func_template->getName()); | EXPECT_EQ("foo", func_template->getName()); | ||||
EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess()); | EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess()); | ||||
} | } | ||||
TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { | TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { | ||||
// We need to simulate this behavior in our AST that we construct as we don't | // We need to simulate this behavior in our AST that we construct as we don't | ||||
▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines |