forked from OSchip/llvm-project
Update ImplicitCastExpr to be able to represent an XValue.
llvm-svn: 108807
This commit is contained in:
parent
08d047666a
commit
c57d34bc35
|
@ -258,7 +258,6 @@ public:
|
|||
/// function returning an rvalue reference.
|
||||
/// lvalues and xvalues are collectively referred to as glvalues, while
|
||||
/// prvalues and xvalues together form rvalues.
|
||||
/// If a
|
||||
Classification Classify(ASTContext &Ctx) const {
|
||||
return ClassifyImpl(Ctx, 0);
|
||||
}
|
||||
|
@ -2045,24 +2044,33 @@ public:
|
|||
///
|
||||
/// In C, implicit casts always produce rvalues. However, in C++, an
|
||||
/// implicit cast whose result is being bound to a reference will be
|
||||
/// an lvalue. For example:
|
||||
/// an lvalue or xvalue. For example:
|
||||
///
|
||||
/// @code
|
||||
/// class Base { };
|
||||
/// class Derived : public Base { };
|
||||
/// Derived &&ref();
|
||||
/// void f(Derived d) {
|
||||
/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base
|
||||
/// Base& b = d; // initializer is an ImplicitCastExpr
|
||||
/// // to an lvalue of type Base
|
||||
/// Base&& r = ref(); // initializer is an ImplicitCastExpr
|
||||
/// // to an xvalue of type Base
|
||||
/// }
|
||||
/// @endcode
|
||||
class ImplicitCastExpr : public CastExpr {
|
||||
/// LvalueCast - Whether this cast produces an lvalue.
|
||||
bool LvalueCast;
|
||||
public:
|
||||
enum ResultCategory {
|
||||
RValue, LValue, XValue
|
||||
};
|
||||
|
||||
private:
|
||||
/// Category - The category this cast produces.
|
||||
ResultCategory Category;
|
||||
|
||||
public:
|
||||
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
|
||||
CXXBaseSpecifierArray BasePath, bool Lvalue)
|
||||
: CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath),
|
||||
LvalueCast(Lvalue) { }
|
||||
CXXBaseSpecifierArray BasePath, ResultCategory Cat)
|
||||
: CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), Category(Cat) { }
|
||||
|
||||
/// \brief Construct an empty implicit cast.
|
||||
explicit ImplicitCastExpr(EmptyShell Shell)
|
||||
|
@ -2072,11 +2080,11 @@ public:
|
|||
return getSubExpr()->getSourceRange();
|
||||
}
|
||||
|
||||
/// isLvalueCast - Whether this cast produces an lvalue.
|
||||
bool isLvalueCast() const { return LvalueCast; }
|
||||
/// getCategory - The value category this cast produces.
|
||||
ResultCategory getCategory() const { return Category; }
|
||||
|
||||
/// setLvalueCast - Set whether this cast produces an lvalue.
|
||||
void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; }
|
||||
/// setCategory - Set the value category this cast produces.
|
||||
void setCategory(ResultCategory Cat) { Category = Cat; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == ImplicitCastExprClass;
|
||||
|
@ -2098,8 +2106,8 @@ public:
|
|||
/// actual type of the expression as determined by semantic
|
||||
/// analysis. These types may differ slightly. For example, in C++ one
|
||||
/// can cast to a reference type, which indicates that the resulting
|
||||
/// expression will be an lvalue. The reference type, however, will
|
||||
/// not be used as the type of the expression.
|
||||
/// expression will be an lvalue or xvalue. The reference type, however,
|
||||
/// will not be used as the type of the expression.
|
||||
class ExplicitCastExpr : public CastExpr {
|
||||
/// TInfo - Source type info for the (written) type
|
||||
/// this expression is casting to.
|
||||
|
|
|
@ -2900,7 +2900,7 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
|
|||
CXXBaseSpecifierArray BasePath;
|
||||
return new (Importer.getToContext()) ImplicitCastExpr(T, E->getCastKind(),
|
||||
SubExpr, BasePath,
|
||||
E->isLvalueCast());
|
||||
E->getCategory());
|
||||
}
|
||||
|
||||
Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
|
||||
|
|
|
@ -1508,7 +1508,8 @@ FieldDecl *Expr::getBitField() {
|
|||
Expr *E = this->IgnoreParens();
|
||||
|
||||
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
||||
if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
|
||||
if (ICE->getCategory() != ImplicitCastExpr::RValue &&
|
||||
ICE->getCastKind() == CastExpr::CK_NoOp)
|
||||
E = ICE->getSubExpr()->IgnoreParens();
|
||||
else
|
||||
break;
|
||||
|
@ -1530,7 +1531,8 @@ bool Expr::refersToVectorElement() const {
|
|||
const Expr *E = this->IgnoreParens();
|
||||
|
||||
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
||||
if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
|
||||
if (ICE->getCategory() != ImplicitCastExpr::RValue &&
|
||||
ICE->getCastKind() == CastExpr::CK_NoOp)
|
||||
E = ICE->getSubExpr()->IgnoreParens();
|
||||
else
|
||||
break;
|
||||
|
|
|
@ -134,10 +134,16 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
// Implicit casts are lvalues if they're lvalue casts. Other than that, we
|
||||
// only specifically record class temporaries.
|
||||
case Expr::ImplicitCastExprClass:
|
||||
if (cast<ImplicitCastExpr>(E)->isLvalueCast())
|
||||
switch (cast<ImplicitCastExpr>(E)->getCategory()) {
|
||||
case ImplicitCastExpr::RValue:
|
||||
return Lang.CPlusPlus && E->getType()->isRecordType() ?
|
||||
Cl::CL_ClassTemporary : Cl::CL_PRValue;
|
||||
case ImplicitCastExpr::LValue:
|
||||
return Cl::CL_LValue;
|
||||
return Lang.CPlusPlus && E->getType()->isRecordType() ?
|
||||
Cl::CL_ClassTemporary : Cl::CL_PRValue;
|
||||
case ImplicitCastExpr::XValue:
|
||||
return Cl::CL_XValue;
|
||||
}
|
||||
llvm_unreachable("Invalid value category of implicit cast.");
|
||||
|
||||
// C++ [expr.prim.general]p4: The presence of parentheses does not affect
|
||||
// whether the expression is an lvalue.
|
||||
|
|
|
@ -340,8 +340,16 @@ void StmtDumper::VisitCastExpr(CastExpr *Node) {
|
|||
|
||||
void StmtDumper::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
|
||||
VisitCastExpr(Node);
|
||||
if (Node->isLvalueCast())
|
||||
switch (Node->getCategory()) {
|
||||
case ImplicitCastExpr::LValue:
|
||||
OS << " lvalue";
|
||||
break;
|
||||
case ImplicitCastExpr::XValue:
|
||||
OS << " xvalue";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
|
||||
|
|
|
@ -325,7 +325,7 @@ void StmtProfiler::VisitCastExpr(CastExpr *S) {
|
|||
|
||||
void StmtProfiler::VisitImplicitCastExpr(ImplicitCastExpr *S) {
|
||||
VisitCastExpr(S);
|
||||
ID.AddBoolean(S->isLvalueCast());
|
||||
ID.AddInteger(S->getCategory());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitExplicitCastExpr(ExplicitCastExpr *S) {
|
||||
|
|
|
@ -897,8 +897,8 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
|
|||
}
|
||||
|
||||
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
|
||||
// And that lvalue casts are never null.
|
||||
if (ICE->isLvalueCast())
|
||||
// And that glvalue casts are never null.
|
||||
if (ICE->getCategory() != ImplicitCastExpr::RValue)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -404,7 +404,8 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
|||
if (getContext().getCanonicalType(Ivar->getType()) !=
|
||||
getContext().getCanonicalType(ArgDecl->getType())) {
|
||||
ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
|
||||
CXXBaseSpecifierArray(), false);
|
||||
CXXBaseSpecifierArray(),
|
||||
ImplicitCastExpr::RValue);
|
||||
BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
|
||||
Ivar->getType(), Loc);
|
||||
EmitStmt(&Assign);
|
||||
|
|
|
@ -588,7 +588,7 @@ void PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
|
|||
|
||||
void PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
|
||||
VisitCastExpr(E);
|
||||
E->setLvalueCast(Record[Idx++]);
|
||||
E->setCategory(static_cast<ImplicitCastExpr::ResultCategory>(Record[Idx++]));
|
||||
}
|
||||
|
||||
void PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
|
||||
|
|
|
@ -602,7 +602,7 @@ void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
|
|||
|
||||
void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
|
||||
VisitCastExpr(E);
|
||||
Record.push_back(E->isLvalueCast());
|
||||
Record.push_back(E->getCategory());
|
||||
Code = pch::EXPR_IMPLICIT_CAST;
|
||||
}
|
||||
|
||||
|
|
|
@ -2108,7 +2108,7 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
|
|||
ImplicitCastExpr *ICE =
|
||||
new (Context) ImplicitCastExpr(pToFunc, CastExpr::CK_Unknown,
|
||||
DRE, CXXBaseSpecifierArray(),
|
||||
/*isLvalue=*/false);
|
||||
ImplicitCastExpr::RValue);
|
||||
|
||||
const FunctionType *FT = msgSendType->getAs<FunctionType>();
|
||||
|
||||
|
@ -5609,7 +5609,9 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
|
|||
}
|
||||
#if 0
|
||||
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
|
||||
CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
|
||||
CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
|
||||
ICE->getSubExpr(),
|
||||
SourceLocation());
|
||||
// Get the new text.
|
||||
std::string SStr;
|
||||
llvm::raw_string_ostream Buf(SStr);
|
||||
|
|
|
@ -152,10 +152,11 @@ Sema::~Sema() {
|
|||
|
||||
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
|
||||
/// If there is already an implicit cast, merge into the existing one.
|
||||
/// If isLvalue, the result of the cast is an lvalue.
|
||||
/// The result is of the given category.
|
||||
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
|
||||
CastExpr::CastKind Kind,
|
||||
bool isLvalue, CXXBaseSpecifierArray BasePath) {
|
||||
ImplicitCastExpr::ResultCategory Category,
|
||||
CXXBaseSpecifierArray BasePath) {
|
||||
QualType ExprTy = Context.getCanonicalType(Expr->getType());
|
||||
QualType TypeTy = Context.getCanonicalType(Ty);
|
||||
|
||||
|
@ -186,12 +187,21 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
|
|||
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
|
||||
if (ImpCast->getCastKind() == Kind && BasePath.empty()) {
|
||||
ImpCast->setType(Ty);
|
||||
ImpCast->setLvalueCast(isLvalue);
|
||||
ImpCast->setCategory(Category);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, BasePath, isLvalue);
|
||||
Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, BasePath, Category);
|
||||
}
|
||||
|
||||
ImplicitCastExpr::ResultCategory Sema::CastCategory(Expr *E) {
|
||||
Expr::Classification Classification = E->Classify(Context);
|
||||
return Classification.isRValue() ?
|
||||
ImplicitCastExpr::RValue :
|
||||
(Classification.isLValue() ?
|
||||
ImplicitCastExpr::LValue :
|
||||
ImplicitCastExpr::XValue);
|
||||
}
|
||||
|
||||
void Sema::DeleteExpr(ExprTy *E) {
|
||||
|
|
|
@ -4153,11 +4153,16 @@ public:
|
|||
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
||||
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
|
||||
|
||||
/// CastCategory - Get the correct forwarded implicit cast result category
|
||||
/// from the inner expression.
|
||||
ImplicitCastExpr::ResultCategory CastCategory(Expr *E);
|
||||
|
||||
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
|
||||
/// cast. If there is already an implicit cast, merge into the existing one.
|
||||
/// If isLvalue, the result of the cast is an lvalue.
|
||||
void ImpCastExprToType(Expr *&Expr, QualType Type, CastExpr::CastKind Kind,
|
||||
bool isLvalue = false,
|
||||
ImplicitCastExpr::ResultCategory Category =
|
||||
ImplicitCastExpr::RValue,
|
||||
CXXBaseSpecifierArray BasePath =
|
||||
CXXBaseSpecifierArray());
|
||||
|
||||
|
|
|
@ -6782,7 +6782,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
|
|||
CastExpr::CK_IntegralCast,
|
||||
ECD->getInitExpr(),
|
||||
CXXBaseSpecifierArray(),
|
||||
/*isLvalue=*/false));
|
||||
ImplicitCastExpr::RValue));
|
||||
if (getLangOptions().CPlusPlus)
|
||||
// C++ [dcl.enum]p4: Following the closing brace of an
|
||||
// enum-specifier, each enumerator has the type of its
|
||||
|
|
|
@ -1536,9 +1536,9 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
|
|||
QualType ArgTy =
|
||||
SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
|
||||
ParamType.getQualifiers());
|
||||
SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
|
||||
SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
|
||||
CastExpr::CK_UncheckedDerivedToBase,
|
||||
/*isLvalue=*/true,
|
||||
ImplicitCastExpr::LValue,
|
||||
CXXBaseSpecifierArray(BaseSpec));
|
||||
|
||||
InitializationKind InitKind
|
||||
|
@ -4858,8 +4858,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
|
|||
// appropriately-qualified base type.
|
||||
Expr *From = OtherRef->Retain();
|
||||
ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
|
||||
CastExpr::CK_UncheckedDerivedToBase, /*isLvalue=*/true,
|
||||
CXXBaseSpecifierArray(Base));
|
||||
CastExpr::CK_UncheckedDerivedToBase,
|
||||
ImplicitCastExpr::LValue, CXXBaseSpecifierArray(Base));
|
||||
|
||||
// Dereference "this".
|
||||
OwningExprResult To = CreateBuiltinUnaryOp(Loc, UnaryOperator::Deref,
|
||||
|
@ -4871,7 +4871,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
|
|||
Context.getCVRQualifiedType(BaseType,
|
||||
CopyAssignOperator->getTypeQualifiers()),
|
||||
CastExpr::CK_UncheckedDerivedToBase,
|
||||
/*isLvalue=*/true, CXXBaseSpecifierArray(Base));
|
||||
ImplicitCastExpr::LValue, CXXBaseSpecifierArray(Base));
|
||||
To = Owned(ToE);
|
||||
|
||||
// Build the copy.
|
||||
|
|
|
@ -1441,9 +1441,8 @@ Sema::PerformObjectMemberConversion(Expr *&From,
|
|||
SourceRange FromRange = From->getSourceRange();
|
||||
SourceLocation FromLoc = FromRange.getBegin();
|
||||
|
||||
bool isLvalue
|
||||
= (From->isLvalue(Context) == Expr::LV_Valid) && !PointerConversions;
|
||||
|
||||
ImplicitCastExpr::ResultCategory Category = CastCategory(From);
|
||||
|
||||
// C++ [class.member.lookup]p8:
|
||||
// [...] Ambiguities can often be resolved by qualifying a name with its
|
||||
// class name.
|
||||
|
@ -1481,7 +1480,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
|
|||
if (PointerConversions)
|
||||
QType = Context.getPointerType(QType);
|
||||
ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase,
|
||||
isLvalue, BasePath);
|
||||
Category, BasePath);
|
||||
|
||||
FromType = QType;
|
||||
FromRecordType = QRecordType;
|
||||
|
@ -1518,7 +1517,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
|
|||
if (PointerConversions)
|
||||
UType = Context.getPointerType(UType);
|
||||
ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase,
|
||||
isLvalue, BasePath);
|
||||
Category, BasePath);
|
||||
FromType = UType;
|
||||
FromRecordType = URecordType;
|
||||
}
|
||||
|
@ -1535,7 +1534,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
|
|||
return true;
|
||||
|
||||
ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase,
|
||||
isLvalue, BasePath);
|
||||
Category, BasePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,10 +296,10 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
|
|||
return ExprError();
|
||||
|
||||
// C++ [expr.typeid]p3:
|
||||
// When typeid is applied to an expression other than an lvalue of a
|
||||
// When typeid is applied to an expression other than an glvalue of a
|
||||
// polymorphic class type [...] [the] expression is an unevaluated
|
||||
// operand. [...]
|
||||
if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) {
|
||||
if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
|
||||
isUnevaluatedOperand = false;
|
||||
|
||||
// We require a vtable to query the type at run time.
|
||||
|
@ -316,7 +316,7 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
|
|||
QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
|
||||
if (!Context.hasSameType(T, UnqualT)) {
|
||||
T = UnqualT;
|
||||
ImpCastExprToType(E, UnqualT, CastExpr::CK_NoOp, E->isLvalue(Context));
|
||||
ImpCastExprToType(E, UnqualT, CastExpr::CK_NoOp, CastCategory(E));
|
||||
Operand.release();
|
||||
Operand = Owned(E);
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
|
|||
// or "pointer to function returning T", [...]
|
||||
if (E->getType().hasQualifiers())
|
||||
ImpCastExprToType(E, E->getType().getUnqualifiedType(), CastExpr::CK_NoOp,
|
||||
E->isLvalue(Context) == Expr::LV_Valid);
|
||||
CastCategory(E));
|
||||
|
||||
DefaultFunctionArrayConversion(E);
|
||||
|
||||
|
@ -1809,7 +1809,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
|
|||
CXXBaseSpecifierArray BasePath;
|
||||
if (CheckPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess))
|
||||
return true;
|
||||
ImpCastExprToType(From, ToType, Kind, /*isLvalue=*/false, BasePath);
|
||||
ImpCastExprToType(From, ToType, Kind, ImplicitCastExpr::RValue, BasePath);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1821,7 +1821,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
|
|||
return true;
|
||||
if (CheckExceptionSpecCompatibility(From, ToType))
|
||||
return true;
|
||||
ImpCastExprToType(From, ToType, Kind, /*isLvalue=*/false, BasePath);
|
||||
ImpCastExprToType(From, ToType, Kind, ImplicitCastExpr::RValue, BasePath);
|
||||
break;
|
||||
}
|
||||
case ICK_Boolean_Conversion: {
|
||||
|
@ -1843,11 +1843,8 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
|
|||
IgnoreBaseAccess))
|
||||
return true;
|
||||
|
||||
ImpCastExprToType(From, ToType.getNonReferenceType(),
|
||||
CastExpr::CK_DerivedToBase,
|
||||
/*isLvalue=*/(From->getType()->isRecordType() &&
|
||||
From->isLvalue(Context) == Expr::LV_Valid),
|
||||
BasePath);
|
||||
ImpCastExprToType(From, ToType.getNonReferenceType(),
|
||||
CastExpr::CK_DerivedToBase, CastCategory(From), BasePath);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1877,18 +1874,21 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
|
|||
// Nothing to do.
|
||||
break;
|
||||
|
||||
case ICK_Qualification:
|
||||
// FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue
|
||||
// references.
|
||||
case ICK_Qualification: {
|
||||
// The qualification keeps the category of the inner expression, unless the
|
||||
// target type isn't a reference.
|
||||
ImplicitCastExpr::ResultCategory Category = ToType->isReferenceType() ?
|
||||
CastCategory(From) : ImplicitCastExpr::RValue;
|
||||
ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
|
||||
CastExpr::CK_NoOp, ToType->isLValueReferenceType());
|
||||
CastExpr::CK_NoOp, Category);
|
||||
|
||||
if (SCS.DeprecatedStringLiteralToCharPtr)
|
||||
Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
|
||||
<< ToType.getNonReferenceType();
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false && "Improper third standard conversion");
|
||||
break;
|
||||
|
@ -1974,11 +1974,12 @@ QualType Sema::CheckPointerToMemberOperands(
|
|||
}
|
||||
// Cast LHS to type of use.
|
||||
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
|
||||
bool isLValue = !isIndirect && lex->isLvalue(Context) == Expr::LV_Valid;
|
||||
|
||||
ImplicitCastExpr::ResultCategory Category =
|
||||
isIndirect ? ImplicitCastExpr::RValue : CastCategory(lex);
|
||||
|
||||
CXXBaseSpecifierArray BasePath;
|
||||
BuildBasePathArray(Paths, BasePath);
|
||||
ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, isLValue,
|
||||
ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, Category,
|
||||
BasePath);
|
||||
}
|
||||
|
||||
|
|
|
@ -2021,12 +2021,14 @@ void InitializationSequence::Step::Destroy() {
|
|||
switch (Kind) {
|
||||
case SK_ResolveAddressOfOverloadedFunction:
|
||||
case SK_CastDerivedToBaseRValue:
|
||||
case SK_CastDerivedToBaseXValue:
|
||||
case SK_CastDerivedToBaseLValue:
|
||||
case SK_BindReference:
|
||||
case SK_BindReferenceToTemporary:
|
||||
case SK_ExtraneousCopyToTemporary:
|
||||
case SK_UserConversion:
|
||||
case SK_QualificationConversionRValue:
|
||||
case SK_QualificationConversionXValue:
|
||||
case SK_QualificationConversionLValue:
|
||||
case SK_ListInitialization:
|
||||
case SK_ConstructorInitialization:
|
||||
|
@ -2091,9 +2093,14 @@ void InitializationSequence::AddAddressOverloadResolutionStep(
|
|||
}
|
||||
|
||||
void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
|
||||
bool IsLValue) {
|
||||
ImplicitCastExpr::ResultCategory Category) {
|
||||
Step S;
|
||||
S.Kind = IsLValue? SK_CastDerivedToBaseLValue : SK_CastDerivedToBaseRValue;
|
||||
switch (Category) {
|
||||
case ImplicitCastExpr::RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
|
||||
case ImplicitCastExpr::XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
|
||||
case ImplicitCastExpr::LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
|
||||
default: llvm_unreachable("No such category");
|
||||
}
|
||||
S.Type = BaseType;
|
||||
Steps.push_back(S);
|
||||
}
|
||||
|
@ -2125,10 +2132,20 @@ void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
|
|||
}
|
||||
|
||||
void InitializationSequence::AddQualificationConversionStep(QualType Ty,
|
||||
bool IsLValue) {
|
||||
ImplicitCastExpr::ResultCategory Category) {
|
||||
Step S;
|
||||
S.Kind = IsLValue? SK_QualificationConversionLValue
|
||||
: SK_QualificationConversionRValue;
|
||||
switch (Category) {
|
||||
case ImplicitCastExpr::RValue:
|
||||
S.Kind = SK_QualificationConversionRValue;
|
||||
break;
|
||||
case ImplicitCastExpr::XValue:
|
||||
S.Kind = SK_QualificationConversionXValue;
|
||||
break;
|
||||
case ImplicitCastExpr::LValue:
|
||||
S.Kind = SK_QualificationConversionLValue;
|
||||
break;
|
||||
default: llvm_unreachable("No such category");
|
||||
}
|
||||
S.Type = Ty;
|
||||
Steps.push_back(S);
|
||||
}
|
||||
|
@ -2375,6 +2392,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
|
|||
|
||||
// Determine whether we need to perform derived-to-base or
|
||||
// cv-qualification adjustments.
|
||||
ImplicitCastExpr::ResultCategory Category = ImplicitCastExpr::RValue;
|
||||
if (T2->isLValueReferenceType())
|
||||
Category = ImplicitCastExpr::LValue;
|
||||
else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>())
|
||||
Category = RRef->getPointeeType()->isFunctionType() ?
|
||||
ImplicitCastExpr::LValue : ImplicitCastExpr::RValue;
|
||||
|
||||
bool NewDerivedToBase = false;
|
||||
Sema::ReferenceCompareResult NewRefRelationship
|
||||
= S.CompareReferenceRelationship(DeclLoc, T1,
|
||||
|
@ -2394,10 +2418,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
|
|||
Sequence.AddDerivedToBaseCastStep(
|
||||
S.Context.getQualifiedType(T1,
|
||||
T2.getNonReferenceType().getQualifiers()),
|
||||
/*isLValue=*/true);
|
||||
Category);
|
||||
|
||||
if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
|
||||
Sequence.AddQualificationConversionStep(cv1T1, T2->isReferenceType());
|
||||
Sequence.AddQualificationConversionStep(cv1T1, Category);
|
||||
|
||||
Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
|
||||
return OR_Success;
|
||||
|
@ -2472,9 +2496,9 @@ static void TryReferenceInitialization(Sema &S,
|
|||
if (DerivedToBase)
|
||||
Sequence.AddDerivedToBaseCastStep(
|
||||
S.Context.getQualifiedType(T1, T2Quals),
|
||||
/*isLValue=*/true);
|
||||
ImplicitCastExpr::LValue);
|
||||
if (T1Quals != T2Quals)
|
||||
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
|
||||
Sequence.AddQualificationConversionStep(cv1T1,ImplicitCastExpr::LValue);
|
||||
bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
|
||||
(Initializer->getBitField() || Initializer->refersToVectorElement());
|
||||
Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
|
||||
|
@ -2550,9 +2574,9 @@ static void TryReferenceInitialization(Sema &S,
|
|||
if (DerivedToBase)
|
||||
Sequence.AddDerivedToBaseCastStep(
|
||||
S.Context.getQualifiedType(T1, T2Quals),
|
||||
/*isLValue=*/false);
|
||||
ImplicitCastExpr::RValue);
|
||||
if (T1Quals != T2Quals)
|
||||
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
|
||||
Sequence.AddQualificationConversionStep(cv1T1,ImplicitCastExpr::RValue);
|
||||
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
|
||||
return;
|
||||
}
|
||||
|
@ -3505,12 +3529,14 @@ InitializationSequence::Perform(Sema &S,
|
|||
switch (Steps.front().Kind) {
|
||||
case SK_ResolveAddressOfOverloadedFunction:
|
||||
case SK_CastDerivedToBaseRValue:
|
||||
case SK_CastDerivedToBaseXValue:
|
||||
case SK_CastDerivedToBaseLValue:
|
||||
case SK_BindReference:
|
||||
case SK_BindReferenceToTemporary:
|
||||
case SK_ExtraneousCopyToTemporary:
|
||||
case SK_UserConversion:
|
||||
case SK_QualificationConversionLValue:
|
||||
case SK_QualificationConversionXValue:
|
||||
case SK_QualificationConversionRValue:
|
||||
case SK_ConversionSequence:
|
||||
case SK_ListInitialization:
|
||||
|
@ -3550,6 +3576,7 @@ InitializationSequence::Perform(Sema &S,
|
|||
break;
|
||||
|
||||
case SK_CastDerivedToBaseRValue:
|
||||
case SK_CastDerivedToBaseXValue:
|
||||
case SK_CastDerivedToBaseLValue: {
|
||||
// We have a derived-to-base cast that produces either an rvalue or an
|
||||
// lvalue. Perform that cast.
|
||||
|
@ -3573,11 +3600,16 @@ InitializationSequence::Perform(Sema &S,
|
|||
cast<CXXRecordDecl>(RecordTy->getDecl()));
|
||||
}
|
||||
|
||||
ImplicitCastExpr::ResultCategory Category =
|
||||
Step->Kind == SK_CastDerivedToBaseLValue ?
|
||||
ImplicitCastExpr::LValue :
|
||||
(Step->Kind == SK_CastDerivedToBaseXValue ?
|
||||
ImplicitCastExpr::XValue :
|
||||
ImplicitCastExpr::RValue);
|
||||
CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type,
|
||||
CastExpr::CK_DerivedToBase,
|
||||
(Expr*)CurInit.release(),
|
||||
BasePath,
|
||||
Step->Kind == SK_CastDerivedToBaseLValue));
|
||||
BasePath, Category));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3711,29 +3743,36 @@ InitializationSequence::Perform(Sema &S,
|
|||
}
|
||||
|
||||
CurInitExpr = CurInit.takeAs<Expr>();
|
||||
// FIXME: xvalues
|
||||
CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
|
||||
CastKind,
|
||||
CurInitExpr,
|
||||
CXXBaseSpecifierArray(),
|
||||
IsLvalue));
|
||||
IsLvalue ? ImplicitCastExpr::LValue : ImplicitCastExpr::RValue));
|
||||
|
||||
if (RequiresCopy)
|
||||
CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
|
||||
move(CurInit), /*IsExtraneousCopy=*/false);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case SK_QualificationConversionLValue:
|
||||
case SK_QualificationConversionRValue:
|
||||
case SK_QualificationConversionXValue:
|
||||
case SK_QualificationConversionRValue: {
|
||||
// Perform a qualification conversion; these can never go wrong.
|
||||
S.ImpCastExprToType(CurInitExpr, Step->Type,
|
||||
CastExpr::CK_NoOp,
|
||||
Step->Kind == SK_QualificationConversionLValue);
|
||||
ImplicitCastExpr::ResultCategory Category =
|
||||
Step->Kind == SK_QualificationConversionLValue ?
|
||||
ImplicitCastExpr::LValue :
|
||||
(Step->Kind == SK_QualificationConversionXValue ?
|
||||
ImplicitCastExpr::XValue :
|
||||
ImplicitCastExpr::RValue);
|
||||
S.ImpCastExprToType(CurInitExpr, Step->Type, CastExpr::CK_NoOp, Category);
|
||||
CurInit.release();
|
||||
CurInit = S.Owned(CurInitExpr);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case SK_ConversionSequence: {
|
||||
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
|
||||
|
||||
|
@ -4288,6 +4327,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
|
|||
OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
|
||||
break;
|
||||
|
||||
case SK_CastDerivedToBaseXValue:
|
||||
OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
|
||||
break;
|
||||
|
||||
case SK_CastDerivedToBaseLValue:
|
||||
OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
|
||||
break;
|
||||
|
@ -4307,10 +4350,13 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
|
|||
case SK_UserConversion:
|
||||
OS << "user-defined conversion via " << S->Function.Function;
|
||||
break;
|
||||
|
||||
|
||||
case SK_QualificationConversionRValue:
|
||||
OS << "qualification conversion (rvalue)";
|
||||
|
||||
case SK_QualificationConversionXValue:
|
||||
OS << "qualification conversion (xvalue)";
|
||||
|
||||
case SK_QualificationConversionLValue:
|
||||
OS << "qualification conversion (lvalue)";
|
||||
break;
|
||||
|
|
|
@ -445,6 +445,8 @@ public:
|
|||
SK_ResolveAddressOfOverloadedFunction,
|
||||
/// \brief Perform a derived-to-base cast, producing an rvalue.
|
||||
SK_CastDerivedToBaseRValue,
|
||||
/// \brief Perform a derived-to-base cast, producing an xvalue.
|
||||
SK_CastDerivedToBaseXValue,
|
||||
/// \brief Perform a derived-to-base cast, producing an lvalue.
|
||||
SK_CastDerivedToBaseLValue,
|
||||
/// \brief Reference binding to an lvalue.
|
||||
|
@ -460,6 +462,8 @@ public:
|
|||
SK_UserConversion,
|
||||
/// \brief Perform a qualification conversion, producing an rvalue.
|
||||
SK_QualificationConversionRValue,
|
||||
/// \brief Perform a qualification conversion, producing an xvalue.
|
||||
SK_QualificationConversionXValue,
|
||||
/// \brief Perform a qualification conversion, producing an lvalue.
|
||||
SK_QualificationConversionLValue,
|
||||
/// \brief Perform an implicit conversion sequence.
|
||||
|
@ -670,7 +674,8 @@ public:
|
|||
///
|
||||
/// \param IsLValue true if the result of this cast will be treated as
|
||||
/// an lvalue.
|
||||
void AddDerivedToBaseCastStep(QualType BaseType, bool IsLValue);
|
||||
void AddDerivedToBaseCastStep(QualType BaseType,
|
||||
ImplicitCastExpr::ResultCategory Category);
|
||||
|
||||
/// \brief Add a new step binding a reference to an object.
|
||||
///
|
||||
|
@ -702,7 +707,8 @@ public:
|
|||
|
||||
/// \brief Add a new step that performs a qualification conversion to the
|
||||
/// given type.
|
||||
void AddQualificationConversionStep(QualType Ty, bool IsLValue);
|
||||
void AddQualificationConversionStep(QualType Ty,
|
||||
ImplicitCastExpr::ResultCategory Category);
|
||||
|
||||
/// \brief Add a new step that applies an implicit conversion sequence.
|
||||
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
|
||||
|
|
|
@ -3042,7 +3042,8 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,
|
|||
|
||||
if (!Context.hasSameType(From->getType(), DestType))
|
||||
ImpCastExprToType(From, DestType, CastExpr::CK_NoOp,
|
||||
/*isLvalue=*/!From->getType()->isPointerType());
|
||||
From->getType()->isPointerType() ?
|
||||
ImplicitCastExpr::RValue : ImplicitCastExpr::LValue);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3721,7 +3722,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
|
|||
From->getLocStart());
|
||||
ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()),
|
||||
CastExpr::CK_FunctionToPointerDecay,
|
||||
&ConversionRef, CXXBaseSpecifierArray(), false);
|
||||
&ConversionRef, CXXBaseSpecifierArray(),
|
||||
ImplicitCastExpr::RValue);
|
||||
|
||||
// Note that it is safe to allocate CallExpr on the stack here because
|
||||
// there are 0 arguments (i.e., nothing is allocated using ASTContext's
|
||||
|
@ -7632,7 +7634,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
|
|||
return new (Context) ImplicitCastExpr(ICE->getType(),
|
||||
ICE->getCastKind(),
|
||||
SubExpr, CXXBaseSpecifierArray(),
|
||||
ICE->isLvalueCast());
|
||||
ICE->getCategory());
|
||||
}
|
||||
|
||||
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
|
||||
|
|
|
@ -2909,8 +2909,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
Arg, Converted);
|
||||
|
||||
if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType())) {
|
||||
ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp,
|
||||
Arg->isLvalue(Context) == Expr::LV_Valid);
|
||||
ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp, CastCategory(Arg));
|
||||
} else if (!Context.hasSameUnqualifiedType(ArgType,
|
||||
ParamType.getNonReferenceType())) {
|
||||
// We can't perform this conversion.
|
||||
|
@ -2973,8 +2972,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
|
||||
// Types match exactly: nothing more to do here.
|
||||
} else if (IsQualificationConversion(ArgType, ParamType)) {
|
||||
ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp,
|
||||
Arg->isLvalue(Context) == Expr::LV_Valid);
|
||||
ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp, CastCategory(Arg));
|
||||
} else {
|
||||
// We can't perform this conversion.
|
||||
Diag(Arg->getSourceRange().getBegin(),
|
||||
|
|
Loading…
Reference in New Issue