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
makeConstInt(clang::ASTContext & ctxt)519 static QualType makeConstInt(clang::ASTContext &ctxt) {
520 QualType result(ctxt.IntTy);
521 result.addConst();
522 return result;
523 }
524
TEST_F(TestTypeSystemClang,TestGetTypeClassDeclType)525 TEST_F(TestTypeSystemClang, TestGetTypeClassDeclType) {
526 clang::ASTContext &ctxt = m_ast->getASTContext();
527 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
528 QualType t = ctxt.getDecltypeType(nullptr_expr, makeConstInt(ctxt));
529 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
530 }
531
TEST_F(TestTypeSystemClang,TestGetTypeClassTypeOf)532 TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOf) {
533 clang::ASTContext &ctxt = m_ast->getASTContext();
534 QualType t = ctxt.getTypeOfType(makeConstInt(ctxt));
535 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
536 }
537
TEST_F(TestTypeSystemClang,TestGetTypeClassTypeOfExpr)538 TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOfExpr) {
539 clang::ASTContext &ctxt = m_ast->getASTContext();
540 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());
541 QualType t = ctxt.getTypeOfExprType(nullptr_expr);
542 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
543 }
544
TEST_F(TestTypeSystemClang,TestGetTypeClassNested)545 TEST_F(TestTypeSystemClang, TestGetTypeClassNested) {
546 clang::ASTContext &ctxt = m_ast->getASTContext();
547 QualType t_base = ctxt.getTypeOfType(makeConstInt(ctxt));
548 QualType t = ctxt.getTypeOfType(t_base);
549 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
550 }
551
TEST_F(TestTypeSystemClang,TestFunctionTemplateConstruction)552 TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {
553 // Tests creating a function template.
554
555 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
556 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
557
558 // Prepare the declarations/types we need for the template.
559 CompilerType clang_type =
560 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
561 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
562 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
563 false);
564 TypeSystemClang::TemplateParameterInfos empty_params;
565
566 // Create the actual function template.
567 clang::FunctionTemplateDecl *func_template =
568 m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func,
569 empty_params);
570
571 EXPECT_EQ(TU, func_template->getDeclContext());
572 EXPECT_EQ("foo", func_template->getName());
573 EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess());
574 }
575
TEST_F(TestTypeSystemClang,TestFunctionTemplateInRecordConstruction)576 TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {
577 // Tests creating a function template inside a record.
578
579 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
580 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
581
582 // Create a record we can put the function template int.
583 CompilerType record_type =
584 clang_utils::createRecordWithField(*m_ast, "record", int_type, "field");
585 clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type);
586
587 // Prepare the declarations/types we need for the template.
588 CompilerType clang_type =
589 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
590 // We create the FunctionDecl for the template in the TU DeclContext because:
591 // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can).
592 // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
593 FunctionDecl *func = m_ast->CreateFunctionDeclaration(
594 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
595 false);
596 TypeSystemClang::TemplateParameterInfos empty_params;
597
598 // Create the actual function template.
599 clang::FunctionTemplateDecl *func_template =
600 m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func,
601 empty_params);
602
603 EXPECT_EQ(record, func_template->getDeclContext());
604 EXPECT_EQ("foo", func_template->getName());
605 EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess());
606 }
607
TEST_F(TestTypeSystemClang,TestDeletingImplicitCopyCstrDueToMoveCStr)608 TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) {
609 // We need to simulate this behavior in our AST that we construct as we don't
610 // have a Sema instance that can do this for us:
611 // C++11 [class.copy]p7, p18:
612 // If the class definition declares a move constructor or move assignment
613 // operator, an implicitly declared copy constructor or copy assignment
614 // operator is defined as deleted.
615
616 // Create a record and start defining it.
617 llvm::StringRef class_name = "S";
618 CompilerType t = clang_utils::createRecord(*m_ast, class_name);
619 m_ast->StartTagDeclarationDefinition(t);
620
621 // Create a move constructor that will delete the implicit copy constructor.
622 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
623 CompilerType param_type = t.GetRValueReferenceType();
624 CompilerType function_type =
625 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1,
626 /*variadic=*/false, /*quals*/ 0U);
627 bool is_virtual = false;
628 bool is_static = false;
629 bool is_inline = false;
630 bool is_explicit = true;
631 bool is_attr_used = false;
632 bool is_artificial = false;
633 m_ast->AddMethodToCXXRecordType(
634 t.GetOpaqueQualType(), class_name, nullptr, function_type,
635 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
636 is_explicit, is_attr_used, is_artificial);
637
638 // Complete the definition and check the created record.
639 m_ast->CompleteTagDeclarationDefinition(t);
640 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));
641 // We can't call defaultedCopyConstructorIsDeleted() as this requires that
642 // the Decl passes through Sema which will actually compute this field.
643 // Instead we check that there is no copy constructor declared by the user
644 // which only leaves a non-deleted defaulted copy constructor as an option
645 // that our record will have no simple copy constructor.
646 EXPECT_FALSE(record->hasUserDeclaredCopyConstructor());
647 EXPECT_FALSE(record->hasSimpleCopyConstructor());
648 }
649
TEST_F(TestTypeSystemClang,TestNotDeletingUserCopyCstrDueToMoveCStr)650 TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {
651 // Tests that we don't delete the a user-defined copy constructor when
652 // a move constructor is provided.
653 // See also the TestDeletingImplicitCopyCstrDueToMoveCStr test.
654 llvm::StringRef class_name = "S";
655 CompilerType t = clang_utils::createRecord(*m_ast, class_name);
656 m_ast->StartTagDeclarationDefinition(t);
657
658 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
659 bool is_virtual = false;
660 bool is_static = false;
661 bool is_inline = false;
662 bool is_explicit = true;
663 bool is_attr_used = false;
664 bool is_artificial = false;
665 // Create a move constructor.
666 {
667 CompilerType param_type = t.GetRValueReferenceType();
668 CompilerType function_type =
669 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1,
670 /*variadic=*/false, /*quals*/ 0U);
671 m_ast->AddMethodToCXXRecordType(
672 t.GetOpaqueQualType(), class_name, nullptr, function_type,
673 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
674 is_explicit, is_attr_used, is_artificial);
675 }
676 // Create a copy constructor.
677 {
678 CompilerType param_type = t.GetLValueReferenceType().AddConstModifier();
679 CompilerType function_type =
680 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1,
681 /*variadic=*/false, /*quals*/ 0U);
682 m_ast->AddMethodToCXXRecordType(
683 t.GetOpaqueQualType(), class_name, nullptr, function_type,
684 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
685 is_explicit, is_attr_used, is_artificial);
686 }
687
688 // Complete the definition and check the created record.
689 m_ast->CompleteTagDeclarationDefinition(t);
690 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));
691 EXPECT_TRUE(record->hasUserDeclaredCopyConstructor());
692 }
693
TEST_F(TestTypeSystemClang,AddMethodToObjCObjectType)694 TEST_F(TestTypeSystemClang, AddMethodToObjCObjectType) {
695 // Create an interface decl and mark it as having external storage.
696 CompilerType c = m_ast->CreateObjCClass("A", m_ast->GetTranslationUnitDecl(),
697 OptionalClangModuleID(),
698 /*IsForwardDecl*/ false,
699 /*IsInternal*/ false);
700 ObjCInterfaceDecl *interface = m_ast->GetAsObjCInterfaceDecl(c);
701 m_ast->SetHasExternalStorage(c.GetOpaqueQualType(), true);
702 EXPECT_TRUE(interface->hasExternalLexicalStorage());
703
704 // Add a method to the interface.
705 std::vector<CompilerType> args;
706 CompilerType func_type =
707 m_ast->CreateFunctionType(m_ast->GetBasicType(lldb::eBasicTypeInt),
708 args.data(), args.size(), /*variadic*/ false,
709 /*quals*/ 0, clang::CallingConv::CC_C);
710 bool variadic = false;
711 bool artificial = false;
712 bool objc_direct = false;
713 clang::ObjCMethodDecl *method = TypeSystemClang::AddMethodToObjCObjectType(
714 c, "-[A foo]", func_type, lldb::eAccessPublic, artificial, variadic,
715 objc_direct);
716 ASSERT_NE(method, nullptr);
717
718 // The interface decl should still have external lexical storage.
719 EXPECT_TRUE(interface->hasExternalLexicalStorage());
720
721 // Test some properties of the created ObjCMethodDecl.
722 EXPECT_FALSE(method->isVariadic());
723 EXPECT_TRUE(method->isImplicit());
724 EXPECT_FALSE(method->isDirectMethod());
725 EXPECT_EQ(method->getDeclName().getObjCSelector().getAsString(), "foo");
726 }
727