Skip to content

Fix MSVC build#5508

Closed
svenk177 wants to merge 4 commits intogoogle:masterfrom
svenk177:fix-msvc-build
Closed

Fix MSVC build#5508
svenk177 wants to merge 4 commits intogoogle:masterfrom
svenk177:fix-msvc-build

Conversation

@svenk177
Copy link
Copy Markdown
Contributor

@svenk177 svenk177 commented Sep 5, 2019

This PR should (hopefully) fix the currently failing build on Visual Studio.
This got overlooked in my last PR (#5491), as the build job was never actually executed for some reason.

Copy link
Copy Markdown
Collaborator

@aardappel aardappel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix.. though if all this does is allow structs to be passed to these functions, it is still incorrect. Please see discussion at the end of #5313
@vglavnyy

#endif

template<typename T> T EndianSwap(T t) {
template<typename T> T EndianSwap(const T &t) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change worries me.. this function is meant for scalars only, and if any compiler anywhere compiles this more slowly than just T, we can't have it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With just T MSVC doesn't seem to propagate the __declspec(align()) attribute if I understand the issue correctly. Making it a const-ref bypasses this.

} else if (sizeof(T) == 2) {
union { T t; uint16_t i; } u;
u.t = t;
union { T t; uint16_t i; } u = { t };
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting.. making the assignment an initialization makes the error go away?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this change MSVC reports: 'flatbuffers::EndianSwap::<unnamed-type-u>::<unnamed-type-u>(void)': attempting to reference a deleted function

Note EndianSwap is only used on big endian machines by EndianScalar, so I commented the #if FLATBUFFERS_LITTLEENDIAN to test it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but can we then make EndianScalar just T again? EndianSwap is fine since it is only ever used on big endian, but EndianScalar should be as obvious a no-op as possible for more naive compilers.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with WriteScalar

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately the const-ref in WriteScalar is required otherwise C2719 't': formal parameter with requested alignment of 8 won't be aligned will persist, as the if-path will be evaluated even if it is not used.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @vglavnyy, lets try the original plan then. EndianScalar (and to some extent WriteScalar) are such core functions in FlatBuffers, called absolutely everywhere, we can't afford the risk that this will regress performance on some compilers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is another issue. The Get function uses ReadScalar via IndirectHelper. This of course will break on big endian machines. I thought about intorducing a GetStruct function, but then iterators and operator[] will be unusable in the current form.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would that not work? IndirectHelper's 3rd case is for struct. It's the same code as for Vector which should work :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSVC is probably weak when it comes to template specialization :(
I'm getting:

error C2719: 't': formal parameter with requested alignment of 8 won't be aligned
note: see reference to function template instantiation 'T flatbuffers::EndianScalar<T>(T)' being compiled
note: while compiling class template member function 'MyGame::Example::NestedStruct flatbuffers::IndirectHelper<T>::Read(const uint8_t *,flatbuffers::uoffset_t)'
note: see reference to function template instantiation 'MyGame::Example::NestedStruct flatbuffers::IndirectHelper<T>::Read(const uint8_t *,flatbuffers::uoffset_t)' being compiled`
note: see reference to class template instantiation 'flatbuffers::IndirectHelper<T>' being compiled
note: see reference to class template instantiation 'flatbuffers::Array<MyGame::Example::NestedStruct,2>' being compiled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, the best solution will be split Array class into two independent classes:
They have different iterators and Read/Write methods.

  1. Array<T> - current implementation.
  2. ArrayOfStruct<S> - a new implementation.

@aardappel ?

@svenk177
Copy link
Copy Markdown
Contributor Author

svenk177 commented Sep 6, 2019

I was probably too quick by going the cure the symptom not the disease route!
I like the proposal by @vglavnyy in #5313 allowing structs to be passed to Mutate.
The other changes are still required though, as MSVC will evaluate the if path anyway and fail to compile it.

EDIT: Seems like VS2013 does not like the solution. Probably we have to use GetMutablePointer or introduce MutateStruct. Alternatively we can inhibit the warning.

vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 15, 2019
vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 15, 2019
vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 15, 2019
@vglavnyy
Copy link
Copy Markdown
Contributor

@aardappel, @svenk177
I have tested another solution with Array specializations (all CI passed).
vglavnyy@857b97a

I can make PR if this solution is fully acceptable.
Or @svenk177 can reuse it in this PR.

@svenk177
Copy link
Copy Markdown
Contributor Author

@vglavnyy This looks great. I thought about a similar solution, but was worried that the code will explode. Now that I look at it, it doesn't seem so bad :)
@aardappel I think we should use this 👍

@vglavnyy
Copy link
Copy Markdown
Contributor

It is possible to fold these three Array into two or one classes with the help of std::conditional and std::enable_if but Android build doesn't have full-featured STL <traits>.

@aardappel
Copy link
Copy Markdown
Collaborator

Yeah, it's a shame there's some duplication there, but if this is more solid, let's use @vglavnyy's implementation.

vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 17, 2019
@vglavnyy
Copy link
Copy Markdown
Contributor

@aardappel
I wrote a new version without code duplication.
But I'm not sure that this templated version is better than the duplication.
The error messages from this SFINAE code will be intimidating.
Make PR with the first variant?

@aardappel
Copy link
Copy Markdown
Collaborator

@vglavnyy I'd be fine with non-duplicated one as well, if it passes CI. But, in the end, your call, if the duplicated version is easier to use, that's ok too.

vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 20, 2019
vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 20, 2019
vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 20, 2019
vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 20, 2019
…e#5508)

- Tag dispatching is used for implicit specialization
- Array<scalar> and Array<struct> have different iterators and accessors
- Array<scalar> and Array<struct> have different Mutate() methods
vglavnyy added a commit to vglavnyy/flatbuffers that referenced this pull request Sep 23, 2019
…e#5508)

- Tag dispatching is used for implicit specialization
- Array<scalar> and Array<struct> have different iterators and accessors
- Array<scalar> and Array<struct> have different Mutate() methods
aardappel pushed a commit that referenced this pull request Sep 23, 2019
* Draft with Array specialization (#5508)

* Array specialization + SFINAE to fold copy-paste (#5508)

* Add implicit specialization of Array<scalar> and Array<struct> (#5508)

- Tag dispatching is used for implicit specialization
- Array<scalar> and Array<struct> have different iterators and accessors
- Array<scalar> and Array<struct> have different Mutate() methods

* Add implicit specialization of Array<scalar> and Array<struct> (#5508)

- Tag dispatching is used for implicit specialization
- Array<scalar> and Array<struct> have different iterators and accessors
- Array<scalar> and Array<struct> have different Mutate() methods
@svenk177 svenk177 closed this Sep 23, 2019
LuckyRu pushed a commit to LuckyRu/flatbuffers that referenced this pull request Oct 2, 2020
…5526)

* Draft with Array specialization (google#5508)

* Array specialization + SFINAE to fold copy-paste (google#5508)

* Add implicit specialization of Array<scalar> and Array<struct> (google#5508)

- Tag dispatching is used for implicit specialization
- Array<scalar> and Array<struct> have different iterators and accessors
- Array<scalar> and Array<struct> have different Mutate() methods

* Add implicit specialization of Array<scalar> and Array<struct> (google#5508)

- Tag dispatching is used for implicit specialization
- Array<scalar> and Array<struct> have different iterators and accessors
- Array<scalar> and Array<struct> have different Mutate() methods
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants