ast: Migrate to using ast::Type

Remove all sem::Type references from the AST.
ConstructedTypes are now all AST types.

The parsers will still create semantic types, but these are now disjoint
and ignored.
The parsers will be updated with future changes to stop creating these
semantic types.

Resolver creates semantic types from the AST types. Most downstream
logic continues to use the semantic types, however transforms will now
need to rebuild AST type information instead of reassigning semantic
information, as semantic nodes are fully rebuilt by the Resolver.

Bug: tint:724
Change-Id: I4ce03a075f13c77648cda5c3691bae202752ecc5
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49747
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton
2021-05-05 09:09:41 +00:00
committed by Commit Bot service account
parent 781de097eb
commit 02ebf0dcae
72 changed files with 1267 additions and 1091 deletions

View File

@@ -218,7 +218,7 @@ TEST_F(SpvParserTest_Composite_Construct, Struct) {
VariableConst{
x_1
none
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S
@@ -835,14 +835,14 @@ TEST_F(SpvParserTest_CompositeInsert, Struct) {
Variable{
x_35
function
__struct_S
__type_name_S
}
}
VariableDeclStatement{
VariableConst{
x_1
none
__struct_S
__type_name_S
{
Identifier[not set]{x_35}
}
@@ -852,7 +852,7 @@ VariableDeclStatement{
Variable{
x_2_1
function
__struct_S
__type_name_S
{
Identifier[not set]{x_1}
}
@@ -869,7 +869,7 @@ VariableDeclStatement{
VariableConst{
x_2
none
__struct_S
__type_name_S
{
Identifier[not set]{x_2_1}
}
@@ -909,21 +909,21 @@ TEST_F(SpvParserTest_CompositeInsert, Struct_DifferOnlyInMemberName) {
Variable{
x_40
function
__struct_S_2
__type_name_S_2
}
}
VariableDeclStatement{
Variable{
x_41
function
__struct_S_2
__type_name_S_2
}
}
VariableDeclStatement{
VariableConst{
x_1
none
__struct_S_1
__type_name_S_1
{
Identifier[not set]{x_40}
}
@@ -933,7 +933,7 @@ VariableDeclStatement{
Variable{
x_2_1
function
__struct_S_1
__type_name_S_1
{
Identifier[not set]{x_1}
}
@@ -950,7 +950,7 @@ VariableDeclStatement{
VariableConst{
x_2
none
__struct_S_1
__type_name_S_1
{
Identifier[not set]{x_2_1}
}
@@ -960,7 +960,7 @@ VariableDeclStatement{
VariableConst{
x_3
none
__struct_S_2
__type_name_S_2
{
Identifier[not set]{x_41}
}
@@ -970,7 +970,7 @@ VariableDeclStatement{
Variable{
x_4_1
function
__struct_S_2
__type_name_S_2
{
Identifier[not set]{x_3}
}
@@ -987,7 +987,7 @@ VariableDeclStatement{
VariableConst{
x_4
none
__struct_S_2
__type_name_S_2
{
Identifier[not set]{x_4_1}
}
@@ -998,7 +998,7 @@ VariableDeclStatement{
Variable{
x_4_1
function
__struct_S_2
__type_name_S_2
{
Identifier[not set]{x_3}
}
@@ -1015,7 +1015,7 @@ VariableDeclStatement{
VariableConst{
x_4
none
__struct_S_2
__type_name_S_2
{
Identifier[not set]{x_4_1}
}
@@ -1066,14 +1066,14 @@ TEST_F(SpvParserTest_CompositeInsert, Struct_Array_Matrix_Vector) {
Variable{
x_37
function
__struct_S_1
__type_name_S_1
}
}
VariableDeclStatement{
VariableConst{
x_1
none
__struct_S_1
__type_name_S_1
{
Identifier[not set]{x_37}
}
@@ -1083,7 +1083,7 @@ VariableDeclStatement{
Variable{
x_2_1
function
__struct_S_1
__type_name_S_1
{
Identifier[not set]{x_1}
}
@@ -1109,7 +1109,7 @@ VariableDeclStatement{
VariableConst{
x_2
none
__struct_S_1
__type_name_S_1
{
Identifier[not set]{x_2_1}
}

View File

@@ -806,7 +806,7 @@ TEST_F(SpvParserTest, RemapStorageBuffer_TypesAndVarDeclarations) {
Variable{
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
})"));
}

View File

@@ -409,7 +409,7 @@ TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Struct) {
VariableConst{
x_11
none
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S

View File

@@ -467,7 +467,7 @@ TEST_F(SpvParserTest, EmitFunctionVariables_ArrayInitializer_Alias) {
Variable{
x_200
function
__alias_Arr__array__u32_2_stride_16
__type_name_Arr
{
TypeConstructor[not set]{
__type_name_Arr
@@ -537,7 +537,7 @@ TEST_F(SpvParserTest, EmitFunctionVariables_ArrayInitializer_Alias_Null) {
Variable{
x_200
function
__alias_Arr__array__u32_2_stride_16
__type_name_Arr
{
TypeConstructor[not set]{
__type_name_Arr
@@ -572,7 +572,7 @@ TEST_F(SpvParserTest, EmitFunctionVariables_StructInitializer) {
Variable{
x_200
function
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S
@@ -612,7 +612,7 @@ TEST_F(SpvParserTest, EmitFunctionVariables_StructInitializer_Null) {
Variable{
x_200
function
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S

View File

@@ -233,7 +233,8 @@ bool AssumesResultSignednessMatchesFirstOperand(GLSLstd450 extended_opcode) {
// @param tp the type pair
// @returns the unwrapped type pair
typ::Type UnwrapIfNeeded(typ::Type tp) {
return typ::Type{tp.ast->UnwrapIfNeeded(), tp.sem->UnwrapIfNeeded()};
return typ::Type{tp.ast ? tp.ast->UnwrapIfNeeded() : nullptr,
tp.sem ? tp.sem->UnwrapIfNeeded() : nullptr};
}
} // namespace
@@ -1037,7 +1038,7 @@ typ::Type ParserImpl::ConvertType(
return result;
}
void ParserImpl::AddConstructedType(Symbol name, typ::Type type) {
void ParserImpl::AddConstructedType(Symbol name, ast::NamedType* type) {
auto iter = constructed_types_.insert(name);
if (iter.second) {
builder_.AST().AddConstructedType(type);
@@ -1539,7 +1540,7 @@ TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
return {};
}
ast::Expression* ParserImpl::MakeNullValue(typ::Type type) {
ast::Expression* ParserImpl::MakeNullValue(ast::Type* type) {
// TODO(dneto): Use the no-operands constructor syntax when it becomes
// available in Tint.
// https://github.com/gpuweb/gpuweb/issues/685
@@ -1550,43 +1551,43 @@ ast::Expression* ParserImpl::MakeNullValue(typ::Type type) {
return nullptr;
}
auto original_type = type;
auto* original_type = type;
type = UnwrapIfNeeded(type);
if (type.ast->Is<ast::Bool>()) {
if (type->Is<ast::Bool>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::BoolLiteral>(Source{}, false));
}
if (type.ast->Is<ast::U32>()) {
if (type->Is<ast::U32>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::UintLiteral>(Source{}, 0u));
}
if (type.ast->Is<ast::I32>()) {
if (type->Is<ast::I32>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::SintLiteral>(Source{}, 0));
}
if (type.ast->Is<ast::F32>()) {
if (type->Is<ast::F32>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::FloatLiteral>(Source{}, 0.0f));
}
if (type.ast->Is<ast::TypeName>()) {
if (type->Is<ast::TypeName>()) {
// TODO(amaiorano): No type constructor for TypeName (yet?)
ast::ExpressionList ast_components;
return create<ast::TypeConstructorExpression>(Source{}, original_type,
std::move(ast_components));
}
if (auto vec_ty = typ::As<typ::Vector>(type)) {
if (auto* vec_ty = type->As<ast::Vector>()) {
ast::ExpressionList ast_components;
for (size_t i = 0; i < vec_ty->size(); ++i) {
ast_components.emplace_back(MakeNullValue(typ::Call_type(vec_ty)));
ast_components.emplace_back(MakeNullValue(vec_ty->type()));
}
return create<ast::TypeConstructorExpression>(
Source{}, builder_.ty.MaybeCreateTypename(type),
std::move(ast_components));
}
if (auto mat_ty = typ::As<typ::Matrix>(type)) {
if (auto* mat_ty = type->As<ast::Matrix>()) {
// Matrix components are columns
auto column_ty = builder_.ty.vec(typ::Call_type(mat_ty), mat_ty->rows());
auto column_ty = builder_.ty.vec(mat_ty->type(), mat_ty->rows());
ast::ExpressionList ast_components;
for (size_t i = 0; i < mat_ty->columns(); ++i) {
ast_components.emplace_back(MakeNullValue(column_ty));
@@ -1595,18 +1596,18 @@ ast::Expression* ParserImpl::MakeNullValue(typ::Type type) {
Source{}, builder_.ty.MaybeCreateTypename(type),
std::move(ast_components));
}
if (auto arr_ty = typ::As<typ::Array>(type)) {
if (auto* arr_ty = type->As<ast::Array>()) {
ast::ExpressionList ast_components;
for (size_t i = 0; i < arr_ty->size(); ++i) {
ast_components.emplace_back(MakeNullValue(typ::Call_type(arr_ty)));
ast_components.emplace_back(MakeNullValue(arr_ty->type()));
}
return create<ast::TypeConstructorExpression>(
Source{}, builder_.ty.MaybeCreateTypename(original_type),
std::move(ast_components));
}
if (auto struct_ty = typ::As<typ::Struct>(type)) {
if (auto* struct_ty = type->As<ast::Struct>()) {
ast::ExpressionList ast_components;
for (auto* member : struct_ty.ast->members()) {
for (auto* member : struct_ty->members()) {
ast_components.emplace_back(MakeNullValue(member->type()));
}
return create<ast::TypeConstructorExpression>(

View File

@@ -334,7 +334,7 @@ class ParserImpl : Reader {
/// Creates an AST expression node for the null value for the given type.
/// @param type the AST type
/// @returns a new expression
ast::Expression* MakeNullValue(typ::Type type);
ast::Expression* MakeNullValue(ast::Type* type);
/// Make a typed expression for the null value for the given type.
/// @param type the AST type
@@ -598,7 +598,7 @@ class ParserImpl : Reader {
/// Adds `type` as a constructed type if it hasn't been added yet.
/// @param name the type's unique name
/// @param type the type to add
void AddConstructedType(Symbol name, typ::Type type);
void AddConstructedType(Symbol name, ast::NamedType* type);
/// Creates a new `ast::Node` owned by the ProgramBuilder.
/// @param args the arguments to pass to the type constructor

View File

@@ -1408,7 +1408,7 @@ TEST_F(SpvModuleScopeVarParserTest, StructInitializer) {
EXPECT_THAT(module_str, HasSubstr(R"(Variable{
x_200
private
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S
@@ -1437,7 +1437,7 @@ TEST_F(SpvModuleScopeVarParserTest, StructNullInitializer) {
EXPECT_THAT(module_str, HasSubstr(R"(Variable{
x_200
private
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S
@@ -1466,7 +1466,7 @@ TEST_F(SpvModuleScopeVarParserTest, StructUndefInitializer) {
EXPECT_THAT(module_str, HasSubstr(R"(Variable{
x_200
private
__struct_S
__type_name_S
{
TypeConstructor[not set]{
__type_name_S
@@ -1553,7 +1553,7 @@ TEST_F(SpvModuleScopeVarParserTest, DescriptorGroupDecoration_Valid) {
}
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
})"))
<< module_str;
}
@@ -1607,7 +1607,7 @@ TEST_F(SpvModuleScopeVarParserTest, BindingDecoration_Valid) {
}
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
})"))
<< module_str;
}
@@ -1664,7 +1664,7 @@ TEST_F(SpvModuleScopeVarParserTest,
Variable{
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
}
)")) << module_str;
}
@@ -1693,7 +1693,7 @@ TEST_F(SpvModuleScopeVarParserTest, ColMajorDecoration_Dropped) {
Variable{
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
}
})")) << module_str;
}
@@ -1722,7 +1722,7 @@ TEST_F(SpvModuleScopeVarParserTest, MatrixStrideDecoration_Dropped) {
Variable{
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
}
})")) << module_str;
}
@@ -1772,7 +1772,7 @@ TEST_F(SpvModuleScopeVarParserTest, StorageBuffer_NonWritable_AllMembers) {
Variable{
myvar
storage
__access_control_read_only__struct_S
__access_control_read_only__type_name_S
}
})")) << module_str;
}
@@ -1801,7 +1801,7 @@ TEST_F(SpvModuleScopeVarParserTest, StorageBuffer_NonWritable_NotAllMembers) {
Variable{
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
}
})")) << module_str;
}
@@ -1833,7 +1833,7 @@ TEST_F(
Variable{
myvar
storage
__access_control_read_write__struct_S
__access_control_read_write__type_name_S
}
})")) << module_str;
}

View File

@@ -401,7 +401,7 @@ Expect<bool> ParserImpl::expect_global_decl() {
if (!expect("type alias", Token::Type::kSemicolon))
return Failure::kErrored;
builder_.AST().AddConstructedType(ta.value);
builder_.AST().AddConstructedType(const_cast<ast::Alias*>(ta.value.ast));
return true;
}
@@ -415,7 +415,8 @@ Expect<bool> ParserImpl::expect_global_decl() {
register_constructed(
builder_.Symbols().NameFor(str.value->impl()->name()), str.value);
builder_.AST().AddConstructedType(str.value);
builder_.AST().AddConstructedType(
const_cast<ast::Struct*>(str.value.ast));
return true;
}
@@ -561,7 +562,8 @@ Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl() {
if (decl.errored)
return Failure::kErrored;
if (decl->type->UnwrapAll()->is_handle()) {
if ((decl->type.sem && decl->type.sem->UnwrapAll()->is_handle()) ||
(decl->type.ast && decl->type.ast->UnwrapAll()->is_handle())) {
// handle types implicitly have the `UniformConstant` storage class.
if (explicit_sc.matched) {
return add_error(
@@ -960,7 +962,7 @@ Maybe<ast::StorageClass> ParserImpl::variable_storage_decoration() {
// type_alias
// : TYPE IDENT EQUAL type_decl
Maybe<typ::Type> ParserImpl::type_alias() {
Maybe<typ::Alias> ParserImpl::type_alias() {
auto t = peek();
if (!t.IsType())
return Failure::kNoMatch;
@@ -1234,7 +1236,7 @@ Expect<ast::StorageClass> ParserImpl::expect_storage_class(
// struct_decl
// : struct_decoration_decl* STRUCT IDENT struct_body_decl
Maybe<sem::StructType*> ParserImpl::struct_decl(ast::DecorationList& decos) {
Maybe<typ::Struct> ParserImpl::struct_decl(ast::DecorationList& decos) {
auto t = peek();
auto source = t.source();
@@ -1250,8 +1252,9 @@ Maybe<sem::StructType*> ParserImpl::struct_decl(ast::DecorationList& decos) {
return Failure::kErrored;
auto sym = builder_.Symbols().Register(name.value);
return create<sem::StructType>(create<ast::Struct>(
source, sym, std::move(body.value), std::move(decos)));
auto* str =
create<ast::Struct>(source, sym, std::move(body.value), std::move(decos));
return typ::Struct{str, create<sem::StructType>(str)};
}
// struct_body_decl

View File

@@ -398,7 +398,7 @@ class ParserImpl {
Maybe<ast::StorageClass> variable_storage_decoration();
/// Parses a `type_alias` grammar element
/// @returns the type alias or nullptr on error
Maybe<typ::Type> type_alias();
Maybe<typ::Alias> type_alias();
/// Parses a `type_decl` grammar element
/// @returns the parsed Type or nullptr if none matched.
Maybe<typ::Type> type_decl();
@@ -415,7 +415,7 @@ class ParserImpl {
/// `struct_decoration_decl*` provided as `decos`.
/// @returns the struct type or nullptr on error
/// @param decos the list of decorations for the struct declaration.
Maybe<sem::StructType*> struct_decl(ast::DecorationList& decos);
Maybe<typ::Struct> struct_decl(ast::DecorationList& decos);
/// Parses a `struct_body_decl` grammar element, erroring on parse failure.
/// @returns the struct members
Expect<ast::StructMemberList> expect_struct_body_decl();

View File

@@ -28,8 +28,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
auto* t = e->As<ast::TypeConstructorExpression>();
ASSERT_TRUE(t->type()->Is<sem::Vector>());
EXPECT_EQ(t->type()->As<sem::Vector>()->size(), 2u);
ASSERT_TRUE(t->type()->Is<ast::Vector>());
EXPECT_EQ(t->type()->As<ast::Vector>()->size(), 2u);
ASSERT_EQ(t->values().size(), 2u);
auto& v = t->values();
@@ -56,8 +56,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_Empty) {
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
auto* t = e->As<ast::TypeConstructorExpression>();
ASSERT_TRUE(t->type()->Is<sem::Vector>());
EXPECT_EQ(t->type()->As<sem::Vector>()->size(), 2u);
ASSERT_TRUE(t->type()->Is<ast::Vector>());
EXPECT_EQ(t->type()->As<ast::Vector>()->size(), 2u);
ASSERT_EQ(t->values().size(), 0u);
}
@@ -71,8 +71,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_TrailingComma) {
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
auto* t = e->As<ast::TypeConstructorExpression>();
ASSERT_TRUE(t->type()->Is<sem::Vector>());
EXPECT_EQ(t->type()->As<sem::Vector>()->size(), 2u);
ASSERT_TRUE(t->type()->Is<ast::Vector>());
EXPECT_EQ(t->type()->As<ast::Vector>()->size(), 2u);
ASSERT_EQ(t->values().size(), 2u);
ASSERT_TRUE(t->values()[0]->Is<ast::ScalarConstructorExpression>());

View File

@@ -34,14 +34,14 @@ TEST_F(ParserImplTest, FunctionDecl) {
EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
EXPECT_TRUE(f->return_type()->Is<ast::Void>());
ASSERT_EQ(f->params().size(), 2u);
EXPECT_EQ(f->params()[0]->symbol(), p->builder().Symbols().Get("a"));
EXPECT_EQ(f->params()[1]->symbol(), p->builder().Symbols().Get("b"));
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
EXPECT_TRUE(f->return_type()->Is<ast::Void>());
auto* body = f->body();
ASSERT_EQ(body->size(), 1u);
@@ -62,10 +62,8 @@ TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
EXPECT_TRUE(f->return_type()->Is<ast::Void>());
ASSERT_EQ(f->params().size(), 0u);
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
auto& decorations = f->decorations();
ASSERT_EQ(decorations.size(), 1u);
@@ -100,10 +98,8 @@ fn main() { return; })");
EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
EXPECT_TRUE(f->return_type()->Is<ast::Void>());
ASSERT_EQ(f->params().size(), 0u);
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
auto& decorations = f->decorations();
ASSERT_EQ(decorations.size(), 2u);
@@ -145,10 +141,8 @@ fn main() { return; })");
EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
EXPECT_TRUE(f->return_type()->Is<ast::Void>());
ASSERT_EQ(f->params().size(), 0u);
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::Void>());
auto& decos = f->decorations();
ASSERT_EQ(decos.size(), 2u);
@@ -187,7 +181,7 @@ TEST_F(ParserImplTest, FunctionDecl_ReturnTypeDecorationList) {
EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
ASSERT_NE(f->return_type(), nullptr);
EXPECT_TRUE(f->return_type()->Is<sem::F32>());
EXPECT_TRUE(f->return_type()->Is<ast::F32>());
ASSERT_EQ(f->params().size(), 0u);
auto& decorations = f->decorations();

View File

@@ -33,8 +33,8 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
EXPECT_TRUE(e->is_const());
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
ASSERT_NE(e->declared_type(), nullptr);
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
ASSERT_NE(e->type(), nullptr);
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->source().range.begin.line, 1u);
EXPECT_EQ(e->source().range.begin.column, 5u);
@@ -114,8 +114,8 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
EXPECT_TRUE(e->is_const());
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
ASSERT_NE(e->declared_type(), nullptr);
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
ASSERT_NE(e->type(), nullptr);
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->source().range.begin.line, 1u);
EXPECT_EQ(e->source().range.begin.column, 21u);

View File

@@ -84,10 +84,10 @@ TEST_F(ParserImplTest, GlobalDecl_TypeAlias) {
auto program = p->program();
ASSERT_EQ(program.AST().ConstructedTypes().size(), 1u);
ASSERT_TRUE(program.AST().ConstructedTypes()[0]->Is<sem::Alias>());
ASSERT_TRUE(program.AST().ConstructedTypes()[0]->Is<ast::Alias>());
EXPECT_EQ(
program.Symbols().NameFor(
program.AST().ConstructedTypes()[0]->As<sem::Alias>()->symbol()),
program.AST().ConstructedTypes()[0]->As<ast::Alias>()->symbol()),
"A");
}
@@ -102,14 +102,16 @@ type B = A;)");
auto program = p->program();
ASSERT_EQ(program.AST().ConstructedTypes().size(), 2u);
ASSERT_TRUE(program.AST().ConstructedTypes()[0]->Is<sem::StructType>());
auto* str = program.AST().ConstructedTypes()[0]->As<sem::StructType>();
EXPECT_EQ(str->impl()->name(), program.Symbols().Get("A"));
ASSERT_TRUE(program.AST().ConstructedTypes()[0]->Is<ast::Struct>());
auto* str = program.AST().ConstructedTypes()[0]->As<ast::Struct>();
EXPECT_EQ(str->name(), program.Symbols().Get("A"));
ASSERT_TRUE(program.AST().ConstructedTypes()[1]->Is<sem::Alias>());
auto* alias = program.AST().ConstructedTypes()[1]->As<sem::Alias>();
ASSERT_TRUE(program.AST().ConstructedTypes()[1]->Is<ast::Alias>());
auto* alias = program.AST().ConstructedTypes()[1]->As<ast::Alias>();
EXPECT_EQ(alias->symbol(), program.Symbols().Get("B"));
EXPECT_EQ(alias->type(), str);
auto* tn = alias->type()->As<ast::TypeName>();
EXPECT_NE(tn, nullptr);
EXPECT_EQ(tn->name(), str->name());
}
TEST_F(ParserImplTest, GlobalDecl_TypeAlias_Invalid) {
@@ -163,13 +165,13 @@ TEST_F(ParserImplTest, GlobalDecl_ParsesStruct) {
auto program = p->program();
ASSERT_EQ(program.AST().ConstructedTypes().size(), 1u);
auto t = program.AST().ConstructedTypes()[0];
auto* t = program.AST().ConstructedTypes()[0];
ASSERT_NE(t, nullptr);
ASSERT_TRUE(t->Is<sem::StructType>());
ASSERT_TRUE(t->Is<ast::Struct>());
auto* str = t->As<sem::StructType>();
EXPECT_EQ(str->impl()->name(), program.Symbols().Get("A"));
EXPECT_EQ(str->impl()->members().size(), 2u);
auto* str = t->As<ast::Struct>();
EXPECT_EQ(str->name(), program.Symbols().Get("A"));
EXPECT_EQ(str->members().size(), 2u);
}
TEST_F(ParserImplTest, GlobalDecl_Struct_WithStride) {
@@ -181,18 +183,18 @@ TEST_F(ParserImplTest, GlobalDecl_Struct_WithStride) {
auto program = p->program();
ASSERT_EQ(program.AST().ConstructedTypes().size(), 1u);
auto t = program.AST().ConstructedTypes()[0];
auto* t = program.AST().ConstructedTypes()[0];
ASSERT_NE(t, nullptr);
ASSERT_TRUE(t->Is<sem::StructType>());
ASSERT_TRUE(t->Is<ast::Struct>());
auto* str = t->As<sem::StructType>();
EXPECT_EQ(str->impl()->name(), program.Symbols().Get("A"));
EXPECT_EQ(str->impl()->members().size(), 1u);
auto* str = t->As<ast::Struct>();
EXPECT_EQ(str->name(), program.Symbols().Get("A"));
EXPECT_EQ(str->members().size(), 1u);
EXPECT_FALSE(str->IsBlockDecorated());
const auto ty = str->impl()->members()[0]->type();
ASSERT_TRUE(ty->Is<sem::ArrayType>());
const auto* arr = ty->As<sem::ArrayType>();
const auto* ty = str->members()[0]->type();
ASSERT_TRUE(ty->Is<ast::Array>());
const auto* arr = ty->As<ast::Array>();
ASSERT_EQ(arr->decorations().size(), 1u);
auto* stride = arr->decorations()[0];
@@ -208,13 +210,13 @@ TEST_F(ParserImplTest, GlobalDecl_Struct_WithDecoration) {
auto program = p->program();
ASSERT_EQ(program.AST().ConstructedTypes().size(), 1u);
auto t = program.AST().ConstructedTypes()[0];
auto* t = program.AST().ConstructedTypes()[0];
ASSERT_NE(t, nullptr);
ASSERT_TRUE(t->Is<sem::StructType>());
ASSERT_TRUE(t->Is<ast::Struct>());
auto* str = t->As<sem::StructType>();
EXPECT_EQ(str->impl()->name(), program.Symbols().Get("A"));
EXPECT_EQ(str->impl()->members().size(), 1u);
auto* str = t->As<ast::Struct>();
EXPECT_EQ(str->name(), program.Symbols().Get("A"));
EXPECT_EQ(str->members().size(), 1u);
EXPECT_TRUE(str->IsBlockDecorated());
}

View File

@@ -31,7 +31,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithoutConstructor) {
ASSERT_NE(e.value, nullptr);
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kPrivate);
EXPECT_EQ(e->source().range.begin.line, 1u);
@@ -54,7 +54,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
ASSERT_NE(e.value, nullptr);
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kPrivate);
EXPECT_EQ(e->source().range.begin.line, 1u);
@@ -79,8 +79,8 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
ASSERT_NE(e.value, nullptr);
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
ASSERT_NE(e->declared_type(), nullptr);
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
ASSERT_NE(e->type(), nullptr);
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kUniform);
EXPECT_EQ(e->source().range.begin.line, 1u);
@@ -109,8 +109,8 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration_MulitpleGroups) {
ASSERT_NE(e.value, nullptr);
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
ASSERT_NE(e->declared_type(), nullptr);
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
ASSERT_NE(e->type(), nullptr);
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kUniform);
EXPECT_EQ(e->source().range.begin.line, 1u);
@@ -180,7 +180,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_SamplerImplicitStorageClass) {
ASSERT_NE(e.value, nullptr);
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("s"));
EXPECT_TRUE(e->declared_type()->Is<sem::Sampler>());
EXPECT_TRUE(e->type()->Is<ast::Sampler>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kUniformConstant);
}
@@ -196,7 +196,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_TextureImplicitStorageClass) {
ASSERT_NE(e.value, nullptr);
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("s"));
EXPECT_TRUE(e->declared_type()->UnwrapAll()->Is<sem::Texture>());
EXPECT_TRUE(e->type()->UnwrapAll()->Is<ast::Texture>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kUniformConstant);
}
@@ -210,7 +210,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_StorageClassIn_Deprecated) {
ASSERT_FALSE(p->has_error()) << p->error();
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kInput);
EXPECT_EQ(
@@ -231,7 +231,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_StorageClassOut_Deprecated) {
ASSERT_FALSE(p->has_error()) << p->error();
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
EXPECT_TRUE(e->declared_type()->Is<sem::F32>());
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kOutput);
EXPECT_EQ(

View File

@@ -22,15 +22,13 @@ namespace {
TEST_F(ParserImplTest, ParamList_Single) {
auto p = parser("a : i32");
auto* i32 = p->builder().create<sem::I32>();
auto e = p->expect_param_list();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_FALSE(e.errored);
EXPECT_EQ(e.value.size(), 1u);
EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("a"));
EXPECT_EQ(e.value[0]->declared_type(), i32);
EXPECT_TRUE(e.value[0]->type()->Is<ast::I32>());
EXPECT_TRUE(e.value[0]->is_const());
ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
@@ -42,17 +40,13 @@ TEST_F(ParserImplTest, ParamList_Single) {
TEST_F(ParserImplTest, ParamList_Multiple) {
auto p = parser("a : i32, b: f32, c: vec2<f32>");
auto* i32 = p->builder().create<sem::I32>();
auto* f32 = p->builder().create<sem::F32>();
auto* vec2 = p->builder().create<sem::Vector>(f32, 2);
auto e = p->expect_param_list();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_FALSE(e.errored);
EXPECT_EQ(e.value.size(), 3u);
EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("a"));
EXPECT_EQ(e.value[0]->declared_type(), i32);
EXPECT_TRUE(e.value[0]->type()->Is<ast::I32>());
EXPECT_TRUE(e.value[0]->is_const());
ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
@@ -61,7 +55,7 @@ TEST_F(ParserImplTest, ParamList_Multiple) {
ASSERT_EQ(e.value[0]->source().range.end.column, 2u);
EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("b"));
EXPECT_EQ(e.value[1]->declared_type(), f32);
EXPECT_TRUE(e.value[1]->type()->Is<ast::F32>());
EXPECT_TRUE(e.value[1]->is_const());
ASSERT_EQ(e.value[1]->source().range.begin.line, 1u);
@@ -70,7 +64,9 @@ TEST_F(ParserImplTest, ParamList_Multiple) {
ASSERT_EQ(e.value[1]->source().range.end.column, 11u);
EXPECT_EQ(e.value[2]->symbol(), p->builder().Symbols().Get("c"));
EXPECT_EQ(e.value[2]->declared_type(), vec2);
ASSERT_TRUE(e.value[2]->type()->Is<ast::Vector>());
ASSERT_TRUE(e.value[2]->type()->As<ast::Vector>()->type()->Is<ast::F32>());
EXPECT_EQ(e.value[2]->type()->As<ast::Vector>()->size(), 2u);
EXPECT_TRUE(e.value[2]->is_const());
ASSERT_EQ(e.value[2]->source().range.begin.line, 1u);
@@ -100,16 +96,15 @@ TEST_F(ParserImplTest, ParamList_Decorations) {
"[[builtin(position)]] coord : vec4<f32>, "
"[[location(1)]] loc1 : f32");
auto* f32 = p->builder().create<sem::F32>();
auto* vec4 = p->builder().create<sem::Vector>(f32, 4);
auto e = p->expect_param_list();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_FALSE(e.errored);
ASSERT_EQ(e.value.size(), 2u);
EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("coord"));
EXPECT_EQ(e.value[0]->declared_type(), vec4);
ASSERT_TRUE(e.value[0]->type()->Is<ast::Vector>());
EXPECT_TRUE(e.value[0]->type()->As<ast::Vector>()->type()->Is<ast::F32>());
EXPECT_EQ(e.value[0]->type()->As<ast::Vector>()->size(), 4u);
EXPECT_TRUE(e.value[0]->is_const());
auto decos0 = e.value[0]->decorations();
ASSERT_EQ(decos0.size(), 1u);
@@ -123,7 +118,7 @@ TEST_F(ParserImplTest, ParamList_Decorations) {
ASSERT_EQ(e.value[0]->source().range.end.column, 28u);
EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("loc1"));
EXPECT_EQ(e.value[1]->declared_type(), f32);
EXPECT_TRUE(e.value[1]->type()->Is<ast::F32>());
EXPECT_TRUE(e.value[1]->is_const());
auto decos1 = e.value[1]->decorations();
ASSERT_EQ(decos1.size(), 1u);

View File

@@ -141,7 +141,9 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_Empty) {
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
auto* constructor = e->As<ast::TypeConstructorExpression>();
EXPECT_EQ(constructor->type(), p->get_constructed("S"));
ASSERT_TRUE(constructor->type()->Is<ast::TypeName>());
EXPECT_EQ(constructor->type()->As<ast::TypeName>()->name(),
p->builder().Symbols().Get("S"));
auto values = constructor->values();
ASSERT_EQ(values.size(), 0u);
@@ -164,7 +166,9 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
auto* constructor = e->As<ast::TypeConstructorExpression>();
EXPECT_EQ(constructor->type(), p->get_constructed("S"));
ASSERT_TRUE(constructor->type()->Is<ast::TypeName>());
EXPECT_EQ(constructor->type()->As<ast::TypeName>()->name(),
p->builder().Symbols().Get("S"));
auto values = constructor->values();
ASSERT_EQ(values.size(), 2u);
@@ -237,8 +241,6 @@ TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_InvalidExpr) {
TEST_F(ParserImplTest, PrimaryExpression_Cast) {
auto p = parser("f32(1)");
auto* f32 = p->builder().create<sem::F32>();
auto e = p->primary_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
@@ -248,7 +250,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
auto* c = e->As<ast::TypeConstructorExpression>();
ASSERT_EQ(c->type(), f32);
ASSERT_TRUE(c->type()->Is<ast::F32>());
ASSERT_EQ(c->values().size(), 1u);
ASSERT_TRUE(c->values()[0]->Is<ast::ConstructorExpression>());
@@ -258,8 +260,6 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
auto p = parser("bitcast<f32>(1)");
auto* f32 = p->builder().create<sem::F32>();
auto e = p->primary_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
@@ -268,8 +268,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
ASSERT_TRUE(e->Is<ast::BitcastExpression>());
auto* c = e->As<ast::BitcastExpression>();
ASSERT_EQ(c->type(), f32);
ASSERT_TRUE(c->type()->Is<ast::F32>());
ASSERT_TRUE(c->expr()->Is<ast::ConstructorExpression>());
ASSERT_TRUE(c->expr()->Is<ast::ScalarConstructorExpression>());
}

View File

@@ -23,7 +23,6 @@ TEST_F(ParserImplTest, StructBodyDecl_Parses) {
auto p = parser("{a : i32;}");
auto& builder = p->builder();
auto* i32 = builder.create<sem::I32>();
auto m = p->expect_struct_body_decl();
ASSERT_FALSE(p->has_error());
@@ -32,7 +31,7 @@ TEST_F(ParserImplTest, StructBodyDecl_Parses) {
const auto* mem = m.value[0];
EXPECT_EQ(mem->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(mem->type(), i32);
EXPECT_TRUE(mem->type()->Is<ast::I32>());
EXPECT_EQ(mem->decorations().size(), 0u);
}

View File

@@ -23,7 +23,6 @@ TEST_F(ParserImplTest, StructMember_Parses) {
auto p = parser("a : i32;");
auto& builder = p->builder();
auto i32 = builder.ty.i32();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
@@ -36,18 +35,17 @@ TEST_F(ParserImplTest, StructMember_Parses) {
ASSERT_NE(m.value, nullptr);
EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(m->type(), i32);
EXPECT_TRUE(m->type()->Is<ast::I32>());
EXPECT_EQ(m->decorations().size(), 0u);
EXPECT_EQ(m->source().range, (Source::Range{{1u, 1u}, {1u, 2u}}));
EXPECT_EQ(m->type().ast->source().range, (Source::Range{{1u, 5u}, {1u, 8u}}));
EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 5u}, {1u, 8u}}));
}
TEST_F(ParserImplTest, StructMember_ParsesWithOffsetDecoration_DEPRECATED) {
auto p = parser("[[offset(2)]] a : i32;");
auto& builder = p->builder();
auto i32 = builder.ty.i32();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
@@ -60,7 +58,7 @@ TEST_F(ParserImplTest, StructMember_ParsesWithOffsetDecoration_DEPRECATED) {
ASSERT_NE(m.value, nullptr);
EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(m->type(), i32);
EXPECT_TRUE(m->type()->Is<ast::I32>());
EXPECT_EQ(m->decorations().size(), 1u);
EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberOffsetDecoration>());
EXPECT_EQ(
@@ -68,15 +66,13 @@ TEST_F(ParserImplTest, StructMember_ParsesWithOffsetDecoration_DEPRECATED) {
2u);
EXPECT_EQ(m->source().range, (Source::Range{{1u, 15u}, {1u, 16u}}));
EXPECT_EQ(m->type().ast->source().range,
(Source::Range{{1u, 19u}, {1u, 22u}}));
EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 19u}, {1u, 22u}}));
}
TEST_F(ParserImplTest, StructMember_ParsesWithAlignDecoration) {
auto p = parser("[[align(2)]] a : i32;");
auto& builder = p->builder();
auto i32 = builder.ty.i32();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
@@ -89,22 +85,20 @@ TEST_F(ParserImplTest, StructMember_ParsesWithAlignDecoration) {
ASSERT_NE(m.value, nullptr);
EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(m->type(), i32);
EXPECT_TRUE(m->type()->Is<ast::I32>());
EXPECT_EQ(m->decorations().size(), 1u);
EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberAlignDecoration>());
EXPECT_EQ(
m->decorations()[0]->As<ast::StructMemberAlignDecoration>()->align(), 2u);
EXPECT_EQ(m->source().range, (Source::Range{{1u, 14u}, {1u, 15u}}));
EXPECT_EQ(m->type().ast->source().range,
(Source::Range{{1u, 18u}, {1u, 21u}}));
EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 18u}, {1u, 21u}}));
}
TEST_F(ParserImplTest, StructMember_ParsesWithSizeDecoration) {
auto p = parser("[[size(2)]] a : i32;");
auto& builder = p->builder();
auto i32 = builder.ty.i32();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
@@ -117,22 +111,20 @@ TEST_F(ParserImplTest, StructMember_ParsesWithSizeDecoration) {
ASSERT_NE(m.value, nullptr);
EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(m->type(), i32);
EXPECT_TRUE(m->type()->Is<ast::I32>());
EXPECT_EQ(m->decorations().size(), 1u);
EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberSizeDecoration>());
EXPECT_EQ(m->decorations()[0]->As<ast::StructMemberSizeDecoration>()->size(),
2u);
EXPECT_EQ(m->source().range, (Source::Range{{1u, 13u}, {1u, 14u}}));
EXPECT_EQ(m->type().ast->source().range,
(Source::Range{{1u, 17u}, {1u, 20u}}));
EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 17u}, {1u, 20u}}));
}
TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
auto p = parser("[[size(2)]] a : i32;");
auto& builder = p->builder();
auto i32 = builder.ty.i32();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
@@ -145,15 +137,14 @@ TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
ASSERT_NE(m.value, nullptr);
EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(m->type(), i32);
EXPECT_TRUE(m->type()->Is<ast::I32>());
EXPECT_EQ(m->decorations().size(), 1u);
EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberSizeDecoration>());
EXPECT_EQ(m->decorations()[0]->As<ast::StructMemberSizeDecoration>()->size(),
2u);
EXPECT_EQ(m->source().range, (Source::Range{{1u, 13u}, {1u, 14u}}));
EXPECT_EQ(m->type().ast->source().range,
(Source::Range{{1u, 17u}, {1u, 20u}}));
EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 17u}, {1u, 20u}}));
}
TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
@@ -161,7 +152,6 @@ TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
[[align(4)]] a : i32;)");
auto& builder = p->builder();
auto i32 = builder.ty.i32();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
@@ -174,7 +164,7 @@ TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
ASSERT_NE(m.value, nullptr);
EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
EXPECT_EQ(m->type(), i32);
EXPECT_TRUE(m->type()->Is<ast::I32>());
EXPECT_EQ(m->decorations().size(), 2u);
EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberSizeDecoration>());
EXPECT_EQ(m->decorations()[0]->As<ast::StructMemberSizeDecoration>()->size(),
@@ -184,8 +174,7 @@ TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
m->decorations()[1]->As<ast::StructMemberAlignDecoration>()->align(), 4u);
EXPECT_EQ(m->source().range, (Source::Range{{2u, 14u}, {2u, 15u}}));
EXPECT_EQ(m->type().ast->source().range,
(Source::Range{{2u, 18u}, {2u, 21u}}));
EXPECT_EQ(m->type()->source().range, (Source::Range{{2u, 18u}, {2u, 21u}}));
}
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {