[NFC][Coroutines] Use structured binding with llvm::enumerate in CoroSplit (#116879)
[llvm-project.git] / lldb / unittests / Symbol / TestTypeSystemClang.cpp
blob0733e42bb463310317e0aaabe4e93d0ac721d990
1 //===-- TestTypeSystemClang.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
10 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
11 #include "TestingSupport/SubsystemRAII.h"
12 #include "TestingSupport/Symbol/ClangTestUtils.h"
13 #include "lldb/Core/Declaration.h"
14 #include "lldb/Host/FileSystem.h"
15 #include "lldb/Host/HostInfo.h"
16 #include "lldb/lldb-enumerations.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/ExprCXX.h"
20 #include "gtest/gtest.h"
22 using namespace clang;
23 using namespace lldb;
24 using namespace lldb_private;
26 class TestTypeSystemClang : public testing::Test {
27 public:
28 SubsystemRAII<FileSystem, HostInfo> subsystems;
30 void SetUp() override {
31 m_holder =
32 std::make_unique<clang_utils::TypeSystemClangHolder>("test ASTContext");
33 m_ast = m_holder->GetAST();
36 void TearDown() override {
37 m_ast = nullptr;
38 m_holder.reset();
41 protected:
43 TypeSystemClang *m_ast = nullptr;
44 std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;
46 QualType GetBasicQualType(BasicType type) const {
47 return ClangUtil::GetQualType(m_ast->GetBasicTypeFromAST(type));
50 QualType GetBasicQualType(const char *name) const {
51 return ClangUtil::GetQualType(
52 m_ast->GetBuiltinTypeByName(ConstString(name)));
56 TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
57 clang::ASTContext &context = m_ast->getASTContext();
59 EXPECT_TRUE(
60 context.hasSameType(GetBasicQualType(eBasicTypeBool), context.BoolTy));
61 EXPECT_TRUE(
62 context.hasSameType(GetBasicQualType(eBasicTypeChar), context.CharTy));
63 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar8),
64 context.Char8Ty));
65 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar16),
66 context.Char16Ty));
67 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar32),
68 context.Char32Ty));
69 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeDouble),
70 context.DoubleTy));
71 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeDoubleComplex),
72 context.getComplexType(context.DoubleTy)));
73 EXPECT_TRUE(
74 context.hasSameType(GetBasicQualType(eBasicTypeFloat), context.FloatTy));
75 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeFloatComplex),
76 context.getComplexType(context.FloatTy)));
77 EXPECT_TRUE(
78 context.hasSameType(GetBasicQualType(eBasicTypeHalf), context.HalfTy));
79 EXPECT_TRUE(
80 context.hasSameType(GetBasicQualType(eBasicTypeInt), context.IntTy));
81 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeInt128),
82 context.Int128Ty));
83 EXPECT_TRUE(
84 context.hasSameType(GetBasicQualType(eBasicTypeLong), context.LongTy));
85 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongDouble),
86 context.LongDoubleTy));
87 EXPECT_TRUE(
88 context.hasSameType(GetBasicQualType(eBasicTypeLongDoubleComplex),
89 context.getComplexType(context.LongDoubleTy)));
90 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongLong),
91 context.LongLongTy));
92 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeNullPtr),
93 context.NullPtrTy));
94 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCClass),
95 context.getObjCClassType()));
96 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCID),
97 context.getObjCIdType()));
98 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCSel),
99 context.getObjCSelType()));
100 EXPECT_TRUE(
101 context.hasSameType(GetBasicQualType(eBasicTypeShort), context.ShortTy));
102 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeSignedChar),
103 context.SignedCharTy));
104 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedChar),
105 context.UnsignedCharTy));
106 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedInt),
107 context.UnsignedIntTy));
108 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedInt128),
109 context.UnsignedInt128Ty));
110 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedLong),
111 context.UnsignedLongTy));
112 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedLongLong),
113 context.UnsignedLongLongTy));
114 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedShort),
115 context.UnsignedShortTy));
116 EXPECT_TRUE(
117 context.hasSameType(GetBasicQualType(eBasicTypeVoid), context.VoidTy));
118 EXPECT_TRUE(
119 context.hasSameType(GetBasicQualType(eBasicTypeWChar), context.WCharTy));
122 TEST_F(TestTypeSystemClang, TestGetBasicTypeFromName) {
123 EXPECT_EQ(GetBasicQualType(eBasicTypeChar), GetBasicQualType("char"));
124 EXPECT_EQ(GetBasicQualType(eBasicTypeSignedChar),
125 GetBasicQualType("signed char"));
126 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedChar),
127 GetBasicQualType("unsigned char"));
128 EXPECT_EQ(GetBasicQualType(eBasicTypeWChar), GetBasicQualType("wchar_t"));
129 EXPECT_EQ(GetBasicQualType(eBasicTypeSignedWChar),
130 GetBasicQualType("signed wchar_t"));
131 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedWChar),
132 GetBasicQualType("unsigned wchar_t"));
133 EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short"));
134 EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short int"));
135 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort),
136 GetBasicQualType("unsigned short"));
137 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort),
138 GetBasicQualType("unsigned short int"));
139 EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("int"));
140 EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("signed int"));
141 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt),
142 GetBasicQualType("unsigned int"));
143 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt),
144 GetBasicQualType("unsigned"));
145 EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long"));
146 EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long int"));
147 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong),
148 GetBasicQualType("unsigned long"));
149 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong),
150 GetBasicQualType("unsigned long int"));
151 EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong),
152 GetBasicQualType("long long"));
153 EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong),
154 GetBasicQualType("long long int"));
155 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong),
156 GetBasicQualType("unsigned long long"));
157 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong),
158 GetBasicQualType("unsigned long long int"));
159 EXPECT_EQ(GetBasicQualType(eBasicTypeInt128), GetBasicQualType("__int128_t"));
160 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt128),
161 GetBasicQualType("__uint128_t"));
162 EXPECT_EQ(GetBasicQualType(eBasicTypeVoid), GetBasicQualType("void"));
163 EXPECT_EQ(GetBasicQualType(eBasicTypeBool), GetBasicQualType("bool"));
164 EXPECT_EQ(GetBasicQualType(eBasicTypeFloat), GetBasicQualType("float"));
165 EXPECT_EQ(GetBasicQualType(eBasicTypeDouble), GetBasicQualType("double"));
166 EXPECT_EQ(GetBasicQualType(eBasicTypeLongDouble),
167 GetBasicQualType("long double"));
168 EXPECT_EQ(GetBasicQualType(eBasicTypeObjCID), GetBasicQualType("id"));
169 EXPECT_EQ(GetBasicQualType(eBasicTypeObjCSel), GetBasicQualType("SEL"));
170 EXPECT_EQ(GetBasicQualType(eBasicTypeNullPtr), GetBasicQualType("nullptr"));
173 void VerifyEncodingAndBitSize(TypeSystemClang &clang_context,
174 lldb::Encoding encoding, unsigned int bit_size) {
175 clang::ASTContext &context = clang_context.getASTContext();
177 CompilerType type =
178 clang_context.GetBuiltinTypeForEncodingAndBitSize(encoding, bit_size);
179 EXPECT_TRUE(type.IsValid());
181 QualType qtype = ClangUtil::GetQualType(type);
182 EXPECT_FALSE(qtype.isNull());
183 if (qtype.isNull())
184 return;
186 uint64_t actual_size = context.getTypeSize(qtype);
187 EXPECT_EQ(bit_size, actual_size);
189 const clang::Type *type_ptr = qtype.getTypePtr();
190 EXPECT_NE(nullptr, type_ptr);
191 if (!type_ptr)
192 return;
194 EXPECT_TRUE(type_ptr->isBuiltinType());
195 switch (encoding) {
196 case eEncodingSint:
197 EXPECT_TRUE(type_ptr->isSignedIntegerType());
198 break;
199 case eEncodingUint:
200 EXPECT_TRUE(type_ptr->isUnsignedIntegerType());
201 break;
202 case eEncodingIEEE754:
203 EXPECT_TRUE(type_ptr->isFloatingType());
204 break;
205 default:
206 FAIL() << "Unexpected encoding";
207 break;
211 TEST_F(TestTypeSystemClang, TestBuiltinTypeForEncodingAndBitSize) {
212 // Make sure we can get types of every possible size in every possible
213 // encoding.
214 // We can't make any guarantee about which specific type we get, because the
215 // standard
216 // isn't that specific. We only need to make sure the compiler hands us some
217 // type that
218 // is both a builtin type and matches the requested bit size.
219 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 8);
220 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 16);
221 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 32);
222 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 64);
223 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 128);
225 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 8);
226 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 16);
227 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 32);
228 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 64);
229 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 128);
231 VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 32);
232 VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);
235 TEST_F(TestTypeSystemClang, TestBuiltinTypeForEmptyTriple) {
236 // Test that we can access type-info of builtin Clang AST
237 // types without crashing even when the target triple is
238 // empty.
240 TypeSystemClang ast("empty triple AST", llvm::Triple{});
242 // This test only makes sense if the builtin ASTContext types were
243 // not initialized.
244 ASSERT_TRUE(ast.getASTContext().VoidPtrTy.isNull());
246 EXPECT_FALSE(ast.GetBuiltinTypeByName(ConstString("int")).IsValid());
247 EXPECT_FALSE(ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
248 "char", dwarf::DW_ATE_signed_char, 8)
249 .IsValid());
250 EXPECT_FALSE(ast.GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 8)
251 .IsValid());
252 EXPECT_FALSE(ast.GetPointerSizedIntType(/*is_signed=*/false));
253 EXPECT_FALSE(ast.GetIntTypeFromBitSize(8, /*is_signed=*/false));
255 CompilerType record_type = ast.CreateRecordType(
256 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "Record",
257 llvm::to_underlying(clang::TagTypeKind::Struct),
258 lldb::eLanguageTypeC_plus_plus, std::nullopt);
259 TypeSystemClang::StartTagDeclarationDefinition(record_type);
260 EXPECT_EQ(ast.AddFieldToRecordType(record_type, "field", record_type,
261 eAccessPublic, /*bitfield_bit_size=*/8),
262 nullptr);
263 TypeSystemClang::CompleteTagDeclarationDefinition(record_type);
266 TEST_F(TestTypeSystemClang, TestDisplayName) {
267 TypeSystemClang ast("some name", llvm::Triple());
268 EXPECT_EQ("some name", ast.getDisplayName());
271 TEST_F(TestTypeSystemClang, TestDisplayNameEmpty) {
272 TypeSystemClang ast("", llvm::Triple());
273 EXPECT_EQ("", ast.getDisplayName());
276 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeInvalid) {
277 EXPECT_FALSE(m_ast->GetEnumerationIntegerType(CompilerType()).IsValid());
280 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeUnexpectedType) {
281 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
282 CompilerType t = m_ast->GetEnumerationIntegerType(int_type);
283 EXPECT_FALSE(t.IsValid());
286 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) {
287 // All possible underlying integer types of enums.
288 const std::vector<lldb::BasicType> types_to_test = {
289 eBasicTypeInt, eBasicTypeUnsignedInt, eBasicTypeLong,
290 eBasicTypeUnsignedLong, eBasicTypeLongLong, eBasicTypeUnsignedLongLong,
293 for (bool scoped : {true, false}) {
294 SCOPED_TRACE("scoped: " + std::to_string(scoped));
295 for (lldb::BasicType basic_type : types_to_test) {
296 SCOPED_TRACE(std::to_string(basic_type));
298 auto holder =
299 std::make_unique<clang_utils::TypeSystemClangHolder>("enum_ast");
300 auto &ast = *holder->GetAST();
302 CompilerType basic_compiler_type = ast.GetBasicType(basic_type);
303 EXPECT_TRUE(basic_compiler_type.IsValid());
305 CompilerType enum_type = ast.CreateEnumerationType(
306 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(),
307 Declaration(), basic_compiler_type, scoped);
309 CompilerType t = ast.GetEnumerationIntegerType(enum_type);
310 // Check that the type we put in at the start is found again.
311 EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName());
316 TEST_F(TestTypeSystemClang, TestOwningModule) {
317 auto holder =
318 std::make_unique<clang_utils::TypeSystemClangHolder>("module_ast");
319 auto &ast = *holder->GetAST();
320 CompilerType basic_compiler_type = ast.GetBasicType(BasicType::eBasicTypeInt);
321 CompilerType enum_type = ast.CreateEnumerationType(
322 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(100),
323 Declaration(), basic_compiler_type, false);
324 auto *ed = TypeSystemClang::GetAsEnumDecl(enum_type);
325 EXPECT_FALSE(!ed);
326 EXPECT_EQ(ed->getOwningModuleID(), 100u);
328 CompilerType record_type = ast.CreateRecordType(
329 nullptr, OptionalClangModuleID(200), lldb::eAccessPublic, "FooRecord",
330 llvm::to_underlying(clang::TagTypeKind::Struct),
331 lldb::eLanguageTypeC_plus_plus, std::nullopt);
332 auto *rd = TypeSystemClang::GetAsRecordDecl(record_type);
333 EXPECT_FALSE(!rd);
334 EXPECT_EQ(rd->getOwningModuleID(), 200u);
336 CompilerType class_type =
337 ast.CreateObjCClass("objc_class", ast.GetTranslationUnitDecl(),
338 OptionalClangModuleID(300), false);
339 auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(class_type);
340 EXPECT_FALSE(!cd);
341 EXPECT_EQ(cd->getOwningModuleID(), 300u);
344 TEST_F(TestTypeSystemClang, TestIsClangType) {
345 clang::ASTContext &context = m_ast->getASTContext();
346 lldb::opaque_compiler_type_t bool_ctype =
347 TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool);
348 CompilerType bool_type(m_ast->weak_from_this(), bool_ctype);
349 CompilerType record_type = m_ast->CreateRecordType(
350 nullptr, OptionalClangModuleID(100), lldb::eAccessPublic, "FooRecord",
351 llvm::to_underlying(clang::TagTypeKind::Struct),
352 lldb::eLanguageTypeC_plus_plus, std::nullopt);
353 // Clang builtin type and record type should pass
354 EXPECT_TRUE(ClangUtil::IsClangType(bool_type));
355 EXPECT_TRUE(ClangUtil::IsClangType(record_type));
357 // Default constructed type should fail
358 EXPECT_FALSE(ClangUtil::IsClangType(CompilerType()));
361 TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) {
362 CompilerType record_type = m_ast->CreateRecordType(
363 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "FooRecord",
364 llvm::to_underlying(clang::TagTypeKind::Struct),
365 lldb::eLanguageTypeC_plus_plus, std::nullopt);
366 QualType qt;
368 qt = ClangUtil::GetQualType(record_type);
369 EXPECT_EQ(0u, qt.getLocalFastQualifiers());
370 record_type = record_type.AddConstModifier();
371 record_type = record_type.AddVolatileModifier();
372 record_type = record_type.AddRestrictModifier();
373 qt = ClangUtil::GetQualType(record_type);
374 EXPECT_NE(0u, qt.getLocalFastQualifiers());
375 record_type = ClangUtil::RemoveFastQualifiers(record_type);
376 qt = ClangUtil::GetQualType(record_type);
377 EXPECT_EQ(0u, qt.getLocalFastQualifiers());
380 TEST_F(TestTypeSystemClang, TestConvertAccessTypeToAccessSpecifier) {
381 EXPECT_EQ(AS_none,
382 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessNone));
383 EXPECT_EQ(AS_none, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
384 eAccessPackage));
385 EXPECT_EQ(AS_public,
386 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessPublic));
387 EXPECT_EQ(AS_private, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
388 eAccessPrivate));
389 EXPECT_EQ(AS_protected, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
390 eAccessProtected));
393 TEST_F(TestTypeSystemClang, TestUnifyAccessSpecifiers) {
394 // Unifying two of the same type should return the same type
395 EXPECT_EQ(AS_public,
396 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_public));
397 EXPECT_EQ(AS_private,
398 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_private));
399 EXPECT_EQ(AS_protected,
400 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_protected));
402 // Otherwise the result should be the strictest of the two.
403 EXPECT_EQ(AS_private,
404 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_public));
405 EXPECT_EQ(AS_private,
406 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_protected));
407 EXPECT_EQ(AS_private,
408 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_private));
409 EXPECT_EQ(AS_private,
410 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_private));
411 EXPECT_EQ(AS_protected,
412 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_public));
413 EXPECT_EQ(AS_protected,
414 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_protected));
416 // None is stricter than everything (by convention)
417 EXPECT_EQ(AS_none,
418 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_public));
419 EXPECT_EQ(AS_none,
420 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_protected));
421 EXPECT_EQ(AS_none,
422 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_private));
423 EXPECT_EQ(AS_none,
424 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_none));
425 EXPECT_EQ(AS_none,
426 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_none));
427 EXPECT_EQ(AS_none,
428 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_none));
431 TEST_F(TestTypeSystemClang, TestRecordHasFields) {
432 CompilerType int_type = m_ast->GetBasicType(eBasicTypeInt);
434 // Test that a record with no fields returns false
435 CompilerType empty_base = m_ast->CreateRecordType(
436 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyBase",
437 llvm::to_underlying(clang::TagTypeKind::Struct),
438 lldb::eLanguageTypeC_plus_plus, std::nullopt);
439 TypeSystemClang::StartTagDeclarationDefinition(empty_base);
440 TypeSystemClang::CompleteTagDeclarationDefinition(empty_base);
442 RecordDecl *empty_base_decl = TypeSystemClang::GetAsRecordDecl(empty_base);
443 EXPECT_NE(nullptr, empty_base_decl);
444 EXPECT_FALSE(m_ast->RecordHasFields(empty_base_decl));
446 // Test that a record with direct fields returns true
447 CompilerType non_empty_base = m_ast->CreateRecordType(
448 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "NonEmptyBase",
449 llvm::to_underlying(clang::TagTypeKind::Struct),
450 lldb::eLanguageTypeC_plus_plus, std::nullopt);
451 TypeSystemClang::StartTagDeclarationDefinition(non_empty_base);
452 FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType(
453 non_empty_base, "MyField", int_type, eAccessPublic, 0);
454 TypeSystemClang::CompleteTagDeclarationDefinition(non_empty_base);
455 RecordDecl *non_empty_base_decl =
456 TypeSystemClang::GetAsRecordDecl(non_empty_base);
457 EXPECT_NE(nullptr, non_empty_base_decl);
458 EXPECT_NE(nullptr, non_empty_base_field_decl);
459 EXPECT_TRUE(m_ast->RecordHasFields(non_empty_base_decl));
461 std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
463 // Test that a record with no direct fields, but fields in a base returns true
464 CompilerType empty_derived = m_ast->CreateRecordType(
465 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived",
466 llvm::to_underlying(clang::TagTypeKind::Struct),
467 lldb::eLanguageTypeC_plus_plus, std::nullopt);
468 TypeSystemClang::StartTagDeclarationDefinition(empty_derived);
469 std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec =
470 m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
471 lldb::eAccessPublic, false, false);
472 bases.push_back(std::move(non_empty_base_spec));
473 bool result = m_ast->TransferBaseClasses(empty_derived.GetOpaqueQualType(),
474 std::move(bases));
475 TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived);
476 EXPECT_TRUE(result);
477 CXXRecordDecl *empty_derived_non_empty_base_cxx_decl =
478 m_ast->GetAsCXXRecordDecl(empty_derived.GetOpaqueQualType());
479 RecordDecl *empty_derived_non_empty_base_decl =
480 TypeSystemClang::GetAsRecordDecl(empty_derived);
481 EXPECT_EQ(1u, m_ast->GetNumBaseClasses(
482 empty_derived_non_empty_base_cxx_decl, false));
483 EXPECT_TRUE(m_ast->RecordHasFields(empty_derived_non_empty_base_decl));
485 // Test that a record with no direct fields, but fields in a virtual base
486 // returns true
487 CompilerType empty_derived2 = m_ast->CreateRecordType(
488 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived2",
489 llvm::to_underlying(clang::TagTypeKind::Struct),
490 lldb::eLanguageTypeC_plus_plus, std::nullopt);
491 TypeSystemClang::StartTagDeclarationDefinition(empty_derived2);
492 std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec =
493 m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
494 lldb::eAccessPublic, true, false);
495 bases.push_back(std::move(non_empty_vbase_spec));
496 result = m_ast->TransferBaseClasses(empty_derived2.GetOpaqueQualType(),
497 std::move(bases));
498 TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived2);
499 EXPECT_TRUE(result);
500 CXXRecordDecl *empty_derived_non_empty_vbase_cxx_decl =
501 m_ast->GetAsCXXRecordDecl(empty_derived2.GetOpaqueQualType());
502 RecordDecl *empty_derived_non_empty_vbase_decl =
503 TypeSystemClang::GetAsRecordDecl(empty_derived2);
504 EXPECT_EQ(1u, m_ast->GetNumBaseClasses(
505 empty_derived_non_empty_vbase_cxx_decl, false));
506 EXPECT_TRUE(
507 m_ast->RecordHasFields(empty_derived_non_empty_vbase_decl));
510 TEST_F(TestTypeSystemClang, TemplateArguments) {
511 TypeSystemClang::TemplateParameterInfos infos;
512 infos.InsertArg("T", TemplateArgument(m_ast->getASTContext().IntTy));
514 llvm::APSInt arg(llvm::APInt(8, 47));
515 infos.InsertArg("I", TemplateArgument(m_ast->getASTContext(), arg,
516 m_ast->getASTContext().IntTy));
518 // template<typename T, int I> struct foo;
519 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(
520 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,
521 "foo", llvm::to_underlying(clang::TagTypeKind::Struct), infos);
522 ASSERT_NE(decl, nullptr);
524 // foo<int, 47>
525 ClassTemplateSpecializationDecl *spec_decl =
526 m_ast->CreateClassTemplateSpecializationDecl(
527 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl,
528 llvm::to_underlying(clang::TagTypeKind::Struct), infos);
529 ASSERT_NE(spec_decl, nullptr);
530 CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl);
531 ASSERT_TRUE(type);
532 m_ast->StartTagDeclarationDefinition(type);
533 m_ast->CompleteTagDeclarationDefinition(type);
535 // typedef foo<int, 47> foo_def;
536 CompilerType typedef_type = type.CreateTypedef(
537 "foo_def", m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), 0);
539 CompilerType auto_type(
540 m_ast->weak_from_this(),
541 m_ast->getASTContext()
542 .getAutoType(ClangUtil::GetCanonicalQualType(typedef_type),
543 clang::AutoTypeKeyword::Auto, false)
544 .getAsOpaquePtr());
546 CompilerType int_type(m_ast->weak_from_this(),
547 m_ast->getASTContext().IntTy.getAsOpaquePtr());
548 for (CompilerType t : {type, typedef_type, auto_type}) {
549 SCOPED_TRACE(t.GetTypeName().AsCString());
551 const bool expand_pack = false;
552 EXPECT_EQ(
553 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0, expand_pack),
554 eTemplateArgumentKindType);
555 EXPECT_EQ(
556 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0, expand_pack),
557 int_type);
558 EXPECT_EQ(std::nullopt, m_ast->GetIntegralTemplateArgument(
559 t.GetOpaqueQualType(), 0, expand_pack));
561 EXPECT_EQ(
562 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1, expand_pack),
563 eTemplateArgumentKindIntegral);
564 EXPECT_EQ(
565 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1, expand_pack),
566 CompilerType());
567 auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1,
568 expand_pack);
569 ASSERT_NE(std::nullopt, result);
570 EXPECT_EQ(arg, result->value);
571 EXPECT_EQ(int_type, result->type);
575 class TestCreateClassTemplateDecl : public TestTypeSystemClang {
576 protected:
577 /// The class templates created so far by the Expect* functions below.
578 llvm::DenseSet<ClassTemplateDecl *> m_created_templates;
580 /// Utility function for creating a class template.
581 ClassTemplateDecl *
582 CreateClassTemplate(const TypeSystemClang::TemplateParameterInfos &infos) {
583 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(
584 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,
585 "foo", llvm::to_underlying(clang::TagTypeKind::Struct), infos);
586 return decl;
589 /// Creates a new class template with the given template parameters.
590 /// Asserts that a new ClassTemplateDecl is created.
591 /// \param description The gtest scope string that should describe the input.
592 /// \param infos The template parameters that the class template should have.
593 /// \returns The created ClassTemplateDecl.
594 ClassTemplateDecl *
595 ExpectNewTemplate(std::string description,
596 const TypeSystemClang::TemplateParameterInfos &infos) {
597 SCOPED_TRACE(description);
598 ClassTemplateDecl *first_template = CreateClassTemplate(infos);
599 // A new template should have been created.
600 EXPECT_FALSE(m_created_templates.contains(first_template))
601 << "Didn't create new class template but reused this existing decl:\n"
602 << ClangUtil::DumpDecl(first_template);
603 m_created_templates.insert(first_template);
605 // Creating a new template with the same arguments should always return
606 // the template created above.
607 ClassTemplateDecl *second_template = CreateClassTemplate(infos);
608 EXPECT_EQ(first_template, second_template)
609 << "Second attempt to create class template didn't reuse first decl:\n"
610 << ClangUtil::DumpDecl(first_template) << "\nInstead created/reused:\n"
611 << ClangUtil::DumpDecl(second_template);
612 return first_template;
615 /// Tries to create a new class template but asserts that an existing class
616 /// template in the current AST is reused (in contract so a new class
617 /// template being created).
618 /// \param description The gtest scope string that should describe the input.
619 /// \param infos The template parameters that the class template should have.
620 void
621 ExpectReusedTemplate(std::string description,
622 const TypeSystemClang::TemplateParameterInfos &infos,
623 ClassTemplateDecl *expected) {
624 SCOPED_TRACE(description);
625 ClassTemplateDecl *td = CreateClassTemplate(infos);
626 EXPECT_EQ(td, expected)
627 << "Created/reused class template is:\n"
628 << ClangUtil::DumpDecl(td) << "\nExpected to reuse:\n"
629 << ClangUtil::DumpDecl(expected);
633 TEST_F(TestCreateClassTemplateDecl, FindExistingTemplates) {
634 // This tests the logic in TypeSystemClang::CreateClassTemplateDecl that
635 // decides whether an existing ClassTemplateDecl in the AST can be reused.
636 // The behaviour should follow the C++ rules for redeclaring templates
637 // (e.g., parameter names can be changed/omitted.)
639 // Test an empty template parameter list: <>
640 ExpectNewTemplate("<>", {{}, {}});
642 clang::TemplateArgument intArg(m_ast->getASTContext().IntTy);
643 clang::TemplateArgument int47Arg(m_ast->getASTContext(),
644 llvm::APSInt(llvm::APInt(32, 47)),
645 m_ast->getASTContext().IntTy);
646 clang::TemplateArgument floatArg(m_ast->getASTContext().FloatTy);
647 clang::TemplateArgument char47Arg(m_ast->getASTContext(),
648 llvm::APSInt(llvm::APInt(8, 47)),
649 m_ast->getASTContext().SignedCharTy);
651 clang::TemplateArgument char123Arg(m_ast->getASTContext(),
652 llvm::APSInt(llvm::APInt(8, 123)),
653 m_ast->getASTContext().SignedCharTy);
655 // Test that <typename T> with T = int creates a new template.
656 ClassTemplateDecl *single_type_arg =
657 ExpectNewTemplate("<typename T>", {{"T"}, {intArg}});
659 // Test that changing the parameter name doesn't create a new class template.
660 ExpectReusedTemplate("<typename A> (A = int)", {{"A"}, {intArg}},
661 single_type_arg);
663 // Test that changing the used type doesn't create a new class template.
664 ExpectReusedTemplate("<typename A> (A = float)", {{"A"}, {floatArg}},
665 single_type_arg);
667 // Test that <typename A, signed char I> creates a new template with A = int
668 // and I = 47;
669 ClassTemplateDecl *type_and_char_value =
670 ExpectNewTemplate("<typename A, signed char I> (I = 47)",
671 {{"A", "I"}, {floatArg, char47Arg}});
673 // Change the value of the I parameter to 123. The previously created
674 // class template should still be reused.
675 ExpectReusedTemplate("<typename A, signed char I> (I = 123)",
676 {{"A", "I"}, {floatArg, char123Arg}},
677 type_and_char_value);
679 // Change the type of the I parameter to int so we have <typename A, int I>.
680 // The class template from above can't be reused.
681 ExpectNewTemplate("<typename A, int I> (I = 123)",
682 {{"A", "I"}, {floatArg, int47Arg}});
684 // Test a second type parameter will also cause a new template to be created.
685 // We now have <typename A, int I, typename B>.
686 ClassTemplateDecl *type_and_char_value_and_type =
687 ExpectNewTemplate("<typename A, int I, typename B>",
688 {{"A", "I", "B"}, {floatArg, int47Arg, intArg}});
690 // Remove all the names from the parameters which shouldn't influence the
691 // way the templates get merged.
692 ExpectReusedTemplate("<typename, int, typename>",
693 {{"", "", ""}, {floatArg, int47Arg, intArg}},
694 type_and_char_value_and_type);
697 TEST_F(TestCreateClassTemplateDecl, FindExistingTemplatesWithParameterPack) {
698 // The same as FindExistingTemplates but for templates with parameter packs.
699 TypeSystemClang::TemplateParameterInfos infos;
700 clang::TemplateArgument intArg(m_ast->getASTContext().IntTy);
701 clang::TemplateArgument int1Arg(m_ast->getASTContext(),
702 llvm::APSInt(llvm::APInt(32, 1)),
703 m_ast->getASTContext().IntTy);
704 clang::TemplateArgument int123Arg(m_ast->getASTContext(),
705 llvm::APSInt(llvm::APInt(32, 123)),
706 m_ast->getASTContext().IntTy);
707 clang::TemplateArgument longArg(m_ast->getASTContext().LongTy);
708 clang::TemplateArgument long1Arg(m_ast->getASTContext(),
709 llvm::APSInt(llvm::APInt(64, 1)),
710 m_ast->getASTContext().LongTy);
712 infos.SetParameterPack(
713 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
714 llvm::SmallVector<const char *>{"", ""},
715 llvm::SmallVector<TemplateArgument>{intArg, intArg}));
717 ClassTemplateDecl *type_pack =
718 ExpectNewTemplate("<typename ...> (int, int)", infos);
720 // Special case: An instantiation for a parameter pack with no values fits
721 // to whatever class template we find. There isn't enough information to
722 // do an actual comparison here.
723 infos.SetParameterPack(
724 std::make_unique<TypeSystemClang::TemplateParameterInfos>());
725 ExpectReusedTemplate("<...> (no values in pack)", infos, type_pack);
727 // Change the type content of pack type values.
728 infos.SetParameterPack(
729 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
730 llvm::SmallVector<const char *>{"", ""},
731 llvm::SmallVector<TemplateArgument>{intArg, longArg}));
732 ExpectReusedTemplate("<typename ...> (int, long)", infos, type_pack);
734 // Change the number of pack values.
735 infos.SetParameterPack(
736 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
737 llvm::SmallVector<const char *>{""},
738 llvm::SmallVector<TemplateArgument>{intArg}));
739 ExpectReusedTemplate("<typename ...> (int)", infos, type_pack);
741 // The names of the pack values shouldn't matter.
742 infos.SetParameterPack(
743 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
744 llvm::SmallVector<const char *>{"A"},
745 llvm::SmallVector<TemplateArgument>{intArg}));
746 ExpectReusedTemplate("<typename ...> (int)", infos, type_pack);
748 // Changing the kind of template argument will create a new template.
749 infos.SetParameterPack(
750 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
751 llvm::SmallVector<const char *>{"A"},
752 llvm::SmallVector<TemplateArgument>{int1Arg}));
753 ClassTemplateDecl *int_pack = ExpectNewTemplate("<int ...> (int = 1)", infos);
755 // Changing the value of integral parameters will not create a new template.
756 infos.SetParameterPack(
757 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
758 llvm::SmallVector<const char *>{"A"},
759 llvm::SmallVector<TemplateArgument>{int123Arg}));
760 ExpectReusedTemplate("<int ...> (int = 123)", infos, int_pack);
762 // Changing the integral type will create a new template.
763 infos.SetParameterPack(
764 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
765 llvm::SmallVector<const char *>{"A"},
766 llvm::SmallVector<TemplateArgument>{long1Arg}));
767 ExpectNewTemplate("<long ...> (long = 1)", infos);
769 // Prependinding a non-pack parameter will create a new template.
770 infos.InsertArg("T", intArg);
771 ExpectNewTemplate("<typename T, long...> (T = int, long = 1)", infos);
774 TEST_F(TestTypeSystemClang, OnlyPackName) {
775 TypeSystemClang::TemplateParameterInfos infos;
776 infos.SetPackName("A");
777 EXPECT_FALSE(infos.IsValid());
780 static QualType makeConstInt(clang::ASTContext &ctxt) {
781 QualType result(ctxt.IntTy);
782 result.addConst();
783 return result;
786 TEST_F(TestTypeSystemClang, TestGetTypeClassDeclType) {
787 clang::ASTContext &ctxt = m_ast->getASTContext();
788 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
789 QualType t = ctxt.getDecltypeType(nullptr_expr, makeConstInt(ctxt));
790 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
793 TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOf) {
794 clang::ASTContext &ctxt = m_ast->getASTContext();
795 QualType t = ctxt.getTypeOfType(makeConstInt(ctxt), TypeOfKind::Qualified);
796 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
799 TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOfExpr) {
800 clang::ASTContext &ctxt = m_ast->getASTContext();
801 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
802 QualType t = ctxt.getTypeOfExprType(nullptr_expr, TypeOfKind::Qualified);
803 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
806 TEST_F(TestTypeSystemClang, TestGetTypeClassNested) {
807 clang::ASTContext &ctxt = m_ast->getASTContext();
808 QualType t_base =
809 ctxt.getTypeOfType(makeConstInt(ctxt), TypeOfKind::Qualified);
810 QualType t = ctxt.getTypeOfType(t_base, TypeOfKind::Qualified);
811 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
814 TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {
815 // Tests creating a function template.
817 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
818 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
820 // Prepare the declarations/types we need for the template.
821 CompilerType clang_type =
822 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
823 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
824 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
825 false);
826 TypeSystemClang::TemplateParameterInfos empty_params;
828 // Create the actual function template.
829 clang::FunctionTemplateDecl *func_template =
830 m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func,
831 empty_params);
833 EXPECT_EQ(TU, func_template->getDeclContext());
834 EXPECT_EQ("foo", func_template->getName());
835 EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess());
838 TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {
839 // Tests creating a function template inside a record.
841 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
842 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
844 // Create a record we can put the function template int.
845 CompilerType record_type =
846 clang_utils::createRecordWithField(*m_ast, "record", int_type, "field");
847 clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type);
849 // Prepare the declarations/types we need for the template.
850 CompilerType clang_type =
851 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
852 // We create the FunctionDecl for the template in the TU DeclContext because:
853 // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can).
854 // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
855 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
856 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
857 false);
858 TypeSystemClang::TemplateParameterInfos empty_params;
860 // Create the actual function template.
861 clang::FunctionTemplateDecl *func_template =
862 m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func,
863 empty_params);
865 EXPECT_EQ(record, func_template->getDeclContext());
866 EXPECT_EQ("foo", func_template->getName());
867 EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess());
870 TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) {
871 // We need to simulate this behavior in our AST that we construct as we don't
872 // have a Sema instance that can do this for us:
873 // C++11 [class.copy]p7, p18:
874 // If the class definition declares a move constructor or move assignment
875 // operator, an implicitly declared copy constructor or copy assignment
876 // operator is defined as deleted.
878 // Create a record and start defining it.
879 llvm::StringRef class_name = "S";
880 CompilerType t = clang_utils::createRecord(*m_ast, class_name);
881 m_ast->StartTagDeclarationDefinition(t);
883 // Create a move constructor that will delete the implicit copy constructor.
884 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
885 CompilerType param_type = t.GetRValueReferenceType();
886 CompilerType function_type =
887 m_ast->CreateFunctionType(return_type, &param_type, /*num_params*/ 1,
888 /*variadic=*/false, /*quals*/ 0U);
889 bool is_virtual = false;
890 bool is_static = false;
891 bool is_inline = false;
892 bool is_explicit = true;
893 bool is_attr_used = false;
894 bool is_artificial = false;
895 m_ast->AddMethodToCXXRecordType(
896 t.GetOpaqueQualType(), class_name, nullptr, function_type,
897 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
898 is_explicit, is_attr_used, is_artificial);
900 // Complete the definition and check the created record.
901 m_ast->CompleteTagDeclarationDefinition(t);
902 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));
903 // We can't call defaultedCopyConstructorIsDeleted() as this requires that
904 // the Decl passes through Sema which will actually compute this field.
905 // Instead we check that there is no copy constructor declared by the user
906 // which only leaves a non-deleted defaulted copy constructor as an option
907 // that our record will have no simple copy constructor.
908 EXPECT_FALSE(record->hasUserDeclaredCopyConstructor());
909 EXPECT_FALSE(record->hasSimpleCopyConstructor());
912 TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {
913 // Tests that we don't delete the a user-defined copy constructor when
914 // a move constructor is provided.
915 // See also the TestDeletingImplicitCopyCstrDueToMoveCStr test.
916 llvm::StringRef class_name = "S";
917 CompilerType t = clang_utils::createRecord(*m_ast, class_name);
918 m_ast->StartTagDeclarationDefinition(t);
920 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
921 bool is_virtual = false;
922 bool is_static = false;
923 bool is_inline = false;
924 bool is_explicit = true;
925 bool is_attr_used = false;
926 bool is_artificial = false;
927 // Create a move constructor.
929 CompilerType param_type = t.GetRValueReferenceType();
930 CompilerType function_type =
931 m_ast->CreateFunctionType(return_type, &param_type, /*num_params*/ 1,
932 /*variadic=*/false, /*quals*/ 0U);
933 m_ast->AddMethodToCXXRecordType(
934 t.GetOpaqueQualType(), class_name, nullptr, function_type,
935 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
936 is_explicit, is_attr_used, is_artificial);
938 // Create a copy constructor.
940 CompilerType param_type = t.GetLValueReferenceType().AddConstModifier();
941 CompilerType function_type =
942 m_ast->CreateFunctionType(return_type, &param_type, /*num_params*/ 1,
943 /*variadic=*/false, /*quals*/ 0U);
944 m_ast->AddMethodToCXXRecordType(
945 t.GetOpaqueQualType(), class_name, nullptr, function_type,
946 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
947 is_explicit, is_attr_used, is_artificial);
950 // Complete the definition and check the created record.
951 m_ast->CompleteTagDeclarationDefinition(t);
952 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));
953 EXPECT_TRUE(record->hasUserDeclaredCopyConstructor());
956 TEST_F(TestTypeSystemClang, AddMethodToObjCObjectType) {
957 // Create an interface decl and mark it as having external storage.
958 CompilerType c = m_ast->CreateObjCClass("A", m_ast->GetTranslationUnitDecl(),
959 OptionalClangModuleID(),
960 /*IsInternal*/ false);
961 ObjCInterfaceDecl *interface = m_ast->GetAsObjCInterfaceDecl(c);
962 m_ast->SetHasExternalStorage(c.GetOpaqueQualType(), true);
963 EXPECT_TRUE(interface->hasExternalLexicalStorage());
965 // Add a method to the interface.
966 std::vector<CompilerType> args;
967 CompilerType func_type =
968 m_ast->CreateFunctionType(m_ast->GetBasicType(lldb::eBasicTypeInt),
969 args.data(), args.size(), /*variadic*/ false,
970 /*quals*/ 0, clang::CallingConv::CC_C);
971 bool variadic = false;
972 bool artificial = false;
973 bool objc_direct = false;
974 clang::ObjCMethodDecl *method = TypeSystemClang::AddMethodToObjCObjectType(
975 c, "-[A foo]", func_type, artificial, variadic, objc_direct);
976 ASSERT_NE(method, nullptr);
978 // The interface decl should still have external lexical storage.
979 EXPECT_TRUE(interface->hasExternalLexicalStorage());
981 // Test some properties of the created ObjCMethodDecl.
982 EXPECT_FALSE(method->isVariadic());
983 EXPECT_TRUE(method->isImplicit());
984 EXPECT_FALSE(method->isDirectMethod());
985 EXPECT_EQ(method->getDeclName().getObjCSelector().getAsString(), "foo");
988 TEST_F(TestTypeSystemClang, GetFullyUnqualifiedType) {
989 CompilerType bool_ = m_ast->GetBasicType(eBasicTypeBool);
990 CompilerType cv_bool = bool_.AddConstModifier().AddVolatileModifier();
992 // const volatile bool -> bool
993 EXPECT_EQ(bool_, cv_bool.GetFullyUnqualifiedType());
995 // const volatile bool[47] -> bool[47]
996 EXPECT_EQ(bool_.GetArrayType(47),
997 cv_bool.GetArrayType(47).GetFullyUnqualifiedType());
999 // const volatile bool[47][42] -> bool[47][42]
1000 EXPECT_EQ(
1001 bool_.GetArrayType(42).GetArrayType(47),
1002 cv_bool.GetArrayType(42).GetArrayType(47).GetFullyUnqualifiedType());
1004 // const volatile bool * -> bool *
1005 EXPECT_EQ(bool_.GetPointerType(),
1006 cv_bool.GetPointerType().GetFullyUnqualifiedType());
1008 // const volatile bool *[47] -> bool *[47]
1009 EXPECT_EQ(
1010 bool_.GetPointerType().GetArrayType(47),
1011 cv_bool.GetPointerType().GetArrayType(47).GetFullyUnqualifiedType());
1014 TEST(TestScratchTypeSystemClang, InferSubASTFromLangOpts) {
1015 LangOptions lang_opts;
1016 EXPECT_EQ(
1017 ScratchTypeSystemClang::DefaultAST,
1018 ScratchTypeSystemClang::InferIsolatedASTKindFromLangOpts(lang_opts));
1020 lang_opts.Modules = true;
1021 EXPECT_EQ(
1022 ScratchTypeSystemClang::IsolatedASTKind::CppModules,
1023 ScratchTypeSystemClang::InferIsolatedASTKindFromLangOpts(lang_opts));
1026 TEST_F(TestTypeSystemClang, GetDeclContextByNameWhenMissingSymbolFile) {
1027 // Test that a type system without a symbol file is handled gracefully.
1028 std::vector<CompilerDecl> decls =
1029 m_ast->DeclContextFindDeclByName(nullptr, ConstString("SomeName"), true);
1031 EXPECT_TRUE(decls.empty());