Skip to content

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

@SimonEbner

Description

@SimonEbner

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());
}

Metadata

Metadata

Assignees

Labels

confirmedsolution: proposed fixa fix for the issue has been proposed and waits for confirmation

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions