Skip to content

GCC 14+ build warnings -Wtemplate-id-cdtor and -Walloc-size #19

@udickow

Description

@udickow

tst-template_cpp20_warning.cpp.txt

Building current kanzi with simply make kanzi on Fedora 42 Linux, i.e. using g++ 15.1.1 and the warning flags -Wall -Wextra, succeeds but with a lot of warnings.

The warnings are of two kinds:

  • -Wtemplate-id-cdtor that is easily fixed in the code and definitely should be
  • -Walloc-size that requires a lot more lines to be changed, debatable whether gcc ought to complain about this and whether to adapt to it

-Wtemplate-id-cdtor warnings

Excerpt:

.../kanzi-cpp/src$ date;\time make kanzi;date
søn 20 jul 10:11:45 CEST 2025
g++ -c -std=c++14 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti  Global.cpp -o obj/Global.o
g++ -c -std=c++14 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti  Event.cpp -o obj/Event.o
g++ -c -std=c++14 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti  entropy/EntropyUtils.cpp -o obj/entropy/EntropyUtils.o
g++ -c -std=c++14 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti  entropy/HuffmanCommon.cpp -o obj/entropy/HuffmanCommon.o
g++ -c -std=c++14 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti  entropy/CMPredictor.cpp -o obj/entropy/CMPredictor.o
g++ -c -std=c++14 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti  entropy/TPAQPredictor.cpp -o obj/entropy/TPAQPredictor.o
I fil inkluderet fra entropy/TPAQPredictor.hpp:24,
                 fra entropy/TPAQPredictor.cpp:16:
entropy/AdaptiveProbMap.hpp:35:35: advarsel: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
   35 |        LinearAdaptiveProbMap<RATE>(int n);
      |                                   ^
entropy/AdaptiveProbMap.hpp:35:35: bemærk: remove the »< >«
entropy/AdaptiveProbMap.hpp:37:8: advarsel: template-id not allowed for destructor in C++20 [-Wtemplate-id-cdtor]
   37 |        ~LinearAdaptiveProbMap<RATE>() { delete[] _data; }
      |        ^
entropy/AdaptiveProbMap.hpp:37:8: bemærk: remove the »< >«
entropy/AdaptiveProbMap.hpp:90:43: advarsel: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
   90 |        LogisticAdaptiveProbMap<FAST, RATE>(int n);
      |                                           ^
entropy/AdaptiveProbMap.hpp:90:43: bemærk: remove the »< >«
entropy/AdaptiveProbMap.hpp:92:8: advarsel: template-id not allowed for destructor in C++20 [-Wtemplate-id-cdtor]
   92 |        ~LogisticAdaptiveProbMap<FAST, RATE>() { delete[] _data; }
      |        ^
[...]

Other projects have also seen the new warnings, occuring since some gcc 14.x with -Wall, and changed their code due to that, see e.g. this OpenJDK comment

Your code is already aware of the potential issue and prepared for the fix, requiring changing as little as this line

#if __cplusplus >= 202002L // simple-template-id in ctors and dtors rejected in C++20

and the identical line 85 further down in the file.

Maybe even delete the #if's with their old-style #else-clauses completely?
Or do you know of any compiler that requires the <...> parts in the constructors and destrucors?
The attached tst-template_cpp20_warning.cpp compiles and runs correctly without warnings with
all from -std=c++20 down to -std=c++98 with g++ 15.1.1, and also with clang++ -stdc=c++14.
You can reproduce the warnings with -DOLD_STYLE. Sample test:

$ grep -A7 '^#if' tst-template_cpp20_warning.cpp
#ifndef OLD_STYLE
  TestClass(int n);
  ~TestClass() { cout << "Goodbye " << _pval << " world!" << endl; }
#else
  TestClass<FOO, BAR>(int n);
  ~TestClass<FOO, BAR>() { cout << "Goodbye " << _pval << " world!" << endl; }
#endif
  int get(void);

$ g++ -std=c++98 -Wall -Wextra -O3 -fomit-frame-pointer -fPIC -DNDEBUG -pedantic -march=native -fno-rtti tst-template_cpp20_warning.cpp

$ ./a.out
Hello 6 world!
Hello 5 world!
tc1.get() = 16
tc2.get() = 25
Goodbye 5 world!
Goodbye 6 world!

-Walloc-size warnings

Excerpt:

transform/BWT.cpp: In constructor »kanzi::BWT::BWT(int)«:
transform/BWT.cpp:39:25: advarsel: allocation of insufficient size »0« for type »kanzi::uint« {aka »unsigned int«} with size »4« [-Walloc-size]
   39 |     _buffer = new uint[0];
      |                         ^
transform/BWT.cpp:40:20: advarsel: allocation of insufficient size »0« for type »int« with size »4« [-Walloc-size]
   40 |     _sa = new int[0];
      |                    ^
[... a lot of these, e.g. also: ...]
io/CompressedOutputStream.cpp: In constructor »kanzi::CompressedOutputStream::CompressedOutputStream(kanzi::OutputStream&, int, const std::string&, const std::string&, int, int, kanzi::uint64, ThreadPool*, bool)«:
io/CompressedOutputStream.cpp:129:54: advarsel: allocation of insufficient size »0« for type »kanzi::byte« {aka »unsigned char«} with size »1« [-Walloc-size]
  129 |     _buffers[_jobs] = new SliceArray<byte>(new byte[0], 0, 0);
      |                                                      ^
io/CompressedOutputStream.cpp:132:53: advarsel: allocation of insufficient size »0« for type »kanzi::byte« {aka »unsigned char«} with size »1« [-Walloc-size]
  132 |        _buffers[i] = new SliceArray<byte>(new byte[0], 0, 0);
      |                                                     ^
[...]

This is also quite legal C++14 but considered suspicious by GCC anyway.
-Walloc-size can catch real problems too, not only pseudo/non-problems like this, so it would be best not to silence it with -Wno-alloc-size (that's only supported by some compiler versions, far from all) and instead replace the 38 near-empty allocations with null pointers and guard an appropriate number of delete[] statements with if ... != nullptr as is currently only done for two TextCodec variables:

.../kanzi-cpp$ git grep -P 'new \w+\[0]'|wc
     38     218    2552

.../kanzi-cpp$ git grep -P 'new \w+\[0]'|head -5
src/entropy/ANSRangeDecoder.cpp:    _buffer = new byte[0];
src/entropy/ANSRangeDecoder.cpp:    _f2s = new uint8[0];
src/entropy/ANSRangeEncoder.cpp:    _buffer = new byte[0];
src/entropy/BinaryEntropyDecoder.cpp:    , _sba(new byte[0], 0)
src/entropy/BinaryEntropyEncoder.cpp:    , _sba(new byte[0], 0)

.../kanzi-cpp$ git grep -P 'if.*nullptr.*delete\s?\[]'|cat
src/transform/TextCodec.hpp:           if (_dictList != nullptr) delete[] _dictList;
src/transform/TextCodec.hpp:           if (_dictMap != nullptr) delete[] _dictMap;
src/transform/TextCodec.hpp:           if (_dictList != nullptr) delete[] _dictList;
src/transform/TextCodec.hpp:           if (_dictMap != nullptr) delete[] _dictMap;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions