[tint][wgsl] Improve 'cannot take address of' diagnostic
Also rename:
`value expression of type 'X' `
to
`value of type 'X' `
As 'expression' is superfluous.
Fixed: tint:2159
Change-Id: Ic32b3af171a1b637f9e16b6f484accdf6fc48b92
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/172863
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/tint/lang/wgsl/resolver/assignment_validation_test.cc b/src/tint/lang/wgsl/resolver/assignment_validation_test.cc
index aeb4d61..826fbd0 100644
--- a/src/tint/lang/wgsl/resolver/assignment_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/assignment_validation_test.cc
@@ -222,7 +222,7 @@
Assign(Expr(Source{{12, 34}}, 1_i), "my_var"));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to value expression of type 'i32')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to value of type 'i32')");
}
TEST_F(ResolverAssignmentValidationTest, AssignToOverride_Fail) {
@@ -292,7 +292,7 @@
Assign(MemberAccessor(Source{{12, 34}}, Expr(Source{{56, 78}}, "a"), "i"), 2_i));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to value expression of type 'i32'
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to value of type 'i32'
56:78 note: 'let' variables are immutable
98:76 note: let 'a' declared here)");
}
diff --git a/src/tint/lang/wgsl/resolver/call_validation_test.cc b/src/tint/lang/wgsl/resolver/call_validation_test.cc
index 9a0d7c1..d7bdc4e 100644
--- a/src/tint/lang/wgsl/resolver/call_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/call_validation_test.cc
@@ -143,7 +143,7 @@
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression");
+ EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of let 'z'");
}
TEST_F(ResolverCallValidationTest,
@@ -214,7 +214,7 @@
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression");
+ EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of value of type 'i32'");
}
TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParam) {
diff --git a/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc b/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc
index ada0fb4..578cd22 100644
--- a/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc
@@ -276,7 +276,7 @@
WrapInFunction(CompoundAssign(Expr(Source{{56, 78}}, 1_i), 1_i, core::BinaryOp::kAdd));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(56:78 error: cannot assign to value expression of type 'i32')");
+ EXPECT_EQ(r()->error(), R"(56:78 error: cannot assign to value of type 'i32')");
}
TEST_F(ResolverCompoundAssignmentValidationTest, LhsAtomic) {
diff --git a/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc b/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc
index cc61eb3..488b5c6 100644
--- a/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc
@@ -49,7 +49,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of value of type 'i32')");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfLet) {
@@ -62,7 +62,45 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of let 'l')");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfConst) {
+ // const c : i32 = 1;
+ // &c
+ auto* l = Const("c", ty.i32(), Expr(1_i));
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "c"));
+
+ WrapInFunction(l, expr);
+
+ EXPECT_FALSE(r()->Resolve());
+
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of const 'c')");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfOverride) {
+ // override c : i32;
+ // &o
+ Override("o", ty.i32());
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "o"));
+
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of override 'o')");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfParameter) {
+ // fn F(p : i32) { _ = &p }
+ // &F
+ Func("F", Vector{Param("p", ty.i32())}, ty.void_(),
+ Vector{
+ Assign(Phony(), AddressOf(Expr(Source{{12, 34}}, "p"))),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of parameter 'p')");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfHandle) {
@@ -75,8 +113,111 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: cannot take the address of expression in handle "
- "address space");
+ R"(12:34 error: cannot take the address of var 't' in handle address space)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfFunction) {
+ // fn F() {}
+ // &F
+ Func("F", Empty, ty.void_(), Empty);
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "F"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot use function 'F' as value
+note: function 'F' declared here
+12:34 note: are you missing '()'?)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfBuiltinFunction) {
+ // &max
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "max"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot use builtin function 'max' as value
+12:34 note: are you missing '()'?)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfType) {
+ // &i32
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "i32"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot use type 'i32' as value
+12:34 note: are you missing '()'?)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfTypeAlias) {
+ // alias T = i32
+ // &T
+ Alias("T", ty.i32());
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "T"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot use type 'i32' as value
+12:34 note: are you missing '()'?)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfAccess) {
+ // &read_write
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "read_write"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot use access 'read_write' as value)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfAddressSpace) {
+ // &handle
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "uniform"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot use address space 'uniform' as value)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfBuiltinValue) {
+ // &position
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "position"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot use builtin value 'position' as value)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfInterpolationSampling) {
+ // ¢roid
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "centroid"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot use interpolation sampling 'centroid' as value)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfInterpolationType) {
+ // &perspective
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "perspective"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot use interpolation type 'perspective' as value)");
+}
+
+TEST_F(ResolverPtrRefValidationTest, AddressOfTexelFormat) {
+ // &rgba8snorm
+ auto* expr = AddressOf(Expr(Source{{12, 34}}, "rgba8snorm"));
+ WrapInFunction(expr);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot use texel format 'rgba8snorm' as value)");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfVectorComponent_MemberAccessor) {
@@ -89,7 +230,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of a vector component");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of a vector component)");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfVectorComponent_IndexAccessor) {
@@ -102,7 +243,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of a vector component");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of a vector component)");
}
TEST_F(ResolverPtrRefValidationTest, IndirectOfAddressOfHandle) {
@@ -115,8 +256,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: cannot take the address of expression in handle "
- "address space");
+ R"(12:34 error: cannot take the address of var 't' in handle address space)");
}
TEST_F(ResolverPtrRefValidationTest, DerefOfLiteral) {
@@ -128,7 +268,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot dereference expression of type 'i32'");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot dereference expression of type 'i32')");
}
TEST_F(ResolverPtrRefValidationTest, DerefOfVar) {
@@ -141,7 +281,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot dereference expression of type 'i32'");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot dereference expression of type 'i32')");
}
TEST_F(ResolverPtrRefValidationTest, InferredPtrAccessMismatch) {
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 16c25ae..3e717d4 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -3694,7 +3694,8 @@
case core::UnaryOp::kAddressOf:
if (auto* ref = expr_ty->As<core::type::Reference>()) {
if (ref->StoreType()->UnwrapRef()->is_handle()) {
- AddError("cannot take the address of expression in handle address space",
+ AddError("cannot take the address of " + sem_.Describe(expr) +
+ " in handle address space",
unary->expr->source);
return nullptr;
}
@@ -3713,7 +3714,7 @@
root_ident = expr->RootIdentifier();
} else {
- AddError("cannot take the address of expression", unary->expr->source);
+ AddError("cannot take the address of " + sem_.Describe(expr), unary->expr->source);
return nullptr;
}
break;
diff --git a/src/tint/lang/wgsl/resolver/resolver_test.cc b/src/tint/lang/wgsl/resolver/resolver_test.cc
index 8eb0457..fe4027e 100644
--- a/src/tint/lang/wgsl/resolver/resolver_test.cc
+++ b/src/tint/lang/wgsl/resolver/resolver_test.cc
@@ -138,7 +138,7 @@
WrapInFunction(cond_var, Switch("i", Case(CaseSelector(AddressOf(1_a)), Block())));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "error: cannot take the address of expression");
+ EXPECT_EQ(r()->error(), "error: cannot take the address of value of type 'abstract-int'");
}
TEST_F(ResolverTest, Stmt_Block) {
@@ -2411,7 +2411,7 @@
});
ASSERT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "error: cannot take the address of expression in handle address space");
+ EXPECT_EQ(r()->error(), "error: cannot take the address of var 's' in handle address space");
}
TEST_F(ResolverTest, ModuleDependencyOrderedDeclarations) {
diff --git a/src/tint/lang/wgsl/resolver/sem_helper.cc b/src/tint/lang/wgsl/resolver/sem_helper.cc
index a68734a..d6e8b89 100644
--- a/src/tint/lang/wgsl/resolver/sem_helper.cc
+++ b/src/tint/lang/wgsl/resolver/sem_helper.cc
@@ -94,7 +94,7 @@
},
[&](const sem::ValueExpression* val_expr) {
auto type = val_expr->Type()->FriendlyName();
- return "value expression of type '" + type + "'";
+ return "value of type '" + type + "'";
},
[&](const sem::TypeExpression* ty_expr) {
auto name = ty_expr->Type()->FriendlyName();