gcc warning about unitialized values caused by turning optimization on - c++

Consider the following code
#include <iostream>
template<typename Value>
struct Wrapper {
Value m_value;
Wrapper() {}
Wrapper(const Wrapper<Value> &copy_from) : m_value(copy_from.m_value) {}
};
template<typename Value>
struct DefaultContainer {
Value m_default;
DefaultContainer(const Value& def) : m_default(def) {}
};
template<typename Value>
struct DefaultContainerUser : public DefaultContainer<Value> {
DefaultContainerUser() : DefaultContainer<Value>(Value()) {}
};
int main() {
DefaultContainerUser<Wrapper<double>> user;
std::cout << user.m_default.m_value << std::endl;
}
When I compile this with c++ -O1 -Werror -Wall test.cpp, I get the following error:
test.cpp: In function ‘int main()’:
test.cpp:8:63: error: ‘<anonymous>.Wrapper<double>::m_value’ is used uninitialized in this function [-Werror=uninitialized]
8 | Wrapper(const Wrapper<Value> &copy_from) : m_value(copy_from.m_value) {}
| ~~~~~~~~~~^~~~~~~
cc1plus: all warnings being treated as errors
If I disable optimizations using -O0, everything works fine. Adding -Wno-error=maybe-uninitialized with optimizations still turned on doesn't help. What am I doing wrong here?
The compiler that I'm using is c++ (GCC) 10.2.1 20201016 (Red Hat 10.2.1-6).

It is normal that the warnings reported by a compiler varies depending on the optimization level. Warnings are usually a bi-product of optimization in the sense that the analysis needed for a particular optimization may uncover possible problems in the code or that transformations applied during optimization may uncover possible errors. This implies that when optimization is off and the analysis and transformations are not performed the problems are not detected.

Related

How can I make GCC/Clang warn about the use of uninitialized members?

I am compiling the code behind
class Test {
public:
Test() {}
int k;
};
int main() {
Test t;
std::cout << t.k << "\n";
}
like
g/clang++ main.cpp -Wall -Wextra --std=c++14 -o exe; ./exe
Why neither of the compilers does not warn me about indeterminate value of the integer is not it a very serious potential bug? How to enable a warning for indeterminate initializations?
For this example, GCC gives me the desired warning when I give it -O1 (or higher).
Presumably whatever mechanism it uses to detect this is tied into the optimisation effort level somehow. It's a notoriously hard thing to do.
Ensure that you heed your release-build warnings as well as debug-build warnings.

thread_local template variable of struct inside anonymous namespace fails to link?

The following example program uses a thread local template variable, and instantiates it using a type inside an anonymous namespace. This produces a linker error in gcc. In clang it actually compiles but does not run correctly.
#include <stdio.h>
template<typename T>
struct container {
container() { printf("construct: %p\n", this); }
~container() { printf("destruct: %p\n", this); }
};
template<typename T>
thread_local container<T> storage;
namespace {
struct bar {};
}
int main() {
auto& ref1 = storage<bar>;
auto& ref2 = storage<bar>;
}
On gcc this fails with a link error:
a.cpp:6:2: warning: ‘container<T>::~container() noexcept [with T = {anonymous}::bar]’ used but never defined
~container() { printf("destruct: %p\n", this); }
^
/tmp/ccgh0P15.o: In function `__tls_init':
a.cpp:(.text+0xa9): undefined reference to `container<(anonymous namespace)::bar>::~container()'
With clang the program compiles but produces very troubling output:
construct: 0x7fb8d1c003d0
construct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
Are there some rough edges surrounding thread_local/templated variables that I am running into here? I am unclear why this would ever produce a link error (the link error disappears if I remove thread_local). In the case of clang how could a double destroy of an object with static storage duration be anything but a compiler bug? In clang the issue disappears if I remove the anonymous namespace OR the thread_local specification, OR by removing one of the references in main().
Can anyone shed some light on this, I am mainly just curious if I am misunderstanding something. Thanks!
EDIT:
clang++ -v
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
g++ -v
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)

Clang Warning on expression side effects

