diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaNamedCast.cpp | 32 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 51 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 18 |
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: { |