Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assignment (using value()) to nonexistent element behaves differently on Xcode 8 vs Xcode 10 #1758

Closed
sbroberg opened this issue Sep 19, 2019 · 5 comments
Labels
kind: bug state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated

Comments

@sbroberg
Copy link

sbroberg commented Sep 19, 2019

  • What is the issue you have?

The following code runs successfully when compiled with Xcode 10, but throws an exception ("[json.exception.type_error.302] type must be number, but is null") when compiled with Xcode 8:

    json _j;
    _j["present"] = 5;
    string key    = "count";

    _j[key] = _j.value(key, 0) + 1;

I'm not sure if this is the fault of the your library, or due to how the two compilers deal with code optimization (although the behavior is consistent for a particular compiler regardless of the -O flag). The exception is occurring because at the time the value() function is executing, there is already an element "count" in _j with the value of null. Presumably this is because the compiler is invoking the code to prep the left-hand-side prior to calling the function in Xcode 8, but waiting until after in Xcode 10.

  • Please describe the steps to reproduce the issue. Can you provide a small but working code example?

See above. The compile line used to build this is:

Xcode 10:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
  -I/Users/stebro/Demo \
  -I/Users/stebro/Demo/include \
  -I/usr/local/include \
  -I/Users/stebro/Demo/3rdParty/googletest-master/googletest/include \
  -O1 \
  -isysroot \
  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk \
  -Werror \
  -Wall \
  -Wextra \
  -Wpedantic \
  -std=gnu++11 \
  -o \
  CMakeFiles/DemoTest.dir/Demo_test.cpp.o \
  -c \
  /Users/stebro/Demo/test/Demo_test.cpp

Xcode 8:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ --version
'Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
  -I/Users/stebro/Demo \
  -I/Users/stebro/Demo/include \
  -I/Users/stebro/Demo/3rdParty/googletest-master/googletest/include \
  -O1 \
  -Werror \
  -Wall \
  -Wextra \
  -Wpedantic \
  -std=gnu++11 \
  -o \
  CMakeFiles/Demo.dir/Demo_test.cpp.o \
  -c \
  /Users/stebro/Demo/test/Demo_test.cpp
  • What is the expected behavior?

Either both builds should throw or both should pass. My personal opinion is that an element with a value of null should return the default value when interrogated with value(key, default), as it's somewhat confusing why "foo": null is different from no foo at all. As someone who's worked with relational databases for decades, I'm familiar with the can of worms that's opened once you start allowing nulls to become part of your data, so I sympathize.

For the time being, I've written my own templated wrapper function around value() that basically does this, and works in both compilers, but I realize that this may not be the contract you wish to enforce:

    template < typename T >
    T value(const json &_j, const string &key, const T &defaultValue) const
    {
        if (_j.is_null() || _j.find(key) == _j.end() || _j[key].is_null()) {
            return defaultValue;
        }
        else {
            return _j.value(key, defaultValue);
        }
    }
  • And what is the actual behavior instead?

See above

See above. They appear to be supported - you list clang-802.0.38 for Xcode 8, we're using clang-802.0.42.
OS for Xcode 10 is 10.14.6
OS for Xcode 8 is 10.12.4

  • Did you use a released version of the library or the version from the develop branch?

Released (version 3.6.1)

No compile errors; I haven't run the unit tests for your library.

@sbroberg sbroberg changed the title Assignment to nonexistent element behaves differently on Xcode 8 vs Xcode 10 Assignment (using value()) to nonexistent element behaves differently on Xcode 8 vs Xcode 10 Sep 19, 2019
@t-b
Copy link
Contributor

t-b commented Oct 16, 2019

@sbroberg See

# OSX / Clang
for the list of XCode versions we are are using for CI. How about proposing a PR which shows your breakage?

@sbroberg
Copy link
Author

When you say propose a PR, you mean a unit test?

I can certainly provide that, although as I mentiined, I think the difficulty lies in the contract of the function, and may be working as designed.

@t-b
Copy link
Contributor

t-b commented Oct 17, 2019

@sbroberg Yes I meant create a unit test and create a pull request from it. If two compilers don't give the same output it is usually a sign for an error.

@nlohmann
Copy link
Owner

nlohmann commented Nov 5, 2019

Any idea how to proceed here?

@stale
Copy link

stale bot commented Dec 5, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Dec 5, 2019
@stale stale bot closed this as completed Dec 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated
Projects
None yet
Development

No branches or pull requests

3 participants