From 7eb0a9eb0cde8444b97f9c5b713d9be7a6f1e607 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 24 Nov 2010 05:12:34 +0000 Subject: [PATCH] Switch a lot of call-sites over to using the new value-kind calculations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120084 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 33 ++++++++++++++++++------------ lib/AST/ASTContext.cpp | 2 +- lib/AST/Expr.cpp | 2 +- lib/AST/ExprClassification.cpp | 2 +- lib/CodeGen/CGExpr.cpp | 10 ++++----- lib/CodeGen/CGExprScalar.cpp | 6 +++--- lib/Sema/SemaCXXCast.cpp | 10 ++++----- lib/Sema/SemaExpr.cpp | 29 +++++++++++++------------- lib/Sema/SemaExprCXX.cpp | 2 +- lib/Sema/SemaInit.cpp | 4 ++-- lib/Sema/SemaOverload.cpp | 6 +++--- lib/Sema/SemaStmt.cpp | 7 +++---- lib/Sema/SemaTemplateDeduction.cpp | 2 +- 13 files changed, 61 insertions(+), 54 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 3050bf9a2e..041446d689 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -127,19 +127,25 @@ public: bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, SourceRange &R2, ASTContext &Ctx) const; - /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or - /// incomplete type other than void. Nonarray expressions that can be lvalues: - /// - name, where name must be a variable - /// - e[i] - /// - (e), where e must be an lvalue - /// - e.name, where e must be an lvalue - /// - e->name - /// - *e, the type of e cannot be a function type - /// - string-constant - /// - reference type [C++ [expr]] - /// - b ? x : y, where x and y are lvalues of suitable types [C++] + /// isLValue - True if this expression is an "l-value" according to + /// the rules of the current language. C and C++ give somewhat + /// different rules for this concept, but in general, the result of + /// an l-value expression identifies a specific object whereas the + /// result of an r-value expression is a value detached from any + /// specific storage. /// - enum isLvalueResult { + /// C++0x divides the concept of "r-value" into pure r-values + /// ("pr-values") and so-called expiring values ("x-values"), which + /// identify specific objects that can be safely cannibalized for + /// their resources. This is an unfortunate abuse of terminology on + /// the part of the C++ committee. In Clang, when we say "r-value", + /// we generally mean a pr-value. + bool isLValue() const { return getValueKind() == VK_LValue; } + bool isRValue() const { return getValueKind() == VK_RValue; } + bool isXValue() const { return getValueKind() == VK_XValue; } + bool isGLValue() const { return getValueKind() != VK_RValue; } + + enum LValueClassification { LV_Valid, LV_NotObjectType, LV_IncompleteVoidType, @@ -149,7 +155,8 @@ public: LV_SubObjCPropertySetting, LV_ClassTemporary }; - isLvalueResult isLvalue(ASTContext &Ctx) const; + /// Reasons why an expression might not be an l-value. + LValueClassification ClassifyLValue(ASTContext &Ctx) const; /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, /// does not have an incomplete type, does not have a const-qualified type, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 12a92f8ac6..7b24770102 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2378,7 +2378,7 @@ static QualType getDecltypeForExpr(const Expr *e, ASTContext &Context) { // Otherwise, where T is the type of e, if e is an lvalue, decltype(e) is // defined as T&, otherwise decltype(e) is defined as T. - if (e->isLvalue(Context) == Expr::LV_Valid) + if (e->isLValue()) T = Context.getLValueReferenceType(T); return T; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c920611075..3e3792e21f 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1460,7 +1460,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { if (isTypeDependent()) return false; - return isLvalue(Ctx) == Expr::LV_MemberFunction; + return ClassifyLValue(Ctx) == Expr::LV_MemberFunction; } static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1, diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index f24ddcbb73..4025f18a3b 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -529,7 +529,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, return Cl::CM_Modifiable; } -Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { +Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const { Classification VC = Classify(Ctx); switch (VC.getKind()) { case Cl::CL_LValue: return LV_Valid; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 7682baa8e5..f802b3981c 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -192,7 +192,7 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, } RValue RV; - if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid) { + if (E->isLValue()) { // Emit the expression as an lvalue. LValue LV = CGF.EmitLValue(E); if (LV.isPropertyRef() || LV.isKVCRef()) { @@ -235,8 +235,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, continue; } } else if (const MemberExpr *ME = dyn_cast(E)) { - if (ME->getBase()->isLvalue(CGF.getContext()) != Expr::LV_Valid && - ME->getBase()->getType()->isRecordType()) { + if (!ME->isArrow() && ME->getBase()->isRValue()) { + assert(ME->getBase()->getType()->isRecordType()); if (FieldDecl *Field = dyn_cast(ME->getMemberDecl())) { E = ME->getBase(); Adjustments.push_back(SubobjectAdjustment(Field)); @@ -1515,7 +1515,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { const PointerType *PT = E->getBase()->getType()->getAs(); Base = MakeAddrLValue(Ptr, PT->getPointeeType()); Base.getQuals().removeObjCGCAttr(); - } else if (E->getBase()->isLvalue(getContext()) == Expr::LV_Valid) { + } else if (E->getBase()->isGLValue()) { // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), // emit the base as an lvalue. assert(E->getBase()->getType()->isVectorType()); @@ -1711,7 +1711,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){ LValue CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator *E) { - if (E->isLvalue(getContext()) == Expr::LV_Valid) { + if (E->isGLValue()) { if (int Cond = ConstantFoldsToSimpleInteger(E->getCond())) { Expr *Live = Cond == 1 ? E->getLHS() : E->getRHS(); if (Live) diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index a5f9890c12..e5ea26c24b 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1474,7 +1474,7 @@ Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) { // If it's an l-value, load through the appropriate subobject l-value. // Note that we have to ask E because Op might be an l-value that // this won't work for, e.g. an Obj-C property. - if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid) + if (E->isGLValue()) return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType()) .getScalarVal(); @@ -1491,7 +1491,7 @@ Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { // If it's an l-value, load through the appropriate subobject l-value. // Note that we have to ask E because Op might be an l-value that // this won't work for, e.g. an Obj-C property. - if (Op->isLvalue(CGF.getContext()) == Expr::LV_Valid) + if (Op->isGLValue()) return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType()) .getScalarVal(); @@ -2548,7 +2548,7 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { const llvm::Type *ClassPtrTy = ConvertType(E->getType()); Expr *BaseExpr = E->getBase(); - if (BaseExpr->isLvalue(getContext()) != Expr::LV_Valid) { + if (BaseExpr->isRValue()) { V = CreateTempAlloca(ClassPtrTy, "resval"); llvm::Value *Src = EmitScalarExpr(BaseExpr); Builder.CreateStore(Src, V); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 06c2758a9b..5997d98fa5 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -375,7 +375,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, return; } } else if (DestReference->isLValueReferenceType()) { - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { + if (!SrcExpr->isLValue()) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; } @@ -698,7 +698,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, if (!R) return TC_NotApplicable; - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) + if (!SrcExpr->isLValue()) return TC_NotApplicable; // Because we try the reference downcast before this function, from now on @@ -739,7 +739,7 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, return TC_NotApplicable; } bool RValueRef = DestReference->isRValueReferenceType(); - if (!RValueRef && SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { + if (!RValueRef && !SrcExpr->isLValue()) { // We know the left side is an lvalue reference, so we can suggest a reason. msg = diag::err_bad_cxx_cast_rvalue; return TC_NotApplicable; @@ -1049,7 +1049,7 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, QualType SrcType = SrcExpr->getType(); if (const LValueReferenceType *DestTypeTmp = DestType->getAs()) { - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { + if (!SrcExpr->isLValue()) { // Cannot const_cast non-lvalue to lvalue reference type. But if this // is C-style, static_cast might find a way, so we simply suggest a // message and tell the parent to keep searching. @@ -1152,7 +1152,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, if (const ReferenceType *DestTypeTmp = DestType->getAs()) { bool LValue = DestTypeTmp->isLValueReferenceType(); - if (LValue && SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { + if (LValue && !SrcExpr->isLValue()) { // Cannot cast non-lvalue to reference type. See the similar comment in // const_cast. msg = diag::err_bad_cxx_cast_rvalue; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fa7069628b..2daeed1257 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -238,8 +238,7 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { // An lvalue or rvalue of type "array of N T" or "array of unknown bound of // T" can be converted to an rvalue of type "pointer to T". // - if (getLangOptions().C99 || getLangOptions().CPlusPlus || - E->isLvalue(Context) == Expr::LV_Valid) + if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue()) ImpCastExprToType(E, Context.getArrayDecayedType(Ty), CK_ArrayToPointerDecay); } @@ -252,7 +251,7 @@ void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type"); if (!Ty->isDependentType() && Ty.hasQualifiers() && (!getLangOptions().CPlusPlus || !Ty->isRecordType()) && - E->isLvalue(Context) == Expr::LV_Valid) { + E->isLValue()) { // C++ [conv.lval]p1: // [...] If T is a non-class type, the type of the rvalue is the // cv-unqualified version of T. Otherwise, the type of the @@ -789,10 +788,16 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, MarkDeclarationReferenced(NameInfo.getLoc(), D); - return Owned(DeclRefExpr::Create(Context, + Expr *E = DeclRefExpr::Create(Context, SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, - SS? SS->getRange() : SourceRange(), - D, NameInfo, Ty, VK)); + SS? SS->getRange() : SourceRange(), + D, NameInfo, Ty, VK); + + // Just in case we're building an illegal pointer-to-member. + if (isa(D) && cast(D)->getBitWidth()) + E->setObjectKind(OK_BitField); + + return Owned(E); } static ExprResult @@ -7045,7 +7050,7 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, // expressions here, but the result of one is always an lvalue anyway. } NamedDecl *dcl = getPrimaryDecl(op); - Expr::isLvalueResult lval = op->isLvalue(S.Context); + Expr::LValueClassification lval = op->ClassifyLValue(S.Context); if (lval == Expr::LV_ClassTemporary) { bool sfinae = S.isSFINAEContext(); @@ -7091,25 +7096,21 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, << op->getSourceRange(); return QualType(); } - } else if (op->getBitField()) { // C99 6.5.3.2p1 + } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1 // The operand cannot be a bit-field S.Diag(OpLoc, diag::err_typecheck_address_of) << "bit-field" << op->getSourceRange(); return QualType(); - } else if (op->refersToVectorElement()) { + } else if (op->getObjectKind() == OK_VectorComponent) { // The operand cannot be an element of a vector S.Diag(OpLoc, diag::err_typecheck_address_of) << "vector element" << op->getSourceRange(); return QualType(); - } else if (isa(op)) { + } else if (op->getObjectKind() == OK_ObjCProperty) { // cannot take address of a property expression. S.Diag(OpLoc, diag::err_typecheck_address_of) << "property expression" << op->getSourceRange(); return QualType(); - } else if (ConditionalOperator *CO = dyn_cast(op)) { - // FIXME: Can LHS ever be null here? - if (!CheckAddressOfOperand(S, CO->getTrueExpr(), OpLoc).isNull()) - return CheckAddressOfOperand(S, CO->getFalseExpr(), OpLoc); } else if (dcl) { // C99 6.5.3.2p1 // We have an lvalue with a decl. Make sure the decl is not declared // with the register storage-class specifier. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fde207ed38..f5d7170e5c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2460,7 +2460,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, // can be converted to match an operand expression E2 of type T2 is defined // as follows: // -- If E2 is an lvalue: - bool ToIsLvalue = (To->isLvalue(Self.Context) == Expr::LV_Valid); + bool ToIsLvalue = To->isLValue(); if (ToIsLvalue) { // E1 can be converted to match E2 if E1 can be implicitly converted to // type "lvalue reference to T2", subject to the constraint that in the diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 1b47332c53..455f7bbba7 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4173,7 +4173,7 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_ReferenceInitFailed: S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) << DestType.getNonReferenceType() - << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid) + << Args[0]->isLValue() << Args[0]->getType() << Args[0]->getSourceRange(); break; @@ -4182,7 +4182,7 @@ bool InitializationSequence::Diagnose(Sema &S, S.Diag(Kind.getLocation(), diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType - << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid) + << Args[0]->isLValue() << Args[0]->getType() << Args[0]->getSourceRange(); break; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5ea7414026..5da655907c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1003,8 +1003,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Lvalue-to-rvalue conversion (C++ 4.1): // An lvalue (3.10) of a non-function, non-array type T can be // converted to an rvalue. - Expr::isLvalueResult argIsLvalue = From->isLvalue(S.Context); - if (argIsLvalue == Expr::LV_Valid && + bool argIsLValue = From->isLValue(); + if (argIsLValue && !FromType->isFunctionType() && !FromType->isArrayType() && S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_Rvalue; @@ -1036,7 +1036,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS.setAllToTypes(FromType); return true; } - } else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) { + } else if (FromType->isFunctionType() && argIsLValue) { // Function-to-pointer conversion (C++ 4.3). SCS.First = ICK_Function_To_Pointer; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 68b7a8c163..48d2b47c8a 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -977,8 +977,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, diag::err_non_variable_decl_in_for)); } else { Expr *FirstE = cast(First); - if (!FirstE->isTypeDependent() && - FirstE->isLvalue(Context) != Expr::LV_Valid) + if (!FirstE->isTypeDependent() && !FirstE->isLValue()) return StmtError(Diag(First->getLocStart(), diag::err_selector_element_not_lvalue) << First->getSourceRange()); @@ -1312,13 +1311,13 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { if (E->isTypeDependent()) return false; - if (E->isLvalue(S.Context) == Expr::LV_Valid) + if (E->isLValue()) return false; // Cool, this is an lvalue. // Okay, this is not an lvalue, but perhaps it is the result of a cast that we // are supposed to allow. const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); - if (E != E2 && E2->isLvalue(S.Context) == Expr::LV_Valid) { + if (E != E2 && E2->isLValue()) { if (!S.getLangOptions().HeinousExtensions) S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) << E->getSourceRange(); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 39996e315d..070c334f87 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1757,7 +1757,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // type deduction. if (ParamRefType->isRValueReferenceType() && ParamRefType->getAs() && - Args[I]->isLvalue(Context) == Expr::LV_Valid) + Args[I]->isLValue()) ArgType = Context.getLValueReferenceType(ArgType); } else { // C++ [temp.deduct.call]p2: -- 2.40.0