mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-09-19 11:09:05 +01:00
Take list of pass-through types from config instead of hardcoding
As we now store ContainerInfo objects in OICodeGen::Config, we can not copy it any more. Change all places that took copies to take const references instead. The copy in OICodeGen modified membersToStub, the contents of which form part of OICache's hash. However, as OICache also previously had its own copy, it would not have been OICodeGen's modifications.
This commit is contained in:
parent
e86ebb7aff
commit
0330ef8945
@ -47,3 +47,8 @@ containers = [
|
|||||||
"PWD/types/thrift_isset_type.toml",
|
"PWD/types/thrift_isset_type.toml",
|
||||||
"PWD/types/weak_ptr_type.toml",
|
"PWD/types/weak_ptr_type.toml",
|
||||||
]
|
]
|
||||||
|
pass_through = [
|
||||||
|
["std::allocator", "memory"],
|
||||||
|
["std::char_traits", "string"],
|
||||||
|
["folly::fbstring_core", "folly/FBString.h"],
|
||||||
|
]
|
||||||
|
@ -712,7 +712,7 @@ void CodeGen::addDrgnRoot(struct drgn_type* drgnType,
|
|||||||
void CodeGen::transform(type_graph::TypeGraph& typeGraph) {
|
void CodeGen::transform(type_graph::TypeGraph& typeGraph) {
|
||||||
type_graph::PassManager pm;
|
type_graph::PassManager pm;
|
||||||
pm.addPass(type_graph::Flattener::createPass());
|
pm.addPass(type_graph::Flattener::createPass());
|
||||||
pm.addPass(type_graph::TypeIdentifier::createPass());
|
pm.addPass(type_graph::TypeIdentifier::createPass(config_.passThroughTypes));
|
||||||
if (config_.features[Feature::PolymorphicInheritance]) {
|
if (config_.features[Feature::PolymorphicInheritance]) {
|
||||||
type_graph::DrgnParser drgnParser{
|
type_graph::DrgnParser drgnParser{
|
||||||
typeGraph, containerInfos_,
|
typeGraph, containerInfos_,
|
||||||
@ -720,7 +720,8 @@ void CodeGen::transform(type_graph::TypeGraph& typeGraph) {
|
|||||||
pm.addPass(type_graph::AddChildren::createPass(drgnParser, symbols_));
|
pm.addPass(type_graph::AddChildren::createPass(drgnParser, symbols_));
|
||||||
// Re-run passes over newly added children
|
// Re-run passes over newly added children
|
||||||
pm.addPass(type_graph::Flattener::createPass());
|
pm.addPass(type_graph::Flattener::createPass());
|
||||||
pm.addPass(type_graph::TypeIdentifier::createPass());
|
pm.addPass(
|
||||||
|
type_graph::TypeIdentifier::createPass(config_.passThroughTypes));
|
||||||
}
|
}
|
||||||
pm.addPass(type_graph::RemoveIgnored::createPass(config_.membersToStub));
|
pm.addPass(type_graph::RemoveIgnored::createPass(config_.membersToStub));
|
||||||
pm.addPass(type_graph::AddPadding::createPass());
|
pm.addPass(type_graph::AddPadding::createPass());
|
||||||
|
@ -37,7 +37,7 @@ class TypeGraph;
|
|||||||
|
|
||||||
class CodeGen {
|
class CodeGen {
|
||||||
public:
|
public:
|
||||||
CodeGen(OICodeGen::Config& config, SymbolService& symbols)
|
CodeGen(const OICodeGen::Config& config, SymbolService& symbols)
|
||||||
: config_(config), symbols_(symbols) {
|
: config_(config), symbols_(symbols) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ class CodeGen {
|
|||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OICodeGen::Config config_;
|
const OICodeGen::Config& config_;
|
||||||
SymbolService& symbols_;
|
SymbolService& symbols_;
|
||||||
std::vector<ContainerInfo> containerInfos_;
|
std::vector<ContainerInfo> containerInfos_;
|
||||||
std::unordered_set<const ContainerInfo*> definedContainers_;
|
std::unordered_set<const ContainerInfo*> definedContainers_;
|
||||||
|
@ -28,6 +28,10 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
class OICache {
|
class OICache {
|
||||||
public:
|
public:
|
||||||
|
OICache(const OICodeGen::Config& generatorConfig)
|
||||||
|
: generatorConfig(generatorConfig) {
|
||||||
|
}
|
||||||
|
|
||||||
fs::path basePath{};
|
fs::path basePath{};
|
||||||
std::shared_ptr<SymbolService> symbols{};
|
std::shared_ptr<SymbolService> symbols{};
|
||||||
bool downloadedRemote = false;
|
bool downloadedRemote = false;
|
||||||
@ -37,7 +41,7 @@ class OICache {
|
|||||||
|
|
||||||
// We need the generator config to download the cache
|
// We need the generator config to download the cache
|
||||||
// with the matching configuration.
|
// with the matching configuration.
|
||||||
OICodeGen::Config generatorConfig{};
|
const OICodeGen::Config& generatorConfig;
|
||||||
|
|
||||||
// Entity is used to index the `extensions` array
|
// Entity is used to index the `extensions` array
|
||||||
// So we must keep the Entity enum and `extensions` array in sync!
|
// So we must keep the Entity enum and `extensions` array in sync!
|
||||||
|
@ -89,9 +89,9 @@ OICodeGen::OICodeGen(const Config& c, SymbolService& s)
|
|||||||
"event",
|
"event",
|
||||||
};
|
};
|
||||||
|
|
||||||
config.membersToStub.reserve(typesToStub.size());
|
membersToStub = config.membersToStub;
|
||||||
for (const auto& type : typesToStub) {
|
for (const auto& type : typesToStub) {
|
||||||
config.membersToStub.emplace_back(type, "*");
|
membersToStub.emplace_back(type, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
// `knownTypes` has been made obsolete by the introduction of using the
|
// `knownTypes` has been made obsolete by the introduction of using the
|
||||||
@ -1269,10 +1269,10 @@ bool OICodeGen::generateMemberDefinition(drgn_type* type,
|
|||||||
std::optional<std::pair<std::string_view, std::string_view>>
|
std::optional<std::pair<std::string_view, std::string_view>>
|
||||||
OICodeGen::isMemberToStub(const std::string& typeName,
|
OICodeGen::isMemberToStub(const std::string& typeName,
|
||||||
const std::string& member) {
|
const std::string& member) {
|
||||||
auto it = std::ranges::find_if(config.membersToStub, [&](auto& s) {
|
auto it = std::ranges::find_if(membersToStub, [&](auto& s) {
|
||||||
return typeName.starts_with(s.first) && s.second == member;
|
return typeName.starts_with(s.first) && s.second == member;
|
||||||
});
|
});
|
||||||
if (it == std::end(config.membersToStub)) {
|
if (it == std::end(membersToStub)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return *it;
|
return *it;
|
||||||
|
@ -51,18 +51,19 @@ struct ParentMember {
|
|||||||
class OICodeGen {
|
class OICodeGen {
|
||||||
public:
|
public:
|
||||||
struct Config {
|
struct Config {
|
||||||
/*
|
Config() = default;
|
||||||
* Note: don't set default values for the config so the user gets an
|
Config(const Config& other) = delete;
|
||||||
* uninitialized field" warning if they missed any.
|
Config& operator=(const Config& other) = delete;
|
||||||
*/
|
Config(Config&& other) = delete;
|
||||||
|
Config& operator=(Config&& other) = delete;
|
||||||
|
|
||||||
bool useDataSegment;
|
bool useDataSegment;
|
||||||
|
FeatureSet features;
|
||||||
FeatureSet features{};
|
std::set<fs::path> containerConfigPaths;
|
||||||
|
std::set<std::string> defaultHeaders;
|
||||||
std::set<fs::path> containerConfigPaths{};
|
std::set<std::string> defaultNamespaces;
|
||||||
std::set<std::string> defaultHeaders{};
|
std::vector<std::pair<std::string, std::string>> membersToStub;
|
||||||
std::set<std::string> defaultNamespaces{};
|
std::vector<ContainerInfo> passThroughTypes;
|
||||||
std::vector<std::pair<std::string, std::string>> membersToStub{};
|
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
std::vector<std::string> toOptions() const;
|
std::vector<std::string> toOptions() const;
|
||||||
@ -108,7 +109,7 @@ class OICodeGen {
|
|||||||
bool isDynamic(drgn_type* type) const;
|
bool isDynamic(drgn_type* type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Config config{};
|
const Config& config;
|
||||||
FuncGen funcGen;
|
FuncGen funcGen;
|
||||||
|
|
||||||
using ContainerTypeMapEntry =
|
using ContainerTypeMapEntry =
|
||||||
@ -152,6 +153,7 @@ class OICodeGen {
|
|||||||
std::map<drgn_type*, drgn_type*> pointerToTypeMap;
|
std::map<drgn_type*, drgn_type*> pointerToTypeMap;
|
||||||
std::set<drgn_type*> thriftIssetStructTypes;
|
std::set<drgn_type*> thriftIssetStructTypes;
|
||||||
std::vector<drgn_type*> topoSortedStructTypes;
|
std::vector<drgn_type*> topoSortedStructTypes;
|
||||||
|
std::vector<std::pair<std::string, std::string>> membersToStub;
|
||||||
|
|
||||||
ContainerInfoRefSet containerTypesFuncDef;
|
ContainerInfoRefSet containerTypesFuncDef;
|
||||||
|
|
||||||
|
@ -655,10 +655,9 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
OICompiler::Config compilerConfig{};
|
OICompiler::Config compilerConfig{};
|
||||||
|
|
||||||
OICodeGen::Config codeGenConfig{
|
OICodeGen::Config codeGenConfig;
|
||||||
.useDataSegment = true,
|
codeGenConfig.useDataSegment = true;
|
||||||
.features = {}, // fill in after processing the config file
|
codeGenConfig.features = {}; // fill in after processing the config file
|
||||||
};
|
|
||||||
|
|
||||||
TreeBuilder::Config tbConfig{
|
TreeBuilder::Config tbConfig{
|
||||||
.features = {}, // fill in after processing the config file
|
.features = {}, // fill in after processing the config file
|
||||||
|
@ -1878,24 +1878,23 @@ bool OIDebugger::removeTrap(pid_t pid, const trapInfo& t) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OIDebugger::OIDebugger(OICodeGen::Config genConfig,
|
OIDebugger::OIDebugger(const OICodeGen::Config& genConfig,
|
||||||
OICompiler::Config ccConfig,
|
OICompiler::Config ccConfig,
|
||||||
TreeBuilder::Config tbConfig)
|
TreeBuilder::Config tbConfig)
|
||||||
: compilerConfig{std::move(ccConfig)},
|
: cache{genConfig},
|
||||||
generatorConfig{std::move(genConfig)},
|
compilerConfig{std::move(ccConfig)},
|
||||||
|
generatorConfig{genConfig},
|
||||||
treeBuilderConfig{std::move(tbConfig)} {
|
treeBuilderConfig{std::move(tbConfig)} {
|
||||||
debug = true;
|
debug = true;
|
||||||
|
|
||||||
cache.generatorConfig = generatorConfig;
|
|
||||||
VLOG(1) << "CodeGen config: " << generatorConfig.toString();
|
VLOG(1) << "CodeGen config: " << generatorConfig.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
OIDebugger::OIDebugger(pid_t pid,
|
OIDebugger::OIDebugger(pid_t pid,
|
||||||
OICodeGen::Config genConfig,
|
const OICodeGen::Config& genConfig,
|
||||||
OICompiler::Config ccConfig,
|
OICompiler::Config ccConfig,
|
||||||
TreeBuilder::Config tbConfig)
|
TreeBuilder::Config tbConfig)
|
||||||
: OIDebugger(
|
: OIDebugger(genConfig, std::move(ccConfig), std::move(tbConfig)) {
|
||||||
std::move(genConfig), std::move(ccConfig), std::move(tbConfig)) {
|
|
||||||
traceePid = pid;
|
traceePid = pid;
|
||||||
symbols = std::make_shared<SymbolService>(traceePid);
|
symbols = std::make_shared<SymbolService>(traceePid);
|
||||||
setDataSegmentSize(dataSegSize);
|
setDataSegmentSize(dataSegSize);
|
||||||
@ -1904,11 +1903,10 @@ OIDebugger::OIDebugger(pid_t pid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
OIDebugger::OIDebugger(fs::path debugInfo,
|
OIDebugger::OIDebugger(fs::path debugInfo,
|
||||||
OICodeGen::Config genConfig,
|
const OICodeGen::Config& genConfig,
|
||||||
OICompiler::Config ccConfig,
|
OICompiler::Config ccConfig,
|
||||||
TreeBuilder::Config tbConfig)
|
TreeBuilder::Config tbConfig)
|
||||||
: OIDebugger(
|
: OIDebugger(genConfig, std::move(ccConfig), std::move(tbConfig)) {
|
||||||
std::move(genConfig), std::move(ccConfig), std::move(tbConfig)) {
|
|
||||||
symbols = std::make_shared<SymbolService>(std::move(debugInfo));
|
symbols = std::make_shared<SymbolService>(std::move(debugInfo));
|
||||||
cache.symbols = symbols;
|
cache.symbols = symbols;
|
||||||
}
|
}
|
||||||
@ -2699,8 +2697,6 @@ void OIDebugger::setDataSegmentSize(size_t size) {
|
|||||||
int pgsz = getpagesize();
|
int pgsz = getpagesize();
|
||||||
dataSegSize = ((size + pgsz - 1) & ~(pgsz - 1));
|
dataSegSize = ((size + pgsz - 1) & ~(pgsz - 1));
|
||||||
|
|
||||||
generatorConfig.useDataSegment = dataSegSize > 0;
|
|
||||||
|
|
||||||
VLOG(1) << "setDataSegmentSize: segment size: " << dataSegSize;
|
VLOG(1) << "setDataSegmentSize: segment size: " << dataSegSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +32,15 @@
|
|||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
class OIDebugger {
|
class OIDebugger {
|
||||||
OIDebugger(OICodeGen::Config, OICompiler::Config, TreeBuilder::Config);
|
OIDebugger(const OICodeGen::Config&, OICompiler::Config, TreeBuilder::Config);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OIDebugger(pid_t, OICodeGen::Config, OICompiler::Config, TreeBuilder::Config);
|
OIDebugger(pid_t,
|
||||||
|
const OICodeGen::Config&,
|
||||||
|
OICompiler::Config,
|
||||||
|
TreeBuilder::Config);
|
||||||
OIDebugger(fs::path,
|
OIDebugger(fs::path,
|
||||||
OICodeGen::Config,
|
const OICodeGen::Config&,
|
||||||
OICompiler::Config,
|
OICompiler::Config,
|
||||||
TreeBuilder::Config);
|
TreeBuilder::Config);
|
||||||
|
|
||||||
@ -170,7 +173,7 @@ class OIDebugger {
|
|||||||
const int replayInstSize = 512;
|
const int replayInstSize = 512;
|
||||||
bool trapsRemoved{false};
|
bool trapsRemoved{false};
|
||||||
std::shared_ptr<SymbolService> symbols;
|
std::shared_ptr<SymbolService> symbols;
|
||||||
OICache cache{};
|
OICache cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map address of valid INT3 instruction to metadata for that interrupt.
|
* Map address of valid INT3 instruction to metadata for that interrupt.
|
||||||
@ -231,7 +234,7 @@ class OIDebugger {
|
|||||||
std::optional<std::vector<uintptr_t>> findRetLocs(FuncDesc&);
|
std::optional<std::vector<uintptr_t>> findRetLocs(FuncDesc&);
|
||||||
|
|
||||||
OICompiler::Config compilerConfig{};
|
OICompiler::Config compilerConfig{};
|
||||||
OICodeGen::Config generatorConfig{};
|
const OICodeGen::Config& generatorConfig;
|
||||||
TreeBuilder::Config treeBuilderConfig{};
|
TreeBuilder::Config treeBuilderConfig{};
|
||||||
std::optional<std::string> generateCode(const irequest&);
|
std::optional<std::string> generateCode(const irequest&);
|
||||||
|
|
||||||
|
@ -84,6 +84,25 @@ std::optional<ObjectIntrospection::FeatureSet> processConfigFile(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (toml::array* arr = (*types)["pass_through"].as_array()) {
|
||||||
|
for (auto&& el : *arr) {
|
||||||
|
auto* type = el.as_array();
|
||||||
|
if (type && type->size() == 2 && (*type)[0].is_string() &&
|
||||||
|
(*type)[1].is_string()) {
|
||||||
|
std::string name = (*type)[0].as_string()->get();
|
||||||
|
std::string header = (*type)[1].as_string()->get();
|
||||||
|
generatorConfig.passThroughTypes.emplace_back(
|
||||||
|
std::move(name), DUMMY_TYPE, std::move(header));
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "pass_through elements must be lists of [type_name, "
|
||||||
|
"header_file]";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "pass_through must be a list";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toml::table* headers = config["headers"].as_table()) {
|
if (toml::table* headers = config["headers"].as_table()) {
|
||||||
|
@ -20,18 +20,10 @@
|
|||||||
|
|
||||||
namespace type_graph {
|
namespace type_graph {
|
||||||
|
|
||||||
// TODO:
|
Pass TypeIdentifier::createPass(
|
||||||
// - read these from a TOML file
|
const std::vector<ContainerInfo>& passThroughTypes) {
|
||||||
// - don't require specifying ctype and header
|
auto fn = [&passThroughTypes](TypeGraph& typeGraph) {
|
||||||
const std::array<ContainerInfo, 3> TypeIdentifier::dummyContainers_ = {
|
TypeIdentifier typeId{typeGraph, passThroughTypes};
|
||||||
ContainerInfo{"std::allocator", DUMMY_TYPE, "memory"},
|
|
||||||
ContainerInfo{"std::char_traits", DUMMY_TYPE, "string"},
|
|
||||||
ContainerInfo{"folly::fbstring_core", DUMMY_TYPE, "folly/FBString.h"},
|
|
||||||
};
|
|
||||||
|
|
||||||
Pass TypeIdentifier::createPass() {
|
|
||||||
auto fn = [](TypeGraph& typeGraph) {
|
|
||||||
TypeIdentifier typeId{typeGraph};
|
|
||||||
for (auto& type : typeGraph.rootTypes()) {
|
for (auto& type : typeGraph.rootTypes()) {
|
||||||
typeId.visit(type);
|
typeId.visit(type);
|
||||||
}
|
}
|
||||||
@ -78,7 +70,7 @@ void TypeIdentifier::visit(Container& c) {
|
|||||||
|
|
||||||
if (Class* paramClass = dynamic_cast<Class*>(param.type)) {
|
if (Class* paramClass = dynamic_cast<Class*>(param.type)) {
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
for (const auto& info : dummyContainers_) {
|
for (const auto& info : passThroughTypes_) {
|
||||||
if (std::regex_search(paramClass->fqName(), info.matcher)) {
|
if (std::regex_search(paramClass->fqName(), info.matcher)) {
|
||||||
// Create dummy containers
|
// Create dummy containers
|
||||||
auto* dummy =
|
auto* dummy =
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "PassManager.h"
|
#include "PassManager.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
@ -34,10 +35,12 @@ class TypeGraph;
|
|||||||
*/
|
*/
|
||||||
class TypeIdentifier : public RecursiveVisitor {
|
class TypeIdentifier : public RecursiveVisitor {
|
||||||
public:
|
public:
|
||||||
static Pass createPass();
|
static Pass createPass(const std::vector<ContainerInfo>& passThroughTypes);
|
||||||
static bool isAllocator(Type& t);
|
static bool isAllocator(Type& t);
|
||||||
|
|
||||||
TypeIdentifier(TypeGraph& typeGraph) : typeGraph_(typeGraph) {
|
TypeIdentifier(TypeGraph& typeGraph,
|
||||||
|
const std::vector<ContainerInfo>& passThroughTypes)
|
||||||
|
: typeGraph_(typeGraph), passThroughTypes_(passThroughTypes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
using RecursiveVisitor::visit;
|
using RecursiveVisitor::visit;
|
||||||
@ -48,8 +51,7 @@ class TypeIdentifier : public RecursiveVisitor {
|
|||||||
private:
|
private:
|
||||||
std::unordered_set<Type*> visited_;
|
std::unordered_set<Type*> visited_;
|
||||||
TypeGraph& typeGraph_;
|
TypeGraph& typeGraph_;
|
||||||
|
const std::vector<ContainerInfo>& passThroughTypes_;
|
||||||
static const std::array<ContainerInfo, 3> dummyContainers_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace type_graph
|
} // namespace type_graph
|
||||||
|
@ -43,6 +43,11 @@ containers = [
|
|||||||
"../types/thrift_isset_type.toml",
|
"../types/thrift_isset_type.toml",
|
||||||
"../types/weak_ptr_type.toml",
|
"../types/weak_ptr_type.toml",
|
||||||
]
|
]
|
||||||
|
pass_through = [
|
||||||
|
["std::allocator", "memory"],
|
||||||
|
["std::char_traits", "string"],
|
||||||
|
["folly::fbstring_core", "folly/FBString.h"],
|
||||||
|
]
|
||||||
|
|
||||||
[headers]
|
[headers]
|
||||||
user_paths = [
|
user_paths = [
|
||||||
|
@ -17,7 +17,7 @@ TEST(TypeIdentifierTest, StubbedParam) {
|
|||||||
container.templateParams.push_back(TemplateParam{&myparam});
|
container.templateParams.push_back(TemplateParam{&myparam});
|
||||||
container.templateParams.push_back(TemplateParam{&myint});
|
container.templateParams.push_back(TemplateParam{&myint});
|
||||||
|
|
||||||
test(TypeIdentifier::createPass(), {container}, R"(
|
test(TypeIdentifier::createPass({}), {container}, R"(
|
||||||
[0] Container: std::vector (size: 24)
|
[0] Container: std::vector (size: 24)
|
||||||
Param
|
Param
|
||||||
Primitive: int32_t
|
Primitive: int32_t
|
||||||
@ -52,7 +52,7 @@ TEST(TypeIdentifierTest, Allocator) {
|
|||||||
container.templateParams.push_back(TemplateParam{&myalloc});
|
container.templateParams.push_back(TemplateParam{&myalloc});
|
||||||
container.templateParams.push_back(TemplateParam{&myint});
|
container.templateParams.push_back(TemplateParam{&myint});
|
||||||
|
|
||||||
test(TypeIdentifier::createPass(), {container}, R"(
|
test(TypeIdentifier::createPass({}), {container}, R"(
|
||||||
[0] Container: std::vector (size: 24)
|
[0] Container: std::vector (size: 24)
|
||||||
Param
|
Param
|
||||||
Primitive: int32_t
|
Primitive: int32_t
|
||||||
@ -90,7 +90,7 @@ TEST(TypeIdentifierTest, AllocatorSize1) {
|
|||||||
container.templateParams.push_back(TemplateParam{&myalloc});
|
container.templateParams.push_back(TemplateParam{&myalloc});
|
||||||
container.templateParams.push_back(TemplateParam{&myint});
|
container.templateParams.push_back(TemplateParam{&myint});
|
||||||
|
|
||||||
test(TypeIdentifier::createPass(), {container}, R"(
|
test(TypeIdentifier::createPass({}), {container}, R"(
|
||||||
[0] Container: std::vector (size: 24)
|
[0] Container: std::vector (size: 24)
|
||||||
Param
|
Param
|
||||||
Primitive: int32_t
|
Primitive: int32_t
|
||||||
|
@ -26,6 +26,7 @@ def main():
|
|||||||
out = {
|
out = {
|
||||||
"types": {
|
"types": {
|
||||||
"containers": [],
|
"containers": [],
|
||||||
|
"pass_through": [],
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"user_paths": [],
|
"user_paths": [],
|
||||||
@ -42,6 +43,7 @@ def main():
|
|||||||
types = cfg.get("types", None)
|
types = cfg.get("types", None)
|
||||||
if types is not None:
|
if types is not None:
|
||||||
out["types"]["containers"] += types.get("containers", [])
|
out["types"]["containers"] += types.get("containers", [])
|
||||||
|
out["types"]["pass_through"] += types.get("pass_through", [])
|
||||||
|
|
||||||
headers = cfg.get("headers", None)
|
headers = cfg.get("headers", None)
|
||||||
if headers is not None:
|
if headers is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user