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/Host/FileSystem.h"
14 #include "lldb/Host/HostInfo.h"
15 #include "lldb/Symbol/Declaration.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
21 using namespace clang;
22 using namespace lldb;
23 using namespace lldb_private;
24
25 class TestTypeSystemClang : public testing::Test {
26 public:
27 SubsystemRAII<FileSystem, HostInfo> subsystems;
28
SetUp()29 void SetUp() override {
30 m_ast.reset(
31 new TypeSystemClang("test ASTContext", HostInfo::GetTargetTriple()));
32 }
33
TearDown()34 void TearDown() override { m_ast.reset(); }
35
36 protected:
37 std::unique_ptr<TypeSystemClang> m_ast;
38
GetBasicQualType(BasicType type) const39 QualType GetBasicQualType(BasicType type) const {
40 return ClangUtil::GetQualType(m_ast->GetBasicTypeFromAST(type));
41 }
42
GetBasicQualType(const char * name) const43 QualType GetBasicQualType(const char *name) const {
44 return ClangUtil::GetQualType(
45 m_ast->GetBuiltinTypeByName(ConstString(name)));
46 }
47 };
48
TEST_F(TestTypeSystemClang,TestGetBasicTypeFromEnum)49 TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
50 clang::ASTContext &context = m_ast->getASTContext();
51
52 EXPECT_TRUE(
53 context.hasSameType(GetBasicQualType(eBasicTypeBool), context.BoolTy));
54 EXPECT_TRUE(
55 context.hasSameType(GetBasicQualType(eBasicTypeChar), context.CharTy));
56 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar16),
57 context.Char16Ty));
58 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar32),
59 context.Char32Ty));
60 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeDouble),
61 context.DoubleTy));
62 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeDoubleComplex),
63 context.DoubleComplexTy));
64 EXPECT_TRUE(
65 context.hasSameType(GetBasicQualType(eBasicTypeFloat), context.FloatTy));
66 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeFloatComplex),
67 context.FloatComplexTy));
68 EXPECT_TRUE(
69 context.hasSameType(GetBasicQualType(eBasicTypeHalf), context.HalfTy));
70 EXPECT_TRUE(
71 context.hasSameType(GetBasicQualType(eBasicTypeInt), context.IntTy));
72 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeInt128),
73 context.Int128Ty));
74 EXPECT_TRUE(
75 context.hasSameType(GetBasicQualType(eBasicTypeLong), context.LongTy));
76 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongDouble),
77 context.LongDoubleTy));
78 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongDoubleComplex),
79 context.LongDoubleComplexTy));
80 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongLong),
81 context.LongLongTy));
82 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeNullPtr),
83 context.NullPtrTy));
84 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCClass),
85 context.getObjCClassType()));
86 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCID),
87 context.getObjCIdType()));
88 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCSel),
89 context.getObjCSelType()));
90 EXPECT_TRUE(
91 context.hasSameType(GetBasicQualType(eBasicTypeShort), context.ShortTy));
92 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeSignedChar),
93 context.SignedCharTy));
94 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedChar),
95 context.UnsignedCharTy));
96 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedInt),
97 context.UnsignedIntTy));
98 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedInt128),
99 context.UnsignedInt128Ty));
100 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedLong),
101 context.UnsignedLongTy));
102 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedLongLong),
103 context.UnsignedLongLongTy));
104 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedShort),
105 context.UnsignedShortTy));
106 EXPECT_TRUE(
107 context.hasSameType(GetBasicQualType(eBasicTypeVoid), context.VoidTy));
108 EXPECT_TRUE(
109 context.hasSameType(GetBasicQualType(eBasicTypeWChar), context.WCharTy));
110 }
111
TEST_F(TestTypeSystemClang,TestGetBasicTypeFromName)112 TEST_F(TestTypeSystemClang, TestGetBasicTypeFromName) {
113 EXPECT_EQ(GetBasicQualType(eBasicTypeChar), GetBasicQualType("char"));
114 EXPECT_EQ(GetBasicQualType(eBasicTypeSignedChar),
115 GetBasicQualType("signed char"));
116 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedChar),
117 GetBasicQualType("unsigned char"));
118 EXPECT_EQ(GetBasicQualType(eBasicTypeWChar), GetBasicQualType("wchar_t"));
119 EXPECT_EQ(GetBasicQualType(eBasicTypeSignedWChar),
120 GetBasicQualType("signed wchar_t"));
121 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedWChar),
122 GetBasicQualType("unsigned wchar_t"));
123 EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short"));
124 EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short int"));
125 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort),
126 GetBasicQualType("unsigned short"));
127 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort),
128 GetBasicQualType("unsigned short int"));
129 EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("int"));
130 EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("signed int"));
131 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt),
132 GetBasicQualType("unsigned int"));
133 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt),
134 GetBasicQualType("unsigned"));
135 EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long"));
136 EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long int"));
137 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong),
138 GetBasicQualType("unsigned long"));
139 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong),
140 GetBasicQualType("unsigned long int"));
141 EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong),
142 GetBasicQualType("long long"));
143 EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong),
144 GetBasicQualType("long long int"));
145 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong),
146 GetBasicQualType("unsigned long long"));
147 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong),
148 GetBasicQualType("unsigned long long int"));
149 EXPECT_EQ(GetBasicQualType(eBasicTypeInt128), GetBasicQualType("__int128_t"));
150 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt128),
151 GetBasicQualType("__uint128_t"));
152 EXPECT_EQ(GetBasicQualType(eBasicTypeVoid), GetBasicQualType("void"));
153 EXPECT_EQ(GetBasicQualType(eBasicTypeBool), GetBasicQualType("bool"));
154 EXPECT_EQ(GetBasicQualType(eBasicTypeFloat), GetBasicQualType("float"));
155 EXPECT_EQ(GetBasicQualType(eBasicTypeDouble), GetBasicQualType("double"));
156 EXPECT_EQ(GetBasicQualType(eBasicTypeLongDouble),
157 GetBasicQualType("long double"));
158 EXPECT_EQ(GetBasicQualType(eBasicTypeObjCID), GetBasicQualType("id"));
159 EXPECT_EQ(GetBasicQualType(eBasicTypeObjCSel), GetBasicQualType("SEL"));
160 EXPECT_EQ(GetBasicQualType(eBasicTypeNullPtr), GetBasicQualType("nullptr"));
161 }
162
VerifyEncodingAndBitSize(TypeSystemClang & clang_context,lldb::Encoding encoding,unsigned int bit_size)163 void VerifyEncodingAndBitSize(TypeSystemClang &clang_context,
164 lldb::Encoding encoding, unsigned int bit_size) {
165 clang::ASTContext &context = clang_context.getASTContext();
166
167 CompilerType type =
168 clang_context.GetBuiltinTypeForEncodingAndBitSize(encoding, bit_size);
169 EXPECT_TRUE(type.IsValid());
170
171 QualType qtype = ClangUtil::GetQualType(type);
172 EXPECT_FALSE(qtype.isNull());
173 if (qtype.isNull())
174 return;
175
176 uint64_t actual_size = context.getTypeSize(qtype);
177 EXPECT_EQ(bit_size, actual_size);
178
179 const clang::Type *type_ptr = qtype.getTypePtr();
180 EXPECT_NE(nullptr, type_ptr);
181 if (!type_ptr)
182 return;
183
184 EXPECT_TRUE(type_ptr->isBuiltinType());
185 switch (encoding) {
186 case eEncodingSint:
187 EXPECT_TRUE(type_ptr->isSignedIntegerType());
188 break;
189 case eEncodingUint:
190 EXPECT_TRUE(type_ptr->isUnsignedIntegerType());
191 break;
192 case eEncodingIEEE754:
193 EXPECT_TRUE(type_ptr->isFloatingType());
194 break;
195 default:
196 FAIL() << "Unexpected encoding";
197 break;
198 }
199 }
200
TEST_F(TestTypeSystemClang,TestBuiltinTypeForEncodingAndBitSize)201 TEST_F(TestTypeSystemClang, TestBuiltinTypeForEncodingAndBitSize) {
202 // Make sure we can get types of every possible size in every possible
203 // encoding.
204 // We can't make any guarantee about which specific type we get, because the
205 // standard
206 // isn't that specific. We only need to make sure the compiler hands us some
207 // type that
208 // is both a builtin type and matches the requested bit size.
209 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 8);
210 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 16);
211 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 32);
212 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 64);
213 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 128);
214
215 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 8);
216 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 16);
217 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 32);
218 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 64);
219 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 128);
220
221 VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 32);
222 VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);
223 }
224
TEST_F(TestTypeSystemClang,TestDisplayName)225 TEST_F(TestTypeSystemClang, TestDisplayName) {
226 TypeSystemClang ast("some name", llvm::Triple());
227 EXPECT_EQ("some name", ast.getDisplayName());
228 }
229
TEST_F(TestTypeSystemClang,TestDisplayNameEmpty)230 TEST_F(TestTypeSystemClang, TestDisplayNameEmpty) {
231 TypeSystemClang ast("", llvm::Triple());
232 EXPECT_EQ("", ast.getDisplayName());
233 }
234
TEST_F(TestTypeSystemClang,TestGetEnumIntegerTypeInvalid)235 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeInvalid) {
236 EXPECT_FALSE(m_ast->GetEnumerationIntegerType(CompilerType()).IsValid());
237 }
238
TEST_F(TestTypeSystemClang,TestGetEnumIntegerTypeUnexpectedType)239 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeUnexpectedType) {
240 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
241 CompilerType t = m_ast->GetEnumerationIntegerType(int_type);
242 EXPECT_FALSE(t.IsValid());
243 }
244
TEST_F(TestTypeSystemClang,TestGetEnumIntegerTypeBasicTypes)245 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) {
246 // All possible underlying integer types of enums.
247 const std::vector<lldb::BasicType> types_to_test = {
248 eBasicTypeInt, eBasicTypeUnsignedInt, eBasicTypeLong,
249 eBasicTypeUnsignedLong, eBasicTypeLongLong, eBasicTypeUnsignedLongLong,
250 };
251
252 for (bool scoped : {true, false}) {
253 SCOPED_TRACE("scoped: " + std::to_string(scoped));
254 for (lldb::BasicType basic_type : types_to_test) {
255 SCOPED_TRACE(std::to_string(basic_type));
256
257 TypeSystemClang ast("enum_ast", HostInfo::GetTargetTriple());
258 CompilerType basic_compiler_type = ast.GetBasicType(basic_type);
259 EXPECT_TRUE(basic_compiler_type.IsValid());
260
261 CompilerType enum_type = ast.CreateEnumerationType(
262 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(),
263 Declaration(), basic_compiler_type, scoped);
264
265 CompilerType t = ast.GetEnumerationIntegerType(enum_type);
266 // Check that the type we put in at the start is found again.
267 EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName());
268 }
269 }
270 }
271
TEST_F(TestTypeSystemClang,TestOwningModule)272 TEST_F(TestTypeSystemClang, TestOwningModule) {
273 TypeSystemClang ast("module_ast", HostInfo::GetTargetTriple());
274 CompilerType basic_compiler_type = ast.GetBasicType(BasicType::eBasicTypeInt);
275 CompilerType enum_type = ast.CreateEnumerationType(
276 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(100),
277 Declaration(), basic_compiler_type, false);
278 auto *ed = TypeSystemClang::GetAsEnumDecl(enum_type);
279 EXPECT_FALSE(!ed);
280 EXPECT_EQ(ed->getOwningModuleID(), 100u);
281
282 CompilerType record_type = ast.CreateRecordType(
283 nullptr, OptionalClangModuleID(200), lldb::eAccessPublic, "FooRecord",
284 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
285 auto *rd = TypeSystemClang::GetAsRecordDecl(record_type);
286 EXPECT_FALSE(!rd);
287 EXPECT_EQ(rd->getOwningModuleID(), 200u);
288
289 CompilerType class_type =
290 ast.CreateObjCClass("objc_class", ast.GetTranslationUnitDecl(),
291 OptionalClangModuleID(300), false, false);
292 auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(class_type);
293 EXPECT_FALSE(!cd);
294 EXPECT_EQ(cd->getOwningModuleID(), 300u);
295 }
296
TEST_F(TestTypeSystemClang,TestIsClangType)297 TEST_F(TestTypeSystemClang, TestIsClangType) {
298 clang::ASTContext &context = m_ast->getASTContext();
299 lldb::opaque_compiler_type_t bool_ctype =
300 TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool);
301 CompilerType bool_type(m_ast.get(), bool_ctype);
302 CompilerType record_type = m_ast->CreateRecordType(
303 nullptr, OptionalClangModuleID(100), lldb::eAccessPublic, "FooRecord",
304 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
305 // Clang builtin type and record type should pass
306 EXPECT_TRUE(ClangUtil::IsClangType(bool_type));
307 EXPECT_TRUE(ClangUtil::IsClangType(record_type));
308
309 // Default constructed type should fail
310 EXPECT_FALSE(ClangUtil::IsClangType(CompilerType()));
311 }
312
TEST_F(TestTypeSystemClang,TestRemoveFastQualifiers)313 TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) {
314 CompilerType record_type = m_ast->CreateRecordType(
315 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "FooRecord",
316 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
317 QualType qt;
318
319 qt = ClangUtil::GetQualType(record_type);
320 EXPECT_EQ(0u, qt.getLocalFastQualifiers());
321 record_type = record_type.AddConstModifier();
322 record_type = record_type.AddVolatileModifier();
323 record_type = record_type.AddRestrictModifier();
324 qt = ClangUtil::GetQualType(record_type);
325 EXPECT_NE(0u, qt.getLocalFastQualifiers());
326 record_type = ClangUtil::RemoveFastQualifiers(record_type);
327 qt = ClangUtil::GetQualType(record_type);
328 EXPECT_EQ(0u, qt.getLocalFastQualifiers());
329 }
330
TEST_F(TestTypeSystemClang,TestConvertAccessTypeToAccessSpecifier)331 TEST_F(TestTypeSystemClang, TestConvertAccessTypeToAccessSpecifier) {
332 EXPECT_EQ(AS_none,
333 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessNone));
334 EXPECT_EQ(AS_none, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
335 eAccessPackage));
336 EXPECT_EQ(AS_public,
337 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessPublic));
338 EXPECT_EQ(AS_private, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
339 eAccessPrivate));
340 EXPECT_EQ(AS_protected, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(
341 eAccessProtected));
342 }
343
TEST_F(TestTypeSystemClang,TestUnifyAccessSpecifiers)344 TEST_F(TestTypeSystemClang, TestUnifyAccessSpecifiers) {
345 // Unifying two of the same type should return the same type
346 EXPECT_EQ(AS_public,
347 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_public));
348 EXPECT_EQ(AS_private,
349 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_private));
350 EXPECT_EQ(AS_protected,
351 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_protected));
352
353 // Otherwise the result should be the strictest of the two.
354 EXPECT_EQ(AS_private,
355 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_public));
356 EXPECT_EQ(AS_private,
357 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_protected));
358 EXPECT_EQ(AS_private,
359 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_private));
360 EXPECT_EQ(AS_private,
361 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_private));
362 EXPECT_EQ(AS_protected,
363 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_public));
364 EXPECT_EQ(AS_protected,
365 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_protected));
366
367 // None is stricter than everything (by convention)
368 EXPECT_EQ(AS_none,
369 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_public));
370 EXPECT_EQ(AS_none,
371 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_protected));
372 EXPECT_EQ(AS_none,
373 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_private));
374 EXPECT_EQ(AS_none,
375 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_none));
376 EXPECT_EQ(AS_none,
377 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_none));
378 EXPECT_EQ(AS_none,
379 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_none));
380 }
381
TEST_F(TestTypeSystemClang,TestRecordHasFields)382 TEST_F(TestTypeSystemClang, TestRecordHasFields) {
383 CompilerType int_type = m_ast->GetBasicType(eBasicTypeInt);
384
385 // Test that a record with no fields returns false
386 CompilerType empty_base = m_ast->CreateRecordType(
387 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyBase",
388 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
389 TypeSystemClang::StartTagDeclarationDefinition(empty_base);
390 TypeSystemClang::CompleteTagDeclarationDefinition(empty_base);
391
392 RecordDecl *empty_base_decl = TypeSystemClang::GetAsRecordDecl(empty_base);
393 EXPECT_NE(nullptr, empty_base_decl);
394 EXPECT_FALSE(TypeSystemClang::RecordHasFields(empty_base_decl));
395
396 // Test that a record with direct fields returns true
397 CompilerType non_empty_base = m_ast->CreateRecordType(
398 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "NonEmptyBase",
399 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
400 TypeSystemClang::StartTagDeclarationDefinition(non_empty_base);
401 FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType(
402 non_empty_base, "MyField", int_type, eAccessPublic, 0);
403 TypeSystemClang::CompleteTagDeclarationDefinition(non_empty_base);
404 RecordDecl *non_empty_base_decl =
405 TypeSystemClang::GetAsRecordDecl(non_empty_base);
406 EXPECT_NE(nullptr, non_empty_base_decl);
407 EXPECT_NE(nullptr, non_empty_base_field_decl);
408 EXPECT_TRUE(TypeSystemClang::RecordHasFields(non_empty_base_decl));
409
410 std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
411
412 // Test that a record with no direct fields, but fields in a base returns true
413 CompilerType empty_derived = m_ast->CreateRecordType(
414 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived",
415 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
416 TypeSystemClang::StartTagDeclarationDefinition(empty_derived);
417 std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec =
418 m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
419 lldb::eAccessPublic, false, false);
420 bases.push_back(std::move(non_empty_base_spec));
421 bool result = m_ast->TransferBaseClasses(empty_derived.GetOpaqueQualType(),
422 std::move(bases));
423 TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived);
424 EXPECT_TRUE(result);
425 CXXRecordDecl *empty_derived_non_empty_base_cxx_decl =
426 m_ast->GetAsCXXRecordDecl(empty_derived.GetOpaqueQualType());
427 RecordDecl *empty_derived_non_empty_base_decl =
428 TypeSystemClang::GetAsRecordDecl(empty_derived);
429 EXPECT_EQ(1u, TypeSystemClang::GetNumBaseClasses(
430 empty_derived_non_empty_base_cxx_decl, false));
431 EXPECT_TRUE(
432 TypeSystemClang::RecordHasFields(empty_derived_non_empty_base_decl));
433
434 // Test that a record with no direct fields, but fields in a virtual base
435 // returns true
436 CompilerType empty_derived2 = m_ast->CreateRecordType(
437 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived2",
438 clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
439 TypeSystemClang::StartTagDeclarationDefinition(empty_derived2);
440 std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec =
441 m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
442 lldb::eAccessPublic, true, false);
443 bases.push_back(std::move(non_empty_vbase_spec));
444 result = m_ast->TransferBaseClasses(empty_derived2.GetOpaqueQualType(),
445 std::move(bases));
446 TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived2);
447 EXPECT_TRUE(result);
448 CXXRecordDecl *empty_derived_non_empty_vbase_cxx_decl =
449 m_ast->GetAsCXXRecordDecl(empty_derived2.GetOpaqueQualType());
450 RecordDecl *empty_derived_non_empty_vbase_decl =
451 TypeSystemClang::GetAsRecordDecl(empty_derived2);
452 EXPECT_EQ(1u, TypeSystemClang::GetNumBaseClasses(
453 empty_derived_non_empty_vbase_cxx_decl, false));
454 EXPECT_TRUE(
455 TypeSystemClang::RecordHasFields(empty_derived_non_empty_vbase_decl));
456 }
457
TEST_F(TestTypeSystemClang,TemplateArguments)458 TEST_F(TestTypeSystemClang, TemplateArguments) {
459 TypeSystemClang::TemplateParameterInfos infos;
460 infos.names.push_back("T");
461 infos.args.push_back(TemplateArgument(m_ast->getASTContext().IntTy));
462 infos.names.push_back("I");
463 llvm::APSInt arg(llvm::APInt(8, 47));
464 infos.args.push_back(TemplateArgument(m_ast->getASTContext(), arg,
465 m_ast->getASTContext().IntTy));
466
467 // template<typename T, int I> struct foo;
468 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(
469 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,
470 "foo", TTK_Struct, infos);
471 ASSERT_NE(decl, nullptr);
472
473 // foo<int, 47>
474 ClassTemplateSpecializationDecl *spec_decl =
475 m_ast->CreateClassTemplateSpecializationDecl(
476 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl,
477 TTK_Struct, infos);
478 ASSERT_NE(spec_decl, nullptr);
479 CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl);
480 ASSERT_TRUE(type);
481 m_ast->StartTagDeclarationDefinition(type);
482 m_ast->CompleteTagDeclarationDefinition(type);
483
484 // typedef foo<int, 47> foo_def;
485 CompilerType typedef_type = m_ast->CreateTypedefType(
486 type, "foo_def",
487 m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), 0);
488
489 CompilerType auto_type(
490 m_ast.get(),
491 m_ast->getASTContext()
492 .getAutoType(ClangUtil::GetCanonicalQualType(typedef_type),
493 clang::AutoTypeKeyword::Auto, false)
494 .getAsOpaquePtr());
495
496 CompilerType int_type(m_ast.get(),
497 m_ast->getASTContext().IntTy.getAsOpaquePtr());
498 for (CompilerType t : {type, typedef_type, auto_type}) {
499 SCOPED_TRACE(t.GetTypeName().AsCString());
500
501 EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0),
502 eTemplateArgumentKindType);
503 EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0),
504 int_type);
505 EXPECT_EQ(llvm::None,
506 m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 0));
507
508 EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1),
509 eTemplateArgumentKindIntegral);
510 EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1),
511 CompilerType());
512 auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1);
513 ASSERT_NE(llvm::None, result);
514 EXPECT_EQ(arg, result->value);
515 EXPECT_EQ(int_type, result->type);
516 }
517 }
518
TEST_F(TestTypeSystemClang,OnlyPackName)519 TEST_F(TestTypeSystemClang, OnlyPackName) {
520 TypeSystemClang::TemplateParameterInfos infos;
521 infos.pack_name = "A";
522 EXPECT_FALSE(infos.IsValid());
523 }
524
makeConstInt(clang::ASTContext & ctxt)525 static QualType makeConstInt(clang::ASTContext &ctxt) {
526 QualType result(ctxt.IntTy);
527 result.addConst();
528 return result;
529 }
530
TEST_F(TestTypeSystemClang,TestGetTypeClassDeclType)531 TEST_F(TestTypeSystemClang, TestGetTypeClassDeclType) {
532 clang::ASTContext &ctxt = m_ast->getASTContext();
533 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
534 QualType t = ctxt.getDecltypeType(nullptr_expr, makeConstInt(ctxt));
535 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
536 }
537
TEST_F(TestTypeSystemClang,TestGetTypeClassTypeOf)538 TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOf) {
539 clang::ASTContext &ctxt = m_ast->getASTContext();
540 QualType t = ctxt.getTypeOfType(makeConstInt(ctxt));
541 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
542 }
543
TEST_F(TestTypeSystemClang,TestGetTypeClassTypeOfExpr)544 TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOfExpr) {
545 clang::ASTContext &ctxt = m_ast->getASTContext();
546 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
547 QualType t = ctxt.getTypeOfExprType(nullptr_expr);
548 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
549 }
550
TEST_F(TestTypeSystemClang,TestGetTypeClassNested)551 TEST_F(TestTypeSystemClang, TestGetTypeClassNested) {
552 clang::ASTContext &ctxt = m_ast->getASTContext();
553 QualType t_base = ctxt.getTypeOfType(makeConstInt(ctxt));
554 QualType t = ctxt.getTypeOfType(t_base);
555 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
556 }
557
TEST_F(TestTypeSystemClang,TestFunctionTemplateConstruction)558 TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {
559 // Tests creating a function template.
560
561 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
562 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
563
564 // Prepare the declarations/types we need for the template.
565 CompilerType clang_type =
566 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
567 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
568 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
569 false);
570 TypeSystemClang::TemplateParameterInfos empty_params;
571
572 // Create the actual function template.
573 clang::FunctionTemplateDecl *func_template =
574 m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func,
575 empty_params);
576
577 EXPECT_EQ(TU, func_template->getDeclContext());
578 EXPECT_EQ("foo", func_template->getName());
579 EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess());
580 }
581
TEST_F(TestTypeSystemClang,TestFunctionTemplateInRecordConstruction)582 TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {
583 // Tests creating a function template inside a record.
584
585 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
586 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
587
588 // Create a record we can put the function template int.
589 CompilerType record_type =
590 clang_utils::createRecordWithField(*m_ast, "record", int_type, "field");
591 clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type);
592
593 // Prepare the declarations/types we need for the template.
594 CompilerType clang_type =
595 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
596 // We create the FunctionDecl for the template in the TU DeclContext because:
597 // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can).
598 // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
599 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
600 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
601 false);
602 TypeSystemClang::TemplateParameterInfos empty_params;
603
604 // Create the actual function template.
605 clang::FunctionTemplateDecl *func_template =
606 m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func,
607 empty_params);
608
609 EXPECT_EQ(record, func_template->getDeclContext());
610 EXPECT_EQ("foo", func_template->getName());
611 EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess());
612 }
613
TEST_F(TestTypeSystemClang,TestDeletingImplicitCopyCstrDueToMoveCStr)614 TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) {
615 // We need to simulate this behavior in our AST that we construct as we don't
616 // have a Sema instance that can do this for us:
617 // C++11 [class.copy]p7, p18:
618 // If the class definition declares a move constructor or move assignment
619 // operator, an implicitly declared copy constructor or copy assignment
620 // operator is defined as deleted.
621
622 // Create a record and start defining it.
623 llvm::StringRef class_name = "S";
624 CompilerType t = clang_utils::createRecord(*m_ast, class_name);
625 m_ast->StartTagDeclarationDefinition(t);
626
627 // Create a move constructor that will delete the implicit copy constructor.
628 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
629 CompilerType param_type = t.GetRValueReferenceType();
630 CompilerType function_type =
631 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1,
632 /*variadic=*/false, /*quals*/ 0U);
633 bool is_virtual = false;
634 bool is_static = false;
635 bool is_inline = false;
636 bool is_explicit = true;
637 bool is_attr_used = false;
638 bool is_artificial = false;
639 m_ast->AddMethodToCXXRecordType(
640 t.GetOpaqueQualType(), class_name, nullptr, function_type,
641 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
642 is_explicit, is_attr_used, is_artificial);
643
644 // Complete the definition and check the created record.
645 m_ast->CompleteTagDeclarationDefinition(t);
646 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));
647 // We can't call defaultedCopyConstructorIsDeleted() as this requires that
648 // the Decl passes through Sema which will actually compute this field.
649 // Instead we check that there is no copy constructor declared by the user
650 // which only leaves a non-deleted defaulted copy constructor as an option
651 // that our record will have no simple copy constructor.
652 EXPECT_FALSE(record->hasUserDeclaredCopyConstructor());
653 EXPECT_FALSE(record->hasSimpleCopyConstructor());
654 }
655
TEST_F(TestTypeSystemClang,TestNotDeletingUserCopyCstrDueToMoveCStr)656 TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {
657 // Tests that we don't delete the a user-defined copy constructor when
658 // a move constructor is provided.
659 // See also the TestDeletingImplicitCopyCstrDueToMoveCStr test.
660 llvm::StringRef class_name = "S";
661 CompilerType t = clang_utils::createRecord(*m_ast, class_name);
662 m_ast->StartTagDeclarationDefinition(t);
663
664 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
665 bool is_virtual = false;
666 bool is_static = false;
667 bool is_inline = false;
668 bool is_explicit = true;
669 bool is_attr_used = false;
670 bool is_artificial = false;
671 // Create a move constructor.
672 {
673 CompilerType param_type = t.GetRValueReferenceType();
674 CompilerType function_type =
675 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1,
676 /*variadic=*/false, /*quals*/ 0U);
677 m_ast->AddMethodToCXXRecordType(
678 t.GetOpaqueQualType(), class_name, nullptr, function_type,
679 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
680 is_explicit, is_attr_used, is_artificial);
681 }
682 // Create a copy constructor.
683 {
684 CompilerType param_type = t.GetLValueReferenceType().AddConstModifier();
685 CompilerType function_type =
686 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1,
687 /*variadic=*/false, /*quals*/ 0U);
688 m_ast->AddMethodToCXXRecordType(
689 t.GetOpaqueQualType(), class_name, nullptr, function_type,
690 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
691 is_explicit, is_attr_used, is_artificial);
692 }
693
694 // Complete the definition and check the created record.
695 m_ast->CompleteTagDeclarationDefinition(t);
696 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));
697 EXPECT_TRUE(record->hasUserDeclaredCopyConstructor());
698 }
699
TEST_F(TestTypeSystemClang,AddMethodToObjCObjectType)700 TEST_F(TestTypeSystemClang, AddMethodToObjCObjectType) {
701 // Create an interface decl and mark it as having external storage.
702 CompilerType c = m_ast->CreateObjCClass("A", m_ast->GetTranslationUnitDecl(),
703 OptionalClangModuleID(),
704 /*IsForwardDecl*/ false,
705 /*IsInternal*/ false);
706 ObjCInterfaceDecl *interface = m_ast->GetAsObjCInterfaceDecl(c);
707 m_ast->SetHasExternalStorage(c.GetOpaqueQualType(), true);
708 EXPECT_TRUE(interface->hasExternalLexicalStorage());
709
710 // Add a method to the interface.
711 std::vector<CompilerType> args;
712 CompilerType func_type =
713 m_ast->CreateFunctionType(m_ast->GetBasicType(lldb::eBasicTypeInt),
714 args.data(), args.size(), /*variadic*/ false,
715 /*quals*/ 0, clang::CallingConv::CC_C);
716 bool variadic = false;
717 bool artificial = false;
718 bool objc_direct = false;
719 clang::ObjCMethodDecl *method = TypeSystemClang::AddMethodToObjCObjectType(
720 c, "-[A foo]", func_type, lldb::eAccessPublic, artificial, variadic,
721 objc_direct);
722 ASSERT_NE(method, nullptr);
723
724 // The interface decl should still have external lexical storage.
725 EXPECT_TRUE(interface->hasExternalLexicalStorage());
726
727 // Test some properties of the created ObjCMethodDecl.
728 EXPECT_FALSE(method->isVariadic());
729 EXPECT_TRUE(method->isImplicit());
730 EXPECT_FALSE(method->isDirectMethod());
731 EXPECT_EQ(method->getDeclName().getObjCSelector().getAsString(), "foo");
732 }
733