forked from OSchip/llvm-project
[lldb] Automatically unwrap parameter packs in template argument accessors
When looking at template arguments in LLDB, we usually care about what the user passed in his code, not whether some of those arguments where passed as a variadic parameter pack. This patch extends all the C++ APIs to look at template parameters to take an additional 'expand_pack' boolean that automatically unwraps the potential argument packs. The equivalent SBAPI calls have been changed to pass true for this parameter. A byproduct of the patch is to also fix the support for template type that have only a parameter pack as argument (like the OnlyPack type in the test). Those were not recognized as template instanciations before. The added test verifies that the SBAPI is able to iterate over the arguments of a variadic template. The original patch was written by Fred Riss almost 4 years ago. Differential revision: https://reviews.llvm.org/D51387
This commit is contained in:
parent
0af4651c0f
commit
b706f56133
|
@ -182,6 +182,8 @@ public:
|
|||
|
||||
lldb::SBType GetTemplateArgumentType(uint32_t idx);
|
||||
|
||||
/// Return the TemplateArgumentKind of the template argument at index idx.
|
||||
/// Variadic argument packs are automatically expanded.
|
||||
lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx);
|
||||
|
||||
lldb::SBType GetFunctionReturnType();
|
||||
|
|
|
@ -338,14 +338,28 @@ public:
|
|||
GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes,
|
||||
std::vector<uint32_t> &child_indexes) const;
|
||||
|
||||
size_t GetNumTemplateArguments() const;
|
||||
/// Return the number of template arguments the type has.
|
||||
/// If expand_pack is true, then variadic argument packs are automatically
|
||||
/// expanded to their supplied arguments. If it is false an argument pack
|
||||
/// will only count as 1 argument.
|
||||
size_t GetNumTemplateArguments(bool expand_pack = false) const;
|
||||
|
||||
lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const;
|
||||
CompilerType GetTypeTemplateArgument(size_t idx) const;
|
||||
// Return the TemplateArgumentKind of the template argument at index idx.
|
||||
// If expand_pack is true, then variadic argument packs are automatically
|
||||
// expanded to their supplied arguments. With expand_pack set to false, an
|
||||
// arguement pack will count as 1 argument and return a type of Pack.
|
||||
lldb::TemplateArgumentKind
|
||||
GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const;
|
||||
CompilerType GetTypeTemplateArgument(size_t idx,
|
||||
bool expand_pack = false) const;
|
||||
|
||||
/// Returns the value of the template argument and its type.
|
||||
/// If expand_pack is true, then variadic argument packs are automatically
|
||||
/// expanded to their supplied arguments. With expand_pack set to false, an
|
||||
/// arguement pack will count as 1 argument and it is invalid to call this
|
||||
/// method on the pack argument.
|
||||
llvm::Optional<IntegralTemplateArgument>
|
||||
GetIntegralTemplateArgument(size_t idx) const;
|
||||
GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const;
|
||||
|
||||
CompilerType GetTypeForFormatters() const;
|
||||
|
||||
|
|
|
@ -346,14 +346,18 @@ public:
|
|||
const char *name, bool omit_empty_base_classes,
|
||||
std::vector<uint32_t> &child_indexes) = 0;
|
||||
|
||||
virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type);
|
||||
virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
|
||||
bool expand_pack);
|
||||
|
||||
virtual lldb::TemplateArgumentKind
|
||||
GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx);
|
||||
virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
|
||||
size_t idx);
|
||||
GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack);
|
||||
virtual CompilerType
|
||||
GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack);
|
||||
virtual llvm::Optional<CompilerType::IntegralTemplateArgument>
|
||||
GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx);
|
||||
GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack);
|
||||
|
||||
// Dumping types
|
||||
|
||||
|
|
|
@ -542,7 +542,8 @@ uint32_t SBType::GetNumberOfTemplateArguments() {
|
|||
LLDB_INSTRUMENT_VA(this);
|
||||
|
||||
if (IsValid())
|
||||
return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments();
|
||||
return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(
|
||||
/*expand_pack=*/true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -553,13 +554,15 @@ lldb::SBType SBType::GetTemplateArgumentType(uint32_t idx) {
|
|||
return SBType();
|
||||
|
||||
CompilerType type;
|
||||
const bool expand_pack = true;
|
||||
switch(GetTemplateArgumentKind(idx)) {
|
||||
case eTemplateArgumentKindType:
|
||||
type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(idx);
|
||||
type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(
|
||||
idx, expand_pack);
|
||||
break;
|
||||
case eTemplateArgumentKindIntegral:
|
||||
type = m_opaque_sp->GetCompilerType(false)
|
||||
.GetIntegralTemplateArgument(idx)
|
||||
.GetIntegralTemplateArgument(idx, expand_pack)
|
||||
->type;
|
||||
break;
|
||||
default:
|
||||
|
@ -574,7 +577,8 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) {
|
|||
LLDB_INSTRUMENT_VA(this, idx);
|
||||
|
||||
if (IsValid())
|
||||
return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(idx);
|
||||
return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(
|
||||
idx, /*expand_pack=*/true);
|
||||
return eTemplateArgumentKindNull;
|
||||
}
|
||||
|
||||
|
|
|
@ -7098,7 +7098,8 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
|
|||
}
|
||||
|
||||
size_t
|
||||
TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
|
||||
TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
|
||||
bool expand_pack) {
|
||||
if (!type)
|
||||
return 0;
|
||||
|
||||
|
@ -7113,8 +7114,17 @@ TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
|
|||
const clang::ClassTemplateSpecializationDecl *template_decl =
|
||||
llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
|
||||
cxx_record_decl);
|
||||
if (template_decl)
|
||||
return template_decl->getTemplateArgs().size();
|
||||
if (template_decl) {
|
||||
const auto &template_arg_list = template_decl->getTemplateArgs();
|
||||
size_t num_args = template_arg_list.size();
|
||||
assert(num_args && "template specialization without any args");
|
||||
if (expand_pack && num_args) {
|
||||
const auto &pack = template_arg_list[num_args - 1];
|
||||
if (pack.getKind() == clang::TemplateArgument::Pack)
|
||||
num_args += pack.pack_size() - 1;
|
||||
}
|
||||
return num_args;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -7151,15 +7161,51 @@ TypeSystemClang::GetAsTemplateSpecialization(
|
|||
}
|
||||
}
|
||||
|
||||
const TemplateArgument *
|
||||
GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl,
|
||||
size_t idx, bool expand_pack) {
|
||||
const auto &args = decl->getTemplateArgs();
|
||||
const size_t args_size = args.size();
|
||||
|
||||
assert(args_size && "template specialization without any args");
|
||||
if (!args_size)
|
||||
return nullptr;
|
||||
|
||||
const size_t last_idx = args_size - 1;
|
||||
|
||||
// We're asked for a template argument that can't be a parameter pack, so
|
||||
// return it without worrying about 'expand_pack'.
|
||||
if (idx < last_idx)
|
||||
return &args[idx];
|
||||
|
||||
// We're asked for the last template argument but we don't want/need to
|
||||
// expand it.
|
||||
if (!expand_pack || args[last_idx].getKind() != clang::TemplateArgument::Pack)
|
||||
return idx >= args.size() ? nullptr : &args[idx];
|
||||
|
||||
// Index into the expanded pack.
|
||||
// Note that 'idx' counts from the beginning of all template arguments
|
||||
// (including the ones preceding the parameter pack).
|
||||
const auto &pack = args[last_idx];
|
||||
const size_t pack_idx = idx - last_idx;
|
||||
const size_t pack_size = pack.pack_size();
|
||||
assert(pack_idx < pack_size && "parameter pack index out-of-bounds");
|
||||
return &pack.pack_elements()[pack_idx];
|
||||
}
|
||||
|
||||
lldb::TemplateArgumentKind
|
||||
TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
|
||||
size_t arg_idx) {
|
||||
size_t arg_idx, bool expand_pack) {
|
||||
const clang::ClassTemplateSpecializationDecl *template_decl =
|
||||
GetAsTemplateSpecialization(type);
|
||||
if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size())
|
||||
if (!template_decl)
|
||||
return eTemplateArgumentKindNull;
|
||||
|
||||
switch (template_decl->getTemplateArgs()[arg_idx].getKind()) {
|
||||
const auto *arg = GetNthTemplateArgument(template_decl, arg_idx, expand_pack);
|
||||
if (!arg)
|
||||
return eTemplateArgumentKindNull;
|
||||
|
||||
switch (arg->getKind()) {
|
||||
case clang::TemplateArgument::Null:
|
||||
return eTemplateArgumentKindNull;
|
||||
|
||||
|
@ -7192,35 +7238,32 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
|
|||
|
||||
CompilerType
|
||||
TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
|
||||
size_t idx) {
|
||||
size_t idx, bool expand_pack) {
|
||||
const clang::ClassTemplateSpecializationDecl *template_decl =
|
||||
GetAsTemplateSpecialization(type);
|
||||
if (!template_decl || idx >= template_decl->getTemplateArgs().size())
|
||||
if (!template_decl)
|
||||
return CompilerType();
|
||||
|
||||
const clang::TemplateArgument &template_arg =
|
||||
template_decl->getTemplateArgs()[idx];
|
||||
if (template_arg.getKind() != clang::TemplateArgument::Type)
|
||||
const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack);
|
||||
if (!arg || arg->getKind() != clang::TemplateArgument::Type)
|
||||
return CompilerType();
|
||||
|
||||
return GetType(template_arg.getAsType());
|
||||
return GetType(arg->getAsType());
|
||||
}
|
||||
|
||||
Optional<CompilerType::IntegralTemplateArgument>
|
||||
TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
|
||||
size_t idx) {
|
||||
size_t idx, bool expand_pack) {
|
||||
const clang::ClassTemplateSpecializationDecl *template_decl =
|
||||
GetAsTemplateSpecialization(type);
|
||||
if (! template_decl || idx >= template_decl->getTemplateArgs().size())
|
||||
if (!template_decl)
|
||||
return llvm::None;
|
||||
|
||||
const clang::TemplateArgument &template_arg =
|
||||
template_decl->getTemplateArgs()[idx];
|
||||
if (template_arg.getKind() != clang::TemplateArgument::Integral)
|
||||
const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack);
|
||||
if (!arg || arg->getKind() != clang::TemplateArgument::Integral)
|
||||
return llvm::None;
|
||||
|
||||
return {
|
||||
{template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}};
|
||||
return {{arg->getAsIntegral(), GetType(arg->getIntegralType())}};
|
||||
}
|
||||
|
||||
CompilerType TypeSystemClang::GetTypeForFormatters(void *type) {
|
||||
|
|
|
@ -91,7 +91,7 @@ public:
|
|||
void SetOwningModule(OptionalClangModuleID id);
|
||||
/// \}
|
||||
};
|
||||
|
||||
|
||||
/// A TypeSystem implementation based on Clang.
|
||||
///
|
||||
/// This class uses a single clang::ASTContext as the backend for storing
|
||||
|
@ -334,7 +334,7 @@ public:
|
|||
|
||||
llvm::SmallVector<const char *, 2> names;
|
||||
llvm::SmallVector<clang::TemplateArgument, 2> args;
|
||||
|
||||
|
||||
const char * pack_name = nullptr;
|
||||
std::unique_ptr<TemplateParameterInfos> packed_args;
|
||||
};
|
||||
|
@ -537,7 +537,7 @@ public:
|
|||
#ifndef NDEBUG
|
||||
bool Verify(lldb::opaque_compiler_type_t type) override;
|
||||
#endif
|
||||
|
||||
|
||||
bool IsArrayType(lldb::opaque_compiler_type_t type,
|
||||
CompilerType *element_type, uint64_t *size,
|
||||
bool *is_incomplete) override;
|
||||
|
@ -810,16 +810,17 @@ public:
|
|||
const char *name, bool omit_empty_base_classes,
|
||||
std::vector<uint32_t> &child_indexes) override;
|
||||
|
||||
size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override;
|
||||
size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
|
||||
bool expand_pack) override;
|
||||
|
||||
lldb::TemplateArgumentKind
|
||||
GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
|
||||
size_t idx) override;
|
||||
GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack) override;
|
||||
CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
|
||||
size_t idx) override;
|
||||
size_t idx, bool expand_pack) override;
|
||||
llvm::Optional<CompilerType::IntegralTemplateArgument>
|
||||
GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
|
||||
size_t idx) override;
|
||||
GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack) override;
|
||||
|
||||
CompilerType GetTypeForFormatters(void *type) override;
|
||||
|
||||
|
|
|
@ -659,30 +659,32 @@ size_t CompilerType::GetIndexOfChildMemberWithName(
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t CompilerType::GetNumTemplateArguments() const {
|
||||
size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const {
|
||||
if (IsValid()) {
|
||||
return m_type_system->GetNumTemplateArguments(m_type);
|
||||
return m_type_system->GetNumTemplateArguments(m_type, expand_pack);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const {
|
||||
TemplateArgumentKind
|
||||
CompilerType::GetTemplateArgumentKind(size_t idx, bool expand_pack) const {
|
||||
if (IsValid())
|
||||
return m_type_system->GetTemplateArgumentKind(m_type, idx);
|
||||
return m_type_system->GetTemplateArgumentKind(m_type, idx, expand_pack);
|
||||
return eTemplateArgumentKindNull;
|
||||
}
|
||||
|
||||
CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const {
|
||||
CompilerType CompilerType::GetTypeTemplateArgument(size_t idx,
|
||||
bool expand_pack) const {
|
||||
if (IsValid()) {
|
||||
return m_type_system->GetTypeTemplateArgument(m_type, idx);
|
||||
return m_type_system->GetTypeTemplateArgument(m_type, idx, expand_pack);
|
||||
}
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
llvm::Optional<CompilerType::IntegralTemplateArgument>
|
||||
CompilerType::GetIntegralTemplateArgument(size_t idx) const {
|
||||
CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const {
|
||||
if (IsValid())
|
||||
return m_type_system->GetIntegralTemplateArgument(m_type, idx);
|
||||
return m_type_system->GetIntegralTemplateArgument(m_type, idx, expand_pack);
|
||||
return llvm::None;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,23 +118,25 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) {
|
|||
return CompilerType(this, type);
|
||||
}
|
||||
|
||||
size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
|
||||
size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
|
||||
bool expand_pack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TemplateArgumentKind
|
||||
TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) {
|
||||
TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack) {
|
||||
return eTemplateArgumentKindNull;
|
||||
}
|
||||
|
||||
CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
|
||||
size_t idx) {
|
||||
size_t idx, bool expand_pack) {
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
llvm::Optional<CompilerType::IntegralTemplateArgument>
|
||||
TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type,
|
||||
size_t idx) {
|
||||
TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
|
||||
bool expand_pack) {
|
||||
return llvm::None;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
"""
|
||||
Test that the type of arguments to C++ template classes that have variadic
|
||||
parameters can be enumerated.
|
||||
"""
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class TemplatePackArgsTestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
def test_template_argument_pack(self):
|
||||
self.build()
|
||||
(_, _, thread, _) = lldbutil.run_to_source_breakpoint(self,
|
||||
'breakpoint here', lldb.SBFileSpec('main.cpp'), exe_name = 'a.out')
|
||||
frame = thread.GetSelectedFrame()
|
||||
|
||||
empty_pack = frame.FindVariable('emptyPack')
|
||||
self.assertTrue(empty_pack.IsValid(),
|
||||
'make sure we find the emptyPack variable')
|
||||
|
||||
only_pack = frame.FindVariable('onlyPack')
|
||||
self.assertTrue(only_pack.IsValid(),
|
||||
'make sure we find the onlyPack variable')
|
||||
self.assertEqual(only_pack.GetType().GetNumberOfTemplateArguments(), 4)
|
||||
self.assertEqual(only_pack.GetType().GetTemplateArgumentType(0).GetName(), 'int')
|
||||
self.assertEqual(only_pack.GetType().GetTemplateArgumentType(1).GetName(), 'char')
|
||||
self.assertEqual(only_pack.GetType().GetTemplateArgumentType(2).GetName(), 'double')
|
||||
# Access the C<double, 42> template parameter.
|
||||
nested_template = only_pack.GetType().GetTemplateArgumentType(3)
|
||||
self.assertEqual(nested_template.GetName(), 'D<int, int, bool>')
|
||||
self.assertEqual(nested_template.GetNumberOfTemplateArguments(), 3)
|
||||
self.assertEqual(nested_template.GetTemplateArgumentType(0).GetName(), 'int')
|
||||
self.assertEqual(nested_template.GetTemplateArgumentType(1).GetName(), 'int')
|
||||
self.assertEqual(nested_template.GetTemplateArgumentType(2).GetName(), 'bool')
|
|
@ -26,7 +26,13 @@ template <> struct D<int, int, bool> : D<int, int> {
|
|||
bool argsAre_Int_bool() { return true; }
|
||||
};
|
||||
|
||||
template <typename... Args> struct OnlyPack {};
|
||||
template <typename T, typename... Args> struct EmptyPack {};
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
EmptyPack<int> emptyPack;
|
||||
OnlyPack<int, char, double, D<int, int, bool>> onlyPack;
|
||||
|
||||
C<int, 16, 32> myC;
|
||||
C<int, 16> myLesserC;
|
||||
myC.member = 64;
|
||||
|
@ -34,7 +40,7 @@ int main(int argc, char const *argv[]) {
|
|||
(void)C<int, 16>().argsAre_16_32();
|
||||
(void)(myC.member != 64);
|
||||
D<int, int, bool> myD;
|
||||
D<int, int> myLesserD;
|
||||
D<int, int> myLesserD; // breakpoint here
|
||||
myD.member = 64;
|
||||
(void)D<int, int, bool>().argsAre_Int_bool();
|
||||
(void)D<int, int>().argsAre_Int_bool();
|
||||
|
|
|
@ -500,18 +500,24 @@ TEST_F(TestTypeSystemClang, TemplateArguments) {
|
|||
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));
|
||||
const bool expand_pack = false;
|
||||
EXPECT_EQ(
|
||||
m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0, expand_pack),
|
||||
eTemplateArgumentKindType);
|
||||
EXPECT_EQ(
|
||||
m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0, expand_pack),
|
||||
int_type);
|
||||
EXPECT_EQ(llvm::None, m_ast->GetIntegralTemplateArgument(
|
||||
t.GetOpaqueQualType(), 0, expand_pack));
|
||||
|
||||
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);
|
||||
EXPECT_EQ(
|
||||
m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1, expand_pack),
|
||||
eTemplateArgumentKindIntegral);
|
||||
EXPECT_EQ(
|
||||
m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1, expand_pack),
|
||||
CompilerType());
|
||||
auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1,
|
||||
expand_pack);
|
||||
ASSERT_NE(llvm::None, result);
|
||||
EXPECT_EQ(arg, result->value);
|
||||
EXPECT_EQ(int_type, result->type);
|
||||
|
|
Loading…
Reference in New Issue