From 906082edf2aea1c6de2926f93a8d7121e49d2a54 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Tue, 20 Jul 2010 04:20:21 +0000 Subject: [PATCH] Update ImplicitCastExpr to be able to represent an XValue. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108807 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 36 ++++++++------ lib/AST/ASTImporter.cpp | 2 +- lib/AST/Expr.cpp | 6 ++- lib/AST/ExprClassification.cpp | 12 +++-- lib/AST/StmtDumper.cpp | 10 +++- lib/AST/StmtProfile.cpp | 2 +- lib/CodeGen/CGExprScalar.cpp | 4 +- lib/CodeGen/CGObjC.cpp | 3 +- lib/Frontend/PCHReaderStmt.cpp | 2 +- lib/Frontend/PCHWriterStmt.cpp | 2 +- lib/Rewrite/RewriteObjC.cpp | 6 ++- lib/Sema/Sema.cpp | 18 +++++-- lib/Sema/Sema.h | 7 ++- lib/Sema/SemaDecl.cpp | 2 +- lib/Sema/SemaDeclCXX.cpp | 10 ++-- lib/Sema/SemaExpr.cpp | 11 ++--- lib/Sema/SemaExprCXX.cpp | 39 ++++++++------- lib/Sema/SemaInit.cpp | 90 +++++++++++++++++++++++++--------- lib/Sema/SemaInit.h | 10 +++- lib/Sema/SemaOverload.cpp | 8 +-- lib/Sema/SemaTemplate.cpp | 6 +-- 21 files changed, 190 insertions(+), 96 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index ade2b09c80..472c91546f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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. diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 0d8896330c..6b2c90c1d1 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -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) { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6524a312dc..724c65aa31 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1508,7 +1508,8 @@ FieldDecl *Expr::getBitField() { Expr *E = this->IgnoreParens(); while (ImplicitCastExpr *ICE = dyn_cast(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(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; diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 60ac347c50..429366ee89 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -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(E)->isLvalueCast()) + switch (cast(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. diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index b388a3b18f..62dcf60be0 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -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) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index cff86a4e1c..de7e906250 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -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) { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index ef38209e1e..d25f6e9acf 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -897,8 +897,8 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) { } if (const ImplicitCastExpr *ICE = dyn_cast(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; } diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index e735a61754..5eed0b6465 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -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); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 051b2257e4..03df4d78d9 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -588,7 +588,7 @@ void PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) { void PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); - E->setLvalueCast(Record[Idx++]); + E->setCategory(static_cast(Record[Idx++])); } void PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 75377286e5..90e48c457f 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -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; } diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 489fec9be0..351667e32f 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -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(); @@ -5609,7 +5609,9 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { } #if 0 if (ImplicitCastExpr *ICE = dyn_cast(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); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index cddc84eeed..33a111f395 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -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(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) { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 64b1b0dd24..490ff65cd9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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()); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f2f9a34215..85ea8bb239 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bd97df2ce9..1927aad4ea 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 447dc38732..73127df5dd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a32dc53b30..82c461128d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7ad177557e..648780f306 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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()) + 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(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(); + // 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; diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index 44c36a735b..4c94aa6058 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -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, diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index c4ab9061b4..9f02dae9f8 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(E)) { diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index c654e008b5..4cb9433589 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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(), -- 2.40.0