Given the following source code:
#include <memory>
#include <typeinfo>
struct Base {
virtual ~Base();
};
struct Derived : Base { };
int main() {
std::unique_ptr<Base> ptr_foo = std::make_unique<Derived>();
typeid(*ptr_foo).name();
return 0;
}
and compiled it with:
clang++ -std=c++14 -Wall -Wextra -Werror -Wpedantic -g -o test test.cpp
Enviroment setup:
linux x86_64
clang version 5.0.0
It does not compile because of warning (note -Werror):
error: expression with side effects will be evaluated
despite being used as an operand to 'typeid'
[-Werror,-Wpotentially-evaluated-expression]
typeid(*ptr_foo).name();
(Just a note: GCC does not claim that kind of potential problematic)
Question
Is there a way to get the information about the type pointed by a unique_ptr without generating that kind of warning?
Note: I am not talking about disabling -Wpotentially-evaluated-expression or avoiding -Werror.
Looks like following should work without warnings and give correct result for derived class
std::unique_ptr<Foo> ptr_foo = std::make_unique<Bar>();
if(ptr_foo.get()){
auto& r = *ptr_foo.get();
std::cout << typeid(r).name() << '\n';
}

Clang compiler option to treat exception specification lax error as warning

Is there a way to treat exception mismatch error as warning in clang?
source_file.cpp:12:18: error: exception specification of overriding function is more lax than base version
virtual void Func(){}
I am getting error with google mock for functions that specify exception specifier. Looking at https://github.com/google/googletest/pull/681 and other reported issue, not sure if this will get fixed in google mock, so at least for test code if possible I would like to disable this.
//clang 3.8.0
#include <iostream>
struct A
{
virtual void Func() throw() {}
};
struct B : public A
{
virtual void Func(){}
};
int main()
{
B b;
return 0;
}
Yes, using the -fms-extensions command line option.
MSVC only warns about this, so with clang MSVC compatibility mode, the code will compile, and the error will be replaced with an equivalent warning.
More about MSVC compatibility mode in clang documentation,
here.

Workaround for debug symbol error with auto member function?

There seems to be an issue with debug symbols and auto.
I have an auto function in a class:
#include <cstddef>
template <typename T>
struct binary_expr {
auto operator()(std::size_t i){
return 1;
}
};
int main(){
binary_expr<double> b;
return 0;
}
When I compile with G++ (4.8.2) and -g, I have this error:
g++ -g -std=c++1y auto.cpp
auto.cpp: In instantiation of ‘struct binary_expr<double>’:
auto.cpp:11:25: required from here
auto.cpp:4:8: internal compiler error: in gen_type_die_with_usage, at dwarf2out.c:19484
struct binary_expr {
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://bugs.gentoo.org/> for instructions.
With clang++ (3.4) and -g, I have this:
clang++ -g -std=c++1y auto.cpp
error: debug information for auto is not yet supported
1 error generated.
If I remove the -g or set the type explicitly, it works perfectly.
Isn't clang++ supposed to be C++14 feature complete ?
Is there a workaround for these limitations or I'm screwed ?
This now seems to works on Clang 3.5 SVN. Live Example. It seems that the culprit was a commit from May 2013, see this message on the Clang mailing list.
PR16091: Error when attempting to emit debug info for undeduced auto
return types
Perhaps we should just suppress this, rather than erroring, but since
we have the infrastructure for it I figured I'd use it - if this is
determined to be not the right thing we should probably remove that
infrastructure entirely. I guess it's lying around from the early days
of implementing debug info support.
// RUN: %clang_cc1 -emit-llvm-only -std=c++1y -g %s 2>&1 | FileCheck %s
2
3 struct foo {
4 auto func(); // CHECK: error: debug information for auto is not yet supported
5 };
6
7 foo f;
However, I cannot find the commit that removed this info, perhaps there was an improvement that now prevents that this behavior is being triggered.
Even after some time, the only workaround I have found is to make the function template, pretty stupid workaround... Apparently, clang has no problem with auto functions that are template. I don't know if this works in every case, but until now it had worked for me.
#include <cstddef>
template <typename T>
struct binary_expr {
template<typename E = void>
auto operator()(std::size_t i){
return 1;
}
};
int main(){
binary_expr<double> b;
return 0;
}