Following code compiles fine with every gcc, with every g++ -std=c++98, with g++-4.5 -std=c++0x, but not with g++ -std=c++0x (or -std=c++11) since 4.6. typedef volatile struct t1s { int a; } t1; typedef struct t2s { t1 b; } t2; t2 x, y; void foo(void) { x = y; } compile with: g++ -std=c++0x vola.cpp vola.cpp: In function 'void foo()': vola.cpp:7:7: error: use of deleted function 't2s& t2s::operator=(const t2s&)' vola.cpp:2:16: error: 't2s& t2s::operator=(const t2s&)' is implicitly deleted because the default definition would be ill-formed: vola.cpp:2:16: error: no matching function for call to 't1s::operator=(const volatile t1&) volatile' vola.cpp:2:16: note: candidates are: vola.cpp:1:25: note: t1s& t1s::operator=(const t1s&) vola.cpp:1:25: note: no known conversion for argument 1 from 'const volatile t1' to 'const t1s&' vola.cpp:1:25: note: t1s& t1s::operator=(t1s&&) vola.cpp:1:25: note: no known conversion for argument 1 from 'const volatile t1' to 't1s&&'
(In reply to comment #0) > Following code compiles fine with every gcc, with every g++ -std=c++98, > with g++-4.5 -std=c++0x, but not with g++ -std=c++0x (or -std=c++11) since 4.6. That's because G++ 4.6 was changed to reject your invalid program, it's supposed to do that, and it means G++ 4.6 is better than G++ 4.5 :) Isn't the error quite clear? Assigning t2s needs to use the assignment operator, but that function can't be implicitly-defined because assigning the volatile member requires t1s::operator=(const volatile t1s&) which doesn't exist, because the implicit-declared copy assignment operator has the signature t1s::operator=(const t1s&) To fix your code you should either define copy assignment for t1s so it works on volatile objects, or define assignment for t2s so it doesn't need t1s::operator= e.g. t2s& operator=(const t2s& t) { b.a = t.b.a; return *this; }
(In reply to comment #1) > Assigning t2s needs to use the assignment operator, but that function can't be > implicitly-defined because assigning the volatile member requires > t1s::operator=(const volatile t1s&) which doesn't exist, Actually that should say: "t1s::operator=(const volatile t1s&) volatile" which doesn't exist,
I agree that it is possible to define operator= for each struct that is using t1 (in the original code (C code, but compiled as C++ code) there is not only t2, and in all of them there are more members). There are simpler methods to fix the code, e.g. to define typedef struct t1s { volatile int a; } t1; It should be equivalent in the volatile qualifier behavior when the volatile qualifier is set for each member of t1. This compiles also fine with gcc-4.6 and does not need several operator= definitions. But that is not the question. The question is if that is a gcc bug or not. If C++11 is really different compared to C++98 here (I'm not sure about that), then I would prefer _one_ clear error message like "error: C++11 does not allow ..." or "error: C++11 demands ..." or similar, and not that weird 3 error messages plus 5 notes about implicitly deleted simple assignments operators.
(In reply to comment #3) > But that is not the question. The question is if that is a gcc bug or > not. If C++11 is really different compared to C++98 here (I'm not sure It's certainly different because there are no deleted functions in C++98, but I'm not sure if the code is valid in C++98 or not, G++ and EDG accept it but clang++ doesn't. As far as I can see C++98 should have the same behaviour, assigning t2 requires assigning a volatile t1, which can't use the implicitly-declared assignment operator. Maybe Jason can clarify. > about that), then I would prefer _one_ clear error message like > "error: C++11 does not allow ..." or "error: C++11 demands ..." or > similar, and not that weird 3 error messages plus 5 notes about > implicitly deleted simple assignments operators. That's not possible in general, and I actually prefer the explanation of which rules caused the error. What do you suggest it prints? There's no easy answer. Attempting to turn that into natural language would go wrong too often and give misleading errors. The problem is that you tried to use the implicit assignment operator, which is deleted, so the compiler tells you why it's deleted. The message is great IMHO, a huge improvement on the diagnostics given by older versions of GCC.
clang is correct in this case; the testcase should be rejected in c++98 mode as well. operator= is defined as memberwise assignment even if it's trivial. So the C++98 mode behavior is the bug.