cpp: allow casting C++ struct reference types to C types
This is safe because the C++ layout is static_assert'ed to be the
same as the C layout. It removes bad-looking reinterpret_cast
from application code.
Mutable reference casts are not allowed. This is because:
- Some C++ structs have RAII objects in them. Casting to C and
then changing the members could cause unexpected lifetime
changes
- Structs with "free members" functions only get const conversion
operators. This is because output structs like this have RAII data
which should not be mutated. The C structs do not have
const-qualified members, so conversion to a mutable C struct would
be unsafe.
Bug: chromium:40195122
Change-Id: I18cd06b04da2ea34803f517e2b640ceaaba408af
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/185966
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/generator/templates/api_cpp.h b/generator/templates/api_cpp.h
index d2ed0de..9790a50 100644
--- a/generator/templates/api_cpp.h
+++ b/generator/templates/api_cpp.h
@@ -336,6 +336,8 @@
inline {{as_cppType(type.name)}}({{as_cppType(type.name)}}&&);
inline {{as_cppType(type.name)}}& operator=({{as_cppType(type.name)}}&&);
{% endif %}
+ inline operator const {{as_cType(type.name)}}&() const noexcept;
+
{% if type.extensible %}
ChainedStruct{{Out}} {{const}} * nextInChain = nullptr;
{% endif %}
@@ -411,6 +413,10 @@
}
{% endif %}
+ {{CppType}}::operator const {{as_cType(type.name)}}&() const noexcept {
+ return *reinterpret_cast<const {{as_cType(type.name)}}*>(this);
+ }
+
static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
{% if type.extensible %}