Implement core issue 5: a temporary created for copy-initialization has a

cv-unqualified type. This is essential in order to allow move-only objects of
const-qualified types to be copy-initialized via a converting constructor.

llvm-svn: 150309
This commit is contained in:
Richard Smith 2012-02-11 19:22:50 +00:00
parent 4c7b490d19
commit b24f06780c
2 changed files with 29 additions and 4 deletions

View File

@ -3743,8 +3743,10 @@ static void TryUserDefinedConversion(Sema &S,
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
// subsumed by the initialization.
Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType,
// subsumed by the initialization. Per DR5, the created temporary is of the
// cv-unqualified type of the destination.
Sequence.AddUserConversionStep(Function, Best->FoundDecl,
DestType.getUnqualifiedType(),
HadMultipleCandidates);
return;
}
@ -3752,7 +3754,7 @@ static void TryUserDefinedConversion(Sema &S,
// Add the user-defined conversion step that calls the conversion function.
QualType ConvType = Function->getCallResultType();
if (ConvType->getAs<RecordType>()) {
// If we're converting to a class type, there may be an copy if
// If we're converting to a class type, there may be an copy of
// the resulting temporary object (possible to create an object of
// a base class type). That copy is not a separate conversion, so
// we just make a note of the actual destination type (possibly a
@ -4899,7 +4901,7 @@ InitializationSequence::Perform(Sema &S,
Loc, ConstructorArgs))
return ExprError();
// Build the an expression that constructs a temporary.
// Build an expression that constructs a temporary.
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
move_arg(ConstructorArgs),
HadMultipleCandidates,

View File

@ -42,3 +42,26 @@ namespace PR6757 {
f(foo);
}
}
namespace DR5 {
// Core issue 5: if a temporary is created in copy-initialization, it is of
// the cv-unqualified version of the destination type.
namespace Ex1 {
struct C { };
C c;
struct A {
A(const A&);
A(const C&);
};
const volatile A a = c; // ok
}
namespace Ex2 {
struct S {
S(S&&); // expected-warning {{C++11}}
S(int);
};
const S a(0);
const S b = 0;
}
}