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 29 void SetUp() override { 30 m_ast.reset( 31 new TypeSystemClang("test ASTContext", HostInfo::GetTargetTriple())); 32 } 33 34 void TearDown() override { m_ast.reset(); } 35 36 protected: 37 std::unique_ptr<TypeSystemClang> m_ast; 38 39 QualType GetBasicQualType(BasicType type) const { 40 return ClangUtil::GetQualType(m_ast->GetBasicTypeFromAST(type)); 41 } 42 43 QualType GetBasicQualType(const char *name) const { 44 return ClangUtil::GetQualType( 45 m_ast->GetBuiltinTypeByName(ConstString(name))); 46 } 47 }; 48 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 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 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 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 225 TEST_F(TestTypeSystemClang, TestDisplayName) { 226 TypeSystemClang ast("some name", llvm::Triple()); 227 EXPECT_EQ("some name", ast.getDisplayName()); 228 } 229 230 TEST_F(TestTypeSystemClang, TestDisplayNameEmpty) { 231 TypeSystemClang ast("", llvm::Triple()); 232 EXPECT_EQ("", ast.getDisplayName()); 233 } 234 235 TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeInvalid) { 236 EXPECT_FALSE(m_ast->GetEnumerationIntegerType(CompilerType()).IsValid()); 237 } 238 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 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 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 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 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 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 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 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 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 519 static QualType makeConstInt(clang::ASTContext &ctxt) { 520 QualType result(ctxt.IntTy); 521 result.addConst(); 522 return result; 523 } 524 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 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 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 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 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, 0, false); 563 TypeSystemClang::TemplateParameterInfos empty_params; 564 565 // Create the actual function template. 566 clang::FunctionTemplateDecl *func_template = 567 m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func, 568 "foo", empty_params); 569 570 EXPECT_EQ(TU, func_template->getDeclContext()); 571 EXPECT_EQ("foo", func_template->getName()); 572 EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess()); 573 } 574 575 TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { 576 // Tests creating a function template inside a record. 577 578 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); 579 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); 580 581 // Create a record we can put the function template int. 582 CompilerType record_type = 583 clang_utils::createRecordWithField(*m_ast, "record", int_type, "field"); 584 clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type); 585 586 // Prepare the declarations/types we need for the template. 587 CompilerType clang_type = 588 m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); 589 // We create the FunctionDecl for the template in the TU DeclContext because: 590 // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can). 591 // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. 592 FunctionDecl *func = m_ast->CreateFunctionDeclaration( 593 TU, OptionalClangModuleID(), "foo", clang_type, 0, false); 594 TypeSystemClang::TemplateParameterInfos empty_params; 595 596 // Create the actual function template. 597 clang::FunctionTemplateDecl *func_template = 598 m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func, 599 "foo", empty_params); 600 601 EXPECT_EQ(record, func_template->getDeclContext()); 602 EXPECT_EQ("foo", func_template->getName()); 603 EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess()); 604 } 605 606 TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { 607 // We need to simulate this behavior in our AST that we construct as we don't 608 // have a Sema instance that can do this for us: 609 // C++11 [class.copy]p7, p18: 610 // If the class definition declares a move constructor or move assignment 611 // operator, an implicitly declared copy constructor or copy assignment 612 // operator is defined as deleted. 613 614 // Create a record and start defining it. 615 llvm::StringRef class_name = "S"; 616 CompilerType t = clang_utils::createRecord(*m_ast, class_name); 617 m_ast->StartTagDeclarationDefinition(t); 618 619 // Create a move constructor that will delete the implicit copy constructor. 620 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid); 621 CompilerType param_type = t.GetRValueReferenceType(); 622 CompilerType function_type = 623 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1, 624 /*variadic=*/false, /*quals*/ 0U); 625 bool is_virtual = false; 626 bool is_static = false; 627 bool is_inline = false; 628 bool is_explicit = true; 629 bool is_attr_used = false; 630 bool is_artificial = false; 631 m_ast->AddMethodToCXXRecordType( 632 t.GetOpaqueQualType(), class_name, nullptr, function_type, 633 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, 634 is_explicit, is_attr_used, is_artificial); 635 636 // Complete the definition and check the created record. 637 m_ast->CompleteTagDeclarationDefinition(t); 638 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t)); 639 // We can't call defaultedCopyConstructorIsDeleted() as this requires that 640 // the Decl passes through Sema which will actually compute this field. 641 // Instead we check that there is no copy constructor declared by the user 642 // which only leaves a non-deleted defaulted copy constructor as an option 643 // that our record will have no simple copy constructor. 644 EXPECT_FALSE(record->hasUserDeclaredCopyConstructor()); 645 EXPECT_FALSE(record->hasSimpleCopyConstructor()); 646 } 647 648 TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { 649 // Tests that we don't delete the a user-defined copy constructor when 650 // a move constructor is provided. 651 // See also the TestDeletingImplicitCopyCstrDueToMoveCStr test. 652 llvm::StringRef class_name = "S"; 653 CompilerType t = clang_utils::createRecord(*m_ast, class_name); 654 m_ast->StartTagDeclarationDefinition(t); 655 656 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid); 657 bool is_virtual = false; 658 bool is_static = false; 659 bool is_inline = false; 660 bool is_explicit = true; 661 bool is_attr_used = false; 662 bool is_artificial = false; 663 // Create a move constructor. 664 { 665 CompilerType param_type = t.GetRValueReferenceType(); 666 CompilerType function_type = 667 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1, 668 /*variadic=*/false, /*quals*/ 0U); 669 m_ast->AddMethodToCXXRecordType( 670 t.GetOpaqueQualType(), class_name, nullptr, function_type, 671 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, 672 is_explicit, is_attr_used, is_artificial); 673 } 674 // Create a copy constructor. 675 { 676 CompilerType param_type = t.GetLValueReferenceType().AddConstModifier(); 677 CompilerType function_type = 678 m_ast->CreateFunctionType(return_type, ¶m_type, /*num_params*/ 1, 679 /*variadic=*/false, /*quals*/ 0U); 680 m_ast->AddMethodToCXXRecordType( 681 t.GetOpaqueQualType(), class_name, nullptr, function_type, 682 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, 683 is_explicit, is_attr_used, is_artificial); 684 } 685 686 // Complete the definition and check the created record. 687 m_ast->CompleteTagDeclarationDefinition(t); 688 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t)); 689 EXPECT_TRUE(record->hasUserDeclaredCopyConstructor()); 690 } 691 692 TEST_F(TestTypeSystemClang, AddMethodToObjCObjectType) { 693 // Create an interface decl and mark it as having external storage. 694 CompilerType c = m_ast->CreateObjCClass("A", m_ast->GetTranslationUnitDecl(), 695 OptionalClangModuleID(), 696 /*IsForwardDecl*/ false, 697 /*IsInternal*/ false); 698 ObjCInterfaceDecl *interface = m_ast->GetAsObjCInterfaceDecl(c); 699 m_ast->SetHasExternalStorage(c.GetOpaqueQualType(), true); 700 EXPECT_TRUE(interface->hasExternalLexicalStorage()); 701 702 // Add a method to the interface. 703 std::vector<CompilerType> args; 704 CompilerType func_type = 705 m_ast->CreateFunctionType(m_ast->GetBasicType(lldb::eBasicTypeInt), 706 args.data(), args.size(), /*variadic*/ false, 707 /*quals*/ 0, clang::CallingConv::CC_C); 708 bool variadic = false; 709 bool artificial = false; 710 bool objc_direct = false; 711 clang::ObjCMethodDecl *method = TypeSystemClang::AddMethodToObjCObjectType( 712 c, "-[A foo]", func_type, lldb::eAccessPublic, artificial, variadic, 713 objc_direct); 714 ASSERT_NE(method, nullptr); 715 716 // The interface decl should still have external lexical storage. 717 EXPECT_TRUE(interface->hasExternalLexicalStorage()); 718 719 // Test some properties of the created ObjCMethodDecl. 720 EXPECT_FALSE(method->isVariadic()); 721 EXPECT_TRUE(method->isImplicit()); 722 EXPECT_FALSE(method->isDirectMethod()); 723 EXPECT_EQ(method->getDeclName().getObjCSelector().getAsString(), "foo"); 724 } 725