writer: Add parentheses for array accesses

The LHS should be wrapped in parentheses if it has lower precedence
than the access. This fixes issues with pointer dereferences followed
by array accesses, where we were previously generating *a[i].

Change-Id: I639f94b642f32119350b0a0d23f4ff2a5d6c3c25
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/52843
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-06-01 12:18:10 +00:00 committed by Tint LUCI CQ
parent 42220ba1b2
commit b487c71e59
5 changed files with 50 additions and 2 deletions

View File

@ -70,7 +70,7 @@ fn f() {
auto* expect = R"(
fn f() {
var m : mat4x4<f32>;
let f : f32 = *(&(*(&(*(&(m))[2]))[1]));
let f : f32 = *(&((*(&((*(&(m)))[2])))[1]));
}
)";
@ -220,7 +220,7 @@ fn f() {
let j : i32 = 1;
let p_save = i;
let q_save = j;
*(&(*(&(arr[p_save]))[q_save])) = 12;
*(&((*(&(arr[p_save])))[q_save])) = 12;
}
)";

View File

@ -165,9 +165,20 @@ bool GeneratorImpl::EmitConstructedType(const sem::Type* ty) {
}
bool GeneratorImpl::EmitArrayAccessor(ast::ArrayAccessorExpression* expr) {
bool paren_lhs =
!expr->array()
->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
ast::IdentifierExpression, ast::MemberAccessorExpression,
ast::TypeConstructorExpression>();
if (paren_lhs) {
out_ << "(";
}
if (!EmitExpression(expr->array())) {
return false;
}
if (paren_lhs) {
out_ << ")";
}
out_ << "[";
if (!EmitExpression(expr->idx_expr())) {

View File

@ -32,6 +32,19 @@ TEST_F(MslGeneratorImplTest, ArrayAccessor) {
EXPECT_EQ(gen.result(), "ary[5]");
}
TEST_F(MslGeneratorImplTest, ArrayAccessor_OfDref) {
Global("ary", ty.array<i32, 10>(), ast::StorageClass::kPrivate);
auto* p = Const("p", nullptr, AddressOf("ary"));
auto* expr = IndexAccessor(Deref("p"), 5);
WrapInFunction(p, expr);
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), "(*(p))[5]");
}
} // namespace
} // namespace msl
} // namespace writer

View File

@ -141,9 +141,20 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) {
}
bool GeneratorImpl::EmitArrayAccessor(ast::ArrayAccessorExpression* expr) {
bool paren_lhs =
!expr->array()
->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
ast::IdentifierExpression, ast::MemberAccessorExpression,
ast::TypeConstructorExpression>();
if (paren_lhs) {
out_ << "(";
}
if (!EmitExpression(expr->array())) {
return false;
}
if (paren_lhs) {
out_ << ")";
}
out_ << "[";
if (!EmitExpression(expr->idx_expr())) {

View File

@ -32,6 +32,19 @@ TEST_F(WgslGeneratorImplTest, ArrayAccessor) {
EXPECT_EQ(gen.result(), "ary[5]");
}
TEST_F(WgslGeneratorImplTest, ArrayAccessor_OfDref) {
Global("ary", ty.array<i32, 10>(), ast::StorageClass::kPrivate);
auto* p = Const("p", nullptr, AddressOf("ary"));
auto* expr = IndexAccessor(Deref("p"), 5);
WrapInFunction(p, expr);
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), "(*(p))[5]");
}
} // namespace
} // namespace wgsl
} // namespace writer