clang not recognizing base class within lambda - c++

I have the following struct MyStruct that calls Foo<int> on construction:
struct MyStruct {
MyStruct() {
Foo<int>();
}
template<typename T>
void Foo() {
[]() {
struct Base {
Base(int n) {}
};
struct Derived : Base {
// using Base=Base; // needs to be uncommented for Apple LLVM version 9.1.0 (clang-902.0.39.2)
Derived() :
Base(0) // problematic line
{}
} derived;
};
}
};
I tried to compile this with clang (via godbolt, command line params --std=c++1y):
3.6: error: type 'Base' is not a direct or virtual base of 'Derived' (see problematic line in code above)
3.7 and newer: compiles (with a warning about unused expressions)
So I expected that with newer versions this should be ok. However, when I tried to compile it on a Mac using XCode9 (which, according to this, uses clang 4.0 (clang --version gives Apple LLVM version 9.1.0 (clang-902.0.39.2))), I get an error from the same line as issued by clang 3.6:
error: member initializer 'Base' does not name a non-static data member or base class
As a workaround, I tried introducing using Base=Base within struct Derived (as indicated), which made it compile via XCode. (As a sidenote: Using the same workaround did not work for clang 3.6 on godbolt.)
So here are my questions:
Is this a compiler bug? If yes: Is it documented somewhere?
Is my workaround using Base=Base valid, well-defined C++?

Related

C++ No matching constructor when using inheritance

I have code like this:
class A{
public:
int b;
};
int main()
{
A a{.b = 5};
}
And the program compiles.
However, when I add another class and I make A inherit that class (like below), it throws an error "no matching function for call to ‘A::A()’" (or "No matching constructor for initialization of A").
class C{
};
class A: public C{
public:
int b;
};
int main()
{
A a{.b = 5};
}
Why?
You are using feature "Designated initializers" which is available since C++20.
Also I can't reproduce this issue: https://godbolt.org/z/fz3PeP
note with C++17 gcc and clang just file an warning, msvc file an error
with C++20 it is fine on all three (msvc needs c++latest option).
with C++14 it files error everywhere
So looks like problem is just compiler version or configuration

Compile error with gcc when in-class initializing unique_ptr of incomplete type to nullptr

I'm writing some code using pimpl idiom with unique_ptr. When I tried to use in-class initialization to set unique_ptr to nullptr by default, gcc gave a compile error, while clang and msvc both successfully compiled the code. And if I didn't use in-class initialization the error went away.
// A.h
#pragma once
#include <memory>
using namespace std;
class B;
class A
{
private:
////////////////////////
// here gives the error!
////////////////////////
unique_ptr<B> impl{nullptr}; // error only with gcc,
// ok with clang and msvc
unique_ptr<B> impl2; // ok with all three
public:
A();
~A();
};
// A.cpp
#include "A.h"
class B
{
private:
int b{5};
public:
B() = default;
~B() = default;
};
A::A() = default;
A::~A() = default;
// main.cpp
#include "A.h"
int main()
{
A a;
return 0;
}
When I compiled the above code, gcc complained "error: invalid application of ‘sizeof’ to incomplete type ‘B’". I've tried both gcc 8.3 and gcc 9.1 with no success. Is this a compiler bug? Thanks!
Edit:
I tried as #eerorika suggested. If the header and source files are merged into one single file, it can compile normally, but not separated.
Edit
Confirmed to be compiler bug and already fixed in gcc9.2.
The program, and the default member initialiser in particular, is well-formed. If a compiler refuses to compile, then it is a bug in the compiler as far as I can tell.
I can reproduce the problem with GCC 9.1 but not 9.2 nor trunk, so it appears to have been fixed. With older versions, you may need to give up using the default member initialiser as a workaround.

C++ "error: "object missing in reference to ..." depends on gcc version

I am facing a compilation error with one gcc version (4.3.2), whereas the same code will be compiled without complaints with a newer version of gcc, e.g. 4.5.2.
The following example illustrates the problem:
class Base {
protected:
int member;
};
template<typename T>
class A : public Base {
};
template<typename T>
class C : public A<T> {
C() {
Base::member = 1;
}
};
int main() {
}
For 4.3.2 I am getting:
test.cpp: In constructor 'C<T>::C()':
test.cpp:4: error: object missing in reference to 'Base::member'
test.cpp:14: error: from this location
For 4.5.2 it compiles just fine.
If one compiler version accepts the code it cannot be completely wrong. My guess is that it conforms to the C++ standard, but the older compiler was lacking a proper implementation of the same.
What exactly is the problem?
Is there a portable way of writing that kind of code such that as much compilers as possible accept it?
This is definitely a bug in the earlier version of g++ but the solution is simple: Just add this-> to the expression, as this->Base::member = 1; which unconfuses the compiler.

porting g++ code to Clang++ issue

Following code is a hypothetical code. This is a perfectly valid code under g++ (4.2.1). When compiled with Clang++ (4.2) it produces error as qualified reference to 'myclass' is a constructor name rather than a type wherever a constructor can be declared
class myclass
{
public:
myclass() { }
~myclass() {}
};
myclass::myclass* funct() {
return new myclass();
}
I could fix this by changing myclass::myclass* to myclass*. However I am not expected to change any code. Is there any commandline flags that I could provide in order to compile this code as is using Clang++ ?
No, there is no such flag : since this program is ill-formed, it should not compile.
If a compiler compiles it, then it is a compiler bug. This bug report looks like the one impacting your particular gcc version.
The code should be fixed to :
myclass* funct() {
return new myclass();
}
gcc 4.9.1 also rejects the code:
error: ‘myclass::myclass’ names the constructor, not the type
Unless the code base is happy with the rather old gcc 4.2, I see no alternative than to fix the code.

Why does this snippet using uniform initialization compile with g++4.6 but not g++4.7?

Note that derived uses C++11 uniform initialization syntax to call the base class constructor.
class base
{
protected:
base()
{}
};
class derived : public base
{
public:
derived()
: base{} // <-- Note the c++11 curly brace syntax
// using uniform initialization. Change the
// braces to () and it works.
{}
};
int main()
{
derived d1;
return 0;
}
g++4.6 compiles this, however g++4.7 does not:
$ g++-4.7 -std=c++11 -Wall -Wextra -pedantic curly.cpp -o curly
curly.cpp: In constructor ‘derived::derived()’:
curly.cpp:4:13: error: ‘base::base()’ is protected
curly.cpp:19:24: error: within this context
What's going on?
Update 1: It also compiles without warnings with clang++-3.1
Update 2: Looks like a compiler bug for sure. It's apparently fixed in GCC 4.7.3.
Paolo Carlini, a GCC/libstdc++ contributor, confirmed it is a bug/regression.
It is probably because in version 4.7 C11 explicit override control was added.
compiling this with icpc ( intel compiler tested with version 11.1 -> 12.1) gives:
-bash-3.2$ icpc -std=c++0x test.c
test.c(15): error: expected a declaration
{}
^
test.c(12): error: expected a "("
: base{} // <-- Note the c++11 curly brace syntax
^
compilation aborted for test.c (code 2)
edit: but then again, c++11 is not fully implemented yet in icpc either
http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/
same as with g++
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
which clearly states it's still experimental, so a bug is very likely.
I found this:
"The draft says that an initializer list initializing a reference is done not by direct binding, but by first constructing a temporary out of the element in the initializer list, and then binding the target reference to that temporary"
So it might be choking on the fact that the temporary created by base{} is being done through a protected constructor.