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