Remove SK_OFFSETOF from SkTypes, clean up offsetof usage.
The motivation for this was to remove SK_OFFSETOF from SkTypes, but
this CL is mostly about cleaning up our use of offsetof generally.
SK_OFFSETOF is removed to SkTypes and added to the two places it is
actually used (for the non standard behavior of finding the offset of
fields in types which are not standard layout).
Older versions of gcc required POD for offsetof to be used without
warning. Newer versions require the more relaxed standard layout.
Now that we no longer build on older versions of gcc, remove the
old warning suppressions.
PODMatrix is renamed to AggregateMatrix. SkMatrix is already POD
(trivial and standard layout). The PODMatrix name implies that the
POD-ness is needed for the offsetof, but it is actually the aggregate
attribute which is needed for compile time constant initialization.
This makes it more obvious that this can be revisited after we can
rely on constexpr constructors.
This also adds skstd::declval since this allows removal of existing
awkward code which casts a constant to a pointer to find the size of
a field.
TBR=reed@google.com
No API change, only removes unused macro.
Review URL: https://codereview.chromium.org/1309523003
diff --git a/gyp/common_conditions.gypi b/gyp/common_conditions.gypi
index 83b634c..e1da050 100644
--- a/gyp/common_conditions.gypi
+++ b/gyp/common_conditions.gypi
@@ -228,7 +228,6 @@
'-std=c++11',
'-fno-rtti',
'-Wnon-virtual-dtor',
- '-Wno-invalid-offsetof', # GCC <4.6 is old-school strict about what is POD.
],
'conditions': [
[ 'skia_fast', { 'cflags': [ '<@(skia_fast_flags)' ] }],
@@ -498,7 +497,6 @@
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'NO', # -fvisibility-inlines-hidden
'GCC_CW_ASM_SYNTAX': 'NO', # remove -fasm-blocks
'GCC_ENABLE_PASCAL_STRINGS': 'NO', # remove -mpascal-strings
- 'GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO': 'NO', # -Wno-invalid-offsetof
'WARNING_CFLAGS': [
'-Wall',
'-Wextra',
@@ -546,7 +544,6 @@
'IPHONEOS_DEPLOYMENT_TARGET': '<(ios_sdk_version)',
'SDKROOT': 'iphoneos',
'TARGETED_DEVICE_FAMILY': '1,2',
- 'GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO': 'NO', # -Wno-invalid-offsetof
'OTHER_CPLUSPLUSFLAGS': [
'-std=c++0x',
'-fvisibility=hidden',
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
index bed33fb8..8eeffb5 100644
--- a/include/core/SkTypes.h
+++ b/include/core/SkTypes.h
@@ -285,9 +285,6 @@
}
//////////////////////////////////////////////////////////////////////////////
-#ifndef SK_OFFSETOF
- #define SK_OFFSETOF(type, field) (size_t)((char*)&(((type*)1)->field) - (char*)1)
-#endif
/** Returns the number of entries in an array (not a pointer) */
template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
diff --git a/include/private/SkTLogic.h b/include/private/SkTLogic.h
index 2710d6d..f93f63b 100644
--- a/include/private/SkTLogic.h
+++ b/include/private/SkTLogic.h
@@ -112,16 +112,39 @@
namespace skstd {
-/** SkTRemoveReference<T>::type is the type of T with any top-level lvalue or rvalue removed. */
-template <typename T> struct remove_reference { typedef T type; };
-template <typename T> struct remove_reference<T&> { typedef T type; };
-template <typename T> struct remove_reference<T&&> { typedef T type; };
+template <typename T> struct remove_const { using type = T; };
+template <typename T> struct remove_const<const T> { using type = T; };
+template <typename T> using remove_const_t = typename remove_const<T>::type;
+
+template <typename T> struct remove_volatile { using type = T; };
+template <typename T> struct remove_volatile<volatile T> { using type = T; };
+template <typename T> using remove_volatile_t = typename remove_volatile<T>::type;
+
+template <typename T> struct remove_cv { using type = remove_volatile_t<remove_const_t<T>>; };
+template <typename T> using remove_cv_t = typename remove_cv<T>::type;
+
+template <typename T> struct remove_reference { using type = T; };
+template <typename T> struct remove_reference<T&> { using type = T; };
+template <typename T> struct remove_reference<T&&> { using type = T; };
template <typename T> using remove_reference_t = typename remove_reference<T>::type;
-/** SkTIsLValueReference<T>::value is true if the type T is an lvalue reference. */
+template <typename T, typename U> struct is_same : SkFalse {};
+template <typename T> struct is_same<T, T> : SkTrue {};
+
+template <typename T> struct is_void : is_same<void, remove_cv_t<T>> {};
+
+template <typename T> struct is_reference : SkFalse {};
+template <typename T> struct is_reference<T&> : SkTrue {};
+template <typename T> struct is_reference<T&&> : SkTrue {};
+
template <typename T> struct is_lvalue_reference : SkFalse {};
template <typename T> struct is_lvalue_reference<T&> : SkTrue {};
+template <typename T> struct add_rvalue_reference {
+ using type = typename SkTIf_c<is_void<T>::value || is_reference<T>::value, T, T&&>::type;
+};
+template <typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
+
} // namespace skstd
/**
diff --git a/include/private/SkTemplates.h b/include/private/SkTemplates.h
index 17dcd59..afab0ef 100644
--- a/include/private/SkTemplates.h
+++ b/include/private/SkTemplates.h
@@ -43,6 +43,8 @@
return static_cast<T&&>(t);
}
+template <typename T> add_rvalue_reference_t<T> declval();
+
} // namespace skstd
///@{
diff --git a/include/svg/parser/SkSVGAttribute.h b/include/svg/parser/SkSVGAttribute.h
index 940ca5a..5ba2916 100644
--- a/include/svg/parser/SkSVGAttribute.h
+++ b/include/svg/parser/SkSVGAttribute.h
@@ -20,7 +20,8 @@
};
#ifndef SK_OFFSETOF
-#define SK_OFFSETOF(a, b) (((size_t) (&(((a*) 1)->b)))-1)
+ // This is offsetof for types which are not standard layout.
+ #define SK_OFFSETOF(type, field) (size_t)((char*)&(((type*)1024)->field) - (char*)1024)
#endif
#ifdef SK_DEBUG
diff --git a/src/animator/SkDisplayInclude.cpp b/src/animator/SkDisplayInclude.cpp
index 860264e..023b391 100644
--- a/src/animator/SkDisplayInclude.cpp
+++ b/src/animator/SkDisplayInclude.cpp
@@ -11,13 +11,6 @@
#include "SkAnimateMaker.h"
#include "SkAnimator.h"
-#if 0
-#undef SK_MEMBER
-#define SK_MEMBER(_member, _type) \
- { #_member, SK_OFFSETOF(BASE_CLASS::_A, _member), SkType_##_type, \
- sizeof(((BASE_CLASS::_A*) 0)->_member) / sizeof(SkScalar) }
-#endif
-
#if SK_USE_CONDENSED_INFO == 0
const SkMemberInfo SkInclude::fInfo[] = {
diff --git a/src/animator/SkMemberInfo.h b/src/animator/SkMemberInfo.h
index e07c322..3588da2 100644
--- a/src/animator/SkMemberInfo.h
+++ b/src/animator/SkMemberInfo.h
@@ -104,13 +104,18 @@
// static bool SetValue(void* value, const char* name, SkDisplayTypes , int count);
};
+#ifndef SK_OFFSETOF
+ // This is offsetof for types which are not standard layout.
+ #define SK_OFFSETOF(type, field) (size_t)((char*)&(((type*)1024)->field) - (char*)1024)
+#endif
+
#define SK_MEMBER(_member, _type) \
{ #_member, SK_OFFSETOF(BASE_CLASS, _member), SkType_##_type, \
- sizeof(((BASE_CLASS*) 1)->_member) / sizeof(SkScalar) }
+ sizeof(skstd::declval<BASE_CLASS>()._member) / sizeof(SkScalar) }
#define SK_MEMBER_ALIAS(_member, _alias, _type) \
{ #_member, SK_OFFSETOF(BASE_CLASS, _alias), SkType_##_type, \
- sizeof(((BASE_CLASS*) 1)->_alias) / sizeof(SkScalar) }
+ sizeof(skstd::declval<BASE_CLASS>()._alias) / sizeof(SkScalar) }
#define SK_MEMBER_ARRAY(_member, _type) \
{ #_member, SK_OFFSETOF(BASE_CLASS, _member), SkType_Array, \
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index e030560..f5e4e80 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1586,33 +1586,34 @@
namespace {
-struct PODMatrix {
+// SkMatrix is C++11 POD (trivial and standard-layout), but not aggregate (it has private fields).
+struct AggregateMatrix {
SkScalar matrix[9];
uint32_t typemask;
const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); }
};
-static_assert(sizeof(PODMatrix) == sizeof(SkMatrix), "PODMatrixSizeMismatch");
+static_assert(sizeof(AggregateMatrix) == sizeof(SkMatrix), "AggregateMatrix size mismatch.");
} // namespace
const SkMatrix& SkMatrix::I() {
- static_assert(offsetof(SkMatrix, fMat) == offsetof(PODMatrix, matrix), "BadfMat");
- static_assert(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), "BadfTypeMask");
+ static_assert(offsetof(SkMatrix,fMat) == offsetof(AggregateMatrix,matrix), "fMat");
+ static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
- static const PODMatrix identity = { {SK_Scalar1, 0, 0,
- 0, SK_Scalar1, 0,
- 0, 0, SK_Scalar1 },
- kIdentity_Mask | kRectStaysRect_Mask};
+ static const AggregateMatrix identity = { {SK_Scalar1, 0, 0,
+ 0, SK_Scalar1, 0,
+ 0, 0, SK_Scalar1 },
+ kIdentity_Mask | kRectStaysRect_Mask};
SkASSERT(identity.asSkMatrix().isIdentity());
return identity.asSkMatrix();
}
const SkMatrix& SkMatrix::InvalidMatrix() {
- static_assert(offsetof(SkMatrix, fMat) == offsetof(PODMatrix, matrix), "BadfMat");
- static_assert(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), "BadfTypeMask");
+ static_assert(offsetof(SkMatrix,fMat) == offsetof(AggregateMatrix,matrix), "fMat");
+ static_assert(offsetof(SkMatrix,fTypeMask) == offsetof(AggregateMatrix,typemask), "fTypeMask");
- static const PODMatrix invalid =
+ static const AggregateMatrix invalid =
{ {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
SK_ScalarMax, SK_ScalarMax, SK_ScalarMax },