| //===-- TestClangASTContext.cpp ---------------------------------------*- C++ |
| //-*-===// |
| |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "gtest/gtest.h" |
| |
| #include "clang/AST/DeclCXX.h" |
| |
| #include "lldb/Host/HostInfo.h" |
| #include "lldb/Symbol/ClangASTContext.h" |
| #include "lldb/Symbol/ClangUtil.h" |
| #include "lldb/Symbol/Declaration.h" |
| #include "lldb/Symbol/GoASTContext.h" |
| |
| using namespace clang; |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| class TestClangASTContext : public testing::Test { |
| public: |
| static void SetUpTestCase() { HostInfo::Initialize(); } |
| |
| static void TearDownTestCase() { HostInfo::Terminate(); } |
| |
| virtual void SetUp() override { |
| std::string triple = HostInfo::GetTargetTriple(); |
| m_ast.reset(new ClangASTContext(triple.c_str())); |
| } |
| |
| virtual void TearDown() override { m_ast.reset(); } |
| |
| protected: |
| std::unique_ptr<ClangASTContext> m_ast; |
| |
| QualType GetBasicQualType(BasicType type) const { |
| return ClangUtil::GetQualType(m_ast->GetBasicTypeFromAST(type)); |
| } |
| |
| QualType GetBasicQualType(const char *name) const { |
| return ClangUtil::GetQualType( |
| m_ast->GetBuiltinTypeByName(ConstString(name))); |
| } |
| }; |
| |
| TEST_F(TestClangASTContext, TestGetBasicTypeFromEnum) { |
| clang::ASTContext *context = m_ast->getASTContext(); |
| |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeBool), context->BoolTy)); |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeChar), context->CharTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeChar16), |
| context->Char16Ty)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeChar32), |
| context->Char32Ty)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeDouble), |
| context->DoubleTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeDoubleComplex), |
| context->DoubleComplexTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeFloat), |
| context->FloatTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeFloatComplex), |
| context->FloatComplexTy)); |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeHalf), context->HalfTy)); |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeInt), context->IntTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeInt128), |
| context->Int128Ty)); |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeLong), context->LongTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeLongDouble), |
| context->LongDoubleTy)); |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeLongDoubleComplex), |
| context->LongDoubleComplexTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeLongLong), |
| context->LongLongTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeNullPtr), |
| context->NullPtrTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeObjCClass), |
| context->getObjCClassType())); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeObjCID), |
| context->getObjCIdType())); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeObjCSel), |
| context->getObjCSelType())); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeShort), |
| context->ShortTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeSignedChar), |
| context->SignedCharTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeUnsignedChar), |
| context->UnsignedCharTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeUnsignedInt), |
| context->UnsignedIntTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeUnsignedInt128), |
| context->UnsignedInt128Ty)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeUnsignedLong), |
| context->UnsignedLongTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeUnsignedLongLong), |
| context->UnsignedLongLongTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeUnsignedShort), |
| context->UnsignedShortTy)); |
| EXPECT_TRUE( |
| context->hasSameType(GetBasicQualType(eBasicTypeVoid), context->VoidTy)); |
| EXPECT_TRUE(context->hasSameType(GetBasicQualType(eBasicTypeWChar), |
| context->WCharTy)); |
| } |
| |
| TEST_F(TestClangASTContext, TestGetBasicTypeFromName) { |
| EXPECT_EQ(GetBasicQualType(eBasicTypeChar), GetBasicQualType("char")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeSignedChar), |
| GetBasicQualType("signed char")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedChar), |
| GetBasicQualType("unsigned char")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeWChar), GetBasicQualType("wchar_t")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeSignedWChar), |
| GetBasicQualType("signed wchar_t")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedWChar), |
| GetBasicQualType("unsigned wchar_t")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeShort), GetBasicQualType("short int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort), |
| GetBasicQualType("unsigned short")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedShort), |
| GetBasicQualType("unsigned short int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeInt), GetBasicQualType("signed int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt), |
| GetBasicQualType("unsigned int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt), |
| GetBasicQualType("unsigned")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeLong), GetBasicQualType("long int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong), |
| GetBasicQualType("unsigned long")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLong), |
| GetBasicQualType("unsigned long int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong), |
| GetBasicQualType("long long")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeLongLong), |
| GetBasicQualType("long long int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong), |
| GetBasicQualType("unsigned long long")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedLongLong), |
| GetBasicQualType("unsigned long long int")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeInt128), GetBasicQualType("__int128_t")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeUnsignedInt128), |
| GetBasicQualType("__uint128_t")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeVoid), GetBasicQualType("void")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeBool), GetBasicQualType("bool")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeFloat), GetBasicQualType("float")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeDouble), GetBasicQualType("double")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeLongDouble), |
| GetBasicQualType("long double")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeObjCID), GetBasicQualType("id")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeObjCSel), GetBasicQualType("SEL")); |
| EXPECT_EQ(GetBasicQualType(eBasicTypeNullPtr), GetBasicQualType("nullptr")); |
| } |
| |
| void VerifyEncodingAndBitSize(clang::ASTContext *context, |
| lldb::Encoding encoding, unsigned int bit_size) { |
| CompilerType type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( |
| context, encoding, bit_size); |
| EXPECT_TRUE(type.IsValid()); |
| |
| QualType qtype = ClangUtil::GetQualType(type); |
| EXPECT_FALSE(qtype.isNull()); |
| if (qtype.isNull()) |
| return; |
| |
| uint64_t actual_size = context->getTypeSize(qtype); |
| EXPECT_EQ(bit_size, actual_size); |
| |
| const clang::Type *type_ptr = qtype.getTypePtr(); |
| EXPECT_NE(nullptr, type_ptr); |
| if (!type_ptr) |
| return; |
| |
| EXPECT_TRUE(type_ptr->isBuiltinType()); |
| if (encoding == eEncodingSint) |
| EXPECT_TRUE(type_ptr->isSignedIntegerType()); |
| else if (encoding == eEncodingUint) |
| EXPECT_TRUE(type_ptr->isUnsignedIntegerType()); |
| else if (encoding == eEncodingIEEE754) |
| EXPECT_TRUE(type_ptr->isFloatingType()); |
| } |
| |
| TEST_F(TestClangASTContext, TestBuiltinTypeForEncodingAndBitSize) { |
| clang::ASTContext *context = m_ast->getASTContext(); |
| |
| // Make sure we can get types of every possible size in every possible |
| // encoding. |
| // We can't make any guarantee about which specific type we get, because the |
| // standard |
| // isn't that specific. We only need to make sure the compiler hands us some |
| // type that |
| // is both a builtin type and matches the requested bit size. |
| VerifyEncodingAndBitSize(context, eEncodingSint, 8); |
| VerifyEncodingAndBitSize(context, eEncodingSint, 16); |
| VerifyEncodingAndBitSize(context, eEncodingSint, 32); |
| VerifyEncodingAndBitSize(context, eEncodingSint, 64); |
| VerifyEncodingAndBitSize(context, eEncodingSint, 128); |
| |
| VerifyEncodingAndBitSize(context, eEncodingUint, 8); |
| VerifyEncodingAndBitSize(context, eEncodingUint, 16); |
| VerifyEncodingAndBitSize(context, eEncodingUint, 32); |
| VerifyEncodingAndBitSize(context, eEncodingUint, 64); |
| VerifyEncodingAndBitSize(context, eEncodingUint, 128); |
| |
| VerifyEncodingAndBitSize(context, eEncodingIEEE754, 32); |
| VerifyEncodingAndBitSize(context, eEncodingIEEE754, 64); |
| } |
| |
| TEST_F(TestClangASTContext, TestIsClangType) { |
| clang::ASTContext *context = m_ast->getASTContext(); |
| lldb::opaque_compiler_type_t bool_ctype = |
| ClangASTContext::GetOpaqueCompilerType(context, lldb::eBasicTypeBool); |
| CompilerType bool_type(m_ast.get(), bool_ctype); |
| CompilerType record_type = m_ast->CreateRecordType( |
| nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, |
| lldb::eLanguageTypeC_plus_plus, nullptr); |
| // Clang builtin type and record type should pass |
| EXPECT_TRUE(ClangUtil::IsClangType(bool_type)); |
| EXPECT_TRUE(ClangUtil::IsClangType(record_type)); |
| |
| // Default constructed type should fail |
| EXPECT_FALSE(ClangUtil::IsClangType(CompilerType())); |
| |
| // Go type should fail |
| GoASTContext go_ast; |
| CompilerType go_type(&go_ast, bool_ctype); |
| EXPECT_FALSE(ClangUtil::IsClangType(go_type)); |
| } |
| |
| TEST_F(TestClangASTContext, TestRemoveFastQualifiers) { |
| CompilerType record_type = m_ast->CreateRecordType( |
| nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, |
| lldb::eLanguageTypeC_plus_plus, nullptr); |
| QualType qt; |
| |
| qt = ClangUtil::GetQualType(record_type); |
| EXPECT_EQ(0u, qt.getLocalFastQualifiers()); |
| record_type = record_type.AddConstModifier(); |
| record_type = record_type.AddVolatileModifier(); |
| record_type = record_type.AddRestrictModifier(); |
| qt = ClangUtil::GetQualType(record_type); |
| EXPECT_NE(0u, qt.getLocalFastQualifiers()); |
| record_type = ClangUtil::RemoveFastQualifiers(record_type); |
| qt = ClangUtil::GetQualType(record_type); |
| EXPECT_EQ(0u, qt.getLocalFastQualifiers()); |
| } |
| |
| TEST_F(TestClangASTContext, TestConvertAccessTypeToAccessSpecifier) { |
| EXPECT_EQ(AS_none, |
| ClangASTContext::ConvertAccessTypeToAccessSpecifier(eAccessNone)); |
| EXPECT_EQ(AS_none, ClangASTContext::ConvertAccessTypeToAccessSpecifier( |
| eAccessPackage)); |
| EXPECT_EQ(AS_public, |
| ClangASTContext::ConvertAccessTypeToAccessSpecifier(eAccessPublic)); |
| EXPECT_EQ(AS_private, ClangASTContext::ConvertAccessTypeToAccessSpecifier( |
| eAccessPrivate)); |
| EXPECT_EQ(AS_protected, ClangASTContext::ConvertAccessTypeToAccessSpecifier( |
| eAccessProtected)); |
| } |
| |
| TEST_F(TestClangASTContext, TestUnifyAccessSpecifiers) { |
| // Unifying two of the same type should return the same type |
| EXPECT_EQ(AS_public, |
| ClangASTContext::UnifyAccessSpecifiers(AS_public, AS_public)); |
| EXPECT_EQ(AS_private, |
| ClangASTContext::UnifyAccessSpecifiers(AS_private, AS_private)); |
| EXPECT_EQ(AS_protected, |
| ClangASTContext::UnifyAccessSpecifiers(AS_protected, AS_protected)); |
| |
| // Otherwise the result should be the strictest of the two. |
| EXPECT_EQ(AS_private, |
| ClangASTContext::UnifyAccessSpecifiers(AS_private, AS_public)); |
| EXPECT_EQ(AS_private, |
| ClangASTContext::UnifyAccessSpecifiers(AS_private, AS_protected)); |
| EXPECT_EQ(AS_private, |
| ClangASTContext::UnifyAccessSpecifiers(AS_public, AS_private)); |
| EXPECT_EQ(AS_private, |
| ClangASTContext::UnifyAccessSpecifiers(AS_protected, AS_private)); |
| EXPECT_EQ(AS_protected, |
| ClangASTContext::UnifyAccessSpecifiers(AS_protected, AS_public)); |
| EXPECT_EQ(AS_protected, |
| ClangASTContext::UnifyAccessSpecifiers(AS_public, AS_protected)); |
| |
| // None is stricter than everything (by convention) |
| EXPECT_EQ(AS_none, |
| ClangASTContext::UnifyAccessSpecifiers(AS_none, AS_public)); |
| EXPECT_EQ(AS_none, |
| ClangASTContext::UnifyAccessSpecifiers(AS_none, AS_protected)); |
| EXPECT_EQ(AS_none, |
| ClangASTContext::UnifyAccessSpecifiers(AS_none, AS_private)); |
| EXPECT_EQ(AS_none, |
| ClangASTContext::UnifyAccessSpecifiers(AS_public, AS_none)); |
| EXPECT_EQ(AS_none, |
| ClangASTContext::UnifyAccessSpecifiers(AS_protected, AS_none)); |
| EXPECT_EQ(AS_none, |
| ClangASTContext::UnifyAccessSpecifiers(AS_private, AS_none)); |
| } |
| |
| TEST_F(TestClangASTContext, TestRecordHasFields) { |
| CompilerType int_type = |
| ClangASTContext::GetBasicType(m_ast->getASTContext(), eBasicTypeInt); |
| |
| // Test that a record with no fields returns false |
| CompilerType empty_base = m_ast->CreateRecordType( |
| nullptr, lldb::eAccessPublic, "EmptyBase", clang::TTK_Struct, |
| lldb::eLanguageTypeC_plus_plus, nullptr); |
| ClangASTContext::StartTagDeclarationDefinition(empty_base); |
| ClangASTContext::CompleteTagDeclarationDefinition(empty_base); |
| |
| RecordDecl *empty_base_decl = ClangASTContext::GetAsRecordDecl(empty_base); |
| EXPECT_NE(nullptr, empty_base_decl); |
| EXPECT_FALSE(ClangASTContext::RecordHasFields(empty_base_decl)); |
| |
| // Test that a record with direct fields returns true |
| CompilerType non_empty_base = m_ast->CreateRecordType( |
| nullptr, lldb::eAccessPublic, "NonEmptyBase", clang::TTK_Struct, |
| lldb::eLanguageTypeC_plus_plus, nullptr); |
| ClangASTContext::StartTagDeclarationDefinition(non_empty_base); |
| FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType( |
| non_empty_base, "MyField", int_type, eAccessPublic, 0); |
| ClangASTContext::CompleteTagDeclarationDefinition(non_empty_base); |
| RecordDecl *non_empty_base_decl = |
| ClangASTContext::GetAsRecordDecl(non_empty_base); |
| EXPECT_NE(nullptr, non_empty_base_decl); |
| EXPECT_NE(nullptr, non_empty_base_field_decl); |
| EXPECT_TRUE(ClangASTContext::RecordHasFields(non_empty_base_decl)); |
| |
| // Test that a record with no direct fields, but fields in a base returns true |
| CompilerType empty_derived = m_ast->CreateRecordType( |
| nullptr, lldb::eAccessPublic, "EmptyDerived", clang::TTK_Struct, |
| lldb::eLanguageTypeC_plus_plus, nullptr); |
| ClangASTContext::StartTagDeclarationDefinition(empty_derived); |
| CXXBaseSpecifier *non_empty_base_spec = m_ast->CreateBaseClassSpecifier( |
| non_empty_base.GetOpaqueQualType(), lldb::eAccessPublic, false, false); |
| bool result = m_ast->SetBaseClassesForClassType( |
| empty_derived.GetOpaqueQualType(), &non_empty_base_spec, 1); |
| ClangASTContext::CompleteTagDeclarationDefinition(empty_derived); |
| EXPECT_TRUE(result); |
| CXXRecordDecl *empty_derived_non_empty_base_cxx_decl = |
| m_ast->GetAsCXXRecordDecl(empty_derived.GetOpaqueQualType()); |
| RecordDecl *empty_derived_non_empty_base_decl = |
| ClangASTContext::GetAsRecordDecl(empty_derived); |
| EXPECT_EQ(1u, ClangASTContext::GetNumBaseClasses( |
| empty_derived_non_empty_base_cxx_decl, false)); |
| EXPECT_TRUE( |
| ClangASTContext::RecordHasFields(empty_derived_non_empty_base_decl)); |
| |
| // Test that a record with no direct fields, but fields in a virtual base |
| // returns true |
| CompilerType empty_derived2 = m_ast->CreateRecordType( |
| nullptr, lldb::eAccessPublic, "EmptyDerived2", clang::TTK_Struct, |
| lldb::eLanguageTypeC_plus_plus, nullptr); |
| ClangASTContext::StartTagDeclarationDefinition(empty_derived2); |
| CXXBaseSpecifier *non_empty_vbase_spec = m_ast->CreateBaseClassSpecifier( |
| non_empty_base.GetOpaqueQualType(), lldb::eAccessPublic, true, false); |
| result = m_ast->SetBaseClassesForClassType(empty_derived2.GetOpaqueQualType(), |
| &non_empty_vbase_spec, 1); |
| ClangASTContext::CompleteTagDeclarationDefinition(empty_derived2); |
| EXPECT_TRUE(result); |
| CXXRecordDecl *empty_derived_non_empty_vbase_cxx_decl = |
| m_ast->GetAsCXXRecordDecl(empty_derived2.GetOpaqueQualType()); |
| RecordDecl *empty_derived_non_empty_vbase_decl = |
| ClangASTContext::GetAsRecordDecl(empty_derived2); |
| EXPECT_EQ(1u, ClangASTContext::GetNumBaseClasses( |
| empty_derived_non_empty_vbase_cxx_decl, false)); |
| EXPECT_TRUE( |
| ClangASTContext::RecordHasFields(empty_derived_non_empty_vbase_decl)); |
| |
| delete non_empty_base_spec; |
| delete non_empty_vbase_spec; |
| } |
| |
| TEST_F(TestClangASTContext, TemplateArguments) { |
| ClangASTContext::TemplateParameterInfos infos; |
| infos.names.push_back("T"); |
| infos.args.push_back(TemplateArgument(m_ast->getASTContext()->IntTy)); |
| infos.names.push_back("I"); |
| llvm::APSInt arg(llvm::APInt(8, 47)); |
| infos.args.push_back(TemplateArgument(*m_ast->getASTContext(), arg, |
| m_ast->getASTContext()->IntTy)); |
| |
| // template<typename T, int I> struct foo; |
| ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl( |
| m_ast->GetTranslationUnitDecl(), eAccessPublic, "foo", TTK_Struct, infos); |
| ASSERT_NE(decl, nullptr); |
| |
| // foo<int, 47> |
| ClassTemplateSpecializationDecl *spec_decl = |
| m_ast->CreateClassTemplateSpecializationDecl( |
| m_ast->GetTranslationUnitDecl(), decl, TTK_Struct, infos); |
| ASSERT_NE(spec_decl, nullptr); |
| CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl); |
| ASSERT_TRUE(type); |
| m_ast->StartTagDeclarationDefinition(type); |
| m_ast->CompleteTagDeclarationDefinition(type); |
| |
| // typedef foo<int, 47> foo_def; |
| CompilerType typedef_type = m_ast->CreateTypedefType( |
| type, "foo_def", |
| CompilerDeclContext(m_ast.get(), m_ast->GetTranslationUnitDecl())); |
| |
| CompilerType auto_type(m_ast->getASTContext(), |
| m_ast->getASTContext()->getAutoType( |
| ClangUtil::GetCanonicalQualType(typedef_type), |
| clang::AutoTypeKeyword::Auto, false)); |
| |
| CompilerType int_type(m_ast->getASTContext(), m_ast->getASTContext()->IntTy); |
| for(CompilerType t: { type, typedef_type, auto_type }) { |
| SCOPED_TRACE(t.GetTypeName().AsCString()); |
| |
| EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0), |
| eTemplateArgumentKindType); |
| EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0), |
| int_type); |
| EXPECT_EQ(llvm::None, |
| m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 0)); |
| |
| EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1), |
| eTemplateArgumentKindIntegral); |
| EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1), |
| CompilerType()); |
| auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1); |
| ASSERT_NE(llvm::None, result); |
| EXPECT_EQ(arg, result->value); |
| EXPECT_EQ(int_type, result->type); |
| } |
| } |