tint/resolver: Fix null dereference

When performing binary / unary ops with non-value expressions.

Bug: chromium:1414658
Change-Id: I7b92f63890da1d9e20e7a1f692fe1fcd28a6f79d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119481
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Ben Clayton 2023-02-10 15:54:54 +00:00 committed by Dawn LUCI CQ
parent e268e5b854
commit c66b5e6922
2 changed files with 55 additions and 3 deletions

View File

@ -61,6 +61,7 @@ std::ostream& operator<<(std::ostream& out, Def def) {
enum class Use { enum class Use {
kAccess, kAccess,
kAddressSpace, kAddressSpace,
kBinaryOp,
kCallExpr, kCallExpr,
kCallStmt, kCallStmt,
kFunctionReturnType, kFunctionReturnType,
@ -68,6 +69,7 @@ enum class Use {
kTexelFormat, kTexelFormat,
kValueExpression, kValueExpression,
kVariableType, kVariableType,
kUnaryOp
}; };
std::ostream& operator<<(std::ostream& out, Use use) { std::ostream& operator<<(std::ostream& out, Use use) {
@ -76,6 +78,8 @@ std::ostream& operator<<(std::ostream& out, Use use) {
return out << "Use::kAccess"; return out << "Use::kAccess";
case Use::kAddressSpace: case Use::kAddressSpace:
return out << "Use::kAddressSpace"; return out << "Use::kAddressSpace";
case Use::kBinaryOp:
return out << "Use::kBinaryOp";
case Use::kCallExpr: case Use::kCallExpr:
return out << "Use::kCallExpr"; return out << "Use::kCallExpr";
case Use::kCallStmt: case Use::kCallStmt:
@ -90,6 +94,8 @@ std::ostream& operator<<(std::ostream& out, Use use) {
return out << "Use::kValueExpression"; return out << "Use::kValueExpression";
case Use::kVariableType: case Use::kVariableType:
return out << "Use::kVariableType"; return out << "Use::kVariableType";
case Use::kUnaryOp:
return out << "Use::kUnaryOp";
} }
return out << "<unknown>"; return out << "<unknown>";
} }
@ -158,6 +164,9 @@ TEST_P(ResolverExpressionKindTest, Test) {
case Use::kCallStmt: case Use::kCallStmt:
Func("f", utils::Empty, ty.void_(), CallStmt(Call(Ident(kUseSource, sym)))); Func("f", utils::Empty, ty.void_(), CallStmt(Call(Ident(kUseSource, sym))));
break; break;
case Use::kBinaryOp:
GlobalVar("v", type::AddressSpace::kPrivate, Mul(1_a, Expr(kUseSource, sym)));
break;
case Use::kFunctionReturnType: case Use::kFunctionReturnType:
Func("f", utils::Empty, ty(kUseSource, sym), Return(Call(sym))); Func("f", utils::Empty, ty(kUseSource, sym), Return(Call(sym)));
break; break;
@ -172,6 +181,9 @@ TEST_P(ResolverExpressionKindTest, Test) {
case Use::kVariableType: case Use::kVariableType:
GlobalVar("v", type::AddressSpace::kPrivate, ty(kUseSource, sym)); GlobalVar("v", type::AddressSpace::kPrivate, ty(kUseSource, sym));
break; break;
case Use::kUnaryOp:
GlobalVar("v", type::AddressSpace::kPrivate, Negation(Expr(kUseSource, sym)));
break;
} }
if (GetParam().error == kPass) { if (GetParam().error == kPass) {
@ -189,6 +201,7 @@ INSTANTIATE_TEST_SUITE_P(
testing::ValuesIn(std::vector<Case>{ testing::ValuesIn(std::vector<Case>{
{Def::kAccess, Use::kAccess, kPass}, {Def::kAccess, Use::kAccess, kPass},
{Def::kAccess, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kAccess, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kAccess, Use::kBinaryOp, R"(5:6 error: cannot use access 'read_write' as value)"},
{Def::kAccess, Use::kCallExpr, {Def::kAccess, Use::kCallExpr,
R"(5:6 error: cannot use access 'read_write' as call target)"}, R"(5:6 error: cannot use access 'read_write' as call target)"},
{Def::kAccess, Use::kCallStmt, {Def::kAccess, Use::kCallStmt,
@ -200,9 +213,12 @@ INSTANTIATE_TEST_SUITE_P(
{Def::kAccess, Use::kValueExpression, {Def::kAccess, Use::kValueExpression,
R"(5:6 error: cannot use access 'read_write' as value)"}, R"(5:6 error: cannot use access 'read_write' as value)"},
{Def::kAccess, Use::kVariableType, R"(5:6 error: cannot use access 'read_write' as type)"}, {Def::kAccess, Use::kVariableType, R"(5:6 error: cannot use access 'read_write' as type)"},
{Def::kAccess, Use::kUnaryOp, R"(5:6 error: cannot use access 'read_write' as value)"},
{Def::kAddressSpace, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kAddressSpace, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kAddressSpace, Use::kAddressSpace, kPass}, {Def::kAddressSpace, Use::kAddressSpace, kPass},
{Def::kAddressSpace, Use::kBinaryOp,
R"(5:6 error: cannot use address space 'workgroup' as value)"},
{Def::kAddressSpace, Use::kCallExpr, {Def::kAddressSpace, Use::kCallExpr,
R"(5:6 error: cannot use address space 'workgroup' as call target)"}, R"(5:6 error: cannot use address space 'workgroup' as call target)"},
{Def::kAddressSpace, Use::kCallStmt, {Def::kAddressSpace, Use::kCallStmt,
@ -216,9 +232,13 @@ INSTANTIATE_TEST_SUITE_P(
R"(5:6 error: cannot use address space 'workgroup' as value)"}, R"(5:6 error: cannot use address space 'workgroup' as value)"},
{Def::kAddressSpace, Use::kVariableType, {Def::kAddressSpace, Use::kVariableType,
R"(5:6 error: cannot use address space 'workgroup' as type)"}, R"(5:6 error: cannot use address space 'workgroup' as type)"},
{Def::kAddressSpace, Use::kUnaryOp,
R"(5:6 error: cannot use address space 'workgroup' as value)"},
{Def::kBuiltinFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kBuiltinFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kBuiltinFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kBuiltinFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kBuiltinFunction, Use::kBinaryOp,
R"(7:8 error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kCallStmt, kPass}, {Def::kBuiltinFunction, Use::kCallStmt, kPass},
{Def::kBuiltinFunction, Use::kFunctionReturnType, {Def::kBuiltinFunction, Use::kFunctionReturnType,
R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"}, R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
@ -229,9 +249,14 @@ INSTANTIATE_TEST_SUITE_P(
R"(7:8 error: missing '(' for builtin function call)"}, R"(7:8 error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kVariableType, {Def::kBuiltinFunction, Use::kVariableType,
R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"}, R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
{Def::kBuiltinFunction, Use::kUnaryOp,
R"(7:8 error: missing '(' for builtin function call)"},
{Def::kBuiltinType, Use::kAccess, kPass}, {Def::kBuiltinType, Use::kAccess, kPass},
{Def::kBuiltinType, Use::kAddressSpace, kPass}, {Def::kBuiltinType, Use::kAddressSpace, kPass},
{Def::kBuiltinType, Use::kBinaryOp,
R"(5:6 error: cannot use type 'vec4<f32>' as value
7:8 note: are you missing '()' for type initializer?)"},
{Def::kBuiltinType, Use::kCallExpr, kPass}, {Def::kBuiltinType, Use::kCallExpr, kPass},
{Def::kBuiltinType, Use::kFunctionReturnType, kPass}, {Def::kBuiltinType, Use::kFunctionReturnType, kPass},
{Def::kBuiltinType, Use::kMemberType, kPass}, {Def::kBuiltinType, Use::kMemberType, kPass},
@ -240,10 +265,14 @@ INSTANTIATE_TEST_SUITE_P(
R"(5:6 error: cannot use type 'vec4<f32>' as value R"(5:6 error: cannot use type 'vec4<f32>' as value
7:8 note: are you missing '()' for type initializer?)"}, 7:8 note: are you missing '()' for type initializer?)"},
{Def::kBuiltinType, Use::kVariableType, kPass}, {Def::kBuiltinType, Use::kVariableType, kPass},
{Def::kBuiltinType, Use::kUnaryOp,
R"(5:6 error: cannot use type 'vec4<f32>' as value
7:8 note: are you missing '()' for type initializer?)"},
{Def::kFunction, Use::kCallExpr, kPass},
{Def::kFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kFunction, Use::kBinaryOp, R"(7:8 error: missing '(' for function call)"},
{Def::kFunction, Use::kCallExpr, kPass},
{Def::kFunction, Use::kCallStmt, kPass}, {Def::kFunction, Use::kCallStmt, kPass},
{Def::kFunction, Use::kFunctionReturnType, {Def::kFunction, Use::kFunctionReturnType,
R"(5:6 error: cannot use function 'FUNCTION' as type R"(5:6 error: cannot use function 'FUNCTION' as type
@ -256,9 +285,13 @@ INSTANTIATE_TEST_SUITE_P(
{Def::kFunction, Use::kVariableType, {Def::kFunction, Use::kVariableType,
R"(5:6 error: cannot use function 'FUNCTION' as type R"(5:6 error: cannot use function 'FUNCTION' as type
1:2 note: 'FUNCTION' declared here)"}, 1:2 note: 'FUNCTION' declared here)"},
{Def::kFunction, Use::kUnaryOp, R"(7:8 error: missing '(' for function call)"},
{Def::kStruct, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kStruct, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kStruct, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kStruct, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
7:8 note: are you missing '()' for type initializer?
1:2 note: 'STRUCT' declared here)"},
{Def::kStruct, Use::kFunctionReturnType, kPass}, {Def::kStruct, Use::kFunctionReturnType, kPass},
{Def::kStruct, Use::kMemberType, kPass}, {Def::kStruct, Use::kMemberType, kPass},
{Def::kStruct, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kStruct, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
@ -267,9 +300,15 @@ INSTANTIATE_TEST_SUITE_P(
7:8 note: are you missing '()' for type initializer? 7:8 note: are you missing '()' for type initializer?
1:2 note: 'STRUCT' declared here)"}, 1:2 note: 'STRUCT' declared here)"},
{Def::kStruct, Use::kVariableType, kPass}, {Def::kStruct, Use::kVariableType, kPass},
{Def::kStruct, Use::kUnaryOp,
R"(5:6 error: cannot use type 'STRUCT' as value
7:8 note: are you missing '()' for type initializer?
1:2 note: 'STRUCT' declared here)"},
{Def::kTexelFormat, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kTexelFormat, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kTexelFormat, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kTexelFormat, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kTexelFormat, Use::kBinaryOp,
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
{Def::kTexelFormat, Use::kCallExpr, {Def::kTexelFormat, Use::kCallExpr,
R"(5:6 error: cannot use texel format 'rgba8unorm' as call target)"}, R"(5:6 error: cannot use texel format 'rgba8unorm' as call target)"},
{Def::kTexelFormat, Use::kCallStmt, {Def::kTexelFormat, Use::kCallStmt,
@ -283,9 +322,14 @@ INSTANTIATE_TEST_SUITE_P(
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"}, R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
{Def::kTexelFormat, Use::kVariableType, {Def::kTexelFormat, Use::kVariableType,
R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"}, R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"},
{Def::kTexelFormat, Use::kUnaryOp,
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
{Def::kTypeAlias, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kTypeAlias, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kTypeAlias, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kTypeAlias, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kTypeAlias, Use::kBinaryOp,
R"(5:6 error: cannot use type 'i32' as value
7:8 note: are you missing '()' for type initializer?)"},
{Def::kTypeAlias, Use::kCallExpr, kPass}, {Def::kTypeAlias, Use::kCallExpr, kPass},
{Def::kTypeAlias, Use::kFunctionReturnType, kPass}, {Def::kTypeAlias, Use::kFunctionReturnType, kPass},
{Def::kTypeAlias, Use::kMemberType, kPass}, {Def::kTypeAlias, Use::kMemberType, kPass},
@ -294,9 +338,13 @@ INSTANTIATE_TEST_SUITE_P(
R"(5:6 error: cannot use type 'i32' as value R"(5:6 error: cannot use type 'i32' as value
7:8 note: are you missing '()' for type initializer?)"}, 7:8 note: are you missing '()' for type initializer?)"},
{Def::kTypeAlias, Use::kVariableType, kPass}, {Def::kTypeAlias, Use::kVariableType, kPass},
{Def::kTypeAlias, Use::kUnaryOp,
R"(5:6 error: cannot use type 'i32' as value
7:8 note: are you missing '()' for type initializer?)"},
{Def::kVariable, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, {Def::kVariable, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
{Def::kVariable, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kVariable, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kVariable, Use::kBinaryOp, kPass},
{Def::kVariable, Use::kCallStmt, {Def::kVariable, Use::kCallStmt,
R"(5:6 error: cannot use const 'VARIABLE' as call target R"(5:6 error: cannot use const 'VARIABLE' as call target
1:2 note: 'VARIABLE' declared here)"}, 1:2 note: 'VARIABLE' declared here)"},
@ -314,6 +362,7 @@ INSTANTIATE_TEST_SUITE_P(
{Def::kVariable, Use::kVariableType, {Def::kVariable, Use::kVariableType,
R"(5:6 error: cannot use const 'VARIABLE' as type R"(5:6 error: cannot use const 'VARIABLE' as type
1:2 note: 'VARIABLE' declared here)"}, 1:2 note: 'VARIABLE' declared here)"},
{Def::kVariable, Use::kUnaryOp, kPass},
})); }));
} // namespace } // namespace

View File

@ -2971,6 +2971,9 @@ sem::ValueExpression* Resolver::MemberAccessor(const ast::MemberAccessorExpressi
sem::ValueExpression* Resolver::Binary(const ast::BinaryExpression* expr) { sem::ValueExpression* Resolver::Binary(const ast::BinaryExpression* expr) {
const auto* lhs = sem_.GetVal(expr->lhs); const auto* lhs = sem_.GetVal(expr->lhs);
const auto* rhs = sem_.GetVal(expr->rhs); const auto* rhs = sem_.GetVal(expr->rhs);
if (!lhs || !rhs) {
return nullptr;
}
auto* lhs_ty = lhs->Type()->UnwrapRef(); auto* lhs_ty = lhs->Type()->UnwrapRef();
auto* rhs_ty = rhs->Type()->UnwrapRef(); auto* rhs_ty = rhs->Type()->UnwrapRef();
@ -3047,10 +3050,10 @@ sem::ValueExpression* Resolver::Binary(const ast::BinaryExpression* expr) {
sem::ValueExpression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) { sem::ValueExpression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
const auto* expr = sem_.GetVal(unary->expr); const auto* expr = sem_.GetVal(unary->expr);
auto* expr_ty = expr->Type(); if (!expr) {
if (!expr_ty) {
return nullptr; return nullptr;
} }
auto* expr_ty = expr->Type();
const type::Type* ty = nullptr; const type::Type* ty = nullptr;
const sem::Variable* root_ident = nullptr; const sem::Variable* root_ident = nullptr;