CloneContext: Assert objects are owned by the program
Check that pre-clone objects are owned by the source program. Check that post-clone object are owned by the target builder. Fixed: tint:469 Change-Id: Idd0eeb8dfb386e295b66b4b6621cc13dc1a30786 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48260 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: Antonio Maiorano <amaiorano@google.com> Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
parent
b895ba1cea
commit
917b14b626
|
@ -81,7 +81,7 @@ class Node : public Castable<Node, Cloneable> {
|
|||
|
||||
/// @param node a pointer to an AST node
|
||||
/// @returns the ProgramID of the given AST node.
|
||||
inline ProgramID ProgramIDOf(ast::Node* node) {
|
||||
inline ProgramID ProgramIDOf(const ast::Node* node) {
|
||||
return node ? node->program_id() : ProgramID();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,11 +32,14 @@ namespace tint {
|
|||
class CloneContext;
|
||||
class Program;
|
||||
class ProgramBuilder;
|
||||
|
||||
namespace ast {
|
||||
class FunctionList;
|
||||
class Node;
|
||||
} // namespace ast
|
||||
|
||||
ProgramID ProgramIDOf(const Program*);
|
||||
ProgramID ProgramIDOf(const ast::Node*);
|
||||
|
||||
/// Cloneable is the base class for all objects that can be cloned
|
||||
class Cloneable : public Castable<Cloneable> {
|
||||
public:
|
||||
|
@ -46,6 +49,11 @@ class Cloneable : public Castable<Cloneable> {
|
|||
virtual Cloneable* Clone(CloneContext* ctx) const = 0;
|
||||
};
|
||||
|
||||
/// @returns an invalid ProgramID
|
||||
inline ProgramID ProgramIDOf(const Cloneable*) {
|
||||
return ProgramID();
|
||||
}
|
||||
|
||||
/// ShareableCloneable is the base class for Cloneable objects which will only
|
||||
/// be cloned once when CloneContext::Clone() is called with the same object
|
||||
/// pointer.
|
||||
|
@ -95,6 +103,8 @@ class CloneContext {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, a);
|
||||
|
||||
// Have we cloned this object already, or was Replace() called for this
|
||||
// object?
|
||||
auto it = cloned_.find(a);
|
||||
|
@ -127,7 +137,11 @@ class CloneContext {
|
|||
cloned_.emplace(a, cloned);
|
||||
}
|
||||
|
||||
return CheckedCast<T>(cloned);
|
||||
auto* out = CheckedCast<T>(cloned);
|
||||
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Clones the Node or type::Type `a` into the ProgramBuilder #dst if `a` is
|
||||
|
@ -149,6 +163,8 @@ class CloneContext {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, a);
|
||||
|
||||
// Have we seen this object before? If so, return the previously cloned
|
||||
// version instead of making yet another copy.
|
||||
auto it = cloned_.find(a);
|
||||
|
|
|
@ -97,6 +97,23 @@ struct NotANode : public Castable<NotANode, Cloneable> {
|
|||
}
|
||||
};
|
||||
|
||||
struct ProgramNode : public Castable<ProgramNode, Cloneable> {
|
||||
ProgramNode(Allocator* alloc, ProgramID id, ProgramID cloned_id)
|
||||
: allocator(alloc), program_id(id), cloned_program_id(cloned_id) {}
|
||||
|
||||
Allocator* const allocator;
|
||||
ProgramID const program_id;
|
||||
ProgramID const cloned_program_id;
|
||||
|
||||
ProgramNode* Clone(CloneContext*) const override {
|
||||
return allocator->Create<ProgramNode>(cloned_program_id, cloned_program_id);
|
||||
}
|
||||
};
|
||||
|
||||
ProgramID ProgramIDOf(const ProgramNode* node) {
|
||||
return node->program_id;
|
||||
}
|
||||
|
||||
struct UniqueTypes {
|
||||
using Node = UniqueNode;
|
||||
using Replaceable = UniqueReplaceable;
|
||||
|
@ -642,6 +659,38 @@ TYPED_TEST(CloneContextTest, CloneNewSymbols_AfterCloneSymbols) {
|
|||
EXPECT_EQ(cloned.Symbols().NameFor(new_c), "c");
|
||||
}
|
||||
|
||||
TYPED_TEST(CloneContextTest, ProgramIDs) {
|
||||
ProgramBuilder dst;
|
||||
Program src(ProgramBuilder{});
|
||||
CloneContext ctx(&dst, &src);
|
||||
Allocator allocator;
|
||||
ctx.Clone(allocator.Create<ProgramNode>(src.ID(), dst.ID()));
|
||||
}
|
||||
|
||||
TYPED_TEST(CloneContextTest, ProgramIDs_ObjectNotOwnedBySrc) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder dst;
|
||||
Program src(ProgramBuilder{});
|
||||
CloneContext ctx(&dst, &src);
|
||||
Allocator allocator;
|
||||
ctx.Clone(allocator.Create<ProgramNode>(ProgramID::New(), dst.ID()));
|
||||
},
|
||||
R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, a))");
|
||||
}
|
||||
|
||||
TYPED_TEST(CloneContextTest, ProgramIDs_ObjectNotOwnedByDst) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder dst;
|
||||
Program src(ProgramBuilder{});
|
||||
CloneContext ctx(&dst, &src);
|
||||
Allocator allocator;
|
||||
ctx.Clone(allocator.Create<ProgramNode>(src.ID(), ProgramID::New()));
|
||||
},
|
||||
R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, out))");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(UniqueNode);
|
||||
|
@ -651,5 +700,6 @@ TINT_INSTANTIATE_TYPEINFO(ShareableNode);
|
|||
TINT_INSTANTIATE_TYPEINFO(ShareableReplaceable);
|
||||
TINT_INSTANTIATE_TYPEINFO(ShareableReplacement);
|
||||
TINT_INSTANTIATE_TYPEINFO(NotANode);
|
||||
TINT_INSTANTIATE_TYPEINFO(ProgramNode);
|
||||
|
||||
} // namespace tint
|
||||
|
|
|
@ -171,6 +171,12 @@ class Program {
|
|||
bool moved_ = false;
|
||||
};
|
||||
|
||||
/// @param program the Program
|
||||
/// @returns the ProgramID of the Program
|
||||
inline ProgramID ProgramIDOf(const Program* program) {
|
||||
return program->ID();
|
||||
}
|
||||
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_PROGRAM_H_
|
||||
|
|
|
@ -1505,6 +1505,12 @@ struct ProgramBuilder::TypesBuilder::CToAST<void> {
|
|||
};
|
||||
//! @endcond
|
||||
|
||||
/// @param builder the ProgramBuilder
|
||||
/// @returns the ProgramID of the ProgramBuilder
|
||||
inline ProgramID ProgramIDOf(const ProgramBuilder* builder) {
|
||||
return builder->ID();
|
||||
}
|
||||
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_PROGRAM_BUILDER_H_
|
||||
|
|
|
@ -102,6 +102,13 @@ class Type : public Castable<Type, ShareableCloneable> {
|
|||
Type();
|
||||
};
|
||||
|
||||
/// @returns the ProgramID of the given type.
|
||||
inline ProgramID ProgramIDOf(const Type*) {
|
||||
/// TODO(crbug.com/tint/724): Actually implement this once we split the `type`
|
||||
/// namespace into ast::Type and sem::Type.
|
||||
return ProgramID();
|
||||
}
|
||||
|
||||
} // namespace type
|
||||
} // namespace tint
|
||||
|
||||
|
|
Loading…
Reference in New Issue