1367 lines · cpp
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-exception6//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/Core/Declaration.h"14#include "lldb/Host/FileSystem.h"15#include "lldb/Host/HostInfo.h"16#include "lldb/lldb-enumerations.h"17#include "clang/AST/DeclCXX.h"18#include "clang/AST/DeclObjC.h"19#include "clang/AST/ExprCXX.h"20#include "llvm/IR/GlobalValue.h"21#include "gtest/gtest.h"22 23using namespace clang;24using namespace lldb;25using namespace lldb_private;26 27class TestTypeSystemClang : public testing::Test {28public:29 SubsystemRAII<FileSystem, HostInfo> subsystems;30 31 void SetUp() override {32 m_holder =33 std::make_unique<clang_utils::TypeSystemClangHolder>("test ASTContext");34 m_ast = m_holder->GetAST();35 }36 37 void TearDown() override {38 m_ast = nullptr;39 m_holder.reset();40 }41 42protected:43 44 TypeSystemClang *m_ast = nullptr;45 std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;46 47 QualType GetBasicQualType(BasicType type) const {48 return ClangUtil::GetQualType(m_ast->GetBasicTypeFromAST(type));49 }50 51 QualType GetBasicQualType(const char *name) const {52 return ClangUtil::GetQualType(53 m_ast->GetBuiltinTypeByName(ConstString(name)));54 }55 56 CompilerType GetBuiltinTypeForDWARFEncodingAndBitSize(57 llvm::StringRef type_name, uint32_t encoding, uint32_t bit_size) const {58 return m_ast->GetBuiltinTypeForDWARFEncodingAndBitSize(type_name, encoding,59 bit_size);60 }61};62 63TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {64 clang::ASTContext &context = m_ast->getASTContext();65 66 EXPECT_TRUE(67 context.hasSameType(GetBasicQualType(eBasicTypeBool), context.BoolTy));68 EXPECT_TRUE(69 context.hasSameType(GetBasicQualType(eBasicTypeChar), context.CharTy));70 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar8),71 context.Char8Ty));72 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar16),73 context.Char16Ty));74 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeChar32),75 context.Char32Ty));76 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeDouble),77 context.DoubleTy));78 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeDoubleComplex),79 context.getComplexType(context.DoubleTy)));80 EXPECT_TRUE(81 context.hasSameType(GetBasicQualType(eBasicTypeFloat), context.FloatTy));82 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeFloatComplex),83 context.getComplexType(context.FloatTy)));84 EXPECT_TRUE(85 context.hasSameType(GetBasicQualType(eBasicTypeHalf), context.HalfTy));86 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeFloat128),87 context.Float128Ty));88 EXPECT_TRUE(89 context.hasSameType(GetBasicQualType(eBasicTypeInt), context.IntTy));90 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeInt128),91 context.Int128Ty));92 EXPECT_TRUE(93 context.hasSameType(GetBasicQualType(eBasicTypeLong), context.LongTy));94 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongDouble),95 context.LongDoubleTy));96 EXPECT_TRUE(97 context.hasSameType(GetBasicQualType(eBasicTypeLongDoubleComplex),98 context.getComplexType(context.LongDoubleTy)));99 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeLongLong),100 context.LongLongTy));101 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeNullPtr),102 context.NullPtrTy));103 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCClass),104 context.getObjCClassType()));105 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCID),106 context.getObjCIdType()));107 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeObjCSel),108 context.getObjCSelType()));109 EXPECT_TRUE(110 context.hasSameType(GetBasicQualType(eBasicTypeShort), context.ShortTy));111 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeSignedChar),112 context.SignedCharTy));113 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedChar),114 context.UnsignedCharTy));115 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedInt),116 context.UnsignedIntTy));117 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedInt128),118 context.UnsignedInt128Ty));119 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedLong),120 context.UnsignedLongTy));121 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedLongLong),122 context.UnsignedLongLongTy));123 EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeUnsignedShort),124 context.UnsignedShortTy));125 EXPECT_TRUE(126 context.hasSameType(GetBasicQualType(eBasicTypeVoid), context.VoidTy));127 EXPECT_TRUE(128 context.hasSameType(GetBasicQualType(eBasicTypeWChar), context.WCharTy));129}130 131TEST_F(TestTypeSystemClang, TestGetBasicTypeFromName) {132 EXPECT_EQ(GetBasicQualType(eBasicTypeChar), GetBasicQualType("char"));133 EXPECT_EQ(GetBasicQualType(eBasicTypeSignedChar),134 GetBasicQualType("signed char"));135 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedChar),136 GetBasicQualType("unsigned char"));137 EXPECT_EQ(GetBasicQualType(eBasicTypeWChar), GetBasicQualType("wchar_t"));138 EXPECT_EQ(GetBasicQualType(eBasicTypeSignedWChar),139 GetBasicQualType("signed wchar_t"));140 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedWChar),141 GetBasicQualType("unsigned wchar_t"));142 EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short"));143 EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short int"));144 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort),145 GetBasicQualType("unsigned short"));146 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort),147 GetBasicQualType("unsigned short int"));148 EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("int"));149 EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("signed int"));150 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt),151 GetBasicQualType("unsigned int"));152 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt),153 GetBasicQualType("unsigned"));154 EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long"));155 EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long int"));156 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong),157 GetBasicQualType("unsigned long"));158 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong),159 GetBasicQualType("unsigned long int"));160 EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong),161 GetBasicQualType("long long"));162 EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong),163 GetBasicQualType("long long int"));164 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong),165 GetBasicQualType("unsigned long long"));166 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong),167 GetBasicQualType("unsigned long long int"));168 EXPECT_EQ(GetBasicQualType(eBasicTypeInt128), GetBasicQualType("__int128_t"));169 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt128),170 GetBasicQualType("__uint128_t"));171 EXPECT_EQ(GetBasicQualType(eBasicTypeInt128), GetBasicQualType("__int128"));172 EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt128),173 GetBasicQualType("unsigned __int128"));174 EXPECT_EQ(GetBasicQualType(eBasicTypeVoid), GetBasicQualType("void"));175 EXPECT_EQ(GetBasicQualType(eBasicTypeBool), GetBasicQualType("bool"));176 EXPECT_EQ(GetBasicQualType(eBasicTypeFloat), GetBasicQualType("float"));177 EXPECT_EQ(GetBasicQualType(eBasicTypeDouble), GetBasicQualType("double"));178 EXPECT_EQ(GetBasicQualType(eBasicTypeLongDouble),179 GetBasicQualType("long double"));180 EXPECT_EQ(GetBasicQualType(eBasicTypeObjCID), GetBasicQualType("id"));181 EXPECT_EQ(GetBasicQualType(eBasicTypeObjCSel), GetBasicQualType("SEL"));182 EXPECT_EQ(GetBasicQualType(eBasicTypeNullPtr), GetBasicQualType("nullptr"));183}184 185void VerifyEncodingAndBitSize(TypeSystemClang &clang_context,186 lldb::Encoding encoding, unsigned int bit_size) {187 clang::ASTContext &context = clang_context.getASTContext();188 189 CompilerType type =190 clang_context.GetBuiltinTypeForEncodingAndBitSize(encoding, bit_size);191 EXPECT_TRUE(type.IsValid());192 193 QualType qtype = ClangUtil::GetQualType(type);194 EXPECT_FALSE(qtype.isNull());195 if (qtype.isNull())196 return;197 198 uint64_t actual_size = context.getTypeSize(qtype);199 EXPECT_EQ(bit_size, actual_size);200 201 const clang::Type *type_ptr = qtype.getTypePtr();202 EXPECT_NE(nullptr, type_ptr);203 if (!type_ptr)204 return;205 206 EXPECT_TRUE(type_ptr->isBuiltinType());207 switch (encoding) {208 case eEncodingSint:209 EXPECT_TRUE(type_ptr->isSignedIntegerType());210 break;211 case eEncodingUint:212 EXPECT_TRUE(type_ptr->isUnsignedIntegerType());213 break;214 case eEncodingIEEE754:215 EXPECT_TRUE(type_ptr->isFloatingType());216 break;217 default:218 FAIL() << "Unexpected encoding";219 break;220 }221}222 223TEST_F(TestTypeSystemClang, TestBuiltinTypeForEncodingAndBitSize) {224 // Make sure we can get types of every possible size in every possible225 // encoding.226 // We can't make any guarantee about which specific type we get, because the227 // standard228 // isn't that specific. We only need to make sure the compiler hands us some229 // type that230 // is both a builtin type and matches the requested bit size.231 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 8);232 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 16);233 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 32);234 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 64);235 VerifyEncodingAndBitSize(*m_ast, eEncodingSint, 128);236 237 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 8);238 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 16);239 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 32);240 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 64);241 VerifyEncodingAndBitSize(*m_ast, eEncodingUint, 128);242 243 VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 32);244 VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);245}246 247TEST_F(TestTypeSystemClang, TestGetBuiltinTypeForDWARFEncodingAndBitSize) {248 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(249 "_BitIn", llvm::dwarf::DW_ATE_signed, 2)250 .IsValid());251 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(252 "BitInt", llvm::dwarf::DW_ATE_signed, 2)253 .IsValid());254 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(255 "_BitInt(2)", llvm::dwarf::DW_ATE_signed_char, 2)256 .IsValid());257 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(258 "_BitInt", llvm::dwarf::DW_ATE_signed_char, 2)259 .IsValid());260 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(261 "_BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)262 .IsValid());263 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(264 "_BitInt", llvm::dwarf::DW_ATE_unsigned, 2)265 .IsValid());266 267 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(268 "_BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)269 .GetTypeName(),270 "_BitInt(2)");271 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(272 "_BitInt", llvm::dwarf::DW_ATE_signed, 2)273 .GetTypeName(),274 "_BitInt(2)");275 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(276 "_BitInt(129)", llvm::dwarf::DW_ATE_signed, 129)277 .GetTypeName(),278 "_BitInt(129)");279 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(280 "_BitInt", llvm::dwarf::DW_ATE_signed, 129)281 .GetTypeName(),282 "_BitInt(129)");283 284 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(285 "unsigned _BitIn", llvm::dwarf::DW_ATE_unsigned, 2)286 .IsValid());287 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(288 "unsigned BitInt", llvm::dwarf::DW_ATE_unsigned, 2)289 .IsValid());290 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(291 "unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned_char, 2)292 .IsValid());293 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(294 "unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned_char, 2)295 .IsValid());296 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(297 "unsigned _BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)298 .IsValid());299 EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(300 "unsigned _BitInt", llvm::dwarf::DW_ATE_signed, 2)301 .IsValid());302 303 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(304 "unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)305 .GetTypeName(),306 "unsigned _BitInt(2)");307 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(308 "unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)309 .GetTypeName(),310 "unsigned _BitInt(2)");311 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(312 "unsigned _BitInt(129)", llvm::dwarf::DW_ATE_unsigned, 129)313 .GetTypeName(),314 "unsigned _BitInt(129)");315 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(316 "unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 129)317 .GetTypeName(),318 "unsigned _BitInt(129)");319}320 321TEST_F(TestTypeSystemClang, TestBitIntTypeInfo) {322 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(323 "_BitInt", llvm::dwarf::DW_ATE_signed, 2)324 .GetTypeInfo(),325 eTypeIsSigned | eTypeIsScalar | eTypeHasValue | eTypeIsInteger);326 EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(327 "unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)328 .GetTypeInfo(),329 eTypeIsScalar | eTypeHasValue | eTypeIsInteger);330}331 332TEST_F(TestTypeSystemClang, TestBuiltinTypeForEmptyTriple) {333 // Test that we can access type-info of builtin Clang AST334 // types without crashing even when the target triple is335 // empty.336 337 TypeSystemClang ast("empty triple AST", llvm::Triple{});338 339 // This test only makes sense if the builtin ASTContext types were340 // not initialized.341 ASSERT_TRUE(ast.getASTContext().VoidPtrTy.isNull());342 343 EXPECT_FALSE(ast.GetBuiltinTypeByName(ConstString("int")).IsValid());344 EXPECT_FALSE(ast.GetBuiltinTypeForDWARFEncodingAndBitSize(345 "char", llvm::dwarf::DW_ATE_signed_char, 8)346 .IsValid());347 EXPECT_FALSE(ast.GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 8)348 .IsValid());349 EXPECT_FALSE(ast.GetPointerSizedIntType(/*is_signed=*/false));350 EXPECT_FALSE(ast.GetIntTypeFromBitSize(8, /*is_signed=*/false));351 352 CompilerType record_type = ast.CreateRecordType(353 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "Record",354 llvm::to_underlying(clang::TagTypeKind::Struct),355 lldb::eLanguageTypeC_plus_plus, std::nullopt);356 TypeSystemClang::StartTagDeclarationDefinition(record_type);357 EXPECT_EQ(ast.AddFieldToRecordType(record_type, "field", record_type,358 eAccessPublic, /*bitfield_bit_size=*/8),359 nullptr);360 TypeSystemClang::CompleteTagDeclarationDefinition(record_type);361}362 363TEST_F(TestTypeSystemClang, TestDisplayName) {364 TypeSystemClang ast("some name", llvm::Triple());365 EXPECT_EQ("some name", ast.getDisplayName());366}367 368TEST_F(TestTypeSystemClang, TestDisplayNameEmpty) {369 TypeSystemClang ast("", llvm::Triple());370 EXPECT_EQ("", ast.getDisplayName());371}372 373TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeInvalid) {374 EXPECT_FALSE(m_ast->GetEnumerationIntegerType(CompilerType()).IsValid());375}376 377TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeUnexpectedType) {378 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);379 CompilerType t = m_ast->GetEnumerationIntegerType(int_type);380 EXPECT_FALSE(t.IsValid());381}382 383TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) {384 // All possible underlying integer types of enums.385 const std::vector<lldb::BasicType> types_to_test = {386 eBasicTypeInt, eBasicTypeUnsignedInt, eBasicTypeLong,387 eBasicTypeUnsignedLong, eBasicTypeLongLong, eBasicTypeUnsignedLongLong,388 };389 390 for (bool scoped : {true, false}) {391 SCOPED_TRACE("scoped: " + std::to_string(scoped));392 for (lldb::BasicType basic_type : types_to_test) {393 SCOPED_TRACE(std::to_string(basic_type));394 395 auto holder =396 std::make_unique<clang_utils::TypeSystemClangHolder>("enum_ast");397 auto &ast = *holder->GetAST();398 399 CompilerType basic_compiler_type = ast.GetBasicType(basic_type);400 EXPECT_TRUE(basic_compiler_type.IsValid());401 402 CompilerType enum_type = ast.CreateEnumerationType(403 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(),404 Declaration(), basic_compiler_type, scoped);405 406 CompilerType t = ast.GetEnumerationIntegerType(enum_type);407 // Check that the type we put in at the start is found again.408 EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName());409 }410 }411}412 413TEST_F(TestTypeSystemClang, TestEnumerationValueSign) {414 CompilerType enum_type = m_ast->CreateEnumerationType(415 "my_enum_signed", m_ast->GetTranslationUnitDecl(),416 OptionalClangModuleID(), Declaration(),417 m_ast->GetBasicType(lldb::eBasicTypeSignedChar), false);418 auto *enum_decl = m_ast->AddEnumerationValueToEnumerationType(419 enum_type, Declaration(), "minus_one", -1, 8);420 EXPECT_TRUE(enum_decl->getInitVal().isSigned());421}422 423TEST_F(TestTypeSystemClang, TestOwningModule) {424 auto holder =425 std::make_unique<clang_utils::TypeSystemClangHolder>("module_ast");426 auto &ast = *holder->GetAST();427 CompilerType basic_compiler_type = ast.GetBasicType(BasicType::eBasicTypeInt);428 CompilerType enum_type = ast.CreateEnumerationType(429 "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(100),430 Declaration(), basic_compiler_type, false);431 auto *ed = TypeSystemClang::GetAsEnumDecl(enum_type);432 EXPECT_FALSE(!ed);433 EXPECT_EQ(ed->getOwningModuleID(), 100u);434 435 CompilerType record_type = ast.CreateRecordType(436 nullptr, OptionalClangModuleID(200), lldb::eAccessPublic, "FooRecord",437 llvm::to_underlying(clang::TagTypeKind::Struct),438 lldb::eLanguageTypeC_plus_plus, std::nullopt);439 auto *rd = TypeSystemClang::GetAsRecordDecl(record_type);440 EXPECT_FALSE(!rd);441 EXPECT_EQ(rd->getOwningModuleID(), 200u);442 443 CompilerType class_type =444 ast.CreateObjCClass("objc_class", ast.GetTranslationUnitDecl(),445 OptionalClangModuleID(300), false);446 auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(class_type);447 EXPECT_FALSE(!cd);448 EXPECT_EQ(cd->getOwningModuleID(), 300u);449}450 451TEST_F(TestTypeSystemClang, TestIsClangType) {452 clang::ASTContext &context = m_ast->getASTContext();453 lldb::opaque_compiler_type_t bool_ctype =454 TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool);455 CompilerType bool_type(m_ast->weak_from_this(), bool_ctype);456 CompilerType record_type = m_ast->CreateRecordType(457 nullptr, OptionalClangModuleID(100), lldb::eAccessPublic, "FooRecord",458 llvm::to_underlying(clang::TagTypeKind::Struct),459 lldb::eLanguageTypeC_plus_plus, std::nullopt);460 // Clang builtin type and record type should pass461 EXPECT_TRUE(ClangUtil::IsClangType(bool_type));462 EXPECT_TRUE(ClangUtil::IsClangType(record_type));463 464 // Default constructed type should fail465 EXPECT_FALSE(ClangUtil::IsClangType(CompilerType()));466}467 468TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) {469 CompilerType record_type = m_ast->CreateRecordType(470 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "FooRecord",471 llvm::to_underlying(clang::TagTypeKind::Struct),472 lldb::eLanguageTypeC_plus_plus, std::nullopt);473 QualType qt;474 475 qt = ClangUtil::GetQualType(record_type);476 EXPECT_EQ(0u, qt.getLocalFastQualifiers());477 record_type = record_type.AddConstModifier();478 record_type = record_type.AddVolatileModifier();479 record_type = record_type.AddRestrictModifier();480 qt = ClangUtil::GetQualType(record_type);481 EXPECT_NE(0u, qt.getLocalFastQualifiers());482 record_type = ClangUtil::RemoveFastQualifiers(record_type);483 qt = ClangUtil::GetQualType(record_type);484 EXPECT_EQ(0u, qt.getLocalFastQualifiers());485}486 487TEST_F(TestTypeSystemClang, TestConvertAccessTypeToAccessSpecifier) {488 EXPECT_EQ(AS_none,489 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessNone));490 EXPECT_EQ(AS_none, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(491 eAccessPackage));492 EXPECT_EQ(AS_public,493 TypeSystemClang::ConvertAccessTypeToAccessSpecifier(eAccessPublic));494 EXPECT_EQ(AS_private, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(495 eAccessPrivate));496 EXPECT_EQ(AS_protected, TypeSystemClang::ConvertAccessTypeToAccessSpecifier(497 eAccessProtected));498}499 500TEST_F(TestTypeSystemClang, TestUnifyAccessSpecifiers) {501 // Unifying two of the same type should return the same type502 EXPECT_EQ(AS_public,503 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_public));504 EXPECT_EQ(AS_private,505 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_private));506 EXPECT_EQ(AS_protected,507 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_protected));508 509 // Otherwise the result should be the strictest of the two.510 EXPECT_EQ(AS_private,511 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_public));512 EXPECT_EQ(AS_private,513 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_protected));514 EXPECT_EQ(AS_private,515 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_private));516 EXPECT_EQ(AS_private,517 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_private));518 EXPECT_EQ(AS_protected,519 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_public));520 EXPECT_EQ(AS_protected,521 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_protected));522 523 // None is stricter than everything (by convention)524 EXPECT_EQ(AS_none,525 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_public));526 EXPECT_EQ(AS_none,527 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_protected));528 EXPECT_EQ(AS_none,529 TypeSystemClang::UnifyAccessSpecifiers(AS_none, AS_private));530 EXPECT_EQ(AS_none,531 TypeSystemClang::UnifyAccessSpecifiers(AS_public, AS_none));532 EXPECT_EQ(AS_none,533 TypeSystemClang::UnifyAccessSpecifiers(AS_protected, AS_none));534 EXPECT_EQ(AS_none,535 TypeSystemClang::UnifyAccessSpecifiers(AS_private, AS_none));536}537 538TEST_F(TestTypeSystemClang, TestRecordHasFields) {539 CompilerType int_type = m_ast->GetBasicType(eBasicTypeInt);540 541 // Test that a record with no fields returns false542 CompilerType empty_base = m_ast->CreateRecordType(543 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyBase",544 llvm::to_underlying(clang::TagTypeKind::Struct),545 lldb::eLanguageTypeC_plus_plus, std::nullopt);546 TypeSystemClang::StartTagDeclarationDefinition(empty_base);547 TypeSystemClang::CompleteTagDeclarationDefinition(empty_base);548 549 RecordDecl *empty_base_decl = TypeSystemClang::GetAsRecordDecl(empty_base);550 EXPECT_NE(nullptr, empty_base_decl);551 EXPECT_FALSE(m_ast->RecordHasFields(empty_base_decl));552 553 // Test that a record with direct fields returns true554 CompilerType non_empty_base = m_ast->CreateRecordType(555 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "NonEmptyBase",556 llvm::to_underlying(clang::TagTypeKind::Struct),557 lldb::eLanguageTypeC_plus_plus, std::nullopt);558 TypeSystemClang::StartTagDeclarationDefinition(non_empty_base);559 FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType(560 non_empty_base, "MyField", int_type, eAccessPublic, 0);561 TypeSystemClang::CompleteTagDeclarationDefinition(non_empty_base);562 RecordDecl *non_empty_base_decl =563 TypeSystemClang::GetAsRecordDecl(non_empty_base);564 EXPECT_NE(nullptr, non_empty_base_decl);565 EXPECT_NE(nullptr, non_empty_base_field_decl);566 EXPECT_TRUE(m_ast->RecordHasFields(non_empty_base_decl));567 568 std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;569 570 // Test that a record with no direct fields, but fields in a base returns true571 CompilerType empty_derived = m_ast->CreateRecordType(572 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived",573 llvm::to_underlying(clang::TagTypeKind::Struct),574 lldb::eLanguageTypeC_plus_plus, std::nullopt);575 TypeSystemClang::StartTagDeclarationDefinition(empty_derived);576 std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec =577 m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),578 lldb::eAccessPublic, false, false);579 bases.push_back(std::move(non_empty_base_spec));580 bool result = m_ast->TransferBaseClasses(empty_derived.GetOpaqueQualType(),581 std::move(bases));582 TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived);583 EXPECT_TRUE(result);584 CXXRecordDecl *empty_derived_non_empty_base_cxx_decl =585 m_ast->GetAsCXXRecordDecl(empty_derived.GetOpaqueQualType());586 RecordDecl *empty_derived_non_empty_base_decl =587 TypeSystemClang::GetAsRecordDecl(empty_derived);588 EXPECT_EQ(1u, m_ast->GetNumBaseClasses(589 empty_derived_non_empty_base_cxx_decl, false));590 EXPECT_TRUE(m_ast->RecordHasFields(empty_derived_non_empty_base_decl));591 592 // Test that a record with no direct fields, but fields in a virtual base593 // returns true594 CompilerType empty_derived2 = m_ast->CreateRecordType(595 nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived2",596 llvm::to_underlying(clang::TagTypeKind::Struct),597 lldb::eLanguageTypeC_plus_plus, std::nullopt);598 TypeSystemClang::StartTagDeclarationDefinition(empty_derived2);599 std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec =600 m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),601 lldb::eAccessPublic, true, false);602 bases.push_back(std::move(non_empty_vbase_spec));603 result = m_ast->TransferBaseClasses(empty_derived2.GetOpaqueQualType(),604 std::move(bases));605 TypeSystemClang::CompleteTagDeclarationDefinition(empty_derived2);606 EXPECT_TRUE(result);607 CXXRecordDecl *empty_derived_non_empty_vbase_cxx_decl =608 m_ast->GetAsCXXRecordDecl(empty_derived2.GetOpaqueQualType());609 RecordDecl *empty_derived_non_empty_vbase_decl =610 TypeSystemClang::GetAsRecordDecl(empty_derived2);611 EXPECT_EQ(1u, m_ast->GetNumBaseClasses(612 empty_derived_non_empty_vbase_cxx_decl, false));613 EXPECT_TRUE(614 m_ast->RecordHasFields(empty_derived_non_empty_vbase_decl));615}616 617TEST_F(TestTypeSystemClang, TemplateArguments) {618 TypeSystemClang::TemplateParameterInfos infos;619 infos.InsertArg("T", TemplateArgument(m_ast->getASTContext().IntTy));620 621 llvm::APSInt arg(llvm::APInt(8, 47));622 infos.InsertArg("I", TemplateArgument(m_ast->getASTContext(), arg,623 m_ast->getASTContext().IntTy));624 625 llvm::APFloat float_arg(5.5f);626 infos.InsertArg("F", TemplateArgument(m_ast->getASTContext(),627 m_ast->getASTContext().FloatTy,628 clang::APValue(float_arg)));629 630 llvm::APFloat double_arg(-15.2);631 infos.InsertArg("D", TemplateArgument(m_ast->getASTContext(),632 m_ast->getASTContext().DoubleTy,633 clang::APValue(double_arg)));634 635 // template<typename T, int I, float F, double D> struct foo;636 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(637 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,638 "foo", llvm::to_underlying(clang::TagTypeKind::Struct), infos);639 ASSERT_NE(decl, nullptr);640 641 // foo<int, 47>642 ClassTemplateSpecializationDecl *spec_decl =643 m_ast->CreateClassTemplateSpecializationDecl(644 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl,645 llvm::to_underlying(clang::TagTypeKind::Struct), infos);646 ASSERT_NE(spec_decl, nullptr);647 CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl);648 ASSERT_TRUE(type);649 m_ast->StartTagDeclarationDefinition(type);650 m_ast->CompleteTagDeclarationDefinition(type);651 652 // typedef foo<int, 47> foo_def;653 CompilerType typedef_type = type.CreateTypedef(654 "foo_def", m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), 0);655 656 CompilerType auto_type(657 m_ast->weak_from_this(),658 m_ast->getASTContext()659 .getAutoType(ClangUtil::GetCanonicalQualType(typedef_type),660 clang::AutoTypeKeyword::Auto, false)661 .getAsOpaquePtr());662 663 CompilerType int_type(m_ast->weak_from_this(),664 m_ast->getASTContext().IntTy.getAsOpaquePtr());665 CompilerType float_type(m_ast->weak_from_this(),666 m_ast->getASTContext().FloatTy.getAsOpaquePtr());667 CompilerType double_type(m_ast->weak_from_this(),668 m_ast->getASTContext().DoubleTy.getAsOpaquePtr());669 for (CompilerType t : {type, typedef_type, auto_type}) {670 SCOPED_TRACE(t.GetTypeName().AsCString());671 672 const bool expand_pack = false;673 EXPECT_EQ(674 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0, expand_pack),675 eTemplateArgumentKindType);676 EXPECT_EQ(677 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0, expand_pack),678 int_type);679 EXPECT_EQ(std::nullopt, m_ast->GetIntegralTemplateArgument(680 t.GetOpaqueQualType(), 0, expand_pack));681 682 EXPECT_EQ(683 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1, expand_pack),684 eTemplateArgumentKindIntegral);685 EXPECT_EQ(686 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1, expand_pack),687 CompilerType());688 auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1,689 expand_pack);690 ASSERT_NE(std::nullopt, result);691 EXPECT_EQ(arg, result->value.GetAPSInt());692 EXPECT_EQ(int_type, result->type);693 694 EXPECT_EQ(695 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 2, expand_pack),696 eTemplateArgumentKindStructuralValue);697 EXPECT_EQ(698 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 2, expand_pack),699 CompilerType());700 auto float_result = m_ast->GetIntegralTemplateArgument(701 t.GetOpaqueQualType(), 2, expand_pack);702 ASSERT_NE(std::nullopt, float_result);703 EXPECT_EQ(float_arg, float_result->value.GetAPFloat());704 EXPECT_EQ(float_type, float_result->type);705 706 EXPECT_EQ(707 m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 3, expand_pack),708 eTemplateArgumentKindStructuralValue);709 EXPECT_EQ(710 m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 3, expand_pack),711 CompilerType());712 auto double_result = m_ast->GetIntegralTemplateArgument(713 t.GetOpaqueQualType(), 3, expand_pack);714 ASSERT_NE(std::nullopt, double_result);715 EXPECT_EQ(double_arg, double_result->value.GetAPFloat());716 EXPECT_EQ(double_type, double_result->type);717 }718}719 720class TestCreateClassTemplateDecl : public TestTypeSystemClang {721protected:722 /// The class templates created so far by the Expect* functions below.723 llvm::DenseSet<ClassTemplateDecl *> m_created_templates;724 725 /// Utility function for creating a class template.726 ClassTemplateDecl *727 CreateClassTemplate(const TypeSystemClang::TemplateParameterInfos &infos) {728 ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(729 m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,730 "foo", llvm::to_underlying(clang::TagTypeKind::Struct), infos);731 return decl;732 }733 734 /// Creates a new class template with the given template parameters.735 /// Asserts that a new ClassTemplateDecl is created.736 /// \param description The gtest scope string that should describe the input.737 /// \param infos The template parameters that the class template should have.738 /// \returns The created ClassTemplateDecl.739 ClassTemplateDecl *740 ExpectNewTemplate(std::string description,741 const TypeSystemClang::TemplateParameterInfos &infos) {742 SCOPED_TRACE(description);743 ClassTemplateDecl *first_template = CreateClassTemplate(infos);744 // A new template should have been created.745 EXPECT_FALSE(m_created_templates.contains(first_template))746 << "Didn't create new class template but reused this existing decl:\n"747 << ClangUtil::DumpDecl(first_template);748 m_created_templates.insert(first_template);749 750 // Creating a new template with the same arguments should always return751 // the template created above.752 ClassTemplateDecl *second_template = CreateClassTemplate(infos);753 EXPECT_EQ(first_template, second_template)754 << "Second attempt to create class template didn't reuse first decl:\n"755 << ClangUtil::DumpDecl(first_template) << "\nInstead created/reused:\n"756 << ClangUtil::DumpDecl(second_template);757 return first_template;758 }759 760 /// Tries to create a new class template but asserts that an existing class761 /// template in the current AST is reused (in contract so a new class762 /// template being created).763 /// \param description The gtest scope string that should describe the input.764 /// \param infos The template parameters that the class template should have.765 void766 ExpectReusedTemplate(std::string description,767 const TypeSystemClang::TemplateParameterInfos &infos,768 ClassTemplateDecl *expected) {769 SCOPED_TRACE(description);770 ClassTemplateDecl *td = CreateClassTemplate(infos);771 EXPECT_EQ(td, expected)772 << "Created/reused class template is:\n"773 << ClangUtil::DumpDecl(td) << "\nExpected to reuse:\n"774 << ClangUtil::DumpDecl(expected);775 }776};777 778TEST_F(TestCreateClassTemplateDecl, FindExistingTemplates) {779 // This tests the logic in TypeSystemClang::CreateClassTemplateDecl that780 // decides whether an existing ClassTemplateDecl in the AST can be reused.781 // The behaviour should follow the C++ rules for redeclaring templates782 // (e.g., parameter names can be changed/omitted.)783 784 // Test an empty template parameter list: <>785 ExpectNewTemplate("<>", {{}, {}});786 787 clang::TemplateArgument intArg(m_ast->getASTContext().IntTy);788 clang::TemplateArgument int47Arg(m_ast->getASTContext(),789 llvm::APSInt(llvm::APInt(32, 47)),790 m_ast->getASTContext().IntTy);791 clang::TemplateArgument floatArg(m_ast->getASTContext().FloatTy);792 clang::TemplateArgument char47Arg(m_ast->getASTContext(),793 llvm::APSInt(llvm::APInt(8, 47)),794 m_ast->getASTContext().SignedCharTy);795 796 clang::TemplateArgument char123Arg(m_ast->getASTContext(),797 llvm::APSInt(llvm::APInt(8, 123)),798 m_ast->getASTContext().SignedCharTy);799 800 // Test that <typename T> with T = int creates a new template.801 ClassTemplateDecl *single_type_arg =802 ExpectNewTemplate("<typename T>", {{"T"}, {intArg}});803 804 // Test that changing the parameter name doesn't create a new class template.805 ExpectReusedTemplate("<typename A> (A = int)", {{"A"}, {intArg}},806 single_type_arg);807 808 // Test that changing the used type doesn't create a new class template.809 ExpectReusedTemplate("<typename A> (A = float)", {{"A"}, {floatArg}},810 single_type_arg);811 812 // Test that <typename A, signed char I> creates a new template with A = int813 // and I = 47;814 ClassTemplateDecl *type_and_char_value =815 ExpectNewTemplate("<typename A, signed char I> (I = 47)",816 {{"A", "I"}, {floatArg, char47Arg}});817 818 // Change the value of the I parameter to 123. The previously created819 // class template should still be reused.820 ExpectReusedTemplate("<typename A, signed char I> (I = 123)",821 {{"A", "I"}, {floatArg, char123Arg}},822 type_and_char_value);823 824 // Change the type of the I parameter to int so we have <typename A, int I>.825 // The class template from above can't be reused.826 ExpectNewTemplate("<typename A, int I> (I = 123)",827 {{"A", "I"}, {floatArg, int47Arg}});828 829 // Test a second type parameter will also cause a new template to be created.830 // We now have <typename A, int I, typename B>.831 ClassTemplateDecl *type_and_char_value_and_type =832 ExpectNewTemplate("<typename A, int I, typename B>",833 {{"A", "I", "B"}, {floatArg, int47Arg, intArg}});834 835 // Remove all the names from the parameters which shouldn't influence the836 // way the templates get merged.837 ExpectReusedTemplate("<typename, int, typename>",838 {{"", "", ""}, {floatArg, int47Arg, intArg}},839 type_and_char_value_and_type);840}841 842TEST_F(TestCreateClassTemplateDecl, FindExistingTemplatesWithParameterPack) {843 // The same as FindExistingTemplates but for templates with parameter packs.844 TypeSystemClang::TemplateParameterInfos infos;845 clang::TemplateArgument intArg(m_ast->getASTContext().IntTy);846 clang::TemplateArgument int1Arg(m_ast->getASTContext(),847 llvm::APSInt(llvm::APInt(32, 1)),848 m_ast->getASTContext().IntTy);849 clang::TemplateArgument int123Arg(m_ast->getASTContext(),850 llvm::APSInt(llvm::APInt(32, 123)),851 m_ast->getASTContext().IntTy);852 clang::TemplateArgument longArg(m_ast->getASTContext().LongTy);853 clang::TemplateArgument long1Arg(m_ast->getASTContext(),854 llvm::APSInt(llvm::APInt(64, 1)),855 m_ast->getASTContext().LongTy);856 857 infos.SetParameterPack(858 std::make_unique<TypeSystemClang::TemplateParameterInfos>(859 llvm::SmallVector<const char *>{"", ""},860 llvm::SmallVector<TemplateArgument>{intArg, intArg}));861 862 ClassTemplateDecl *type_pack =863 ExpectNewTemplate("<typename ...> (int, int)", infos);864 865 // Special case: An instantiation for a parameter pack with no values fits866 // to whatever class template we find. There isn't enough information to867 // do an actual comparison here.868 infos.SetParameterPack(869 std::make_unique<TypeSystemClang::TemplateParameterInfos>());870 ExpectReusedTemplate("<...> (no values in pack)", infos, type_pack);871 872 // Change the type content of pack type values.873 infos.SetParameterPack(874 std::make_unique<TypeSystemClang::TemplateParameterInfos>(875 llvm::SmallVector<const char *>{"", ""},876 llvm::SmallVector<TemplateArgument>{intArg, longArg}));877 ExpectReusedTemplate("<typename ...> (int, long)", infos, type_pack);878 879 // Change the number of pack values.880 infos.SetParameterPack(881 std::make_unique<TypeSystemClang::TemplateParameterInfos>(882 llvm::SmallVector<const char *>{""},883 llvm::SmallVector<TemplateArgument>{intArg}));884 ExpectReusedTemplate("<typename ...> (int)", infos, type_pack);885 886 // The names of the pack values shouldn't matter.887 infos.SetParameterPack(888 std::make_unique<TypeSystemClang::TemplateParameterInfos>(889 llvm::SmallVector<const char *>{"A"},890 llvm::SmallVector<TemplateArgument>{intArg}));891 ExpectReusedTemplate("<typename ...> (int)", infos, type_pack);892 893 // Changing the kind of template argument will create a new template.894 infos.SetParameterPack(895 std::make_unique<TypeSystemClang::TemplateParameterInfos>(896 llvm::SmallVector<const char *>{"A"},897 llvm::SmallVector<TemplateArgument>{int1Arg}));898 ClassTemplateDecl *int_pack = ExpectNewTemplate("<int ...> (int = 1)", infos);899 900 // Changing the value of integral parameters will not create a new template.901 infos.SetParameterPack(902 std::make_unique<TypeSystemClang::TemplateParameterInfos>(903 llvm::SmallVector<const char *>{"A"},904 llvm::SmallVector<TemplateArgument>{int123Arg}));905 ExpectReusedTemplate("<int ...> (int = 123)", infos, int_pack);906 907 // Changing the integral type will create a new template.908 infos.SetParameterPack(909 std::make_unique<TypeSystemClang::TemplateParameterInfos>(910 llvm::SmallVector<const char *>{"A"},911 llvm::SmallVector<TemplateArgument>{long1Arg}));912 ExpectNewTemplate("<long ...> (long = 1)", infos);913 914 // Prependinding a non-pack parameter will create a new template.915 infos.InsertArg("T", intArg);916 ExpectNewTemplate("<typename T, long...> (T = int, long = 1)", infos);917}918 919TEST_F(TestTypeSystemClang, OnlyPackName) {920 TypeSystemClang::TemplateParameterInfos infos;921 infos.SetPackName("A");922 EXPECT_FALSE(infos.IsValid());923}924 925static QualType makeConstInt(clang::ASTContext &ctxt) {926 QualType result(ctxt.IntTy);927 result.addConst();928 return result;929}930 931TEST_F(TestTypeSystemClang, TestGetTypeClassDeclType) {932 clang::ASTContext &ctxt = m_ast->getASTContext();933 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());934 QualType t = ctxt.getDecltypeType(nullptr_expr, makeConstInt(ctxt));935 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));936}937 938TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOf) {939 clang::ASTContext &ctxt = m_ast->getASTContext();940 QualType t = ctxt.getTypeOfType(makeConstInt(ctxt), TypeOfKind::Qualified);941 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));942}943 944TEST_F(TestTypeSystemClang, TestGetTypeClassTypeOfExpr) {945 clang::ASTContext &ctxt = m_ast->getASTContext();946 auto *nullptr_expr = new (ctxt) CXXNullPtrLiteralExpr(ctxt.NullPtrTy, SourceLocation());947 QualType t = ctxt.getTypeOfExprType(nullptr_expr, TypeOfKind::Qualified);948 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));949}950 951TEST_F(TestTypeSystemClang, TestGetTypeClassNested) {952 clang::ASTContext &ctxt = m_ast->getASTContext();953 QualType t_base =954 ctxt.getTypeOfType(makeConstInt(ctxt), TypeOfKind::Qualified);955 QualType t = ctxt.getTypeOfType(t_base, TypeOfKind::Qualified);956 EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));957}958 959TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {960 // Tests creating a function template.961 962 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);963 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();964 965 // Prepare the declarations/types we need for the template.966 CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U);967 FunctionDecl *func = m_ast->CreateFunctionDeclaration(968 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,969 false, /*asm_label=*/{});970 TypeSystemClang::TemplateParameterInfos empty_params;971 972 // Create the actual function template.973 clang::FunctionTemplateDecl *func_template =974 m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func,975 empty_params);976 977 EXPECT_EQ(TU, func_template->getDeclContext());978 EXPECT_EQ("foo", func_template->getName());979 EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess());980}981 982TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {983 // Tests creating a function template inside a record.984 985 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);986 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();987 988 // Create a record we can put the function template int.989 CompilerType record_type =990 clang_utils::createRecordWithField(*m_ast, "record", int_type, "field");991 clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type);992 993 // Prepare the declarations/types we need for the template.994 CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U);995 // We create the FunctionDecl for the template in the TU DeclContext because:996 // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can).997 // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.998 FunctionDecl *func = m_ast->CreateFunctionDeclaration(999 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,1000 false, /*asm_label=*/{});1001 TypeSystemClang::TemplateParameterInfos empty_params;1002 1003 // Create the actual function template.1004 clang::FunctionTemplateDecl *func_template =1005 m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func,1006 empty_params);1007 1008 EXPECT_EQ(record, func_template->getDeclContext());1009 EXPECT_EQ("foo", func_template->getName());1010 EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess());1011}1012 1013TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) {1014 // We need to simulate this behavior in our AST that we construct as we don't1015 // have a Sema instance that can do this for us:1016 // C++11 [class.copy]p7, p18:1017 // If the class definition declares a move constructor or move assignment1018 // operator, an implicitly declared copy constructor or copy assignment1019 // operator is defined as deleted.1020 1021 // Create a record and start defining it.1022 llvm::StringRef class_name = "S";1023 CompilerType t = clang_utils::createRecord(*m_ast, class_name);1024 m_ast->StartTagDeclarationDefinition(t);1025 1026 // Create a move constructor that will delete the implicit copy constructor.1027 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);1028 std::array<CompilerType, 1> args{t.GetRValueReferenceType()};1029 CompilerType function_type = m_ast->CreateFunctionType(1030 return_type, args, /*variadic=*/false, /*quals*/ 0U);1031 bool is_virtual = false;1032 bool is_static = false;1033 bool is_inline = false;1034 bool is_explicit = true;1035 bool is_attr_used = false;1036 bool is_artificial = false;1037 m_ast->AddMethodToCXXRecordType(1038 t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type,1039 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,1040 is_explicit, is_attr_used, is_artificial);1041 1042 // Complete the definition and check the created record.1043 m_ast->CompleteTagDeclarationDefinition(t);1044 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));1045 // We can't call defaultedCopyConstructorIsDeleted() as this requires that1046 // the Decl passes through Sema which will actually compute this field.1047 // Instead we check that there is no copy constructor declared by the user1048 // which only leaves a non-deleted defaulted copy constructor as an option1049 // that our record will have no simple copy constructor.1050 EXPECT_FALSE(record->hasUserDeclaredCopyConstructor());1051 EXPECT_FALSE(record->hasSimpleCopyConstructor());1052}1053 1054TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {1055 // Tests that we don't delete the a user-defined copy constructor when1056 // a move constructor is provided.1057 // See also the TestDeletingImplicitCopyCstrDueToMoveCStr test.1058 llvm::StringRef class_name = "S";1059 CompilerType t = clang_utils::createRecord(*m_ast, class_name);1060 m_ast->StartTagDeclarationDefinition(t);1061 1062 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);1063 bool is_virtual = false;1064 bool is_static = false;1065 bool is_inline = false;1066 bool is_explicit = true;1067 bool is_attr_used = false;1068 bool is_artificial = false;1069 // Create a move constructor.1070 {1071 std::array<CompilerType, 1> args{t.GetRValueReferenceType()};1072 CompilerType function_type = m_ast->CreateFunctionType(1073 return_type, args, /*variadic=*/false, /*quals*/ 0U);1074 m_ast->AddMethodToCXXRecordType(1075 t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type,1076 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,1077 is_explicit, is_attr_used, is_artificial);1078 }1079 // Create a copy constructor.1080 {1081 std::array<CompilerType, 1> args{1082 t.GetLValueReferenceType().AddConstModifier()};1083 CompilerType function_type =1084 m_ast->CreateFunctionType(return_type, args,1085 /*variadic=*/false, /*quals*/ 0U);1086 m_ast->AddMethodToCXXRecordType(1087 t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type,1088 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,1089 is_explicit, is_attr_used, is_artificial);1090 }1091 1092 // Complete the definition and check the created record.1093 m_ast->CompleteTagDeclarationDefinition(t);1094 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));1095 EXPECT_TRUE(record->hasUserDeclaredCopyConstructor());1096}1097 1098TEST_F(TestTypeSystemClang, AddMethodToObjCObjectType) {1099 // Create an interface decl and mark it as having external storage.1100 CompilerType c = m_ast->CreateObjCClass("A", m_ast->GetTranslationUnitDecl(),1101 OptionalClangModuleID(),1102 /*IsInternal*/ false);1103 ObjCInterfaceDecl *interface = m_ast->GetAsObjCInterfaceDecl(c);1104 m_ast->SetHasExternalStorage(c.GetOpaqueQualType(), true);1105 EXPECT_TRUE(interface->hasExternalLexicalStorage());1106 1107 // Add a method to the interface.1108 std::vector<CompilerType> args;1109 CompilerType func_type = m_ast->CreateFunctionType(1110 m_ast->GetBasicType(lldb::eBasicTypeInt), args, /*variadic*/ false,1111 /*quals*/ 0, clang::CallingConv::CC_C);1112 bool variadic = false;1113 bool artificial = false;1114 bool objc_direct = false;1115 clang::ObjCMethodDecl *method = TypeSystemClang::AddMethodToObjCObjectType(1116 c, "-[A foo]", func_type, artificial, variadic, objc_direct);1117 ASSERT_NE(method, nullptr);1118 1119 // The interface decl should still have external lexical storage.1120 EXPECT_TRUE(interface->hasExternalLexicalStorage());1121 1122 // Test some properties of the created ObjCMethodDecl.1123 EXPECT_FALSE(method->isVariadic());1124 EXPECT_TRUE(method->isImplicit());1125 EXPECT_FALSE(method->isDirectMethod());1126 EXPECT_EQ(method->getDeclName().getObjCSelector().getAsString(), "foo");1127}1128 1129TEST_F(TestTypeSystemClang, GetFullyUnqualifiedType) {1130 CompilerType bool_ = m_ast->GetBasicType(eBasicTypeBool);1131 CompilerType cv_bool = bool_.AddConstModifier().AddVolatileModifier();1132 1133 // const volatile bool -> bool1134 EXPECT_EQ(bool_, cv_bool.GetFullyUnqualifiedType());1135 1136 // const volatile bool[47] -> bool[47]1137 EXPECT_EQ(bool_.GetArrayType(47),1138 cv_bool.GetArrayType(47).GetFullyUnqualifiedType());1139 1140 // const volatile bool[47][42] -> bool[47][42]1141 EXPECT_EQ(1142 bool_.GetArrayType(42).GetArrayType(47),1143 cv_bool.GetArrayType(42).GetArrayType(47).GetFullyUnqualifiedType());1144 1145 // const volatile bool * -> bool *1146 EXPECT_EQ(bool_.GetPointerType(),1147 cv_bool.GetPointerType().GetFullyUnqualifiedType());1148 1149 // const volatile bool *[47] -> bool *[47]1150 EXPECT_EQ(1151 bool_.GetPointerType().GetArrayType(47),1152 cv_bool.GetPointerType().GetArrayType(47).GetFullyUnqualifiedType());1153}1154 1155TEST(TestScratchTypeSystemClang, InferSubASTFromLangOpts) {1156 LangOptions lang_opts;1157 EXPECT_EQ(1158 ScratchTypeSystemClang::DefaultAST,1159 ScratchTypeSystemClang::InferIsolatedASTKindFromLangOpts(lang_opts));1160 1161 lang_opts.Modules = true;1162 EXPECT_EQ(1163 ScratchTypeSystemClang::IsolatedASTKind::CppModules,1164 ScratchTypeSystemClang::InferIsolatedASTKindFromLangOpts(lang_opts));1165}1166 1167TEST_F(TestTypeSystemClang, GetDeclContextByNameWhenMissingSymbolFile) {1168 // Test that a type system without a symbol file is handled gracefully.1169 std::vector<CompilerDecl> decls =1170 m_ast->DeclContextFindDeclByName(nullptr, ConstString("SomeName"), true);1171 1172 EXPECT_TRUE(decls.empty());1173}1174 1175TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) {1176 // Tests that AddMethodToCXXRecordType creates ParmVarDecl's with1177 // a correct clang::DeclContext.1178 1179 llvm::StringRef class_name = "S";1180 CompilerType t = clang_utils::createRecord(*m_ast, class_name);1181 m_ast->StartTagDeclarationDefinition(t);1182 1183 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);1184 const bool is_virtual = false;1185 const bool is_static = false;1186 const bool is_inline = false;1187 const bool is_explicit = true;1188 const bool is_attr_used = false;1189 const bool is_artificial = false;1190 1191 llvm::SmallVector<CompilerType> param_types{1192 m_ast->GetBasicType(lldb::eBasicTypeInt),1193 m_ast->GetBasicType(lldb::eBasicTypeShort)};1194 CompilerType function_type =1195 m_ast->CreateFunctionType(return_type, param_types,1196 /*variadic=*/false, /*quals*/ 0U);1197 m_ast->AddMethodToCXXRecordType(1198 t.GetOpaqueQualType(), "myFunc", /*asm_label=*/{}, function_type,1199 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,1200 is_explicit, is_attr_used, is_artificial);1201 1202 // Complete the definition and check the created record.1203 m_ast->CompleteTagDeclarationDefinition(t);1204 1205 auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));1206 1207 auto method_it = record->method_begin();1208 ASSERT_NE(method_it, record->method_end());1209 1210 EXPECT_EQ(method_it->getNumParams(), param_types.size());1211 1212 // DeclContext of each parameter should be the CXXMethodDecl itself.1213 EXPECT_EQ(method_it->getParamDecl(0)->getDeclContext(), *method_it);1214 EXPECT_EQ(method_it->getParamDecl(1)->getDeclContext(), *method_it);1215}1216 1217TEST_F(TestTypeSystemClang, TestGetTypeInfo) {1218 // Tests TypeSystemClang::GetTypeInfo1219 1220 const ASTContext &ast = m_ast->getASTContext();1221 1222 CompilerType complex_int = m_ast->GetType(ast.getComplexType(ast.IntTy));1223 EXPECT_EQ(complex_int.GetTypeInfo(),1224 (eTypeIsInteger | eTypeIsComplex | eTypeIsBuiltIn | eTypeHasValue));1225 1226 CompilerType complex_float = m_ast->GetType(ast.getComplexType(ast.FloatTy));1227 EXPECT_EQ(complex_float.GetTypeInfo(),1228 (eTypeIsFloat | eTypeIsComplex | eTypeIsBuiltIn | eTypeHasValue));1229 1230 CompilerType vector_of_int =1231 m_ast->GetType(ast.getVectorType(ast.IntTy, 1, VectorKind::Generic));1232 EXPECT_EQ(vector_of_int.GetTypeInfo(),1233 (eTypeIsInteger | eTypeIsVector | eTypeHasChildren));1234 1235 CompilerType vector_of_float =1236 m_ast->GetType(ast.getVectorType(ast.FloatTy, 1, VectorKind::Generic));1237 EXPECT_EQ(vector_of_float.GetTypeInfo(),1238 (eTypeIsFloat | eTypeIsVector | eTypeHasChildren));1239}1240 1241TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) {1242 // Tests TypeSystemClang::DeclGetMangledName for constructors/destructors1243 // with and without AsmLabels.1244 1245 llvm::StringRef class_name = "S";1246 CompilerType t = clang_utils::createRecord(*m_ast, class_name);1247 m_ast->StartTagDeclarationDefinition(t);1248 1249 CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);1250 const bool is_virtual = false;1251 const bool is_static = false;1252 const bool is_inline = false;1253 const bool is_explicit = true;1254 const bool is_attr_used = false;1255 const bool is_artificial = false;1256 1257 CompilerType function_type =1258 m_ast->CreateFunctionType(return_type, {},1259 /*variadic=*/false, /*quals*/ 0U);1260 auto *ctor_nolabel = m_ast->AddMethodToCXXRecordType(1261 t.GetOpaqueQualType(), "S", /*asm_label=*/{}, function_type,1262 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,1263 is_explicit, is_attr_used, is_artificial);1264 1265 auto *dtor_nolabel = m_ast->AddMethodToCXXRecordType(1266 t.GetOpaqueQualType(), "~S", /*asm_label=*/{}, function_type,1267 lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,1268 is_explicit, is_attr_used, is_artificial);1269 1270 auto *ctor = m_ast->AddMethodToCXXRecordType(1271 t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func::0x0:0x0:S",1272 function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,1273 is_inline, is_explicit, is_attr_used, is_artificial);1274 1275 auto *dtor = m_ast->AddMethodToCXXRecordType(1276 t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func::0x0:0x0:~S",1277 function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,1278 is_inline, is_explicit, is_attr_used, is_artificial);1279 1280 m_ast->CompleteTagDeclarationDefinition(t);1281 1282 ASSERT_TRUE(ctor_nolabel);1283 ASSERT_TRUE(dtor_nolabel);1284 ASSERT_TRUE(ctor);1285 ASSERT_TRUE(dtor);1286 1287#ifdef _WIN321288 EXPECT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(),1289 "??0S@@QEAA@XZ");1290 EXPECT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(),1291 "??_DS@@QEAAXXZ");1292#else1293 EXPECT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(),1294 "_ZN1SC1Ev");1295 EXPECT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(),1296 "_ZN1SD1Ev");1297#endif1298 1299 EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(1300 m_ast->DeclGetMangledName(ctor).GetStringRef())1301 .data(),1302 "$__lldb_func:C0:0x0:0x0:S");1303 EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(1304 m_ast->DeclGetMangledName(dtor).GetStringRef())1305 .data(),1306 "$__lldb_func:D1:0x0:0x0:~S");1307}1308 1309struct AsmLabelTestCase {1310 llvm::StringRef mangled;1311 llvm::StringRef expected;1312};1313 1314class TestTypeSystemClangAsmLabel1315 : public testing::TestWithParam<AsmLabelTestCase> {1316public:1317 SubsystemRAII<FileSystem, HostInfo> subsystems;1318 1319 void SetUp() override {1320 m_holder =1321 std::make_unique<clang_utils::TypeSystemClangHolder>("test ASTContext");1322 m_ast = m_holder->GetAST();1323 }1324 1325 void TearDown() override {1326 m_ast = nullptr;1327 m_holder.reset();1328 }1329 1330protected:1331 TypeSystemClang *m_ast = nullptr;1332 std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;1333};1334 1335static AsmLabelTestCase g_asm_label_test_cases[] = {1336 {/*mangled=*/"$__lldb_func::0x0:0x0:_Z3foov",1337 /*expected=*/"_Z3foov"},1338 {/*mangled=*/"$__lldb_func::0x0:0x0:foo",1339 /*expected=*/"$__lldb_func::0x0:0x0:foo"},1340 {/*mangled=*/"foo",1341 /*expected=*/"foo"},1342 {/*mangled=*/"_Z3foov",1343 /*expected=*/"_Z3foov"},1344 {/*mangled=*/"$__lldb_func:",1345 /*expected=*/"$__lldb_func:"},1346};1347 1348TEST_P(TestTypeSystemClangAsmLabel, DeclGetMangledName) {1349 const auto &[mangled, expected] = GetParam();1350 1351 CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);1352 clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();1353 1354 // Prepare the declarations/types we need for the template.1355 CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U);1356 FunctionDecl *func = m_ast->CreateFunctionDeclaration(1357 TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,1358 false, /*asm_label=*/mangled);1359 1360 ASSERT_EQ(llvm::GlobalValue::dropLLVMManglingEscape(1361 m_ast->DeclGetMangledName(func).GetStringRef()),1362 expected);1363}1364 1365INSTANTIATE_TEST_SUITE_P(AsmLabelTests, TestTypeSystemClangAsmLabel,1366 testing::ValuesIn(g_asm_label_test_cases));1367