mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-15 03:41:34 +00:00
resolver: Validate storage class for var initializers
Bug: chromium:1243418 Change-Id: Ia0cec7d77767783b2a3b85400a03c805b51699d8 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/62942 Commit-Queue: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
e9fdd50443
commit
231648c6a9
@ -520,15 +520,16 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto storage_class = var->declared_storage_class();
|
auto storage_class = var->declared_storage_class();
|
||||||
if (storage_class == ast::StorageClass::kNone) {
|
if (storage_class == ast::StorageClass::kNone && !var->is_const()) {
|
||||||
if (storage_type->UnwrapRef()->is_handle()) {
|
// No declared storage class. Infer from usage / type.
|
||||||
|
if (kind == VariableKind::kLocal) {
|
||||||
|
storage_class = ast::StorageClass::kFunction;
|
||||||
|
} else if (storage_type->UnwrapRef()->is_handle()) {
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
|
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
|
||||||
// If the store type is a texture type or a sampler type, then the
|
// If the store type is a texture type or a sampler type, then the
|
||||||
// variable declaration must not have a storage class decoration. The
|
// variable declaration must not have a storage class decoration. The
|
||||||
// storage class will always be handle.
|
// storage class will always be handle.
|
||||||
storage_class = ast::StorageClass::kUniformConstant;
|
storage_class = ast::StorageClass::kUniformConstant;
|
||||||
} else if (kind == VariableKind::kLocal && !var->is_const()) {
|
|
||||||
storage_class = ast::StorageClass::kFunction;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,8 +546,9 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
|
|||||||
builder_->create<sem::Reference>(storage_type, storage_class, access);
|
builder_->create<sem::Reference>(storage_type, storage_class, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rhs_type && !ValidateVariableConstructor(var, storage_type, type_name,
|
if (rhs_type &&
|
||||||
rhs_type, rhs_type_name)) {
|
!ValidateVariableConstructor(var, storage_class, storage_type, type_name,
|
||||||
|
rhs_type, rhs_type_name)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,6 +575,7 @@ ast::Access Resolver::DefaultAccessForStorageClass(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Resolver::ValidateVariableConstructor(const ast::Variable* var,
|
bool Resolver::ValidateVariableConstructor(const ast::Variable* var,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
const sem::Type* storage_type,
|
const sem::Type* storage_type,
|
||||||
const std::string& type_name,
|
const std::string& type_name,
|
||||||
const sem::Type* rhs_type,
|
const sem::Type* rhs_type,
|
||||||
@ -587,6 +590,26 @@ bool Resolver::ValidateVariableConstructor(const ast::Variable* var,
|
|||||||
var->source());
|
var->source());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!var->is_const()) {
|
||||||
|
switch (storage_class) {
|
||||||
|
case ast::StorageClass::kPrivate:
|
||||||
|
case ast::StorageClass::kFunction:
|
||||||
|
break; // Allowed an initializer
|
||||||
|
default:
|
||||||
|
// https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
|
||||||
|
// Optionally has an initializer expression, if the variable is in the
|
||||||
|
// private or function storage classes.
|
||||||
|
AddError("var of storage class '" +
|
||||||
|
std::string(ast::str(storage_class)) +
|
||||||
|
"' cannot have an initializer. var initializers are only "
|
||||||
|
"supported for the storage classes "
|
||||||
|
"'private' and 'function'",
|
||||||
|
var->source());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +306,7 @@ class Resolver {
|
|||||||
bool ValidateSwitch(const ast::SwitchStatement* s);
|
bool ValidateSwitch(const ast::SwitchStatement* s);
|
||||||
bool ValidateVariable(const VariableInfo* info);
|
bool ValidateVariable(const VariableInfo* info);
|
||||||
bool ValidateVariableConstructor(const ast::Variable* var,
|
bool ValidateVariableConstructor(const ast::Variable* var,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
const sem::Type* storage_type,
|
const sem::Type* storage_type,
|
||||||
const std::string& type_name,
|
const std::string& type_name,
|
||||||
const sem::Type* rhs_type,
|
const sem::Type* rhs_type,
|
||||||
|
@ -341,6 +341,18 @@ TEST_F(ResolverVarLetValidationTest, NonConstructibleType_InferredType) {
|
|||||||
"12:34 error: function variable must have a constructible type");
|
"12:34 error: function variable must have a constructible type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverVarLetValidationTest, InvalidStorageClassForInitializer) {
|
||||||
|
// var<workgroup> v : f32 = 1.23;
|
||||||
|
Global(Source{{12, 34}}, "v", ty.f32(), ast::StorageClass::kWorkgroup,
|
||||||
|
Expr(1.23f));
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: var of storage class 'workgroup' cannot have "
|
||||||
|
"an initializer. var initializers are only supported for the "
|
||||||
|
"storage classes 'private' and 'function'");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
Loading…
x
Reference in New Issue
Block a user