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

source code of lldb/unittests/Symbol/TestTypeSystemClang.cpp