aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDeclCXX.cpp31
-rw-r--r--lib/Sema/SemaExprCXX.cpp8
-rw-r--r--lib/Sema/SemaInit.cpp2
-rw-r--r--lib/Sema/SemaNamedCast.cpp32
-rw-r--r--lib/Sema/SemaOverload.cpp51
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp18
-rw-r--r--lib/Sema/SemaType.cpp18
8 files changed, 113 insertions, 49 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 29d0796dcb..13c3e87bfe 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -272,7 +272,7 @@ public:
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
- QualType BuildReferenceType(QualType T, unsigned Quals,
+ QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index fa84c7d2de..acf8224542 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -802,7 +802,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
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 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
//
// 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::PerformInitializationByConstructor(QualType ClassType,
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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
}
// 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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
// 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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
// 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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
}
// -- 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 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
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.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 5450d1949f..b3d94c372d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -764,7 +764,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// the constructor or conversion operator, and then cope with the
// standard conversions.
ImpCastExprToType(From, ToType.getNonReferenceType(),
- ToType->isReferenceType());
+ ToType->isLValueReferenceType());
return false;
case ImplicitConversionSequence::EllipsisConversion:
@@ -800,7 +800,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// FIXME: Create a temporary object by calling the copy
// constructor.
ImpCastExprToType(From, ToType.getNonReferenceType(),
- ToType->isReferenceType());
+ ToType->isLValueReferenceType());
return false;
}
@@ -893,8 +893,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
break;
case ICK_Qualification:
+ // FIXME: Not sure about lvalue vs rvalue here in the presence of
+ // rvalue references.
ImpCastExprToType(From, ToType.getNonReferenceType(),
- ToType->isReferenceType());
+ ToType->isLValueReferenceType());
break;
default:
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 02df9b32fa..e0d3b7e545 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -121,7 +121,7 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
return false;
// C++ [dcl.init.ref]p1:
- // A variable declared to be a T&, that is "reference to type T"
+ // A variable declared to be a T& or T&&, that is "reference to type T"
// (8.3.2), shall be initialized by an object, or function, of
// type T or by an object that can be converted into a T.
if (DeclType->isReferenceType())
diff --git a/lib/Sema/SemaNamedCast.cpp b/lib/Sema/SemaNamedCast.cpp
index a8ad10d382..9f5c5e5870 100644
--- a/lib/Sema/SemaNamedCast.cpp
+++ b/lib/Sema/SemaNamedCast.cpp
@@ -115,9 +115,10 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr->getType();
- if (const ReferenceType *DestTypeTmp = DestType->getAsReferenceType()) {
+ if (const LValueReferenceType *DestTypeTmp =
+ DestType->getAsLValueReferenceType()) {
if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
- // Cannot cast non-lvalue to reference type.
+ // Cannot cast non-lvalue to lvalue reference type.
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
<< "const_cast" << OrigDestType << SrcExpr->getSourceRange();
return;
@@ -141,6 +142,8 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
if (!DestType->isPointerType() && !DestType->isMemberPointerType()) {
// Cannot cast to non-pointer, non-reference type. Note that, if DestType
// was a reference type, we converted it to a pointer above.
+ // The status of rvalue references isn't entirely clear, but it looks like
+ // conversion to them is simply invalid.
// C++ 5.2.11p3: For two pointer types [...]
Self.Diag(OpRange.getBegin(), diag::err_bad_const_cast_dest)
<< OrigDestType << DestRange;
@@ -214,7 +217,8 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr->getType();
- if (const ReferenceType *DestTypeTmp = DestType->getAsReferenceType()) {
+ if (const LValueReferenceType *DestTypeTmp =
+ DestType->getAsLValueReferenceType()) {
if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
// Cannot cast non-lvalue to reference type.
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
@@ -228,6 +232,14 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// This code does this transformation for the checked types.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
+ } else if (const RValueReferenceType *DestTypeTmp =
+ DestType->getAsRValueReferenceType()) {
+ // Both the reference conversion and the rvalue rules apply.
+ Self.DefaultFunctionArrayConversion(SrcExpr);
+ SrcType = SrcExpr->getType();
+
+ DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+ SrcType = Self.Context.getPointerType(SrcType);
} else {
// C++ 5.2.10p1: [...] the lvalue-to-rvalue, array-to-pointer, and
// function-to-pointer standard conversions are performed on the
@@ -425,6 +437,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// conversion using B's conversion constructor.
// DR 427 specifies that the downcast is to be applied here.
+ // FIXME: With N2812, casts to rvalue refs will change.
+
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
if (DestType->isVoidType()) {
return;
@@ -787,9 +801,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
return;
}
- // C++ 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
- // complete class type, [...]. If T is a reference type, v shall be an
- // lvalue of a complete class type, [...].
+ // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
+ // complete class type, [...]. If T is an lvalue reference type, v shall be
+ // an lvalue of a complete class type, [...]. If T is an rvalue reference
+ // type, v shall be an expression having a complete effective class type,
+ // [...]
QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
QualType SrcPointee;
@@ -801,12 +817,14 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
<< OrigSrcType << SrcExpr->getSourceRange();
return;
}
- } else {
+ } else if (DestReference->isLValueReferenceType()) {
if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
<< "dynamic_cast" << OrigDestType << OpRange;
}
SrcPointee = SrcType;
+ } else {
+ SrcPointee = SrcType;
}
const RecordType *SrcRecord = SrcPointee->getAsRecordType();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 8943aa602e..5321935cfc 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -519,8 +519,10 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// We were able to resolve the address of the overloaded function,
// so we can convert to the type of that function.
FromType = Fn->getType();
- if (ToType->isReferenceType())
- FromType = Context.getReferenceType(FromType);
+ if (ToType->isLValueReferenceType())
+ FromType = Context.getLValueReferenceType(FromType);
+ else if (ToType->isRValueReferenceType())
+ FromType = Context.getRValueReferenceType(FromType);
else if (ToType->isMemberPointerType()) {
// Resolve address only succeeds if both sides are member pointers,
// but it doesn't have to be the same class. See DR 247.
@@ -2734,7 +2736,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
Arith < NumArithmeticTypes; ++Arith) {
QualType ArithTy = ArithmeticTypes[Arith];
QualType ParamTypes[2]
- = { Context.getReferenceType(ArithTy), Context.IntTy };
+ = { Context.getLValueReferenceType(ArithTy), Context.IntTy };
// Non-volatile version.
if (NumArgs == 1)
@@ -2743,7 +2745,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
// Volatile version
- ParamTypes[0] = Context.getReferenceType(ArithTy.withVolatile());
+ ParamTypes[0] = Context.getLValueReferenceType(ArithTy.withVolatile());
if (NumArgs == 1)
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
@@ -2767,7 +2769,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
continue;
QualType ParamTypes[2] = {
- Context.getReferenceType(*Ptr), Context.IntTy
+ Context.getLValueReferenceType(*Ptr), Context.IntTy
};
// Without volatile
@@ -2778,7 +2780,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// With volatile
- ParamTypes[0] = Context.getReferenceType((*Ptr).withVolatile());
+ ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
if (NumArgs == 1)
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
@@ -2802,7 +2804,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
Ptr != CandidateTypes.pointer_end(); ++Ptr) {
QualType ParamTy = *Ptr;
QualType PointeeTy = ParamTy->getAsPointerType()->getPointeeType();
- AddBuiltinCandidate(Context.getReferenceType(PointeeTy),
+ AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy),
&ParamTy, Args, 1, CandidateSet);
}
break;
@@ -3021,14 +3023,14 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
QualType ParamTypes[2];
// T& operator=(T&, T)
- ParamTypes[0] = Context.getReferenceType(*Enum);
+ ParamTypes[0] = Context.getLValueReferenceType(*Enum);
ParamTypes[1] = *Enum;
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssignmentOperator=*/false);
if (!Context.getCanonicalType(*Enum).isVolatileQualified()) {
// volatile T& operator=(volatile T&, T)
- ParamTypes[0] = Context.getReferenceType((*Enum).withVolatile());
+ ParamTypes[0] = Context.getLValueReferenceType((*Enum).withVolatile());
ParamTypes[1] = *Enum;
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssignmentOperator=*/false);
@@ -3060,13 +3062,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
ParamTypes[1] = (Op == OO_Equal)? *Ptr : Context.getPointerDiffType();
// non-volatile version
- ParamTypes[0] = Context.getReferenceType(*Ptr);
+ ParamTypes[0] = Context.getLValueReferenceType(*Ptr);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// volatile version
- ParamTypes[0] = Context.getReferenceType((*Ptr).withVolatile());
+ ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
}
@@ -3094,13 +3096,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
ParamTypes[1] = ArithmeticTypes[Right];
// Add this built-in operator as a candidate (VQ is empty).
- ParamTypes[0] = Context.getReferenceType(ArithmeticTypes[Left]);
+ ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
// Add this built-in operator as a candidate (VQ is 'volatile').
ParamTypes[0] = ArithmeticTypes[Left].withVolatile();
- ParamTypes[0] = Context.getReferenceType(ParamTypes[0]);
+ ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
}
@@ -3132,13 +3134,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
ParamTypes[1] = ArithmeticTypes[Right];
// Add this built-in operator as a candidate (VQ is empty).
- ParamTypes[0] = Context.getReferenceType(ArithmeticTypes[Left]);
+ ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
// Add this built-in operator as a candidate (VQ is 'volatile').
ParamTypes[0] = ArithmeticTypes[Left];
ParamTypes[0].addVolatile();
- ParamTypes[0] = Context.getReferenceType(ParamTypes[0]);
+ ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
}
}
@@ -3190,7 +3192,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
Ptr != CandidateTypes.pointer_end(); ++Ptr) {
QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
QualType PointeeType = (*Ptr)->getAsPointerType()->getPointeeType();
- QualType ResultTy = Context.getReferenceType(PointeeType);
+ QualType ResultTy = Context.getLValueReferenceType(PointeeType);
// T& operator[](T*, ptrdiff_t)
AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
@@ -3407,11 +3409,17 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
// retaining as many typedefs as possible while still showing
// the function type (and, therefore, its parameter types).
QualType FnType = Cand->Surrogate->getConversionType();
- bool isReference = false;
+ bool isLValueReference = false;
+ bool isRValueReference = false;
bool isPointer = false;
- if (const ReferenceType *FnTypeRef = FnType->getAsReferenceType()) {
+ if (const LValueReferenceType *FnTypeRef =
+ FnType->getAsLValueReferenceType()) {
FnType = FnTypeRef->getPointeeType();
- isReference = true;
+ isLValueReference = true;
+ } else if (const RValueReferenceType *FnTypeRef =
+ FnType->getAsRValueReferenceType()) {
+ FnType = FnTypeRef->getPointeeType();
+ isRValueReference = true;
}
if (const PointerType *FnTypePtr = FnType->getAsPointerType()) {
FnType = FnTypePtr->getPointeeType();
@@ -3421,7 +3429,8 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
FnType = QualType(FnType->getAsFunctionType(), 0);
// Reconstruct the pointer/reference as appropriate.
if (isPointer) FnType = Context.getPointerType(FnType);
- if (isReference) FnType = Context.getReferenceType(FnType);
+ if (isRValueReference) FnType = Context.getRValueReferenceType(FnType);
+ if (isLValueReference) FnType = Context.getLValueReferenceType(FnType);
Diag(Cand->Surrogate->getLocation(), diag::err_ovl_surrogate_cand)
<< FnType;
@@ -4144,7 +4153,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// FIXME: Represent the user-defined conversion in the AST!
ImpCastExprToType(Object,
Conv->getConversionType().getNonReferenceType(),
- Conv->getConversionType()->isReferenceType());
+ Conv->getConversionType()->isLValueReferenceType());
return ActOnCallExpr(S, ExprArg(*this, Object), LParenLoc,
MultiExprArg(*this, (ExprTy**)Args, NumArgs),
CommaLocs, RParenLoc).release();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dbdc5a8a71..fd541f3680 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -218,14 +218,24 @@ TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
return QualType();
}
-QualType
-TemplateTypeInstantiator::InstantiateReferenceType(const ReferenceType *T,
- unsigned Quals) const {
+QualType
+TemplateTypeInstantiator::InstantiateLValueReferenceType(
+ const LValueReferenceType *T, unsigned Quals) const {
+ QualType ReferentType = Instantiate(T->getPointeeType());
+ if (ReferentType.isNull())
+ return QualType();
+
+ return SemaRef.BuildReferenceType(ReferentType, true, Quals, Loc, Entity);
+}
+
+QualType
+TemplateTypeInstantiator::InstantiateRValueReferenceType(
+ const RValueReferenceType *T, unsigned Quals) const {
QualType ReferentType = Instantiate(T->getPointeeType());
if (ReferentType.isNull())
return QualType();
- return SemaRef.BuildReferenceType(ReferentType, Quals, Loc, Entity);
+ return SemaRef.BuildReferenceType(ReferentType, false, Quals, Loc, Entity);
}
QualType
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index bfbc6c3708..ac0e1e1f73 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -319,8 +319,16 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
///
/// \returns A suitable reference type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildReferenceType(QualType T, unsigned Quals,
+QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
SourceLocation Loc, DeclarationName Entity) {
+ if (LValueRef) {
+ if (const RValueReferenceType *R = T->getAsRValueReferenceType()) {
+ // FIXME: Find the C++0x reference for reference collapsing.
+ // In reference collapsing, lvalue refs win over rvalue refs.
+ return Context.getLValueReferenceType(R->getPointeeType()).
+ getQualifiedType(Quals);
+ }
+ }
if (T->isReferenceType()) {
// C++ [dcl.ref]p4: There shall be no references to references.
//
@@ -367,7 +375,9 @@ QualType Sema::BuildReferenceType(QualType T, unsigned Quals,
Quals &= ~QualType::Volatile;
// Handle restrict on references.
- return Context.getReferenceType(T).getQualifiedType(Quals);
+ if (LValueRef)
+ return Context.getLValueReferenceType(T).getQualifiedType(Quals);
+ return Context.getRValueReferenceType(T).getQualifiedType(Quals);
}
/// \brief Build an array type.
@@ -603,8 +613,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
break;
case DeclaratorChunk::Reference:
- T = BuildReferenceType(T,
- DeclType.Ref.HasRestrict? QualType::Restrict : 0,
+ T = BuildReferenceType(T, DeclType.Ref.LValueRef,
+ DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
DeclType.Loc, Name);
break;
case DeclaratorChunk::Array: {