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 "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"
21
22using namespace clang;
23using namespace lldb;
24using namespace lldb_private;
25
26class TestTypeSystemClang : public testing::Test {
27public:
28 SubsystemRAII<FileSystem, HostInfo> subsystems;
29
30 void SetUp() override {
31 m_holder =
32 std::make_unique<clang_utils::TypeSystemClangHolder>(args: "test ASTContext");
33 m_ast = m_holder->GetAST();
34 }
35
36 void TearDown() override {
37 m_ast = nullptr;
38 m_holder.reset();
39 }
40
41protected:
42
43 TypeSystemClang *m_ast = nullptr;
44 std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;
45
46 QualType GetBasicQualType(BasicType type) const {
47 return ClangUtil::GetQualType(ct: m_ast->GetBasicTypeFromAST(basic_type: type));
48 }
49
50 QualType GetBasicQualType(const char *name) const {
51 return ClangUtil::GetQualType(
52 ct: m_ast->GetBuiltinTypeByName(name: ConstString(name)));
53 }
54};
55
56TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
57 clang::ASTContext &context = m_ast->getASTContext();
58
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));
120}
121
122TEST_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"));
171}
172
173void VerifyEncodingAndBitSize(TypeSystemClang &clang_context,
174 lldb::Encoding encoding, unsigned int bit_size) {
175 clang::ASTContext &context = clang_context.getASTContext();
176
177 CompilerType type =
178 clang_context.GetBuiltinTypeForEncodingAndBitSize(encoding, bit_size);
179 EXPECT_TRUE(type.IsValid());
180
181 QualType qtype = ClangUtil::GetQualType(ct: type);
182 EXPECT_FALSE(qtype.isNull());
183 if (qtype.isNull())
184 return;
185
186 uint64_t actual_size = context.getTypeSize(T: qtype);
187 EXPECT_EQ(bit_size, actual_size);
188
189 const clang::Type *type_ptr = qtype.getTypePtr();
190 EXPECT_NE(nullptr, type_ptr);
191 if (!type_ptr)
192 return;
193
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;
208 }
209}
210
211TEST_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(clang_context&: *m_ast, encoding: eEncodingSint, bit_size: 8);
220 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingSint, bit_size: 16);
221 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingSint, bit_size: 32);
222 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingSint, bit_size: 64);
223 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingSint, bit_size: 128);
224
225 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingUint, bit_size: 8);
226 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingUint, bit_size: 16);
227 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingUint, bit_size: 32);
228 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingUint, bit_size: 64);
229 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingUint, bit_size: 128);
230
231 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingIEEE754, bit_size: 32);
232 VerifyEncodingAndBitSize(clang_context&: *m_ast, encoding: eEncodingIEEE754, bit_size: 64);
233}
234
235TEST_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.
239
240 TypeSystemClang ast("empty triple AST", llvm::Triple{});
241
242 // This test only makes sense if the builtin ASTContext types were
243 // not initialized.
244 ASSERT_TRUE(ast.getASTContext().VoidPtrTy.isNull());
245
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));
254
255 CompilerType record_type = ast.CreateRecordType(
256 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic, name: "Record",
257 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
258 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
259 TypeSystemClang::StartTagDeclarationDefinition(type: record_type);
260 EXPECT_EQ(ast.AddFieldToRecordType(record_type, "field", record_type,
261 eAccessPublic, /*bitfield_bit_size=*/8),
262 nullptr);
263 TypeSystemClang::CompleteTagDeclarationDefinition(type: record_type);
264}
265
266TEST_F(TestTypeSystemClang, TestDisplayName) {
267 TypeSystemClang ast("some name", llvm::Triple());
268 EXPECT_EQ("some name", ast.getDisplayName());
269}
270
271TEST_F(TestTypeSystemClang, TestDisplayNameEmpty) {
272 TypeSystemClang ast("", llvm::Triple());
273 EXPECT_EQ("", ast.getDisplayName());
274}
275
276TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeInvalid) {
277 EXPECT_FALSE(m_ast->GetEnumerationIntegerType(CompilerType()).IsValid());
278}
279
280TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeUnexpectedType) {
281 CompilerType int_type = m_ast->GetBasicType(type: lldb::eBasicTypeInt);
282 CompilerType t = m_ast->GetEnumerationIntegerType(type: int_type);
283 EXPECT_FALSE(t.IsValid());
284}
285
286TEST_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,
291 };
292
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));
297
298 auto holder =
299 std::make_unique<clang_utils::TypeSystemClangHolder>(args: "enum_ast");
300 auto &ast = *holder->GetAST();
301
302 CompilerType basic_compiler_type = ast.GetBasicType(type: basic_type);
303 EXPECT_TRUE(basic_compiler_type.IsValid());
304
305 CompilerType enum_type = ast.CreateEnumerationType(
306 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(),
307 Declaration(), basic_compiler_type, scoped);
308
309 CompilerType t = ast.GetEnumerationIntegerType(type: 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());
312 }
313 }
314}
315
316TEST_F(TestTypeSystemClang, TestEnumerationValueSign) {
317 CompilerType enum_type = m_ast->CreateEnumerationType(
318 "my_enum_signed", m_ast->GetTranslationUnitDecl(),
319 OptionalClangModuleID(), Declaration(),
320 m_ast->GetBasicType(type: lldb::eBasicTypeSignedChar), false);
321 auto *enum_decl = m_ast->AddEnumerationValueToEnumerationType(
322 enum_type, decl: Declaration(), name: "minus_one", enum_value: -1, enum_value_bit_size: 8);
323 EXPECT_TRUE(enum_decl->getInitVal().isSigned());
324}
325
326TEST_F(TestTypeSystemClang, TestOwningModule) {
327 auto holder =
328 std::make_unique<clang_utils::TypeSystemClangHolder>(args: "module_ast");
329 auto &ast = *holder->GetAST();
330 CompilerType basic_compiler_type = ast.GetBasicType(type: BasicType::eBasicTypeInt);
331 CompilerType enum_type = ast.CreateEnumerationType(
332 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(100),
333 Declaration(), basic_compiler_type, false);
334 auto *ed = TypeSystemClang::GetAsEnumDecl(type: enum_type);
335 EXPECT_FALSE(!ed);
336 EXPECT_EQ(ed->getOwningModuleID(), 100u);
337
338 CompilerType record_type = ast.CreateRecordType(
339 decl_ctx: nullptr, owning_module: OptionalClangModuleID(200), access_type: lldb::eAccessPublic, name: "FooRecord",
340 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
341 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
342 auto *rd = TypeSystemClang::GetAsRecordDecl(type: record_type);
343 EXPECT_FALSE(!rd);
344 EXPECT_EQ(rd->getOwningModuleID(), 200u);
345
346 CompilerType class_type =
347 ast.CreateObjCClass("objc_class", ast.GetTranslationUnitDecl(),
348 OptionalClangModuleID(300), false);
349 auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(type: class_type);
350 EXPECT_FALSE(!cd);
351 EXPECT_EQ(cd->getOwningModuleID(), 300u);
352}
353
354TEST_F(TestTypeSystemClang, TestIsClangType) {
355 clang::ASTContext &context = m_ast->getASTContext();
356 lldb::opaque_compiler_type_t bool_ctype =
357 TypeSystemClang::GetOpaqueCompilerType(ast: &context, basic_type: lldb::eBasicTypeBool);
358 CompilerType bool_type(m_ast->weak_from_this(), bool_ctype);
359 CompilerType record_type = m_ast->CreateRecordType(
360 decl_ctx: nullptr, owning_module: OptionalClangModuleID(100), access_type: lldb::eAccessPublic, name: "FooRecord",
361 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
362 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
363 // Clang builtin type and record type should pass
364 EXPECT_TRUE(ClangUtil::IsClangType(bool_type));
365 EXPECT_TRUE(ClangUtil::IsClangType(record_type));
366
367 // Default constructed type should fail
368 EXPECT_FALSE(ClangUtil::IsClangType(CompilerType()));
369}
370
371TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) {
372 CompilerType record_type = m_ast->CreateRecordType(
373 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic, name: "FooRecord",
374 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
375 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
376 QualType qt;
377
378 qt = ClangUtil::GetQualType(ct: record_type);
379 EXPECT_EQ(0u, qt.getLocalFastQualifiers());
380 record_type = record_type.AddConstModifier();
381 record_type = record_type.AddVolatileModifier();
382 record_type = record_type.AddRestrictModifier();
383 qt = ClangUtil::GetQualType(ct: record_type);
384 EXPECT_NE(0u, qt.getLocalFastQualifiers());
385 record_type = ClangUtil::RemoveFastQualifiers(ct: record_type);
386 qt = ClangUtil::GetQualType(ct: record_type);
387 EXPECT_EQ(0u, qt.getLocalFastQualifiers());
388}
389
390TEST_F(TestTypeSystemClang, TestConvertAccessTypeToAccessSpecifier) {
391 EXPECT_EQ(AS_none,
392 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessNone));
393 EXPECT_EQ(AS_none, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
394 eAccessPackage));
395 EXPECT_EQ(AS_public,
396 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessPublic));
397 EXPECT_EQ(AS_private, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
398 eAccessPrivate));
399 EXPECT_EQ(AS_protected, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
400 eAccessProtected));
401}
402
403TEST_F(TestTypeSystemClang, TestUnifyAccessSpecifiers) {
404 // Unifying two of the same type should return the same type
405 EXPECT_EQ(AS_public,
406 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_public));
407 EXPECT_EQ(AS_private,
408 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_private));
409 EXPECT_EQ(AS_protected,
410 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_protected));
411
412 // Otherwise the result should be the strictest of the two.
413 EXPECT_EQ(AS_private,
414 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_public));
415 EXPECT_EQ(AS_private,
416 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_protected));
417 EXPECT_EQ(AS_private,
418 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_private));
419 EXPECT_EQ(AS_private,
420 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_private));
421 EXPECT_EQ(AS_protected,
422 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_public));
423 EXPECT_EQ(AS_protected,
424 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_protected));
425
426 // None is stricter than everything (by convention)
427 EXPECT_EQ(AS_none,
428 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_public));
429 EXPECT_EQ(AS_none,
430 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_protected));
431 EXPECT_EQ(AS_none,
432 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_private));
433 EXPECT_EQ(AS_none,
434 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_none));
435 EXPECT_EQ(AS_none,
436 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_none));
437 EXPECT_EQ(AS_none,
438 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_none));
439}
440
441TEST_F(TestTypeSystemClang, TestRecordHasFields) {
442 CompilerType int_type = m_ast->GetBasicType(type: eBasicTypeInt);
443
444 // Test that a record with no fields returns false
445 CompilerType empty_base = m_ast->CreateRecordType(
446 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic, name: "EmptyBase",
447 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
448 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
449 TypeSystemClang::StartTagDeclarationDefinition(type: empty_base);
450 TypeSystemClang::CompleteTagDeclarationDefinition(type: empty_base);
451
452 RecordDecl *empty_base_decl = TypeSystemClang::GetAsRecordDecl(type: empty_base);
453 EXPECT_NE(nullptr, empty_base_decl);
454 EXPECT_FALSE(m_ast->RecordHasFields(empty_base_decl));
455
456 // Test that a record with direct fields returns true
457 CompilerType non_empty_base = m_ast->CreateRecordType(
458 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic, name: "NonEmptyBase",
459 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
460 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
461 TypeSystemClang::StartTagDeclarationDefinition(type: non_empty_base);
462 FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType(
463 type: non_empty_base, name: "MyField", field_type: int_type, access: eAccessPublic, bitfield_bit_size: 0);
464 TypeSystemClang::CompleteTagDeclarationDefinition(type: non_empty_base);
465 RecordDecl *non_empty_base_decl =
466 TypeSystemClang::GetAsRecordDecl(type: non_empty_base);
467 EXPECT_NE(nullptr, non_empty_base_decl);
468 EXPECT_NE(nullptr, non_empty_base_field_decl);
469 EXPECT_TRUE(m_ast->RecordHasFields(non_empty_base_decl));
470
471 std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
472
473 // Test that a record with no direct fields, but fields in a base returns true
474 CompilerType empty_derived = m_ast->CreateRecordType(
475 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic, name: "EmptyDerived",
476 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
477 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
478 TypeSystemClang::StartTagDeclarationDefinition(type: empty_derived);
479 std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec =
480 m_ast->CreateBaseClassSpecifier(type: non_empty_base.GetOpaqueQualType(),
481 access: lldb::eAccessPublic, is_virtual: false, base_of_class: false);
482 bases.push_back(x: std::move(non_empty_base_spec));
483 bool result = m_ast->TransferBaseClasses(type: empty_derived.GetOpaqueQualType(),
484 bases: std::move(bases));
485 TypeSystemClang::CompleteTagDeclarationDefinition(type: empty_derived);
486 EXPECT_TRUE(result);
487 CXXRecordDecl *empty_derived_non_empty_base_cxx_decl =
488 m_ast->GetAsCXXRecordDecl(type: empty_derived.GetOpaqueQualType());
489 RecordDecl *empty_derived_non_empty_base_decl =
490 TypeSystemClang::GetAsRecordDecl(type: empty_derived);
491 EXPECT_EQ(1u, m_ast->GetNumBaseClasses(
492 empty_derived_non_empty_base_cxx_decl, false));
493 EXPECT_TRUE(m_ast->RecordHasFields(empty_derived_non_empty_base_decl));
494
495 // Test that a record with no direct fields, but fields in a virtual base
496 // returns true
497 CompilerType empty_derived2 = m_ast->CreateRecordType(
498 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic, name: "EmptyDerived2",
499 kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
500 language: lldb::eLanguageTypeC_plus_plus, metadata: std::nullopt);
501 TypeSystemClang::StartTagDeclarationDefinition(type: empty_derived2);
502 std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec =
503 m_ast->CreateBaseClassSpecifier(type: non_empty_base.GetOpaqueQualType(),
504 access: lldb::eAccessPublic, is_virtual: true, base_of_class: false);
505 bases.push_back(x: std::move(non_empty_vbase_spec));
506 result = m_ast->TransferBaseClasses(type: empty_derived2.GetOpaqueQualType(),
507 bases: std::move(bases));
508 TypeSystemClang::CompleteTagDeclarationDefinition(type: empty_derived2);
509 EXPECT_TRUE(result);
510 CXXRecordDecl *empty_derived_non_empty_vbase_cxx_decl =
511 m_ast->GetAsCXXRecordDecl(type: empty_derived2.GetOpaqueQualType());
512 RecordDecl *empty_derived_non_empty_vbase_decl =
513 TypeSystemClang::GetAsRecordDecl(type: empty_derived2);
514 EXPECT_EQ(1u, m_ast->GetNumBaseClasses(
515 empty_derived_non_empty_vbase_cxx_decl, false));
516 EXPECT_TRUE(
517 m_ast->RecordHasFields(empty_derived_non_empty_vbase_decl));
518}
519
520TEST_F(TestTypeSystemClang, TemplateArguments) {
521 TypeSystemClang::TemplateParameterInfos infos;
522 infos.InsertArg(name: "T", arg: TemplateArgument(m_ast->getASTContext().IntTy));
523
524 llvm::APSInt arg(llvm::APInt(8, 47));
525 infos.InsertArg(name: "I", arg: TemplateArgument(m_ast->getASTContext(), arg,
526 m_ast->getASTContext().IntTy));
527
528 llvm::APFloat float_arg(5.5f);
529 infos.InsertArg(name: "F", arg: TemplateArgument(m_ast->getASTContext(),
530 m_ast->getASTContext().FloatTy,
531 clang::APValue(float_arg)));
532
533 llvm::APFloat double_arg(-15.2);
534 infos.InsertArg(name: "D", arg: TemplateArgument(m_ast->getASTContext(),
535 m_ast->getASTContext().DoubleTy,
536 clang::APValue(double_arg)));
537
538 // template<typename T, int I, float F, double D> struct foo;
539 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(
540 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,
541 "foo", llvm::to_underlying(E: clang::TagTypeKind::Struct), infos);
542 ASSERT_NE(decl, nullptr);
543
544 // foo<int, 47>
545 ClassTemplateSpecializationDecl *spec_decl =
546 m_ast->CreateClassTemplateSpecializationDecl(
547 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl,
548 llvm::to_underlying(E: clang::TagTypeKind::Struct), infos);
549 ASSERT_NE(spec_decl, nullptr);
550 CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl);
551 ASSERT_TRUE(type);
552 m_ast->StartTagDeclarationDefinition(type);
553 m_ast->CompleteTagDeclarationDefinition(type);
554
555 // typedef foo<int, 47> foo_def;
556 CompilerType typedef_type = type.CreateTypedef(
557 name: "foo_def", decl_ctx: m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), payload: 0);
558
559 CompilerType auto_type(
560 m_ast->weak_from_this(),
561 m_ast->getASTContext()
562 .getAutoType(DeducedType: ClangUtil::GetCanonicalQualType(ct: typedef_type),
563 Keyword: clang::AutoTypeKeyword::Auto, IsDependent: false)
564 .getAsOpaquePtr());
565
566 CompilerType int_type(m_ast->weak_from_this(),
567 m_ast->getASTContext().IntTy.getAsOpaquePtr());
568 CompilerType float_type(m_ast->weak_from_this(),
569 m_ast->getASTContext().FloatTy.getAsOpaquePtr());
570 CompilerType double_type(m_ast->weak_from_this(),
571 m_ast->getASTContext().DoubleTy.getAsOpaquePtr());
572 for (CompilerType t : {type, typedef_type, auto_type}) {
573 SCOPED_TRACE(t.GetTypeName().AsCString());
574
575 const bool expand_pack = false;
576 EXPECT_EQ(
577 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0, expand_pack),
578 eTemplateArgumentKindType);
579 EXPECT_EQ(
580 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0, expand_pack),
581 int_type);
582 EXPECT_EQ(std::nullopt, m_ast->GetIntegralTemplateArgument(
583 t.GetOpaqueQualType(), 0, expand_pack));
584
585 EXPECT_EQ(
586 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1, expand_pack),
587 eTemplateArgumentKindIntegral);
588 EXPECT_EQ(
589 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1, expand_pack),
590 CompilerType());
591 auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1,
592 expand_pack);
593 ASSERT_NE(std::nullopt, result);
594 EXPECT_EQ(arg, result->value.GetAPSInt());
595 EXPECT_EQ(int_type, result->type);
596
597 EXPECT_EQ(
598 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 2, expand_pack),
599 eTemplateArgumentKindStructuralValue);
600 EXPECT_EQ(
601 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 2, expand_pack),
602 CompilerType());
603 auto float_result = m_ast->GetIntegralTemplateArgument(
604 t.GetOpaqueQualType(), 2, expand_pack);
605 ASSERT_NE(std::nullopt, float_result);
606 EXPECT_EQ(float_arg, float_result->value.GetAPFloat());
607 EXPECT_EQ(float_type, float_result->type);
608
609 EXPECT_EQ(
610 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 3, expand_pack),
611 eTemplateArgumentKindStructuralValue);
612 EXPECT_EQ(
613 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 3, expand_pack),
614 CompilerType());
615 auto double_result = m_ast->GetIntegralTemplateArgument(
616 t.GetOpaqueQualType(), 3, expand_pack);
617 ASSERT_NE(std::nullopt, double_result);
618 EXPECT_EQ(double_arg, double_result->value.GetAPFloat());
619 EXPECT_EQ(double_type, double_result->type);
620 }
621}
622
623class TestCreateClassTemplateDecl : public TestTypeSystemClang {
624protected:
625 /// The class templates created so far by the Expect* functions below.
626 llvm::DenseSet<ClassTemplateDecl *> m_created_templates;
627
628 /// Utility function for creating a class template.
629 ClassTemplateDecl *
630 CreateClassTemplate(const TypeSystemClang::TemplateParameterInfos &infos) {
631 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(
632 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,
633 "foo", llvm::to_underlying(E: clang::TagTypeKind::Struct), infos);
634 return decl;
635 }
636
637 /// Creates a new class template with the given template parameters.
638 /// Asserts that a new ClassTemplateDecl is created.
639 /// \param description The gtest scope string that should describe the input.
640 /// \param infos The template parameters that the class template should have.
641 /// \returns The created ClassTemplateDecl.
642 ClassTemplateDecl *
643 ExpectNewTemplate(std::string description,
644 const TypeSystemClang::TemplateParameterInfos &infos) {
645 SCOPED_TRACE(description);
646 ClassTemplateDecl *first_template = CreateClassTemplate(infos);
647 // A new template should have been created.
648 EXPECT_FALSE(m_created_templates.contains(first_template))
649 << "Didn't create new class template but reused this existing decl:\n"
650 << ClangUtil::DumpDecl(first_template);
651 m_created_templates.insert(V: first_template);
652
653 // Creating a new template with the same arguments should always return
654 // the template created above.
655 ClassTemplateDecl *second_template = CreateClassTemplate(infos);
656 EXPECT_EQ(first_template, second_template)
657 << "Second attempt to create class template didn't reuse first decl:\n"
658 << ClangUtil::DumpDecl(first_template) << "\nInstead created/reused:\n"
659 << ClangUtil::DumpDecl(second_template);
660 return first_template;
661 }
662
663 /// Tries to create a new class template but asserts that an existing class
664 /// template in the current AST is reused (in contract so a new class
665 /// template being created).
666 /// \param description The gtest scope string that should describe the input.
667 /// \param infos The template parameters that the class template should have.
668 void
669 ExpectReusedTemplate(std::string description,
670 const TypeSystemClang::TemplateParameterInfos &infos,
671 ClassTemplateDecl *expected) {
672 SCOPED_TRACE(description);
673 ClassTemplateDecl *td = CreateClassTemplate(infos);
674 EXPECT_EQ(td, expected)
675 << "Created/reused class template is:\n"
676 << ClangUtil::DumpDecl(td) << "\nExpected to reuse:\n"
677 << ClangUtil::DumpDecl(expected);
678 }
679};
680
681TEST_F(TestCreateClassTemplateDecl, FindExistingTemplates) {
682 // This tests the logic in TypeSystemClang::CreateClassTemplateDecl that
683 // decides whether an existing ClassTemplateDecl in the AST can be reused.
684 // The behaviour should follow the C++ rules for redeclaring templates
685 // (e.g., parameter names can be changed/omitted.)
686
687 // Test an empty template parameter list: <>
688 ExpectNewTemplate(description: "<>", infos: {{}, {}});
689
690 clang::TemplateArgument intArg(m_ast->getASTContext().IntTy);
691 clang::TemplateArgument int47Arg(m_ast->getASTContext(),
692 llvm::APSInt(llvm::APInt(32, 47)),
693 m_ast->getASTContext().IntTy);
694 clang::TemplateArgument floatArg(m_ast->getASTContext().FloatTy);
695 clang::TemplateArgument char47Arg(m_ast->getASTContext(),
696 llvm::APSInt(llvm::APInt(8, 47)),
697 m_ast->getASTContext().SignedCharTy);
698
699 clang::TemplateArgument char123Arg(m_ast->getASTContext(),
700 llvm::APSInt(llvm::APInt(8, 123)),
701 m_ast->getASTContext().SignedCharTy);
702
703 // Test that <typename T> with T = int creates a new template.
704 ClassTemplateDecl *single_type_arg =
705 ExpectNewTemplate(description: "<typename T>", infos: {{"T"}, {intArg}});
706
707 // Test that changing the parameter name doesn't create a new class template.
708 ExpectReusedTemplate(description: "<typename A> (A = int)", infos: {{"A"}, {intArg}},
709 expected: single_type_arg);
710
711 // Test that changing the used type doesn't create a new class template.
712 ExpectReusedTemplate(description: "<typename A> (A = float)", infos: {{"A"}, {floatArg}},
713 expected: single_type_arg);
714
715 // Test that <typename A, signed char I> creates a new template with A = int
716 // and I = 47;
717 ClassTemplateDecl *type_and_char_value =
718 ExpectNewTemplate("<typename A, signed char I> (I = 47)",
719 {{"A", "I"}, {floatArg, char47Arg}});
720
721 // Change the value of the I parameter to 123. The previously created
722 // class template should still be reused.
723 ExpectReusedTemplate("<typename A, signed char I> (I = 123)",
724 {{"A", "I"}, {floatArg, char123Arg}},
725 type_and_char_value);
726
727 // Change the type of the I parameter to int so we have <typename A, int I>.
728 // The class template from above can't be reused.
729 ExpectNewTemplate("<typename A, int I> (I = 123)",
730 {{"A", "I"}, {floatArg, int47Arg}});
731
732 // Test a second type parameter will also cause a new template to be created.
733 // We now have <typename A, int I, typename B>.
734 ClassTemplateDecl *type_and_char_value_and_type =
735 ExpectNewTemplate("<typename A, int I, typename B>",
736 {{"A", "I", "B"}, {floatArg, int47Arg, intArg}});
737
738 // Remove all the names from the parameters which shouldn't influence the
739 // way the templates get merged.
740 ExpectReusedTemplate("<typename, int, typename>",
741 {{"", "", ""}, {floatArg, int47Arg, intArg}},
742 type_and_char_value_and_type);
743}
744
745TEST_F(TestCreateClassTemplateDecl, FindExistingTemplatesWithParameterPack) {
746 // The same as FindExistingTemplates but for templates with parameter packs.
747 TypeSystemClang::TemplateParameterInfos infos;
748 clang::TemplateArgument intArg(m_ast->getASTContext().IntTy);
749 clang::TemplateArgument int1Arg(m_ast->getASTContext(),
750 llvm::APSInt(llvm::APInt(32, 1)),
751 m_ast->getASTContext().IntTy);
752 clang::TemplateArgument int123Arg(m_ast->getASTContext(),
753 llvm::APSInt(llvm::APInt(32, 123)),
754 m_ast->getASTContext().IntTy);
755 clang::TemplateArgument longArg(m_ast->getASTContext().LongTy);
756 clang::TemplateArgument long1Arg(m_ast->getASTContext(),
757 llvm::APSInt(llvm::APInt(64, 1)),
758 m_ast->getASTContext().LongTy);
759
760 infos.SetParameterPack(
761 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
762 args: llvm::SmallVector<const char *>{"", ""},
763 args: llvm::SmallVector<TemplateArgument>{intArg, intArg}));
764
765 ClassTemplateDecl *type_pack =
766 ExpectNewTemplate(description: "<typename ...> (int, int)", infos);
767
768 // Special case: An instantiation for a parameter pack with no values fits
769 // to whatever class template we find. There isn't enough information to
770 // do an actual comparison here.
771 infos.SetParameterPack(
772 std::make_unique<TypeSystemClang::TemplateParameterInfos>());
773 ExpectReusedTemplate(description: "<...> (no values in pack)", infos, expected: type_pack);
774
775 // Change the type content of pack type values.
776 infos.SetParameterPack(
777 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
778 args: llvm::SmallVector<const char *>{"", ""},
779 args: llvm::SmallVector<TemplateArgument>{intArg, longArg}));
780 ExpectReusedTemplate(description: "<typename ...> (int, long)", infos, expected: type_pack);
781
782 // Change the number of pack values.
783 infos.SetParameterPack(
784 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
785 args: llvm::SmallVector<const char *>{""},
786 args: llvm::SmallVector<TemplateArgument>{intArg}));
787 ExpectReusedTemplate(description: "<typename ...> (int)", infos, expected: type_pack);
788
789 // The names of the pack values shouldn't matter.
790 infos.SetParameterPack(
791 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
792 args: llvm::SmallVector<const char *>{"A"},
793 args: llvm::SmallVector<TemplateArgument>{intArg}));
794 ExpectReusedTemplate(description: "<typename ...> (int)", infos, expected: type_pack);
795
796 // Changing the kind of template argument will create a new template.
797 infos.SetParameterPack(
798 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
799 args: llvm::SmallVector<const char *>{"A"},
800 args: llvm::SmallVector<TemplateArgument>{int1Arg}));
801 ClassTemplateDecl *int_pack = ExpectNewTemplate(description: "<int ...> (int = 1)", infos);
802
803 // Changing the value of integral parameters will not create a new template.
804 infos.SetParameterPack(
805 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
806 args: llvm::SmallVector<const char *>{"A"},
807 args: llvm::SmallVector<TemplateArgument>{int123Arg}));
808 ExpectReusedTemplate(description: "<int ...> (int = 123)", infos, expected: int_pack);
809
810 // Changing the integral type will create a new template.
811 infos.SetParameterPack(
812 std::make_unique<TypeSystemClang::TemplateParameterInfos>(
813 args: llvm::SmallVector<const char *>{"A"},
814 args: llvm::SmallVector<TemplateArgument>{long1Arg}));
815 ExpectNewTemplate(description: "<long ...> (long = 1)", infos);
816
817 // Prependinding a non-pack parameter will create a new template.
818 infos.InsertArg(name: "T", arg: intArg);
819 ExpectNewTemplate(description: "<typename T, long...> (T = int, long = 1)", infos);
820}
821
822TEST_F(TestTypeSystemClang, OnlyPackName) {
823 TypeSystemClang::TemplateParameterInfos infos;
824 infos.SetPackName("A");
825 EXPECT_FALSE(infos.IsValid());
826}
827
828static QualType makeConstInt(clang::ASTContext &ctxt) {
829 QualType result(ctxt.IntTy);
830 result.addConst();
831 return result;
832}
833
834TEST_F(TestTypeSystemClang, TestGetTypeClassDeclType) {
835 clang::ASTContext &ctxt = m_ast->getASTContext();
836 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
837 QualType t = ctxt.getDecltypeType(e: nullptr_expr, UnderlyingType: makeConstInt(ctxt));
838 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
839}
840
841TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOf) {
842 clang::ASTContext &ctxt = m_ast->getASTContext();
843 QualType t = ctxt.getTypeOfType(QT: makeConstInt(ctxt), Kind: TypeOfKind::Qualified);
844 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
845}
846
847TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOfExpr) {
848 clang::ASTContext &ctxt = m_ast->getASTContext();
849 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
850 QualType t = ctxt.getTypeOfExprType(E: nullptr_expr, Kind: TypeOfKind::Qualified);
851 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
852}
853
854TEST_F(TestTypeSystemClang, TestGetTypeClassNested) {
855 clang::ASTContext &ctxt = m_ast->getASTContext();
856 QualType t_base =
857 ctxt.getTypeOfType(QT: makeConstInt(ctxt), Kind: TypeOfKind::Qualified);
858 QualType t = ctxt.getTypeOfType(QT: t_base, Kind: TypeOfKind::Qualified);
859 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
860}
861
862TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {
863 // Tests creating a function template.
864
865 CompilerType int_type = m_ast->GetBasicType(type: lldb::eBasicTypeInt);
866 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
867
868 // Prepare the declarations/types we need for the template.
869 CompilerType clang_type = m_ast->CreateFunctionType(result_type: int_type, args: {}, is_variadic: false, type_quals: 0U);
870 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
871 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
872 false);
873 TypeSystemClang::TemplateParameterInfos empty_params;
874
875 // Create the actual function template.
876 clang::FunctionTemplateDecl *func_template =
877 m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func,
878 empty_params);
879
880 EXPECT_EQ(TU, func_template->getDeclContext());
881 EXPECT_EQ("foo", func_template->getName());
882 EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess());
883}
884
885TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {
886 // Tests creating a function template inside a record.
887
888 CompilerType int_type = m_ast->GetBasicType(type: lldb::eBasicTypeInt);
889 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
890
891 // Create a record we can put the function template int.
892 CompilerType record_type =
893 clang_utils::createRecordWithField(ast&: *m_ast, record_name: "record", field_type: int_type, field_name: "field");
894 clang::TagDecl *record = ClangUtil::GetAsTagDecl(type: record_type);
895
896 // Prepare the declarations/types we need for the template.
897 CompilerType clang_type = m_ast->CreateFunctionType(result_type: int_type, args: {}, is_variadic: false, type_quals: 0U);
898 // We create the FunctionDecl for the template in the TU DeclContext because:
899 // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can).
900 // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
901 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
902 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
903 false);
904 TypeSystemClang::TemplateParameterInfos empty_params;
905
906 // Create the actual function template.
907 clang::FunctionTemplateDecl *func_template =
908 m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func,
909 empty_params);
910
911 EXPECT_EQ(record, func_template->getDeclContext());
912 EXPECT_EQ("foo", func_template->getName());
913 EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess());
914}
915
916TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) {
917 // We need to simulate this behavior in our AST that we construct as we don't
918 // have a Sema instance that can do this for us:
919 // C++11 [class.copy]p7, p18:
920 // If the class definition declares a move constructor or move assignment
921 // operator, an implicitly declared copy constructor or copy assignment
922 // operator is defined as deleted.
923
924 // Create a record and start defining it.
925 llvm::StringRef class_name = "S";
926 CompilerType t = clang_utils::createRecord(ast&: *m_ast, name: class_name);
927 m_ast->StartTagDeclarationDefinition(type: t);
928
929 // Create a move constructor that will delete the implicit copy constructor.
930 CompilerType return_type = m_ast->GetBasicType(type: lldb::eBasicTypeVoid);
931 std::array<CompilerType, 1> args{t.GetRValueReferenceType()};
932 CompilerType function_type = m_ast->CreateFunctionType(
933 result_type: return_type, args, /*variadic=*/is_variadic: false, /*quals*/ type_quals: 0U);
934 bool is_virtual = false;
935 bool is_static = false;
936 bool is_inline = false;
937 bool is_explicit = true;
938 bool is_attr_used = false;
939 bool is_artificial = false;
940 m_ast->AddMethodToCXXRecordType(
941 type: t.GetOpaqueQualType(), name: class_name, mangled_name: nullptr, method_type: function_type,
942 access: lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
943 is_explicit, is_attr_used, is_artificial);
944
945 // Complete the definition and check the created record.
946 m_ast->CompleteTagDeclarationDefinition(type: t);
947 auto *record = llvm::cast<CXXRecordDecl>(Val: ClangUtil::GetAsTagDecl(type: t));
948 // We can't call defaultedCopyConstructorIsDeleted() as this requires that
949 // the Decl passes through Sema which will actually compute this field.
950 // Instead we check that there is no copy constructor declared by the user
951 // which only leaves a non-deleted defaulted copy constructor as an option
952 // that our record will have no simple copy constructor.
953 EXPECT_FALSE(record->hasUserDeclaredCopyConstructor());
954 EXPECT_FALSE(record->hasSimpleCopyConstructor());
955}
956
957TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {
958 // Tests that we don't delete the a user-defined copy constructor when
959 // a move constructor is provided.
960 // See also the TestDeletingImplicitCopyCstrDueToMoveCStr test.
961 llvm::StringRef class_name = "S";
962 CompilerType t = clang_utils::createRecord(ast&: *m_ast, name: class_name);
963 m_ast->StartTagDeclarationDefinition(type: t);
964
965 CompilerType return_type = m_ast->GetBasicType(type: lldb::eBasicTypeVoid);
966 bool is_virtual = false;
967 bool is_static = false;
968 bool is_inline = false;
969 bool is_explicit = true;
970 bool is_attr_used = false;
971 bool is_artificial = false;
972 // Create a move constructor.
973 {
974 std::array<CompilerType, 1> args{t.GetRValueReferenceType()};
975 CompilerType function_type = m_ast->CreateFunctionType(
976 result_type: return_type, args, /*variadic=*/is_variadic: false, /*quals*/ type_quals: 0U);
977 m_ast->AddMethodToCXXRecordType(
978 type: t.GetOpaqueQualType(), name: class_name, mangled_name: nullptr, method_type: function_type,
979 access: lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
980 is_explicit, is_attr_used, is_artificial);
981 }
982 // Create a copy constructor.
983 {
984 std::array<CompilerType, 1> args{
985 t.GetLValueReferenceType().AddConstModifier()};
986 CompilerType function_type =
987 m_ast->CreateFunctionType(result_type: return_type, args,
988 /*variadic=*/is_variadic: false, /*quals*/ type_quals: 0U);
989 m_ast->AddMethodToCXXRecordType(
990 type: t.GetOpaqueQualType(), name: class_name, mangled_name: nullptr, method_type: function_type,
991 access: lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
992 is_explicit, is_attr_used, is_artificial);
993 }
994
995 // Complete the definition and check the created record.
996 m_ast->CompleteTagDeclarationDefinition(type: t);
997 auto *record = llvm::cast<CXXRecordDecl>(Val: ClangUtil::GetAsTagDecl(type: t));
998 EXPECT_TRUE(record->hasUserDeclaredCopyConstructor());
999}
1000
1001TEST_F(TestTypeSystemClang, AddMethodToObjCObjectType) {
1002 // Create an interface decl and mark it as having external storage.
1003 CompilerType c = m_ast->CreateObjCClass("A", m_ast->GetTranslationUnitDecl(),
1004 OptionalClangModuleID(),
1005 /*IsInternal*/ false);
1006 ObjCInterfaceDecl *interface = m_ast->GetAsObjCInterfaceDecl(type: c);
1007 m_ast->SetHasExternalStorage(type: c.GetOpaqueQualType(), has_extern: true);
1008 EXPECT_TRUE(interface->hasExternalLexicalStorage());
1009
1010 // Add a method to the interface.
1011 std::vector<CompilerType> args;
1012 CompilerType func_type = m_ast->CreateFunctionType(
1013 result_type: m_ast->GetBasicType(type: lldb::eBasicTypeInt), args, /*variadic*/ is_variadic: false,
1014 /*quals*/ type_quals: 0, cc: clang::CallingConv::CC_C);
1015 bool variadic = false;
1016 bool artificial = false;
1017 bool objc_direct = false;
1018 clang::ObjCMethodDecl *method = TypeSystemClang::AddMethodToObjCObjectType(
1019 type: c, name: "-[A foo]", method_compiler_type: func_type, is_artificial: artificial, is_variadic: variadic, is_objc_direct_call: objc_direct);
1020 ASSERT_NE(method, nullptr);
1021
1022 // The interface decl should still have external lexical storage.
1023 EXPECT_TRUE(interface->hasExternalLexicalStorage());
1024
1025 // Test some properties of the created ObjCMethodDecl.
1026 EXPECT_FALSE(method->isVariadic());
1027 EXPECT_TRUE(method->isImplicit());
1028 EXPECT_FALSE(method->isDirectMethod());
1029 EXPECT_EQ(method->getDeclName().getObjCSelector().getAsString(), "foo");
1030}
1031
1032TEST_F(TestTypeSystemClang, GetFullyUnqualifiedType) {
1033 CompilerType bool_ = m_ast->GetBasicType(type: eBasicTypeBool);
1034 CompilerType cv_bool = bool_.AddConstModifier().AddVolatileModifier();
1035
1036 // const volatile bool -> bool
1037 EXPECT_EQ(bool_, cv_bool.GetFullyUnqualifiedType());
1038
1039 // const volatile bool[47] -> bool[47]
1040 EXPECT_EQ(bool_.GetArrayType(47),
1041 cv_bool.GetArrayType(47).GetFullyUnqualifiedType());
1042
1043 // const volatile bool[47][42] -> bool[47][42]
1044 EXPECT_EQ(
1045 bool_.GetArrayType(42).GetArrayType(47),
1046 cv_bool.GetArrayType(42).GetArrayType(47).GetFullyUnqualifiedType());
1047
1048 // const volatile bool * -> bool *
1049 EXPECT_EQ(bool_.GetPointerType(),
1050 cv_bool.GetPointerType().GetFullyUnqualifiedType());
1051
1052 // const volatile bool *[47] -> bool *[47]
1053 EXPECT_EQ(
1054 bool_.GetPointerType().GetArrayType(47),
1055 cv_bool.GetPointerType().GetArrayType(47).GetFullyUnqualifiedType());
1056}
1057
1058TEST(TestScratchTypeSystemClang, InferSubASTFromLangOpts) {
1059 LangOptions lang_opts;
1060 EXPECT_EQ(
1061 ScratchTypeSystemClang::DefaultAST,
1062 ScratchTypeSystemClang::InferIsolatedASTKindFromLangOpts(lang_opts));
1063
1064 lang_opts.Modules = true;
1065 EXPECT_EQ(
1066 ScratchTypeSystemClang::IsolatedASTKind::CppModules,
1067 ScratchTypeSystemClang::InferIsolatedASTKindFromLangOpts(lang_opts));
1068}
1069
1070TEST_F(TestTypeSystemClang, GetDeclContextByNameWhenMissingSymbolFile) {
1071 // Test that a type system without a symbol file is handled gracefully.
1072 std::vector<CompilerDecl> decls =
1073 m_ast->DeclContextFindDeclByName(opaque_decl_ctx: nullptr, name: ConstString("SomeName"), ignore_using_decls: true);
1074
1075 EXPECT_TRUE(decls.empty());
1076}
1077
1078TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) {
1079 // Tests that AddMethodToCXXRecordType creates ParmVarDecl's with
1080 // a correct clang::DeclContext.
1081
1082 llvm::StringRef class_name = "S";
1083 CompilerType t = clang_utils::createRecord(ast&: *m_ast, name: class_name);
1084 m_ast->StartTagDeclarationDefinition(type: t);
1085
1086 CompilerType return_type = m_ast->GetBasicType(type: lldb::eBasicTypeVoid);
1087 const bool is_virtual = false;
1088 const bool is_static = false;
1089 const bool is_inline = false;
1090 const bool is_explicit = true;
1091 const bool is_attr_used = false;
1092 const bool is_artificial = false;
1093
1094 llvm::SmallVector<CompilerType> param_types{
1095 m_ast->GetBasicType(type: lldb::eBasicTypeInt),
1096 m_ast->GetBasicType(type: lldb::eBasicTypeShort)};
1097 CompilerType function_type =
1098 m_ast->CreateFunctionType(result_type: return_type, args: param_types,
1099 /*variadic=*/is_variadic: false, /*quals*/ type_quals: 0U);
1100 m_ast->AddMethodToCXXRecordType(
1101 type: t.GetOpaqueQualType(), name: "myFunc", mangled_name: nullptr, method_type: function_type,
1102 access: lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
1103 is_explicit, is_attr_used, is_artificial);
1104
1105 // Complete the definition and check the created record.
1106 m_ast->CompleteTagDeclarationDefinition(type: t);
1107
1108 auto *record = llvm::cast<CXXRecordDecl>(Val: ClangUtil::GetAsTagDecl(type: t));
1109
1110 auto method_it = record->method_begin();
1111 ASSERT_NE(method_it, record->method_end());
1112
1113 EXPECT_EQ(method_it->getNumParams(), param_types.size());
1114
1115 // DeclContext of each parameter should be the CXXMethodDecl itself.
1116 EXPECT_EQ(method_it->getParamDecl(0)->getDeclContext(), *method_it);
1117 EXPECT_EQ(method_it->getParamDecl(1)->getDeclContext(), *method_it);
1118}
1119

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