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

clang-tidy: Call to virtual function during construction #1046

Closed
SimonEbner opened this issue Apr 9, 2018 · 3 comments
Closed

clang-tidy: Call to virtual function during construction #1046

SimonEbner opened this issue Apr 9, 2018 · 3 comments
Assignees
Labels
confirmed solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Milestone

Comments

@SimonEbner
Copy link

SimonEbner commented Apr 9, 2018

Bug Report

  • What is the issue you have?
    When running clang-tidy on a minimal example I get the warning Call to virtual function during construction [clang-analyzer-optin.cplusplus.VirtualCall]

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

  1. Clone the repo with tag v3.1.2
  2. Create a cpp file:
#include <nlohmann/json.hpp>

int main()
{
    std::ifstream in("a.json");
    nlohmann::json j;
    in >> j;
}
  1. Run clang-tidy on it: clang-tidy b.cc -- -I.
  • What is the expected behavior?
    No warnings emitted

  • And what is the actual behavior instead?
    One warning emitted by the parsing of the ifstream (full output at the end)

  • Which compiler and operating system are you using? Is it a supported compiler?

 % lsb_release -a 
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.3 LTS
Release:	16.04
Codename:	xenial
% clang --version
clang version 7.0.0 (https://git.llvm.org/git/clang 7f273fa6df66a8dfbfa2170d5bd307d9f426fd1a) (https://git.llvm.org/git/llvm 0a9e4fe67e24fe921d2ed544471bbb53d579f790)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
% clang-tidy --version
LLVM (http://llvm.org/):
  LLVM version 7.0.0svn
  Optimized build with assertions.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: broadwell
  • Did you use a released version of the library or the version from the develop branch?
    I used tag v3.1.2

This is the full output:

./nlohmann/detail/input/input_adapters.hpp:74:18: warning: Call to virtual function during construction [clang-analyzer-optin.cplusplus.VirtualCall]
        if ((c = get_character()) == 0xEF)
                 ^
/home/simon/test/b.cc:8:5: note: Calling 'operator>>'
    in >> j;
    ^
./nlohmann/json.hpp:6135:16: note: Calling constructor for 'input_adapter'
        parser(detail::input_adapter(i)).parse(false, j);
               ^
./nlohmann/detail/input/input_adapters.hpp:175:14: note: Calling 'make_shared'
        : ia(std::make_shared<input_stream_adapter>(i)) {}
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:635:14: note: Calling 'allocate_shared'
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:619:14: note: Calling constructor for 'shared_ptr'
      return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:319:4: note: Calling constructor for '__shared_ptr'
        : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:1096:14: note: Calling constructor for '__shared_count'
        : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
                    ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:617:18: note: Calling constructor for '_Sp_counted_ptr_inplace'
          ::new (__mem) _Sp_cp_type(std::move(__a),
                        ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:522:4: note: Calling 'allocator_traits::construct'
          allocator_traits<_Alloc>::construct(__a, _M_ptr(),
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/alloc_traits.h:530:4: note: Calling 'new_allocator::construct'
        { __a.construct(__p, std::forward<_Args>(__args)...); }
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/ext/new_allocator.h:120:23: note: Calling constructor for 'input_stream_adapter'
        { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
                             ^
./nlohmann/detail/input/input_adapters.hpp:74:18: note: This constructor of an object of type 'input_stream_adapter' has not returned when the virtual method was called
        if ((c = get_character()) == 0xEF)
                 ^
./nlohmann/detail/input/input_adapters.hpp:74:18: note: Call to virtual function during construction
./nlohmann/detail/input/input_adapters.hpp:76:22: warning: Call to virtual function during construction [clang-analyzer-optin.cplusplus.VirtualCall]
            if ((c = get_character()) == 0xBB)
                     ^
/home/simon/test/b.cc:8:5: note: Calling 'operator>>'
    in >> j;
    ^
./nlohmann/json.hpp:6135:16: note: Calling constructor for 'input_adapter'
        parser(detail::input_adapter(i)).parse(false, j);
               ^
./nlohmann/detail/input/input_adapters.hpp:175:14: note: Calling 'make_shared'
        : ia(std::make_shared<input_stream_adapter>(i)) {}
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:635:14: note: Calling 'allocate_shared'
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:619:14: note: Calling constructor for 'shared_ptr'
      return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:319:4: note: Calling constructor for '__shared_ptr'
        : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:1096:14: note: Calling constructor for '__shared_count'
        : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
                    ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:617:18: note: Calling constructor for '_Sp_counted_ptr_inplace'
          ::new (__mem) _Sp_cp_type(std::move(__a),
                        ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:522:4: note: Calling 'allocator_traits::construct'
          allocator_traits<_Alloc>::construct(__a, _M_ptr(),
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/alloc_traits.h:530:4: note: Calling 'new_allocator::construct'
        { __a.construct(__p, std::forward<_Args>(__args)...); }
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/ext/new_allocator.h:120:23: note: Calling constructor for 'input_stream_adapter'
        { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
                             ^
./nlohmann/detail/input/input_adapters.hpp:74:13: note: Assuming the condition is true
        if ((c = get_character()) == 0xEF)
            ^
./nlohmann/detail/input/input_adapters.hpp:74:9: note: Taking true branch
        if ((c = get_character()) == 0xEF)
        ^
./nlohmann/detail/input/input_adapters.hpp:76:22: note: This constructor of an object of type 'input_stream_adapter' has not returned when the virtual method was called
            if ((c = get_character()) == 0xBB)
                     ^
./nlohmann/detail/input/input_adapters.hpp:76:22: note: Call to virtual function during construction
./nlohmann/detail/input/input_adapters.hpp:78:26: warning: Call to virtual function during construction [clang-analyzer-optin.cplusplus.VirtualCall]
                if ((c = get_character()) == 0xBF)
                         ^
/home/simon/test/b.cc:8:5: note: Calling 'operator>>'
    in >> j;
    ^
./nlohmann/json.hpp:6135:16: note: Calling constructor for 'input_adapter'
        parser(detail::input_adapter(i)).parse(false, j);
               ^
./nlohmann/detail/input/input_adapters.hpp:175:14: note: Calling 'make_shared'
        : ia(std::make_shared<input_stream_adapter>(i)) {}
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:635:14: note: Calling 'allocate_shared'
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:619:14: note: Calling constructor for 'shared_ptr'
      return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,
             ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr.h:319:4: note: Calling constructor for '__shared_ptr'
        : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:1096:14: note: Calling constructor for '__shared_count'
        : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
                    ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:617:18: note: Calling constructor for '_Sp_counted_ptr_inplace'
          ::new (__mem) _Sp_cp_type(std::move(__a),
                        ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/shared_ptr_base.h:522:4: note: Calling 'allocator_traits::construct'
          allocator_traits<_Alloc>::construct(__a, _M_ptr(),
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/alloc_traits.h:530:4: note: Calling 'new_allocator::construct'
        { __a.construct(__p, std::forward<_Args>(__args)...); }
          ^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/ext/new_allocator.h:120:23: note: Calling constructor for 'input_stream_adapter'
        { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
                             ^
./nlohmann/detail/input/input_adapters.hpp:74:13: note: Assuming the condition is true
        if ((c = get_character()) == 0xEF)
            ^
./nlohmann/detail/input/input_adapters.hpp:74:9: note: Taking true branch
        if ((c = get_character()) == 0xEF)
        ^
./nlohmann/detail/input/input_adapters.hpp:76:17: note: Assuming the condition is true
            if ((c = get_character()) == 0xBB)
                ^
./nlohmann/detail/input/input_adapters.hpp:76:13: note: Taking true branch
            if ((c = get_character()) == 0xBB)
            ^
./nlohmann/detail/input/input_adapters.hpp:78:26: note: This constructor of an object of type 'input_stream_adapter' has not returned when the virtual method was called
                if ((c = get_character()) == 0xBF)
                         ^
./nlohmann/detail/input/input_adapters.hpp:78:26: note: Call to virtual function during construction

Maybe related to #94 ?

P.s. the warning is not triggered if I use the json::parse explicitely like so:

int main()
{
    std::ifstream t("file.txt");
    std::stringstream buffer;
    buffer << t.rdbuf();
    auto j = nlohmann::json::parse(buffer.str());
}
@nlohmann
Copy link
Owner

Thanks for reporting!

This issue will be fixed with #971. There, the skipping of the BOM (this is the code where get_character is called) will be moved into the lexer. I hence mark the issue as "proposed fix".

The reason that the issue is not triggered by calling json::parse(buffer.str()) is that it uses a different input adapter.

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Apr 10, 2018
@nlohmann nlohmann self-assigned this Apr 10, 2018
@stale
Copy link

stale bot commented May 10, 2018

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 May 10, 2018
@stale stale bot closed this as completed May 17, 2018
@nlohmann nlohmann added this to the Release 3.1.3 milestone May 27, 2018
@nlohmann nlohmann removed the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label May 27, 2018
@nlohmann
Copy link
Owner

Fixed with #971.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants