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, &param_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, &param_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, &param_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