Almost complete implementation of rvalue references. One bug, and a few unclear areas. Maybe Doug can shed some light on some of the fixmes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67059 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index fa84c7d..acf8224 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -802,7 +802,7 @@
QualType ArgType = ClassType;
if (HasConstCopyConstructor)
ArgType = ArgType.withConst();
- ArgType = Context.getReferenceType(ArgType);
+ ArgType = Context.getLValueReferenceType(ArgType);
// An implicitly-declared copy constructor is an inline public
// member of its class.
@@ -880,10 +880,10 @@
//
// X& X::operator=(X&)
QualType ArgType = ClassType;
- QualType RetType = Context.getReferenceType(ArgType);
+ QualType RetType = Context.getLValueReferenceType(ArgType);
if (HasConstCopyAssignment)
ArgType = ArgType.withConst();
- ArgType = Context.getReferenceType(ArgType);
+ ArgType = Context.getLValueReferenceType(ArgType);
// An implicitly-declared copy assignment operator is an inline public
// member of its class.
@@ -1630,7 +1630,8 @@
Sema::ReferenceCompareResult
Sema::CompareReferenceRelationship(QualType T1, QualType T2,
bool& DerivedToBase) {
- assert(!T1->isReferenceType() && "T1 must be the pointee type of the reference type");
+ assert(!T1->isReferenceType() &&
+ "T1 must be the pointee type of the reference type");
assert(!T2->isReferenceType() && "T2 cannot be a reference type");
T1 = Context.getCanonicalType(T1);
@@ -1713,6 +1714,7 @@
}
// Compute some basic properties of the types and the initializer.
+ bool isRValRef = DeclType->isRValueReferenceType();
bool DerivedToBase = false;
Expr::isLvalueResult InitLvalue = Init->isLvalue(Context);
ReferenceCompareResult RefRelationship
@@ -1738,6 +1740,15 @@
RefRelationship >= Ref_Compatible_With_Added_Qualification) {
BindsDirectly = true;
+ // Rvalue references cannot bind to lvalues (N2812).
+ // FIXME: This part of rvalue references is still in flux. Revisit later.
+ if (isRValRef) {
+ if (!ICS)
+ Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref)
+ << Init->getSourceRange();
+ return true;
+ }
+
if (ICS) {
// C++ [over.ics.ref]p1:
// When a parameter of reference type binds directly (8.5.3)
@@ -1774,7 +1785,9 @@
// 92) (this conversion is selected by enumerating the
// applicable conversion functions (13.3.1.6) and choosing
// the best one through overload resolution (13.3)),
- if (!SuppressUserConversions && T2->isRecordType()) {
+ // FIXME: Without standard language for N2812, the rvalue reference treatment
+ // here is pretty much a guess.
+ if (!isRValRef && !SuppressUserConversions && T2->isRecordType()) {
// FIXME: Look for conversions in base classes!
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAsRecordType()->getDecl());
@@ -1790,7 +1803,7 @@
// If the conversion function doesn't return a reference type,
// it can't be considered for this conversion.
// FIXME: This will change when we support rvalue references.
- if (Conv->getConversionType()->isReferenceType() &&
+ if (Conv->getConversionType()->isLValueReferenceType() &&
(AllowExplicit || !Conv->isExplicit()))
AddConversionCandidate(Conv, Init, DeclType, CandidateSet);
}
@@ -1862,8 +1875,8 @@
}
// -- Otherwise, the reference shall be to a non-volatile const
- // type (i.e., cv1 shall be const).
- if (T1.getCVRQualifiers() != QualType::Const) {
+ // type (i.e., cv1 shall be const), or shall be an rvalue reference.
+ if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
if (!ICS)
Diag(Init->getSourceRange().getBegin(),
diag::err_not_reference_to_const_init)
@@ -2200,6 +2213,8 @@
RequireCompleteType(Begin, BaseType, DK))
Invalid = true;
+ // FIXME: C++0x [except.handle] names the handler as cv T or cv T&, i.e.
+ // rvalue references aren't there. Oversight or intentional?
// FIXME: Need to test for ability to copy-construct and destroy the
// exception variable.
// FIXME: Need to check for abstract classes.