[cfe-commits] r67059 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/CodeGen/ lib/Sema/ test/Parser/ test/SemaCXX/
Sebastian Redl
sebastian.redl at getdesigned.at
Mon Mar 16 16:22:08 PDT 2009
Author: cornedbee
Date: Mon Mar 16 18:22:08 2009
New Revision: 67059
URL: http://llvm.org/viewvc/llvm-project?rev=67059&view=rev
Log:
Almost complete implementation of rvalue references. One bug, and a few unclear areas. Maybe Doug can shed some light on some of the fixmes.
Added:
cfe/trunk/test/Parser/cxx0x-rvalue-reference.cpp
cfe/trunk/test/SemaCXX/rval-references.cpp
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/AST/TypeNodes.def
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Builtins.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/AST/TypeSerialization.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaNamedCast.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/Parser/cxx-reference.cpp
cfe/trunk/test/SemaCXX/convert-to-bool.cpp
cfe/trunk/test/SemaCXX/overloaded-operator.cpp
cfe/trunk/test/SemaCXX/references.cpp
cfe/trunk/test/SemaCXX/static-cast.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Mar 16 18:22:08 2009
@@ -59,7 +59,8 @@
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
- llvm::FoldingSet<ReferenceType> ReferenceTypes;
+ llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
+ llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
@@ -207,9 +208,13 @@
/// of the specified type.
QualType getBlockPointerType(QualType T);
- /// getReferenceType - Return the uniqued reference to the type for a
- /// reference to the specified type.
- QualType getReferenceType(QualType T);
+ /// getLValueReferenceType - Return the uniqued reference to the type for an
+ /// lvalue reference to the specified type.
+ QualType getLValueReferenceType(QualType T);
+
+ /// getRValueReferenceType - Return the uniqued reference to the type for an
+ /// rvalue reference to the specified type.
+ QualType getRValueReferenceType(QualType T);
/// getMemberPointerType - Return the uniqued reference to the type for a
/// member pointer to the specified type in the specified class. The class
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Mar 16 18:22:08 2009
@@ -337,6 +337,8 @@
bool isPointerType() const;
bool isBlockPointerType() const;
bool isReferenceType() const;
+ bool isLValueReferenceType() const;
+ bool isRValueReferenceType() const;
bool isFunctionPointerType() const;
bool isMemberPointerType() const;
bool isMemberFunctionPointerType() const;
@@ -383,6 +385,8 @@
const PointerType *getAsPointerType() const;
const BlockPointerType *getAsBlockPointerType() const;
const ReferenceType *getAsReferenceType() const;
+ const LValueReferenceType *getAsLValueReferenceType() const;
+ const RValueReferenceType *getAsRValueReferenceType() const;
const MemberPointerType *getAsMemberPointerType() const;
const TagType *getAsTagType() const;
const RecordType *getAsRecordType() const;
@@ -674,19 +678,17 @@
friend class Type;
};
-/// ReferenceType - C++ 8.3.2 - Reference Declarators.
+/// ReferenceType - Base for LValueReferenceType and RValueReferenceType
///
class ReferenceType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
- ReferenceType(QualType Referencee, QualType CanonicalRef) :
- Type(Reference, CanonicalRef, Referencee->isDependentType()),
+protected:
+ ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) :
+ Type(tc, CanonicalRef, Referencee->isDependentType()),
PointeeType(Referencee) {
}
- friend class ASTContext; // ASTContext creates these.
public:
- virtual void getAsStringInternal(std::string &InnerString) const;
-
QualType getPointeeType() const { return PointeeType; }
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -696,11 +698,52 @@
ID.AddPointer(Referencee.getAsOpaquePtr());
}
- static bool classof(const Type *T) { return T->getTypeClass() == Reference; }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LValueReference ||
+ T->getTypeClass() == RValueReference;
+ }
static bool classof(const ReferenceType *) { return true; }
protected:
virtual void EmitImpl(llvm::Serializer& S) const;
+};
+
+/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
+///
+class LValueReferenceType : public ReferenceType {
+ LValueReferenceType(QualType Referencee, QualType CanonicalRef) :
+ ReferenceType(LValueReference, Referencee, CanonicalRef) {
+ }
+ friend class ASTContext; // ASTContext creates these
+public:
+ virtual void getAsStringInternal(std::string &InnerString) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LValueReference;
+ }
+ static bool classof(const LValueReferenceType *) { return true; }
+
+protected:
+ static Type* CreateImpl(ASTContext& Context, llvm::Deserializer& D);
+ friend class Type;
+};
+
+/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference
+///
+class RValueReferenceType : public ReferenceType {
+ RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
+ ReferenceType(RValueReference, Referencee, CanonicalRef) {
+ }
+ friend class ASTContext; // ASTContext creates these
+public:
+ virtual void getAsStringInternal(std::string &InnerString) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == RValueReference;
+ }
+ static bool classof(const RValueReferenceType *) { return true; }
+
+protected:
static Type* CreateImpl(ASTContext& Context, llvm::Deserializer& D);
friend class Type;
};
@@ -1798,6 +1841,12 @@
inline bool Type::isReferenceType() const {
return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
}
+inline bool Type::isLValueReferenceType() const {
+ return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isRValueReferenceType() const {
+ return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType());
+}
inline bool Type::isFunctionPointerType() const {
if (const PointerType* T = getAsPointerType())
return T->getPointeeType()->isFunctionType();
Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Mon Mar 16 18:22:08 2009
@@ -51,7 +51,9 @@
TYPE(Complex, Type)
TYPE(Pointer, Type)
TYPE(BlockPointer, Type)
-TYPE(Reference, Type)
+ABSTRACT_TYPE(Reference, Type)
+TYPE(LValueReference, Reference)
+TYPE(RValueReference, Reference)
TYPE(MemberPointer, Type)
ABSTRACT_TYPE(Array, Type)
TYPE(ConstantArray, ArrayType)
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Mon Mar 16 18:22:08 2009
@@ -304,9 +304,12 @@
"destructor cannot be declared using a typedef %0 of the class name")
// C++ initialization
+DIAG(err_lvalue_to_rvalue_ref, ERROR,
+ "rvalue reference cannot bind to lvalue")
// FIXME: passing in an English string as %1!
DIAG(err_not_reference_to_const_init, ERROR,
- "non-const reference to type %0 cannot be initialized with a %1 of type %2")
+ "non-const lvalue reference to type %0 cannot be initialized "
+ "with a %1 of type %2")
// FIXME: passing in an English string as %1!
DIAG(err_reference_init_drops_quals, ERROR,
"initialization of reference to type %0 with a %1 of type %2 drops qualifiers")
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Mar 16 18:22:08 2009
@@ -271,9 +271,11 @@
"destructor cannot be declared using a typedef %0 of the class name">;
// C++ initialization
+def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
// FIXME: passing in an English string as %1!
def err_not_reference_to_const_init : Error<
- "non-const reference to type %0 cannot be initialized with a %1 of type %2">;
+ "non-const lvalue reference to type %0 cannot be initialized "
+ "with a %1 of type %2">;
// FIXME: passing in an English string as %1!
def err_reference_init_drops_quals : Error<
"initialization of reference to type %0 with a %1 of type %2 drops "
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Mar 16 18:22:08 2009
@@ -85,9 +85,9 @@
fprintf(stderr, " %d types total.\n", (int)Types.size());
unsigned NumBuiltin = 0, NumPointer = 0, NumArray = 0, NumFunctionP = 0;
unsigned NumVector = 0, NumComplex = 0, NumBlockPointer = 0;
- unsigned NumFunctionNP = 0, NumTypeName = 0, NumTagged = 0, NumReference = 0;
- unsigned NumMemberPointer = 0;
-
+ unsigned NumFunctionNP = 0, NumTypeName = 0, NumTagged = 0;
+ unsigned NumLValueReference = 0, NumRValueReference = 0, NumMemberPointer = 0;
+
unsigned NumTagStruct = 0, NumTagUnion = 0, NumTagEnum = 0, NumTagClass = 0;
unsigned NumObjCInterfaces = 0, NumObjCQualifiedInterfaces = 0;
unsigned NumObjCQualifiedIds = 0;
@@ -101,8 +101,10 @@
++NumPointer;
else if (isa<BlockPointerType>(T))
++NumBlockPointer;
- else if (isa<ReferenceType>(T))
- ++NumReference;
+ else if (isa<LValueReferenceType>(T))
+ ++NumLValueReference;
+ else if (isa<RValueReferenceType>(T))
+ ++NumRValueReference;
else if (isa<MemberPointerType>(T))
++NumMemberPointer;
else if (isa<ComplexType>(T))
@@ -145,7 +147,8 @@
fprintf(stderr, " %d builtin types\n", NumBuiltin);
fprintf(stderr, " %d pointer types\n", NumPointer);
fprintf(stderr, " %d block pointer types\n", NumBlockPointer);
- fprintf(stderr, " %d reference types\n", NumReference);
+ fprintf(stderr, " %d lvalue reference types\n", NumLValueReference);
+ fprintf(stderr, " %d rvalue reference types\n", NumRValueReference);
fprintf(stderr, " %d member pointer types\n", NumMemberPointer);
fprintf(stderr, " %d complex types\n", NumComplex);
fprintf(stderr, " %d array types\n", NumArray);
@@ -165,10 +168,12 @@
NumObjCQualifiedIds);
fprintf(stderr, " %d typeof types\n", NumTypeOfTypes);
fprintf(stderr, " %d typeof exprs\n", NumTypeOfExprTypes);
-
+
fprintf(stderr, "Total bytes = %d\n", int(NumBuiltin*sizeof(BuiltinType)+
NumPointer*sizeof(PointerType)+NumArray*sizeof(ArrayType)+
NumComplex*sizeof(ComplexType)+NumVector*sizeof(VectorType)+
+ NumLValueReference*sizeof(LValueReferenceType)+
+ NumRValueReference*sizeof(RValueReferenceType)+
NumMemberPointer*sizeof(MemberPointerType)+
NumFunctionP*sizeof(FunctionProtoType)+
NumFunctionNP*sizeof(FunctionNoProtoType)+
@@ -411,7 +416,8 @@
Align = Target.getPointerAlign(AS);
break;
}
- case Type::Reference:
+ case Type::LValueReference:
+ case Type::RValueReference:
// "When applied to a reference or a reference type, the result is the size
// of the referenced type." C++98 5.3.3p2: expr.sizeof.
// FIXME: This is wrong for struct layout: a reference in a struct has
@@ -910,32 +916,65 @@
return QualType(New, 0);
}
-/// getReferenceType - Return the uniqued reference to the type for a reference
-/// to the specified type.
-QualType ASTContext::getReferenceType(QualType T) {
+/// getLValueReferenceType - Return the uniqued reference to the type for an
+/// lvalue reference to the specified type.
+QualType ASTContext::getLValueReferenceType(QualType T) {
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
ReferenceType::Profile(ID, T);
void *InsertPos = 0;
- if (ReferenceType *RT = ReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
+ if (LValueReferenceType *RT =
+ LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
-
+
// If the referencee type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
- Canonical = getReferenceType(getCanonicalType(T));
-
+ Canonical = getLValueReferenceType(getCanonicalType(T));
+
+ // Get the new insert position for the node we care about.
+ LValueReferenceType *NewIP =
+ LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
+ }
+
+ LValueReferenceType *New = new (*this,8) LValueReferenceType(T, Canonical);
+ Types.push_back(New);
+ LValueReferenceTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// getRValueReferenceType - Return the uniqued reference to the type for an
+/// rvalue reference to the specified type.
+QualType ASTContext::getRValueReferenceType(QualType T) {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ ReferenceType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (RValueReferenceType *RT =
+ RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(RT, 0);
+
+ // If the referencee type isn't canonical, this won't be a canonical type
+ // either, so fill in the canonical type field.
+ QualType Canonical;
+ if (!T->isCanonical()) {
+ Canonical = getRValueReferenceType(getCanonicalType(T));
+
// Get the new insert position for the node we care about.
- ReferenceType *NewIP = ReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
+ RValueReferenceType *NewIP =
+ RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
}
- ReferenceType *New = new (*this,8) ReferenceType(T, Canonical);
+ RValueReferenceType *New = new (*this,8) RValueReferenceType(T, Canonical);
Types.push_back(New);
- ReferenceTypes.InsertNode(New, InsertPos);
+ RValueReferenceTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
@@ -2641,9 +2680,12 @@
// C++ [expr]: If an expression initially has the type "reference to T", the
// type is adjusted to "T" prior to any further analysis, the expression
// designates the object or function denoted by the reference, and the
- // expression is an lvalue.
+ // expression is an lvalue unless the reference is an rvalue reference and
+ // the expression is a function call (possibly inside parentheses).
// FIXME: C++ shouldn't be going through here! The rules are different
// enough that they should be handled separately.
+ // FIXME: Merging of lvalue and rvalue references is incorrect. C++ *really*
+ // shouldn't be going through here!
if (const ReferenceType *RT = LHS->getAsReferenceType())
LHS = RT->getPointeeType();
if (const ReferenceType *RT = RHS->getAsReferenceType())
@@ -2746,7 +2788,8 @@
assert(false && "Non-canonical and dependent types shouldn't get here");
return QualType();
- case Type::Reference:
+ case Type::LValueReference:
+ case Type::RValueReference:
case Type::MemberPointer:
assert(false && "C++ should never be in mergeTypes");
return QualType();
Modified: cfe/trunk/lib/AST/Builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Builtins.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Builtins.cpp (original)
+++ cfe/trunk/lib/AST/Builtins.cpp Mon Mar 16 18:22:08 2009
@@ -183,7 +183,7 @@
if (Type->isArrayType()) {
Type = Context.getArrayDecayedType(Type);
} else {
- Type = Context.getReferenceType(Type);
+ Type = Context.getLValueReferenceType(Type);
}
break;
case 'V': {
@@ -224,8 +224,9 @@
Type = Context.getPointerType(Type);
break;
case '&':
- Type = Context.getReferenceType(Type);
+ Type = Context.getLValueReferenceType(Type);
break;
+ // FIXME: There's no way to have a built-in with an rvalue ref arg.
case 'C':
Type = Type.getQualifiedType(QualType::Const);
break;
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Mar 16 18:22:08 2009
@@ -102,7 +102,7 @@
continue;
bool AcceptsConst = true;
QualType ArgType = FnType->getArgType(0);
- if (const ReferenceType *Ref = ArgType->getAsReferenceType()) {
+ if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType()) {
ArgType = Ref->getPointeeType();
// Is it a non-const reference?
if (!ArgType.isConstQualified())
@@ -152,7 +152,7 @@
assert(FnType && "Overloaded operator has no proto function type.");
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
QualType ArgType = FnType->getArgType(0);
- if (const ReferenceType *Ref = ArgType->getAsReferenceType())
+ if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType())
ArgType = Ref->getPointeeType();
ArgType = ArgType.getUnqualifiedType();
@@ -263,8 +263,9 @@
const ParmVarDecl *Param = getParamDecl(0);
- // Do we have a reference type?
- const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
+ // Do we have a reference type? Rvalue references don't count.
+ const LValueReferenceType *ParamRefType =
+ Param->getType()->getAsLValueReferenceType();
if (!ParamRefType)
return false;
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Mar 16 18:22:08 2009
@@ -575,10 +575,7 @@
if (TR->isVoidType() && !Ctx.getCanonicalType(TR).getCVRQualifiers())
return LV_IncompleteVoidType;
- /// FIXME: Expressions can't have reference type, so the following
- /// isn't needed.
- if (TR->isReferenceType()) // C++ [expr]
- return LV_Valid;
+ assert(!TR->isReferenceType() && "Expressions can't have reference type.");
// the type looks fine, now check the expression
switch (getStmtClass()) {
@@ -691,16 +688,16 @@
case CallExprClass:
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass: {
- // C++ [expr.call]p10:
+ // C++0x [expr.call]p10
// A function call is an lvalue if and only if the result type
- // is a reference.
+ // is an lvalue reference.
QualType CalleeType = cast<CallExpr>(this)->getCallee()->getType();
if (const PointerType *FnTypePtr = CalleeType->getAsPointerType())
CalleeType = FnTypePtr->getPointeeType();
if (const FunctionType *FnType = CalleeType->getAsFunctionType())
- if (FnType->getResultType()->isReferenceType())
+ if (FnType->getResultType()->isLValueReferenceType())
return LV_Valid;
-
+
break;
}
case CompoundLiteralExprClass: // C99 6.5.2.5p5
@@ -733,10 +730,11 @@
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
// The result of an explicit cast is an lvalue if the type we are
- // casting to is a reference type. See C++ [expr.cast]p1,
+ // casting to is an lvalue reference type. See C++ [expr.cast]p1,
// C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2,
// C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1.
- if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isReferenceType())
+ if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->
+ isLValueReferenceType())
return LV_Valid;
break;
case CXXTypeidExprClass:
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Mar 16 18:22:08 2009
@@ -696,6 +696,7 @@
/// as GCC.
static int EvaluateBuiltinClassifyType(const CallExpr *E) {
// The following enum mimics the values returned by GCC.
+ // FIXME: Does GCC differ between lvalue and rvalue references here?
enum gcc_type_class {
no_type_class = -1,
void_type_class, integer_type_class, char_type_class,
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Mar 16 18:22:08 2009
@@ -117,7 +117,8 @@
case IncompleteArray:
case FunctionProto:
case FunctionNoProto:
- case Reference:
+ case LValueReference:
+ case RValueReference:
case Record:
return true;
default:
@@ -264,9 +265,9 @@
// If this is directly a reference type, return it.
if (const ReferenceType *RTy = dyn_cast<ReferenceType>(this))
return RTy;
-
+
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ReferenceType>(CanonicalType)) {
+ if (!isa<ReferenceType>(CanonicalType)) {
// Look through type qualifiers
if (isa<ReferenceType>(CanonicalType.getUnqualifiedType()))
return CanonicalType.getUnqualifiedType()->getAsReferenceType();
@@ -278,6 +279,42 @@
return getDesugaredType()->getAsReferenceType();
}
+const LValueReferenceType *Type::getAsLValueReferenceType() const {
+ // If this is directly an lvalue reference type, return it.
+ if (const LValueReferenceType *RTy = dyn_cast<LValueReferenceType>(this))
+ return RTy;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<LValueReferenceType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<LValueReferenceType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsLValueReferenceType();
+ return 0;
+ }
+
+ // If this is a typedef for an lvalue reference type, strip the typedef off
+ // without losing all typedef information.
+ return getDesugaredType()->getAsLValueReferenceType();
+}
+
+const RValueReferenceType *Type::getAsRValueReferenceType() const {
+ // If this is directly an rvalue reference type, return it.
+ if (const RValueReferenceType *RTy = dyn_cast<RValueReferenceType>(this))
+ return RTy;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<RValueReferenceType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<RValueReferenceType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsRValueReferenceType();
+ return 0;
+ }
+
+ // If this is a typedef for an rvalue reference type, strip the typedef off
+ // without losing all typedef information.
+ return getDesugaredType()->getAsRValueReferenceType();
+}
+
const MemberPointerType *Type::getAsMemberPointerType() const {
// If this is directly a member pointer type, return it.
if (const MemberPointerType *MTy = dyn_cast<MemberPointerType>(this))
@@ -1116,14 +1153,25 @@
PointeeType.getAsStringInternal(S);
}
-void ReferenceType::getAsStringInternal(std::string &S) const {
+void LValueReferenceType::getAsStringInternal(std::string &S) const {
S = '&' + S;
-
+
// Handle things like 'int (&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
if (isa<ArrayType>(getPointeeType()))
S = '(' + S + ')';
-
+
+ getPointeeType().getAsStringInternal(S);
+}
+
+void RValueReferenceType::getAsStringInternal(std::string &S) const {
+ S = "&&" + S;
+
+ // Handle things like 'int (&&A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(getPointeeType()))
+ S = '(' + S + ')';
+
getPointeeType().getAsStringInternal(S);
}
@@ -1133,7 +1181,7 @@
C += "::*";
S = C + S;
- // Handle things like 'int (&A)[4];' correctly.
+ // Handle things like 'int (Cls::*A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
if (isa<ArrayType>(getPointeeType()))
S = '(' + S + ')';
Modified: cfe/trunk/lib/AST/TypeSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeSerialization.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypeSerialization.cpp (original)
+++ cfe/trunk/lib/AST/TypeSerialization.cpp Mon Mar 16 18:22:08 2009
@@ -107,8 +107,12 @@
D.RegisterPtr(PtrID, BlockPointerType::CreateImpl(Context, D));
break;
- case Type::Reference:
- D.RegisterPtr(PtrID, ReferenceType::CreateImpl(Context, D));
+ case Type::LValueReference:
+ D.RegisterPtr(PtrID, LValueReferenceType::CreateImpl(Context, D));
+ break;
+
+ case Type::RValueReference:
+ D.RegisterPtr(PtrID, RValueReferenceType::CreateImpl(Context, D));
break;
case Type::Record:
@@ -261,8 +265,12 @@
S.Emit(getPointeeType());
}
-Type* ReferenceType::CreateImpl(ASTContext& Context, Deserializer& D) {
- return Context.getReferenceType(QualType::ReadVal(D)).getTypePtr();
+Type* LValueReferenceType::CreateImpl(ASTContext& Context, Deserializer& D) {
+ return Context.getLValueReferenceType(QualType::ReadVal(D)).getTypePtr();
+}
+
+Type* RValueReferenceType::CreateImpl(ASTContext& Context, Deserializer& D) {
+ return Context.getRValueReferenceType(QualType::ReadVal(D)).getTypePtr();
}
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Mar 16 18:22:08 2009
@@ -502,7 +502,8 @@
assert(false && "Dependent types cannot show up in debug information");
case Type::Complex:
- case Type::Reference:
+ case Type::LValueReference:
+ case Type::RValueReference:
case Type::Vector:
case Type::ExtVector:
case Type::ExtQual:
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Mar 16 18:22:08 2009
@@ -571,6 +571,7 @@
return V;
} else if (E->getType()->isReferenceType()) {
+ // FIXME: An expression cannot have reference type.
return EmitLValue(Op).getAddress();
}
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Mon Mar 16 18:22:08 2009
@@ -266,7 +266,8 @@
ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType());
return llvm::StructType::get(EltTy, EltTy, NULL);
}
- case Type::Reference: {
+ case Type::LValueReference:
+ case Type::RValueReference: {
const ReferenceType &RTy = cast<ReferenceType>(Ty);
QualType ETy = RTy.getPointeeType();
llvm::OpaqueType *PointeeType = llvm::OpaqueType::get();
Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Mon Mar 16 18:22:08 2009
@@ -365,12 +365,17 @@
mangleType(PT->getPointeeType());
}
// ::= R <type> # reference-to
- // ::= O <type> # rvalue reference-to (C++0x)
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(T.getTypePtr())) {
- // FIXME: rvalue references
+ else if (const LValueReferenceType *RT =
+ dyn_cast<LValueReferenceType>(T.getTypePtr())) {
Out << 'R';
mangleType(RT->getPointeeType());
}
+ // ::= O <type> # rvalue reference-to (C++0x)
+ else if (const RValueReferenceType *RT =
+ dyn_cast<RValueReferenceType>(T.getTypePtr())) {
+ Out << 'O';
+ mangleType(RT->getPointeeType());
+ }
// ::= C <type> # complex pair (C 2000)
else if (const ComplexType *CT = dyn_cast<ComplexType>(T.getTypePtr())) {
Out << 'C';
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Mar 16 18:22:08 2009
@@ -272,7 +272,7 @@
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,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Mar 16 18:22:08 2009
@@ -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.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Mar 16 18:22:08 2009
@@ -764,7 +764,7 @@
// 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 @@
// FIXME: Create a temporary object by calling the copy
// constructor.
ImpCastExprToType(From, ToType.getNonReferenceType(),
- ToType->isReferenceType());
+ ToType->isLValueReferenceType());
return false;
}
@@ -893,8 +893,10 @@
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:
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Mar 16 18:22:08 2009
@@ -121,7 +121,7 @@
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())
Modified: cfe/trunk/lib/Sema/SemaNamedCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaNamedCast.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaNamedCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaNamedCast.cpp Mon Mar 16 18:22:08 2009
@@ -115,9 +115,10 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
<< 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();
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Mar 16 18:22:08 2009
@@ -519,8 +519,10 @@
// 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 @@
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 @@
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 @@
continue;
QualType ParamTypes[2] = {
- Context.getReferenceType(*Ptr), Context.IntTy
+ Context.getLValueReferenceType(*Ptr), Context.IntTy
};
// Without volatile
@@ -2778,7 +2780,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Mar 16 18:22:08 2009
@@ -218,14 +218,24 @@
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
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Mar 16 18:22:08 2009
@@ -319,8 +319,16 @@
///
/// \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 @@
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 @@
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: {
Modified: cfe/trunk/test/Parser/cxx-reference.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-reference.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-reference.cpp (original)
+++ cfe/trunk/test/Parser/cxx-reference.cpp Mon Mar 16 18:22:08 2009
@@ -1,4 +1,4 @@
-// RUN: clang -fsyntax-only -verify -std=c++0x %s
+// RUN: clang -fsyntax-only -verify %s
extern char *bork;
char *& bar = bork;
@@ -17,8 +17,3 @@
int & volatile Y = val; // expected-error {{'volatile' qualifier may not be applied to a reference}}
int & const volatile Z = val; /* expected-error {{'const' qualifier may not be applied}} \
expected-error {{'volatile' qualifier may not be applied}} */
-
-int && r1(int &&a);
-
-typedef int && R;
-void r2(const R a);
Added: cfe/trunk/test/Parser/cxx0x-rvalue-reference.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-rvalue-reference.cpp?rev=67059&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-rvalue-reference.cpp (added)
+++ cfe/trunk/test/Parser/cxx0x-rvalue-reference.cpp Mon Mar 16 18:22:08 2009
@@ -0,0 +1,6 @@
+// RUN: clang -fsyntax-only -verify -std=c++0x %s
+
+int && r1(int &&a);
+
+typedef int && R;
+void r2(const R a);
Modified: cfe/trunk/test/SemaCXX/convert-to-bool.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/convert-to-bool.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/convert-to-bool.cpp (original)
+++ cfe/trunk/test/SemaCXX/convert-to-bool.cpp Mon Mar 16 18:22:08 2009
@@ -49,7 +49,7 @@
}
void test_explicit_conv_to_ref(ExplicitConvToRef ecr) {
- int& i1 = ecr; // expected-error{{non-const reference to type 'int' cannot be initialized with a value of type 'struct ExplicitConvToRef'}}
+ int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot be initialized with a value of type 'struct ExplicitConvToRef'}}
int& i2(ecr); // okay
}
@@ -61,7 +61,7 @@
};
void test_copy_init_conversions(C c) {
- A &a = c; // expected-error{{non-const reference to type 'struct A' cannot be initialized with a value of type 'struct C'}}
+ A &a = c; // expected-error{{non-const lvalue reference to type 'struct A' cannot be initialized with a value of type 'struct C'}}
B &b = b; // okay
}
Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Mon Mar 16 18:22:08 2009
@@ -67,7 +67,7 @@
float &f1 = (e1 == e2);
float &f2 = (enum1 == e2);
float &f3 = (e1 == enum2);
- float &f4 = (enum1 == enum2); // expected-error{{non-const reference to type 'float' cannot be initialized with a temporary of type '_Bool'}}
+ float &f4 = (enum1 == enum2); // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a temporary of type '_Bool'}}
}
Modified: cfe/trunk/test/SemaCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/references.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/references.cpp (original)
+++ cfe/trunk/test/SemaCXX/references.cpp Mon Mar 16 18:22:08 2009
@@ -44,9 +44,9 @@
// C++ [dcl.init.ref]p5b2
void test4() {
- double& rd2 = 2.0; // expected-error{{non-const reference to type 'double' cannot be initialized with a temporary of type 'double'}}
+ double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a temporary of type 'double'}}
int i = 2;
- double& rd3 = i; // expected-error{{non-const reference to type 'double' cannot be initialized with a value of type 'int'}}
+ double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a value of type 'int'}}
const A& rca = fB();
}
Added: cfe/trunk/test/SemaCXX/rval-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/rval-references.cpp?rev=67059&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/rval-references.cpp (added)
+++ cfe/trunk/test/SemaCXX/rval-references.cpp Mon Mar 16 18:22:08 2009
@@ -0,0 +1,33 @@
+// RUN: clang -fsyntax-only -verify -std=c++0x %s
+
+typedef int&& irr;
+typedef irr& ilr_c1; // Collapses to int&
+typedef int& ilr;
+typedef ilr&& ilr_c2; // Collapses to int&
+
+irr ret_irr() {
+ return 0;
+}
+
+struct not_int {};
+
+int over(int&);
+not_int over(int&&);
+
+void f() {
+ int &&virr1; // expected-error {{declaration of reference variable 'virr1' requires an initializer}}
+ int &&virr2 = 0;
+ // FIXME: named rvalue references are lvalues!
+ //int &&virr3 = virr1; // xpected-error {{rvalue reference cannot bind to lvalue}}
+ int i1 = 0;
+ int &&virr4 = i1; // expected-error {{rvalue reference cannot bind to lvalue}}
+ int &&virr5 = ret_irr();
+
+ int i2 = over(i1);
+ not_int ni1 = over(0);
+ int i3 = over(virr2);
+ not_int ni2 = over(ret_irr());
+
+ ilr_c1 vilr1 = i1;
+ ilr_c2 vilr2 = i1;
+}
Modified: cfe/trunk/test/SemaCXX/static-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-cast.cpp?rev=67059&r1=67058&r2=67059&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-cast.cpp Mon Mar 16 18:22:08 2009
@@ -54,7 +54,7 @@
//(void)static_cast<A*>((H*)0); // {{static_cast from 'struct H *' to 'struct A *' is not allowed}}
(void)static_cast<int>((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}}
(void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'struct B **' to 'struct A **' is not allowed}}
- (void)static_cast<char&>(i); // expected-error {{non-const reference to type 'char' cannot be initialized with a value of type 'int'}}
+ (void)static_cast<char&>(i); // expected-error {{non-const lvalue reference to type 'char' cannot be initialized with a value of type 'int'}}
}
// Anything to void
@@ -86,7 +86,7 @@
(void)static_cast<H*>((A*)0); // expected-error {{ambiguous static_cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}}
(void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous static_cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}}
(void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'struct B *' to 'struct E *' is not allowed}}
- (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const reference to type 'struct E' cannot be initialized with a value of type 'struct B'}}
+ (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'struct E' cannot be initialized with a value of type 'struct B'}}
// TODO: Test inaccessible base in context where it's accessible, i.e.
// member function and friend.
More information about the cfe-commits
mailing list