10b57cec5SDimitry Andric //===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements semantic analysis for expressions involving 100b57cec5SDimitry Andric // pseudo-object references. Pseudo-objects are conceptual objects 110b57cec5SDimitry Andric // whose storage is entirely abstract and all accesses to which are 120b57cec5SDimitry Andric // translated through some sort of abstraction barrier. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // For example, Objective-C objects can have "properties", either 150b57cec5SDimitry Andric // declared or undeclared. A property may be accessed by writing 160b57cec5SDimitry Andric // expr.prop 170b57cec5SDimitry Andric // where 'expr' is an r-value of Objective-C pointer type and 'prop' 180b57cec5SDimitry Andric // is the name of the property. If this expression is used in a context 190b57cec5SDimitry Andric // needing an r-value, it is treated as if it were a message-send 200b57cec5SDimitry Andric // of the associated 'getter' selector, typically: 210b57cec5SDimitry Andric // [expr prop] 220b57cec5SDimitry Andric // If it is used as the LHS of a simple assignment, it is treated 230b57cec5SDimitry Andric // as a message-send of the associated 'setter' selector, typically: 240b57cec5SDimitry Andric // [expr setProp: RHS] 250b57cec5SDimitry Andric // If it is used as the LHS of a compound assignment, or the operand 260b57cec5SDimitry Andric // of a unary increment or decrement, both are required; for example, 270b57cec5SDimitry Andric // 'expr.prop *= 100' would be translated to: 280b57cec5SDimitry Andric // [expr setProp: [expr prop] * 100] 290b57cec5SDimitry Andric // 300b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 310b57cec5SDimitry Andric 32*0fca6ea1SDimitry Andric #include "clang/Sema/SemaPseudoObject.h" 330b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 340b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 350b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 360b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 370b57cec5SDimitry Andric #include "clang/Sema/Initialization.h" 380b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h" 39*0fca6ea1SDimitry Andric #include "clang/Sema/SemaInternal.h" 40*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h" 410b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric using namespace clang; 440b57cec5SDimitry Andric using namespace sema; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric namespace { 470b57cec5SDimitry Andric // Basically just a very focused copy of TreeTransform. 480b57cec5SDimitry Andric struct Rebuilder { 490b57cec5SDimitry Andric Sema &S; 500b57cec5SDimitry Andric unsigned MSPropertySubscriptCount; 510b57cec5SDimitry Andric typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy; 520b57cec5SDimitry Andric const SpecificRebuilderRefTy &SpecificCallback; 530b57cec5SDimitry Andric Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback) 540b57cec5SDimitry Andric : S(S), MSPropertySubscriptCount(0), 550b57cec5SDimitry Andric SpecificCallback(SpecificCallback) {} 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) { 580b57cec5SDimitry Andric // Fortunately, the constraint that we're rebuilding something 590b57cec5SDimitry Andric // with a base limits the number of cases here. 600b57cec5SDimitry Andric if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) 610b57cec5SDimitry Andric return refExpr; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric if (refExpr->isExplicitProperty()) { 640b57cec5SDimitry Andric return new (S.Context) ObjCPropertyRefExpr( 650b57cec5SDimitry Andric refExpr->getExplicitProperty(), refExpr->getType(), 660b57cec5SDimitry Andric refExpr->getValueKind(), refExpr->getObjectKind(), 670b57cec5SDimitry Andric refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric return new (S.Context) ObjCPropertyRefExpr( 700b57cec5SDimitry Andric refExpr->getImplicitPropertyGetter(), 710b57cec5SDimitry Andric refExpr->getImplicitPropertySetter(), refExpr->getType(), 720b57cec5SDimitry Andric refExpr->getValueKind(), refExpr->getObjectKind(), 730b57cec5SDimitry Andric refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) { 760b57cec5SDimitry Andric assert(refExpr->getBaseExpr()); 770b57cec5SDimitry Andric assert(refExpr->getKeyExpr()); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric return new (S.Context) ObjCSubscriptRefExpr( 800b57cec5SDimitry Andric SpecificCallback(refExpr->getBaseExpr(), 0), 810b57cec5SDimitry Andric SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(), 820b57cec5SDimitry Andric refExpr->getValueKind(), refExpr->getObjectKind(), 830b57cec5SDimitry Andric refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(), 840b57cec5SDimitry Andric refExpr->getRBracket()); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) { 870b57cec5SDimitry Andric assert(refExpr->getBaseExpr()); 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric return new (S.Context) MSPropertyRefExpr( 900b57cec5SDimitry Andric SpecificCallback(refExpr->getBaseExpr(), 0), 910b57cec5SDimitry Andric refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(), 920b57cec5SDimitry Andric refExpr->getValueKind(), refExpr->getQualifierLoc(), 930b57cec5SDimitry Andric refExpr->getMemberLoc()); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) { 960b57cec5SDimitry Andric assert(refExpr->getBase()); 970b57cec5SDimitry Andric assert(refExpr->getIdx()); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric auto *NewBase = rebuild(refExpr->getBase()); 1000b57cec5SDimitry Andric ++MSPropertySubscriptCount; 1010b57cec5SDimitry Andric return new (S.Context) MSPropertySubscriptExpr( 1020b57cec5SDimitry Andric NewBase, 1030b57cec5SDimitry Andric SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount), 1040b57cec5SDimitry Andric refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(), 1050b57cec5SDimitry Andric refExpr->getRBracketLoc()); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric Expr *rebuild(Expr *e) { 1090b57cec5SDimitry Andric // Fast path: nothing to look through. 1100b57cec5SDimitry Andric if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e)) 1110b57cec5SDimitry Andric return rebuildObjCPropertyRefExpr(PRE); 1120b57cec5SDimitry Andric if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e)) 1130b57cec5SDimitry Andric return rebuildObjCSubscriptRefExpr(SRE); 1140b57cec5SDimitry Andric if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e)) 1150b57cec5SDimitry Andric return rebuildMSPropertyRefExpr(MSPRE); 1160b57cec5SDimitry Andric if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e)) 1170b57cec5SDimitry Andric return rebuildMSPropertySubscriptExpr(MSPSE); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // Otherwise, we should look through and rebuild anything that 1200b57cec5SDimitry Andric // IgnoreParens would. 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { 1230b57cec5SDimitry Andric e = rebuild(parens->getSubExpr()); 1240b57cec5SDimitry Andric return new (S.Context) ParenExpr(parens->getLParen(), 1250b57cec5SDimitry Andric parens->getRParen(), 1260b57cec5SDimitry Andric e); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { 1300b57cec5SDimitry Andric assert(uop->getOpcode() == UO_Extension); 1310b57cec5SDimitry Andric e = rebuild(uop->getSubExpr()); 1325ffd83dbSDimitry Andric return UnaryOperator::Create( 1335ffd83dbSDimitry Andric S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(), 1345ffd83dbSDimitry Andric uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(), 1355ffd83dbSDimitry Andric S.CurFPFeatureOverrides()); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 1390b57cec5SDimitry Andric assert(!gse->isResultDependent()); 1400b57cec5SDimitry Andric unsigned resultIndex = gse->getResultIndex(); 1410b57cec5SDimitry Andric unsigned numAssocs = gse->getNumAssocs(); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric SmallVector<Expr *, 8> assocExprs; 1440b57cec5SDimitry Andric SmallVector<TypeSourceInfo *, 8> assocTypes; 1450b57cec5SDimitry Andric assocExprs.reserve(numAssocs); 1460b57cec5SDimitry Andric assocTypes.reserve(numAssocs); 1470b57cec5SDimitry Andric 148480093f4SDimitry Andric for (const GenericSelectionExpr::Association assoc : 1490b57cec5SDimitry Andric gse->associations()) { 1500b57cec5SDimitry Andric Expr *assocExpr = assoc.getAssociationExpr(); 1510b57cec5SDimitry Andric if (assoc.isSelected()) 1520b57cec5SDimitry Andric assocExpr = rebuild(assocExpr); 1530b57cec5SDimitry Andric assocExprs.push_back(assocExpr); 1540b57cec5SDimitry Andric assocTypes.push_back(assoc.getTypeSourceInfo()); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 15706c3fb27SDimitry Andric if (gse->isExprPredicate()) 1580b57cec5SDimitry Andric return GenericSelectionExpr::Create( 1590b57cec5SDimitry Andric S.Context, gse->getGenericLoc(), gse->getControllingExpr(), 1600b57cec5SDimitry Andric assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(), 1610b57cec5SDimitry Andric gse->containsUnexpandedParameterPack(), resultIndex); 16206c3fb27SDimitry Andric return GenericSelectionExpr::Create( 16306c3fb27SDimitry Andric S.Context, gse->getGenericLoc(), gse->getControllingType(), 16406c3fb27SDimitry Andric assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(), 16506c3fb27SDimitry Andric gse->containsUnexpandedParameterPack(), resultIndex); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) { 1690b57cec5SDimitry Andric assert(!ce->isConditionDependent()); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric Expr *LHS = ce->getLHS(), *RHS = ce->getRHS(); 1720b57cec5SDimitry Andric Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS; 1730b57cec5SDimitry Andric rebuiltExpr = rebuild(rebuiltExpr); 1740b57cec5SDimitry Andric 1755ffd83dbSDimitry Andric return new (S.Context) 1765ffd83dbSDimitry Andric ChooseExpr(ce->getBuiltinLoc(), ce->getCond(), LHS, RHS, 1775ffd83dbSDimitry Andric rebuiltExpr->getType(), rebuiltExpr->getValueKind(), 1785ffd83dbSDimitry Andric rebuiltExpr->getObjectKind(), ce->getRParenLoc(), 1795ffd83dbSDimitry Andric ce->isConditionTrue()); 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric llvm_unreachable("bad expression to rebuild!"); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric }; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric class PseudoOpBuilder { 1870b57cec5SDimitry Andric public: 1880b57cec5SDimitry Andric Sema &S; 1890b57cec5SDimitry Andric unsigned ResultIndex; 1900b57cec5SDimitry Andric SourceLocation GenericLoc; 1910b57cec5SDimitry Andric bool IsUnique; 1920b57cec5SDimitry Andric SmallVector<Expr *, 4> Semantics; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique) 1950b57cec5SDimitry Andric : S(S), ResultIndex(PseudoObjectExpr::NoResult), 1960b57cec5SDimitry Andric GenericLoc(genericLoc), IsUnique(IsUnique) {} 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric virtual ~PseudoOpBuilder() {} 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric /// Add a normal semantic expression. 2010b57cec5SDimitry Andric void addSemanticExpr(Expr *semantic) { 2020b57cec5SDimitry Andric Semantics.push_back(semantic); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric /// Add the 'result' semantic expression. 2060b57cec5SDimitry Andric void addResultSemanticExpr(Expr *resultExpr) { 2070b57cec5SDimitry Andric assert(ResultIndex == PseudoObjectExpr::NoResult); 2080b57cec5SDimitry Andric ResultIndex = Semantics.size(); 2090b57cec5SDimitry Andric Semantics.push_back(resultExpr); 2100b57cec5SDimitry Andric // An OVE is not unique if it is used as the result expression. 2110b57cec5SDimitry Andric if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back())) 2120b57cec5SDimitry Andric OVE->setIsUnique(false); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric ExprResult buildRValueOperation(Expr *op); 2160b57cec5SDimitry Andric ExprResult buildAssignmentOperation(Scope *Sc, 2170b57cec5SDimitry Andric SourceLocation opLoc, 2180b57cec5SDimitry Andric BinaryOperatorKind opcode, 2190b57cec5SDimitry Andric Expr *LHS, Expr *RHS); 2200b57cec5SDimitry Andric ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 2210b57cec5SDimitry Andric UnaryOperatorKind opcode, 2220b57cec5SDimitry Andric Expr *op); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric virtual ExprResult complete(Expr *syntacticForm); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric OpaqueValueExpr *capture(Expr *op); 2270b57cec5SDimitry Andric OpaqueValueExpr *captureValueAsResult(Expr *op); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric void setResultToLastSemantic() { 2300b57cec5SDimitry Andric assert(ResultIndex == PseudoObjectExpr::NoResult); 2310b57cec5SDimitry Andric ResultIndex = Semantics.size() - 1; 2320b57cec5SDimitry Andric // An OVE is not unique if it is used as the result expression. 2330b57cec5SDimitry Andric if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back())) 2340b57cec5SDimitry Andric OVE->setIsUnique(false); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric /// Return true if assignments have a non-void result. 2380b57cec5SDimitry Andric static bool CanCaptureValue(Expr *exp) { 2390b57cec5SDimitry Andric if (exp->isGLValue()) 2400b57cec5SDimitry Andric return true; 2410b57cec5SDimitry Andric QualType ty = exp->getType(); 2420b57cec5SDimitry Andric assert(!ty->isIncompleteType()); 2430b57cec5SDimitry Andric assert(!ty->isDependentType()); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl()) 2460b57cec5SDimitry Andric return ClassDecl->isTriviallyCopyable(); 2470b57cec5SDimitry Andric return true; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric virtual Expr *rebuildAndCaptureObject(Expr *) = 0; 2510b57cec5SDimitry Andric virtual ExprResult buildGet() = 0; 2520b57cec5SDimitry Andric virtual ExprResult buildSet(Expr *, SourceLocation, 2530b57cec5SDimitry Andric bool captureSetValueAsResult) = 0; 2540b57cec5SDimitry Andric /// Should the result of an assignment be the formal result of the 2550b57cec5SDimitry Andric /// setter call or the value that was passed to the setter? 2560b57cec5SDimitry Andric /// 2570b57cec5SDimitry Andric /// Different pseudo-object language features use different language rules 2580b57cec5SDimitry Andric /// for this. 2590b57cec5SDimitry Andric /// The default is to use the set value. Currently, this affects the 2600b57cec5SDimitry Andric /// behavior of simple assignments, compound assignments, and prefix 2610b57cec5SDimitry Andric /// increment and decrement. 2620b57cec5SDimitry Andric /// Postfix increment and decrement always use the getter result as the 2630b57cec5SDimitry Andric /// expression result. 2640b57cec5SDimitry Andric /// 2650b57cec5SDimitry Andric /// If this method returns true, and the set value isn't capturable for 2660b57cec5SDimitry Andric /// some reason, the result of the expression will be void. 2670b57cec5SDimitry Andric virtual bool captureSetValueAsResult() const { return true; } 2680b57cec5SDimitry Andric }; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric /// A PseudoOpBuilder for Objective-C \@properties. 2710b57cec5SDimitry Andric class ObjCPropertyOpBuilder : public PseudoOpBuilder { 2720b57cec5SDimitry Andric ObjCPropertyRefExpr *RefExpr; 2730b57cec5SDimitry Andric ObjCPropertyRefExpr *SyntacticRefExpr; 2740b57cec5SDimitry Andric OpaqueValueExpr *InstanceReceiver; 2750b57cec5SDimitry Andric ObjCMethodDecl *Getter; 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric ObjCMethodDecl *Setter; 2780b57cec5SDimitry Andric Selector SetterSelector; 2790b57cec5SDimitry Andric Selector GetterSelector; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric public: 2820b57cec5SDimitry Andric ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique) 2830b57cec5SDimitry Andric : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique), 2840b57cec5SDimitry Andric RefExpr(refExpr), SyntacticRefExpr(nullptr), 2850b57cec5SDimitry Andric InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) { 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric ExprResult buildRValueOperation(Expr *op); 2890b57cec5SDimitry Andric ExprResult buildAssignmentOperation(Scope *Sc, 2900b57cec5SDimitry Andric SourceLocation opLoc, 2910b57cec5SDimitry Andric BinaryOperatorKind opcode, 2920b57cec5SDimitry Andric Expr *LHS, Expr *RHS); 2930b57cec5SDimitry Andric ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 2940b57cec5SDimitry Andric UnaryOperatorKind opcode, 2950b57cec5SDimitry Andric Expr *op); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric bool tryBuildGetOfReference(Expr *op, ExprResult &result); 2980b57cec5SDimitry Andric bool findSetter(bool warn=true); 2990b57cec5SDimitry Andric bool findGetter(); 3000b57cec5SDimitry Andric void DiagnoseUnsupportedPropertyUse(); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric Expr *rebuildAndCaptureObject(Expr *syntacticBase) override; 3030b57cec5SDimitry Andric ExprResult buildGet() override; 3040b57cec5SDimitry Andric ExprResult buildSet(Expr *op, SourceLocation, bool) override; 3050b57cec5SDimitry Andric ExprResult complete(Expr *SyntacticForm) override; 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric bool isWeakProperty() const; 3080b57cec5SDimitry Andric }; 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric /// A PseudoOpBuilder for Objective-C array/dictionary indexing. 3110b57cec5SDimitry Andric class ObjCSubscriptOpBuilder : public PseudoOpBuilder { 3120b57cec5SDimitry Andric ObjCSubscriptRefExpr *RefExpr; 3130b57cec5SDimitry Andric OpaqueValueExpr *InstanceBase; 3140b57cec5SDimitry Andric OpaqueValueExpr *InstanceKey; 3150b57cec5SDimitry Andric ObjCMethodDecl *AtIndexGetter; 3160b57cec5SDimitry Andric Selector AtIndexGetterSelector; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric ObjCMethodDecl *AtIndexSetter; 3190b57cec5SDimitry Andric Selector AtIndexSetterSelector; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric public: 3220b57cec5SDimitry Andric ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique) 3230b57cec5SDimitry Andric : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique), 3240b57cec5SDimitry Andric RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr), 3250b57cec5SDimitry Andric AtIndexGetter(nullptr), AtIndexSetter(nullptr) {} 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric ExprResult buildRValueOperation(Expr *op); 3280b57cec5SDimitry Andric ExprResult buildAssignmentOperation(Scope *Sc, 3290b57cec5SDimitry Andric SourceLocation opLoc, 3300b57cec5SDimitry Andric BinaryOperatorKind opcode, 3310b57cec5SDimitry Andric Expr *LHS, Expr *RHS); 3320b57cec5SDimitry Andric Expr *rebuildAndCaptureObject(Expr *syntacticBase) override; 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric bool findAtIndexGetter(); 3350b57cec5SDimitry Andric bool findAtIndexSetter(); 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric ExprResult buildGet() override; 3380b57cec5SDimitry Andric ExprResult buildSet(Expr *op, SourceLocation, bool) override; 3390b57cec5SDimitry Andric }; 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric class MSPropertyOpBuilder : public PseudoOpBuilder { 3420b57cec5SDimitry Andric MSPropertyRefExpr *RefExpr; 3430b57cec5SDimitry Andric OpaqueValueExpr *InstanceBase; 3440b57cec5SDimitry Andric SmallVector<Expr *, 4> CallArgs; 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric public: 3490b57cec5SDimitry Andric MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique) 3500b57cec5SDimitry Andric : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique), 3510b57cec5SDimitry Andric RefExpr(refExpr), InstanceBase(nullptr) {} 3520b57cec5SDimitry Andric MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique) 3530b57cec5SDimitry Andric : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique), 3540b57cec5SDimitry Andric InstanceBase(nullptr) { 3550b57cec5SDimitry Andric RefExpr = getBaseMSProperty(refExpr); 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric Expr *rebuildAndCaptureObject(Expr *) override; 3590b57cec5SDimitry Andric ExprResult buildGet() override; 3600b57cec5SDimitry Andric ExprResult buildSet(Expr *op, SourceLocation, bool) override; 3610b57cec5SDimitry Andric bool captureSetValueAsResult() const override { return false; } 3620b57cec5SDimitry Andric }; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric /// Capture the given expression in an OpaqueValueExpr. 3660b57cec5SDimitry Andric OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { 3670b57cec5SDimitry Andric // Make a new OVE whose source is the given expression. 3680b57cec5SDimitry Andric OpaqueValueExpr *captured = 3690b57cec5SDimitry Andric new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), 3700b57cec5SDimitry Andric e->getValueKind(), e->getObjectKind(), 3710b57cec5SDimitry Andric e); 3720b57cec5SDimitry Andric if (IsUnique) 3730b57cec5SDimitry Andric captured->setIsUnique(true); 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // Make sure we bind that in the semantics. 3760b57cec5SDimitry Andric addSemanticExpr(captured); 3770b57cec5SDimitry Andric return captured; 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric /// Capture the given expression as the result of this pseudo-object 3810b57cec5SDimitry Andric /// operation. This routine is safe against expressions which may 3820b57cec5SDimitry Andric /// already be captured. 3830b57cec5SDimitry Andric /// 3840b57cec5SDimitry Andric /// \returns the captured expression, which will be the 3850b57cec5SDimitry Andric /// same as the input if the input was already captured 3860b57cec5SDimitry Andric OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { 3870b57cec5SDimitry Andric assert(ResultIndex == PseudoObjectExpr::NoResult); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric // If the expression hasn't already been captured, just capture it 3900b57cec5SDimitry Andric // and set the new semantic 3910b57cec5SDimitry Andric if (!isa<OpaqueValueExpr>(e)) { 3920b57cec5SDimitry Andric OpaqueValueExpr *cap = capture(e); 3930b57cec5SDimitry Andric setResultToLastSemantic(); 3940b57cec5SDimitry Andric return cap; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric // Otherwise, it must already be one of our semantic expressions; 3980b57cec5SDimitry Andric // set ResultIndex to its index. 3990b57cec5SDimitry Andric unsigned index = 0; 4000b57cec5SDimitry Andric for (;; ++index) { 4010b57cec5SDimitry Andric assert(index < Semantics.size() && 4020b57cec5SDimitry Andric "captured expression not found in semantics!"); 4030b57cec5SDimitry Andric if (e == Semantics[index]) break; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric ResultIndex = index; 4060b57cec5SDimitry Andric // An OVE is not unique if it is used as the result expression. 4070b57cec5SDimitry Andric cast<OpaqueValueExpr>(e)->setIsUnique(false); 4080b57cec5SDimitry Andric return cast<OpaqueValueExpr>(e); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric /// The routine which creates the final PseudoObjectExpr. 4120b57cec5SDimitry Andric ExprResult PseudoOpBuilder::complete(Expr *syntactic) { 4130b57cec5SDimitry Andric return PseudoObjectExpr::Create(S.Context, syntactic, 4140b57cec5SDimitry Andric Semantics, ResultIndex); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric /// The main skeleton for building an r-value operation. 4180b57cec5SDimitry Andric ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { 4190b57cec5SDimitry Andric Expr *syntacticBase = rebuildAndCaptureObject(op); 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric ExprResult getExpr = buildGet(); 4220b57cec5SDimitry Andric if (getExpr.isInvalid()) return ExprError(); 4230b57cec5SDimitry Andric addResultSemanticExpr(getExpr.get()); 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric return complete(syntacticBase); 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric /// The basic skeleton for building a simple or compound 4290b57cec5SDimitry Andric /// assignment operation. 4300b57cec5SDimitry Andric ExprResult 4310b57cec5SDimitry Andric PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 4320b57cec5SDimitry Andric BinaryOperatorKind opcode, 4330b57cec5SDimitry Andric Expr *LHS, Expr *RHS) { 4340b57cec5SDimitry Andric assert(BinaryOperator::isAssignmentOp(opcode)); 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric Expr *syntacticLHS = rebuildAndCaptureObject(LHS); 4370b57cec5SDimitry Andric OpaqueValueExpr *capturedRHS = capture(RHS); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric // In some very specific cases, semantic analysis of the RHS as an 4400b57cec5SDimitry Andric // expression may require it to be rewritten. In these cases, we 4410b57cec5SDimitry Andric // cannot safely keep the OVE around. Fortunately, we don't really 4420b57cec5SDimitry Andric // need to: we don't use this particular OVE in multiple places, and 4430b57cec5SDimitry Andric // no clients rely that closely on matching up expressions in the 4440b57cec5SDimitry Andric // semantic expression with expressions from the syntactic form. 4450b57cec5SDimitry Andric Expr *semanticRHS = capturedRHS; 4460b57cec5SDimitry Andric if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) { 4470b57cec5SDimitry Andric semanticRHS = RHS; 4480b57cec5SDimitry Andric Semantics.pop_back(); 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric Expr *syntactic; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric ExprResult result; 4540b57cec5SDimitry Andric if (opcode == BO_Assign) { 4550b57cec5SDimitry Andric result = semanticRHS; 4565ffd83dbSDimitry Andric syntactic = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS, 4570b57cec5SDimitry Andric opcode, capturedRHS->getType(), 4585ffd83dbSDimitry Andric capturedRHS->getValueKind(), OK_Ordinary, 4595ffd83dbSDimitry Andric opcLoc, S.CurFPFeatureOverrides()); 4605ffd83dbSDimitry Andric 4610b57cec5SDimitry Andric } else { 4620b57cec5SDimitry Andric ExprResult opLHS = buildGet(); 4630b57cec5SDimitry Andric if (opLHS.isInvalid()) return ExprError(); 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric // Build an ordinary, non-compound operation. 4660b57cec5SDimitry Andric BinaryOperatorKind nonCompound = 4670b57cec5SDimitry Andric BinaryOperator::getOpForCompoundAssignment(opcode); 4680b57cec5SDimitry Andric result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS); 4690b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 4700b57cec5SDimitry Andric 4715ffd83dbSDimitry Andric syntactic = CompoundAssignOperator::Create( 4725ffd83dbSDimitry Andric S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(), 4735ffd83dbSDimitry Andric result.get()->getValueKind(), OK_Ordinary, opcLoc, 4745ffd83dbSDimitry Andric S.CurFPFeatureOverrides(), opLHS.get()->getType(), 4755ffd83dbSDimitry Andric result.get()->getType()); 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric // The result of the assignment, if not void, is the value set into 4790b57cec5SDimitry Andric // the l-value. 4800b57cec5SDimitry Andric result = buildSet(result.get(), opcLoc, captureSetValueAsResult()); 4810b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 4820b57cec5SDimitry Andric addSemanticExpr(result.get()); 4830b57cec5SDimitry Andric if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() && 4840b57cec5SDimitry Andric (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) 4850b57cec5SDimitry Andric setResultToLastSemantic(); 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric return complete(syntactic); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric /// The basic skeleton for building an increment or decrement 4910b57cec5SDimitry Andric /// operation. 4920b57cec5SDimitry Andric ExprResult 4930b57cec5SDimitry Andric PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 4940b57cec5SDimitry Andric UnaryOperatorKind opcode, 4950b57cec5SDimitry Andric Expr *op) { 4960b57cec5SDimitry Andric assert(UnaryOperator::isIncrementDecrementOp(opcode)); 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric Expr *syntacticOp = rebuildAndCaptureObject(op); 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric // Load the value. 5010b57cec5SDimitry Andric ExprResult result = buildGet(); 5020b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric QualType resultType = result.get()->getType(); 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric // That's the postfix result. 5070b57cec5SDimitry Andric if (UnaryOperator::isPostfix(opcode) && 5080b57cec5SDimitry Andric (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) { 5090b57cec5SDimitry Andric result = capture(result.get()); 5100b57cec5SDimitry Andric setResultToLastSemantic(); 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric // Add or subtract a literal 1. 5140b57cec5SDimitry Andric llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); 5150b57cec5SDimitry Andric Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, 5160b57cec5SDimitry Andric GenericLoc); 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric if (UnaryOperator::isIncrementOp(opcode)) { 5190b57cec5SDimitry Andric result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one); 5200b57cec5SDimitry Andric } else { 5210b57cec5SDimitry Andric result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric // Store that back into the result. The value stored is the result 5260b57cec5SDimitry Andric // of a prefix operation. 5270b57cec5SDimitry Andric result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) && 5280b57cec5SDimitry Andric captureSetValueAsResult()); 5290b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 5300b57cec5SDimitry Andric addSemanticExpr(result.get()); 5310b57cec5SDimitry Andric if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() && 5320b57cec5SDimitry Andric !result.get()->getType()->isVoidType() && 5330b57cec5SDimitry Andric (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) 5340b57cec5SDimitry Andric setResultToLastSemantic(); 5350b57cec5SDimitry Andric 5365ffd83dbSDimitry Andric UnaryOperator *syntactic = 5375ffd83dbSDimitry Andric UnaryOperator::Create(S.Context, syntacticOp, opcode, resultType, 5385ffd83dbSDimitry Andric VK_LValue, OK_Ordinary, opcLoc, 5390b57cec5SDimitry Andric !resultType->isDependentType() 5400b57cec5SDimitry Andric ? S.Context.getTypeSize(resultType) >= 5410b57cec5SDimitry Andric S.Context.getTypeSize(S.Context.IntTy) 5425ffd83dbSDimitry Andric : false, 5435ffd83dbSDimitry Andric S.CurFPFeatureOverrides()); 5440b57cec5SDimitry Andric return complete(syntactic); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5490b57cec5SDimitry Andric // Objective-C @property and implicit property references 5500b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric /// Look up a method in the receiver type of an Objective-C property 5530b57cec5SDimitry Andric /// reference. 5540b57cec5SDimitry Andric static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 5550b57cec5SDimitry Andric const ObjCPropertyRefExpr *PRE) { 5560b57cec5SDimitry Andric if (PRE->isObjectReceiver()) { 5570b57cec5SDimitry Andric const ObjCObjectPointerType *PT = 5580b57cec5SDimitry Andric PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric // Special case for 'self' in class method implementations. 5610b57cec5SDimitry Andric if (PT->isObjCClassType() && 562*0fca6ea1SDimitry Andric S.ObjC().isSelfExpr(const_cast<Expr *>(PRE->getBase()))) { 5630b57cec5SDimitry Andric // This cast is safe because isSelfExpr is only true within 5640b57cec5SDimitry Andric // methods. 5650b57cec5SDimitry Andric ObjCMethodDecl *method = 5660b57cec5SDimitry Andric cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); 567*0fca6ea1SDimitry Andric return S.ObjC().LookupMethodInObjectType( 568*0fca6ea1SDimitry Andric sel, S.Context.getObjCInterfaceType(method->getClassInterface()), 5690b57cec5SDimitry Andric /*instance*/ false); 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 572*0fca6ea1SDimitry Andric return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric if (PRE->isSuperReceiver()) { 5760b57cec5SDimitry Andric if (const ObjCObjectPointerType *PT = 5770b57cec5SDimitry Andric PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 578*0fca6ea1SDimitry Andric return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true); 5790b57cec5SDimitry Andric 580*0fca6ea1SDimitry Andric return S.ObjC().LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), 581*0fca6ea1SDimitry Andric false); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric assert(PRE->isClassReceiver() && "Invalid expression"); 5850b57cec5SDimitry Andric QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 586*0fca6ea1SDimitry Andric return S.ObjC().LookupMethodInObjectType(sel, IT, false); 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric bool ObjCPropertyOpBuilder::isWeakProperty() const { 5900b57cec5SDimitry Andric QualType T; 5910b57cec5SDimitry Andric if (RefExpr->isExplicitProperty()) { 5920b57cec5SDimitry Andric const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty(); 5935ffd83dbSDimitry Andric if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) 5940b57cec5SDimitry Andric return true; 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric T = Prop->getType(); 5970b57cec5SDimitry Andric } else if (Getter) { 5980b57cec5SDimitry Andric T = Getter->getReturnType(); 5990b57cec5SDimitry Andric } else { 6000b57cec5SDimitry Andric return false; 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric return T.getObjCLifetime() == Qualifiers::OCL_Weak; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric bool ObjCPropertyOpBuilder::findGetter() { 6070b57cec5SDimitry Andric if (Getter) return true; 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric // For implicit properties, just trust the lookup we already did. 6100b57cec5SDimitry Andric if (RefExpr->isImplicitProperty()) { 6110b57cec5SDimitry Andric if ((Getter = RefExpr->getImplicitPropertyGetter())) { 6120b57cec5SDimitry Andric GetterSelector = Getter->getSelector(); 6130b57cec5SDimitry Andric return true; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric else { 6160b57cec5SDimitry Andric // Must build the getter selector the hard way. 6170b57cec5SDimitry Andric ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter(); 6180b57cec5SDimitry Andric assert(setter && "both setter and getter are null - cannot happen"); 619*0fca6ea1SDimitry Andric const IdentifierInfo *setterName = 6200b57cec5SDimitry Andric setter->getSelector().getIdentifierInfoForSlot(0); 621*0fca6ea1SDimitry Andric const IdentifierInfo *getterName = 6220b57cec5SDimitry Andric &S.Context.Idents.get(setterName->getName().substr(3)); 6230b57cec5SDimitry Andric GetterSelector = 6240b57cec5SDimitry Andric S.PP.getSelectorTable().getNullarySelector(getterName); 6250b57cec5SDimitry Andric return false; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 6300b57cec5SDimitry Andric Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); 6310b57cec5SDimitry Andric return (Getter != nullptr); 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric /// Try to find the most accurate setter declaration for the property 6350b57cec5SDimitry Andric /// reference. 6360b57cec5SDimitry Andric /// 6370b57cec5SDimitry Andric /// \return true if a setter was found, in which case Setter 6380b57cec5SDimitry Andric bool ObjCPropertyOpBuilder::findSetter(bool warn) { 6390b57cec5SDimitry Andric // For implicit properties, just trust the lookup we already did. 6400b57cec5SDimitry Andric if (RefExpr->isImplicitProperty()) { 6410b57cec5SDimitry Andric if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 6420b57cec5SDimitry Andric Setter = setter; 6430b57cec5SDimitry Andric SetterSelector = setter->getSelector(); 6440b57cec5SDimitry Andric return true; 6450b57cec5SDimitry Andric } else { 646*0fca6ea1SDimitry Andric const IdentifierInfo *getterName = RefExpr->getImplicitPropertyGetter() 647*0fca6ea1SDimitry Andric ->getSelector() 6480b57cec5SDimitry Andric .getIdentifierInfoForSlot(0); 6490b57cec5SDimitry Andric SetterSelector = 6500b57cec5SDimitry Andric SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), 6510b57cec5SDimitry Andric S.PP.getSelectorTable(), 6520b57cec5SDimitry Andric getterName); 6530b57cec5SDimitry Andric return false; 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric // For explicit properties, this is more involved. 6580b57cec5SDimitry Andric ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 6590b57cec5SDimitry Andric SetterSelector = prop->getSetterName(); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric // Do a normal method lookup first. 6620b57cec5SDimitry Andric if (ObjCMethodDecl *setter = 6630b57cec5SDimitry Andric LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 6640b57cec5SDimitry Andric if (setter->isPropertyAccessor() && warn) 6650b57cec5SDimitry Andric if (const ObjCInterfaceDecl *IFace = 6660b57cec5SDimitry Andric dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { 6670b57cec5SDimitry Andric StringRef thisPropertyName = prop->getName(); 6680b57cec5SDimitry Andric // Try flipping the case of the first character. 6690b57cec5SDimitry Andric char front = thisPropertyName.front(); 6700b57cec5SDimitry Andric front = isLowercase(front) ? toUppercase(front) : toLowercase(front); 6710b57cec5SDimitry Andric SmallString<100> PropertyName = thisPropertyName; 6720b57cec5SDimitry Andric PropertyName[0] = front; 673*0fca6ea1SDimitry Andric const IdentifierInfo *AltMember = 674*0fca6ea1SDimitry Andric &S.PP.getIdentifierTable().get(PropertyName); 6750b57cec5SDimitry Andric if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration( 6760b57cec5SDimitry Andric AltMember, prop->getQueryKind())) 6770b57cec5SDimitry Andric if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) { 6780b57cec5SDimitry Andric S.Diag(RefExpr->getExprLoc(), diag::err_property_setter_ambiguous_use) 6790b57cec5SDimitry Andric << prop << prop1 << setter->getSelector(); 6800b57cec5SDimitry Andric S.Diag(prop->getLocation(), diag::note_property_declare); 6810b57cec5SDimitry Andric S.Diag(prop1->getLocation(), diag::note_property_declare); 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric Setter = setter; 6850b57cec5SDimitry Andric return true; 6860b57cec5SDimitry Andric } 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric // That can fail in the somewhat crazy situation that we're 6890b57cec5SDimitry Andric // type-checking a message send within the @interface declaration 6900b57cec5SDimitry Andric // that declared the @property. But it's not clear that that's 6910b57cec5SDimitry Andric // valuable to support. 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric return false; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() { 6970b57cec5SDimitry Andric if (S.getCurLexicalContext()->isObjCContainer() && 6980b57cec5SDimitry Andric S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl && 6990b57cec5SDimitry Andric S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) { 7000b57cec5SDimitry Andric if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) { 7010b57cec5SDimitry Andric S.Diag(RefExpr->getLocation(), 7020b57cec5SDimitry Andric diag::err_property_function_in_objc_container); 7030b57cec5SDimitry Andric S.Diag(prop->getLocation(), diag::note_property_declare); 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric /// Capture the base object of an Objective-C property expression. 7090b57cec5SDimitry Andric Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 7100b57cec5SDimitry Andric assert(InstanceReceiver == nullptr); 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric // If we have a base, capture it in an OVE and rebuild the syntactic 7130b57cec5SDimitry Andric // form to use the OVE as its base. 7140b57cec5SDimitry Andric if (RefExpr->isObjectReceiver()) { 7150b57cec5SDimitry Andric InstanceReceiver = capture(RefExpr->getBase()); 7160b57cec5SDimitry Andric syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * { 7170b57cec5SDimitry Andric return InstanceReceiver; 7180b57cec5SDimitry Andric }).rebuild(syntacticBase); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric if (ObjCPropertyRefExpr * 7220b57cec5SDimitry Andric refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens())) 7230b57cec5SDimitry Andric SyntacticRefExpr = refE; 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric return syntacticBase; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric /// Load from an Objective-C property reference. 7290b57cec5SDimitry Andric ExprResult ObjCPropertyOpBuilder::buildGet() { 7300b57cec5SDimitry Andric findGetter(); 7310b57cec5SDimitry Andric if (!Getter) { 7320b57cec5SDimitry Andric DiagnoseUnsupportedPropertyUse(); 7330b57cec5SDimitry Andric return ExprError(); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric if (SyntacticRefExpr) 7370b57cec5SDimitry Andric SyntacticRefExpr->setIsMessagingGetter(); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric QualType receiverType = RefExpr->getReceiverType(S.Context); 7400b57cec5SDimitry Andric if (!Getter->isImplicit()) 7410b57cec5SDimitry Andric S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true); 7420b57cec5SDimitry Andric // Build a message-send. 7430b57cec5SDimitry Andric ExprResult msg; 7440b57cec5SDimitry Andric if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) || 7450b57cec5SDimitry Andric RefExpr->isObjectReceiver()) { 7460b57cec5SDimitry Andric assert(InstanceReceiver || RefExpr->isSuperReceiver()); 747*0fca6ea1SDimitry Andric msg = S.ObjC().BuildInstanceMessageImplicit( 748*0fca6ea1SDimitry Andric InstanceReceiver, receiverType, GenericLoc, Getter->getSelector(), 749bdd1243dSDimitry Andric Getter, std::nullopt); 7500b57cec5SDimitry Andric } else { 751*0fca6ea1SDimitry Andric msg = S.ObjC().BuildClassMessageImplicit( 752*0fca6ea1SDimitry Andric receiverType, RefExpr->isSuperReceiver(), GenericLoc, 753*0fca6ea1SDimitry Andric Getter->getSelector(), Getter, std::nullopt); 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric return msg; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric /// Store to an Objective-C property reference. 7590b57cec5SDimitry Andric /// 7600b57cec5SDimitry Andric /// \param captureSetValueAsResult If true, capture the actual 7610b57cec5SDimitry Andric /// value being set as the value of the property operation. 7620b57cec5SDimitry Andric ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 7630b57cec5SDimitry Andric bool captureSetValueAsResult) { 7640b57cec5SDimitry Andric if (!findSetter(false)) { 7650b57cec5SDimitry Andric DiagnoseUnsupportedPropertyUse(); 7660b57cec5SDimitry Andric return ExprError(); 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric if (SyntacticRefExpr) 7700b57cec5SDimitry Andric SyntacticRefExpr->setIsMessagingSetter(); 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric QualType receiverType = RefExpr->getReceiverType(S.Context); 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric // Use assignment constraints when possible; they give us better 7750b57cec5SDimitry Andric // diagnostics. "When possible" basically means anything except a 7760b57cec5SDimitry Andric // C++ class type. 7770b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { 7780b57cec5SDimitry Andric QualType paramType = (*Setter->param_begin())->getType() 7790b57cec5SDimitry Andric .substObjCMemberType( 7800b57cec5SDimitry Andric receiverType, 7810b57cec5SDimitry Andric Setter->getDeclContext(), 7820b57cec5SDimitry Andric ObjCSubstitutionContext::Parameter); 7830b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { 7840b57cec5SDimitry Andric ExprResult opResult = op; 7850b57cec5SDimitry Andric Sema::AssignConvertType assignResult 7860b57cec5SDimitry Andric = S.CheckSingleAssignmentConstraints(paramType, opResult); 7870b57cec5SDimitry Andric if (opResult.isInvalid() || 7880b57cec5SDimitry Andric S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 7890b57cec5SDimitry Andric op->getType(), opResult.get(), 7900b57cec5SDimitry Andric Sema::AA_Assigning)) 7910b57cec5SDimitry Andric return ExprError(); 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric op = opResult.get(); 7940b57cec5SDimitry Andric assert(op && "successful assignment left argument invalid?"); 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric // Arguments. 7990b57cec5SDimitry Andric Expr *args[] = { op }; 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric // Build a message-send. 8020b57cec5SDimitry Andric ExprResult msg; 8030b57cec5SDimitry Andric if (!Setter->isImplicit()) 8040b57cec5SDimitry Andric S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true); 8050b57cec5SDimitry Andric if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) || 8060b57cec5SDimitry Andric RefExpr->isObjectReceiver()) { 807*0fca6ea1SDimitry Andric msg = S.ObjC().BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 808*0fca6ea1SDimitry Andric GenericLoc, SetterSelector, 809*0fca6ea1SDimitry Andric Setter, MultiExprArg(args, 1)); 8100b57cec5SDimitry Andric } else { 811*0fca6ea1SDimitry Andric msg = S.ObjC().BuildClassMessageImplicit( 812*0fca6ea1SDimitry Andric receiverType, RefExpr->isSuperReceiver(), GenericLoc, SetterSelector, 813*0fca6ea1SDimitry Andric Setter, MultiExprArg(args, 1)); 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric if (!msg.isInvalid() && captureSetValueAsResult) { 8170b57cec5SDimitry Andric ObjCMessageExpr *msgExpr = 8180b57cec5SDimitry Andric cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 8190b57cec5SDimitry Andric Expr *arg = msgExpr->getArg(0); 8200b57cec5SDimitry Andric if (CanCaptureValue(arg)) 8210b57cec5SDimitry Andric msgExpr->setArg(0, captureValueAsResult(arg)); 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric return msg; 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric /// @property-specific behavior for doing lvalue-to-rvalue conversion. 8280b57cec5SDimitry Andric ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 8290b57cec5SDimitry Andric // Explicit properties always have getters, but implicit ones don't. 8300b57cec5SDimitry Andric // Check that before proceeding. 8310b57cec5SDimitry Andric if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) { 8320b57cec5SDimitry Andric S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 8330b57cec5SDimitry Andric << RefExpr->getSourceRange(); 8340b57cec5SDimitry Andric return ExprError(); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 8380b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 841*0fca6ea1SDimitry Andric S.ObjC().DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 8420b57cec5SDimitry Andric Getter, RefExpr->getLocation()); 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric // As a special case, if the method returns 'id', try to get 8450b57cec5SDimitry Andric // a better type from the property. 846fe6060f1SDimitry Andric if (RefExpr->isExplicitProperty() && result.get()->isPRValue()) { 8470b57cec5SDimitry Andric QualType receiverType = RefExpr->getReceiverType(S.Context); 8480b57cec5SDimitry Andric QualType propType = RefExpr->getExplicitProperty() 8490b57cec5SDimitry Andric ->getUsageType(receiverType); 8500b57cec5SDimitry Andric if (result.get()->getType()->isObjCIdType()) { 8510b57cec5SDimitry Andric if (const ObjCObjectPointerType *ptr 8520b57cec5SDimitry Andric = propType->getAs<ObjCObjectPointerType>()) { 8530b57cec5SDimitry Andric if (!ptr->isObjCIdType()) 8540b57cec5SDimitry Andric result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric if (propType.getObjCLifetime() == Qualifiers::OCL_Weak && 8580b57cec5SDimitry Andric !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, 8590b57cec5SDimitry Andric RefExpr->getLocation())) 8600b57cec5SDimitry Andric S.getCurFunction()->markSafeWeakUse(RefExpr); 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric return result; 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric /// Try to build this as a call to a getter that returns a reference. 8670b57cec5SDimitry Andric /// 8680b57cec5SDimitry Andric /// \return true if it was possible, whether or not it actually 8690b57cec5SDimitry Andric /// succeeded 8700b57cec5SDimitry Andric bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 8710b57cec5SDimitry Andric ExprResult &result) { 8720b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus) return false; 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric findGetter(); 8750b57cec5SDimitry Andric if (!Getter) { 8760b57cec5SDimitry Andric // The property has no setter and no getter! This can happen if the type is 8770b57cec5SDimitry Andric // invalid. Error have already been reported. 8780b57cec5SDimitry Andric result = ExprError(); 8790b57cec5SDimitry Andric return true; 8800b57cec5SDimitry Andric } 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric // Only do this if the getter returns an l-value reference type. 8830b57cec5SDimitry Andric QualType resultType = Getter->getReturnType(); 8840b57cec5SDimitry Andric if (!resultType->isLValueReferenceType()) return false; 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric result = buildRValueOperation(op); 8870b57cec5SDimitry Andric return true; 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric /// @property-specific behavior for doing assignments. 8910b57cec5SDimitry Andric ExprResult 8920b57cec5SDimitry Andric ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 8930b57cec5SDimitry Andric SourceLocation opcLoc, 8940b57cec5SDimitry Andric BinaryOperatorKind opcode, 8950b57cec5SDimitry Andric Expr *LHS, Expr *RHS) { 8960b57cec5SDimitry Andric assert(BinaryOperator::isAssignmentOp(opcode)); 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric // If there's no setter, we have no choice but to try to assign to 8990b57cec5SDimitry Andric // the result of the getter. 9000b57cec5SDimitry Andric if (!findSetter()) { 9010b57cec5SDimitry Andric ExprResult result; 9020b57cec5SDimitry Andric if (tryBuildGetOfReference(LHS, result)) { 9030b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 9040b57cec5SDimitry Andric return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS); 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // Otherwise, it's an error. 9080b57cec5SDimitry Andric S.Diag(opcLoc, diag::err_nosetter_property_assignment) 9090b57cec5SDimitry Andric << unsigned(RefExpr->isImplicitProperty()) 9100b57cec5SDimitry Andric << SetterSelector 9110b57cec5SDimitry Andric << LHS->getSourceRange() << RHS->getSourceRange(); 9120b57cec5SDimitry Andric return ExprError(); 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric // If there is a setter, we definitely want to use it. 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric // Verify that we can do a compound assignment. 9180b57cec5SDimitry Andric if (opcode != BO_Assign && !findGetter()) { 9190b57cec5SDimitry Andric S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 9200b57cec5SDimitry Andric << LHS->getSourceRange() << RHS->getSourceRange(); 9210b57cec5SDimitry Andric return ExprError(); 9220b57cec5SDimitry Andric } 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric ExprResult result = 9250b57cec5SDimitry Andric PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 9260b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric // Various warnings about property assignments in ARC. 9290b57cec5SDimitry Andric if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { 930*0fca6ea1SDimitry Andric S.ObjC().checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 9310b57cec5SDimitry Andric S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric return result; 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric /// @property-specific behavior for doing increments and decrements. 9380b57cec5SDimitry Andric ExprResult 9390b57cec5SDimitry Andric ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 9400b57cec5SDimitry Andric UnaryOperatorKind opcode, 9410b57cec5SDimitry Andric Expr *op) { 9420b57cec5SDimitry Andric // If there's no setter, we have no choice but to try to assign to 9430b57cec5SDimitry Andric // the result of the getter. 9440b57cec5SDimitry Andric if (!findSetter()) { 9450b57cec5SDimitry Andric ExprResult result; 9460b57cec5SDimitry Andric if (tryBuildGetOfReference(op, result)) { 9470b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 9480b57cec5SDimitry Andric return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get()); 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric // Otherwise, it's an error. 9520b57cec5SDimitry Andric S.Diag(opcLoc, diag::err_nosetter_property_incdec) 9530b57cec5SDimitry Andric << unsigned(RefExpr->isImplicitProperty()) 9540b57cec5SDimitry Andric << unsigned(UnaryOperator::isDecrementOp(opcode)) 9550b57cec5SDimitry Andric << SetterSelector 9560b57cec5SDimitry Andric << op->getSourceRange(); 9570b57cec5SDimitry Andric return ExprError(); 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric // If there is a setter, we definitely want to use it. 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric // We also need a getter. 9630b57cec5SDimitry Andric if (!findGetter()) { 9640b57cec5SDimitry Andric assert(RefExpr->isImplicitProperty()); 9650b57cec5SDimitry Andric S.Diag(opcLoc, diag::err_nogetter_property_incdec) 9660b57cec5SDimitry Andric << unsigned(UnaryOperator::isDecrementOp(opcode)) 9670b57cec5SDimitry Andric << GetterSelector 9680b57cec5SDimitry Andric << op->getSourceRange(); 9690b57cec5SDimitry Andric return ExprError(); 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { 9760b57cec5SDimitry Andric if (isWeakProperty() && !S.isUnevaluatedContext() && 9770b57cec5SDimitry Andric !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, 9780b57cec5SDimitry Andric SyntacticForm->getBeginLoc())) 9790b57cec5SDimitry Andric S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, 9800b57cec5SDimitry Andric SyntacticRefExpr->isMessagingGetter()); 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric return PseudoOpBuilder::complete(SyntacticForm); 9830b57cec5SDimitry Andric } 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric // ObjCSubscript build stuff. 9860b57cec5SDimitry Andric // 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue 9890b57cec5SDimitry Andric /// conversion. 9900b57cec5SDimitry Andric /// FIXME. Remove this routine if it is proven that no additional 9910b57cec5SDimitry Andric /// specifity is needed. 9920b57cec5SDimitry Andric ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { 9930b57cec5SDimitry Andric ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 9940b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 9950b57cec5SDimitry Andric return result; 9960b57cec5SDimitry Andric } 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric /// objective-c subscripting-specific behavior for doing assignments. 9990b57cec5SDimitry Andric ExprResult 10000b57cec5SDimitry Andric ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, 10010b57cec5SDimitry Andric SourceLocation opcLoc, 10020b57cec5SDimitry Andric BinaryOperatorKind opcode, 10030b57cec5SDimitry Andric Expr *LHS, Expr *RHS) { 10040b57cec5SDimitry Andric assert(BinaryOperator::isAssignmentOp(opcode)); 10050b57cec5SDimitry Andric // There must be a method to do the Index'ed assignment. 10060b57cec5SDimitry Andric if (!findAtIndexSetter()) 10070b57cec5SDimitry Andric return ExprError(); 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric // Verify that we can do a compound assignment. 10100b57cec5SDimitry Andric if (opcode != BO_Assign && !findAtIndexGetter()) 10110b57cec5SDimitry Andric return ExprError(); 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric ExprResult result = 10140b57cec5SDimitry Andric PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 10150b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric // Various warnings about objc Index'ed assignments in ARC. 10180b57cec5SDimitry Andric if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { 1019*0fca6ea1SDimitry Andric S.ObjC().checkRetainCycles(InstanceBase->getSourceExpr(), RHS); 10200b57cec5SDimitry Andric S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric return result; 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric /// Capture the base object of an Objective-C Index'ed expression. 10270b57cec5SDimitry Andric Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 10280b57cec5SDimitry Andric assert(InstanceBase == nullptr); 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric // Capture base expression in an OVE and rebuild the syntactic 10310b57cec5SDimitry Andric // form to use the OVE as its base expression. 10320b57cec5SDimitry Andric InstanceBase = capture(RefExpr->getBaseExpr()); 10330b57cec5SDimitry Andric InstanceKey = capture(RefExpr->getKeyExpr()); 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric syntacticBase = 10360b57cec5SDimitry Andric Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { 10370b57cec5SDimitry Andric switch (Idx) { 10380b57cec5SDimitry Andric case 0: 10390b57cec5SDimitry Andric return InstanceBase; 10400b57cec5SDimitry Andric case 1: 10410b57cec5SDimitry Andric return InstanceKey; 10420b57cec5SDimitry Andric default: 10430b57cec5SDimitry Andric llvm_unreachable("Unexpected index for ObjCSubscriptExpr"); 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric }).rebuild(syntacticBase); 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric return syntacticBase; 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF 10510b57cec5SDimitry Andric /// objects used as dictionary subscript key objects. 10520b57cec5SDimitry Andric static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, 10530b57cec5SDimitry Andric Expr *Key) { 10540b57cec5SDimitry Andric if (ContainerT.isNull()) 10550b57cec5SDimitry Andric return; 10560b57cec5SDimitry Andric // dictionary subscripting. 10570b57cec5SDimitry Andric // - (id)objectForKeyedSubscript:(id)key; 1058*0fca6ea1SDimitry Andric const IdentifierInfo *KeyIdents[] = { 1059*0fca6ea1SDimitry Andric &S.Context.Idents.get("objectForKeyedSubscript")}; 10600b57cec5SDimitry Andric Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1061*0fca6ea1SDimitry Andric ObjCMethodDecl *Getter = S.ObjC().LookupMethodInObjectType( 1062*0fca6ea1SDimitry Andric GetterSelector, ContainerT, true /*instance*/); 10630b57cec5SDimitry Andric if (!Getter) 10640b57cec5SDimitry Andric return; 10650b57cec5SDimitry Andric QualType T = Getter->parameters()[0]->getType(); 1066*0fca6ea1SDimitry Andric S.ObjC().CheckObjCConversion(Key->getSourceRange(), T, Key, 1067*0fca6ea1SDimitry Andric CheckedConversionKind::Implicit); 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric bool ObjCSubscriptOpBuilder::findAtIndexGetter() { 10710b57cec5SDimitry Andric if (AtIndexGetter) 10720b57cec5SDimitry Andric return true; 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric Expr *BaseExpr = RefExpr->getBaseExpr(); 10750b57cec5SDimitry Andric QualType BaseT = BaseExpr->getType(); 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric QualType ResultType; 10780b57cec5SDimitry Andric if (const ObjCObjectPointerType *PTy = 10790b57cec5SDimitry Andric BaseT->getAs<ObjCObjectPointerType>()) { 10800b57cec5SDimitry Andric ResultType = PTy->getPointeeType(); 10810b57cec5SDimitry Andric } 1082*0fca6ea1SDimitry Andric SemaObjC::ObjCSubscriptKind Res = 1083*0fca6ea1SDimitry Andric S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr()); 1084*0fca6ea1SDimitry Andric if (Res == SemaObjC::OS_Error) { 10850b57cec5SDimitry Andric if (S.getLangOpts().ObjCAutoRefCount) 10860b57cec5SDimitry Andric CheckKeyForObjCARCConversion(S, ResultType, 10870b57cec5SDimitry Andric RefExpr->getKeyExpr()); 10880b57cec5SDimitry Andric return false; 10890b57cec5SDimitry Andric } 1090*0fca6ea1SDimitry Andric bool arrayRef = (Res == SemaObjC::OS_Array); 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric if (ResultType.isNull()) { 10930b57cec5SDimitry Andric S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 10940b57cec5SDimitry Andric << BaseExpr->getType() << arrayRef; 10950b57cec5SDimitry Andric return false; 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric if (!arrayRef) { 10980b57cec5SDimitry Andric // dictionary subscripting. 10990b57cec5SDimitry Andric // - (id)objectForKeyedSubscript:(id)key; 1100*0fca6ea1SDimitry Andric const IdentifierInfo *KeyIdents[] = { 1101*0fca6ea1SDimitry Andric &S.Context.Idents.get("objectForKeyedSubscript")}; 11020b57cec5SDimitry Andric AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 11030b57cec5SDimitry Andric } 11040b57cec5SDimitry Andric else { 11050b57cec5SDimitry Andric // - (id)objectAtIndexedSubscript:(size_t)index; 1106*0fca6ea1SDimitry Andric const IdentifierInfo *KeyIdents[] = { 1107*0fca6ea1SDimitry Andric &S.Context.Idents.get("objectAtIndexedSubscript")}; 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 1112*0fca6ea1SDimitry Andric AtIndexGetter = S.ObjC().LookupMethodInObjectType( 1113*0fca6ea1SDimitry Andric AtIndexGetterSelector, ResultType, true /*instance*/); 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { 1116480093f4SDimitry Andric AtIndexGetter = ObjCMethodDecl::Create( 1117480093f4SDimitry Andric S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector, 1118480093f4SDimitry Andric S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */, 1119480093f4SDimitry Andric S.Context.getTranslationUnitDecl(), true /*Instance*/, 1120480093f4SDimitry Andric false /*isVariadic*/, 11210b57cec5SDimitry Andric /*isPropertyAccessor=*/false, 1122480093f4SDimitry Andric /*isSynthesizedAccessorStub=*/false, 11230b57cec5SDimitry Andric /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 11245f757f3fSDimitry Andric ObjCImplementationControl::Required, false); 11250b57cec5SDimitry Andric ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, 11260b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 11270b57cec5SDimitry Andric arrayRef ? &S.Context.Idents.get("index") 11280b57cec5SDimitry Andric : &S.Context.Idents.get("key"), 11290b57cec5SDimitry Andric arrayRef ? S.Context.UnsignedLongTy 11300b57cec5SDimitry Andric : S.Context.getObjCIdType(), 11310b57cec5SDimitry Andric /*TInfo=*/nullptr, 11320b57cec5SDimitry Andric SC_None, 11330b57cec5SDimitry Andric nullptr); 1134bdd1243dSDimitry Andric AtIndexGetter->setMethodParams(S.Context, Argument, std::nullopt); 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric 11370b57cec5SDimitry Andric if (!AtIndexGetter) { 11380b57cec5SDimitry Andric if (!BaseT->isObjCIdType()) { 11390b57cec5SDimitry Andric S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found) 11400b57cec5SDimitry Andric << BaseExpr->getType() << 0 << arrayRef; 11410b57cec5SDimitry Andric return false; 11420b57cec5SDimitry Andric } 1143*0fca6ea1SDimitry Andric AtIndexGetter = S.ObjC().LookupInstanceMethodInGlobalPool( 1144*0fca6ea1SDimitry Andric AtIndexGetterSelector, RefExpr->getSourceRange(), true); 11450b57cec5SDimitry Andric } 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric if (AtIndexGetter) { 11480b57cec5SDimitry Andric QualType T = AtIndexGetter->parameters()[0]->getType(); 11490b57cec5SDimitry Andric if ((arrayRef && !T->isIntegralOrEnumerationType()) || 11500b57cec5SDimitry Andric (!arrayRef && !T->isObjCObjectPointerType())) { 11510b57cec5SDimitry Andric S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 11520b57cec5SDimitry Andric arrayRef ? diag::err_objc_subscript_index_type 11530b57cec5SDimitry Andric : diag::err_objc_subscript_key_type) << T; 11540b57cec5SDimitry Andric S.Diag(AtIndexGetter->parameters()[0]->getLocation(), 11550b57cec5SDimitry Andric diag::note_parameter_type) << T; 11560b57cec5SDimitry Andric return false; 11570b57cec5SDimitry Andric } 11580b57cec5SDimitry Andric QualType R = AtIndexGetter->getReturnType(); 11590b57cec5SDimitry Andric if (!R->isObjCObjectPointerType()) { 11600b57cec5SDimitry Andric S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 11610b57cec5SDimitry Andric diag::err_objc_indexing_method_result_type) << R << arrayRef; 11620b57cec5SDimitry Andric S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) << 11630b57cec5SDimitry Andric AtIndexGetter->getDeclName(); 11640b57cec5SDimitry Andric } 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric return true; 11670b57cec5SDimitry Andric } 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric bool ObjCSubscriptOpBuilder::findAtIndexSetter() { 11700b57cec5SDimitry Andric if (AtIndexSetter) 11710b57cec5SDimitry Andric return true; 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andric Expr *BaseExpr = RefExpr->getBaseExpr(); 11740b57cec5SDimitry Andric QualType BaseT = BaseExpr->getType(); 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric QualType ResultType; 11770b57cec5SDimitry Andric if (const ObjCObjectPointerType *PTy = 11780b57cec5SDimitry Andric BaseT->getAs<ObjCObjectPointerType>()) { 11790b57cec5SDimitry Andric ResultType = PTy->getPointeeType(); 11800b57cec5SDimitry Andric } 11810b57cec5SDimitry Andric 1182*0fca6ea1SDimitry Andric SemaObjC::ObjCSubscriptKind Res = 1183*0fca6ea1SDimitry Andric S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr()); 1184*0fca6ea1SDimitry Andric if (Res == SemaObjC::OS_Error) { 11850b57cec5SDimitry Andric if (S.getLangOpts().ObjCAutoRefCount) 11860b57cec5SDimitry Andric CheckKeyForObjCARCConversion(S, ResultType, 11870b57cec5SDimitry Andric RefExpr->getKeyExpr()); 11880b57cec5SDimitry Andric return false; 11890b57cec5SDimitry Andric } 1190*0fca6ea1SDimitry Andric bool arrayRef = (Res == SemaObjC::OS_Array); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric if (ResultType.isNull()) { 11930b57cec5SDimitry Andric S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 11940b57cec5SDimitry Andric << BaseExpr->getType() << arrayRef; 11950b57cec5SDimitry Andric return false; 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric if (!arrayRef) { 11990b57cec5SDimitry Andric // dictionary subscripting. 12000b57cec5SDimitry Andric // - (void)setObject:(id)object forKeyedSubscript:(id)key; 1201*0fca6ea1SDimitry Andric const IdentifierInfo *KeyIdents[] = { 12020b57cec5SDimitry Andric &S.Context.Idents.get("setObject"), 1203*0fca6ea1SDimitry Andric &S.Context.Idents.get("forKeyedSubscript")}; 12040b57cec5SDimitry Andric AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric else { 12070b57cec5SDimitry Andric // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 1208*0fca6ea1SDimitry Andric const IdentifierInfo *KeyIdents[] = { 12090b57cec5SDimitry Andric &S.Context.Idents.get("setObject"), 1210*0fca6ea1SDimitry Andric &S.Context.Idents.get("atIndexedSubscript")}; 12110b57cec5SDimitry Andric AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 12120b57cec5SDimitry Andric } 1213*0fca6ea1SDimitry Andric AtIndexSetter = S.ObjC().LookupMethodInObjectType( 1214*0fca6ea1SDimitry Andric AtIndexSetterSelector, ResultType, true /*instance*/); 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { 12170b57cec5SDimitry Andric TypeSourceInfo *ReturnTInfo = nullptr; 12180b57cec5SDimitry Andric QualType ReturnType = S.Context.VoidTy; 12190b57cec5SDimitry Andric AtIndexSetter = ObjCMethodDecl::Create( 12200b57cec5SDimitry Andric S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector, 12210b57cec5SDimitry Andric ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(), 12220b57cec5SDimitry Andric true /*Instance*/, false /*isVariadic*/, 12230b57cec5SDimitry Andric /*isPropertyAccessor=*/false, 1224480093f4SDimitry Andric /*isSynthesizedAccessorStub=*/false, 12250b57cec5SDimitry Andric /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 12265f757f3fSDimitry Andric ObjCImplementationControl::Required, false); 12270b57cec5SDimitry Andric SmallVector<ParmVarDecl *, 2> Params; 12280b57cec5SDimitry Andric ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter, 12290b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 12300b57cec5SDimitry Andric &S.Context.Idents.get("object"), 12310b57cec5SDimitry Andric S.Context.getObjCIdType(), 12320b57cec5SDimitry Andric /*TInfo=*/nullptr, 12330b57cec5SDimitry Andric SC_None, 12340b57cec5SDimitry Andric nullptr); 12350b57cec5SDimitry Andric Params.push_back(object); 12360b57cec5SDimitry Andric ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, 12370b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 12380b57cec5SDimitry Andric arrayRef ? &S.Context.Idents.get("index") 12390b57cec5SDimitry Andric : &S.Context.Idents.get("key"), 12400b57cec5SDimitry Andric arrayRef ? S.Context.UnsignedLongTy 12410b57cec5SDimitry Andric : S.Context.getObjCIdType(), 12420b57cec5SDimitry Andric /*TInfo=*/nullptr, 12430b57cec5SDimitry Andric SC_None, 12440b57cec5SDimitry Andric nullptr); 12450b57cec5SDimitry Andric Params.push_back(key); 1246bdd1243dSDimitry Andric AtIndexSetter->setMethodParams(S.Context, Params, std::nullopt); 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andric if (!AtIndexSetter) { 12500b57cec5SDimitry Andric if (!BaseT->isObjCIdType()) { 12510b57cec5SDimitry Andric S.Diag(BaseExpr->getExprLoc(), 12520b57cec5SDimitry Andric diag::err_objc_subscript_method_not_found) 12530b57cec5SDimitry Andric << BaseExpr->getType() << 1 << arrayRef; 12540b57cec5SDimitry Andric return false; 12550b57cec5SDimitry Andric } 1256*0fca6ea1SDimitry Andric AtIndexSetter = S.ObjC().LookupInstanceMethodInGlobalPool( 1257*0fca6ea1SDimitry Andric AtIndexSetterSelector, RefExpr->getSourceRange(), true); 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric 12600b57cec5SDimitry Andric bool err = false; 12610b57cec5SDimitry Andric if (AtIndexSetter && arrayRef) { 12620b57cec5SDimitry Andric QualType T = AtIndexSetter->parameters()[1]->getType(); 12630b57cec5SDimitry Andric if (!T->isIntegralOrEnumerationType()) { 12640b57cec5SDimitry Andric S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 12650b57cec5SDimitry Andric diag::err_objc_subscript_index_type) << T; 12660b57cec5SDimitry Andric S.Diag(AtIndexSetter->parameters()[1]->getLocation(), 12670b57cec5SDimitry Andric diag::note_parameter_type) << T; 12680b57cec5SDimitry Andric err = true; 12690b57cec5SDimitry Andric } 12700b57cec5SDimitry Andric T = AtIndexSetter->parameters()[0]->getType(); 12710b57cec5SDimitry Andric if (!T->isObjCObjectPointerType()) { 12720b57cec5SDimitry Andric S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 12730b57cec5SDimitry Andric diag::err_objc_subscript_object_type) << T << arrayRef; 12740b57cec5SDimitry Andric S.Diag(AtIndexSetter->parameters()[0]->getLocation(), 12750b57cec5SDimitry Andric diag::note_parameter_type) << T; 12760b57cec5SDimitry Andric err = true; 12770b57cec5SDimitry Andric } 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric else if (AtIndexSetter && !arrayRef) 12800b57cec5SDimitry Andric for (unsigned i=0; i <2; i++) { 12810b57cec5SDimitry Andric QualType T = AtIndexSetter->parameters()[i]->getType(); 12820b57cec5SDimitry Andric if (!T->isObjCObjectPointerType()) { 12830b57cec5SDimitry Andric if (i == 1) 12840b57cec5SDimitry Andric S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 12850b57cec5SDimitry Andric diag::err_objc_subscript_key_type) << T; 12860b57cec5SDimitry Andric else 12870b57cec5SDimitry Andric S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 12880b57cec5SDimitry Andric diag::err_objc_subscript_dic_object_type) << T; 12890b57cec5SDimitry Andric S.Diag(AtIndexSetter->parameters()[i]->getLocation(), 12900b57cec5SDimitry Andric diag::note_parameter_type) << T; 12910b57cec5SDimitry Andric err = true; 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andric return !err; 12960b57cec5SDimitry Andric } 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric // Get the object at "Index" position in the container. 12990b57cec5SDimitry Andric // [BaseExpr objectAtIndexedSubscript : IndexExpr]; 13000b57cec5SDimitry Andric ExprResult ObjCSubscriptOpBuilder::buildGet() { 13010b57cec5SDimitry Andric if (!findAtIndexGetter()) 13020b57cec5SDimitry Andric return ExprError(); 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric QualType receiverType = InstanceBase->getType(); 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andric // Build a message-send. 13070b57cec5SDimitry Andric ExprResult msg; 13080b57cec5SDimitry Andric Expr *Index = InstanceKey; 13090b57cec5SDimitry Andric 13100b57cec5SDimitry Andric // Arguments. 13110b57cec5SDimitry Andric Expr *args[] = { Index }; 13120b57cec5SDimitry Andric assert(InstanceBase); 13130b57cec5SDimitry Andric if (AtIndexGetter) 13140b57cec5SDimitry Andric S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc); 1315*0fca6ea1SDimitry Andric msg = S.ObjC().BuildInstanceMessageImplicit( 1316*0fca6ea1SDimitry Andric InstanceBase, receiverType, GenericLoc, AtIndexGetterSelector, 1317*0fca6ea1SDimitry Andric AtIndexGetter, MultiExprArg(args, 1)); 13180b57cec5SDimitry Andric return msg; 13190b57cec5SDimitry Andric } 13200b57cec5SDimitry Andric 13210b57cec5SDimitry Andric /// Store into the container the "op" object at "Index"'ed location 13220b57cec5SDimitry Andric /// by building this messaging expression: 13230b57cec5SDimitry Andric /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 13240b57cec5SDimitry Andric /// \param captureSetValueAsResult If true, capture the actual 13250b57cec5SDimitry Andric /// value being set as the value of the property operation. 13260b57cec5SDimitry Andric ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 13270b57cec5SDimitry Andric bool captureSetValueAsResult) { 13280b57cec5SDimitry Andric if (!findAtIndexSetter()) 13290b57cec5SDimitry Andric return ExprError(); 13300b57cec5SDimitry Andric if (AtIndexSetter) 13310b57cec5SDimitry Andric S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc); 13320b57cec5SDimitry Andric QualType receiverType = InstanceBase->getType(); 13330b57cec5SDimitry Andric Expr *Index = InstanceKey; 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric // Arguments. 13360b57cec5SDimitry Andric Expr *args[] = { op, Index }; 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andric // Build a message-send. 1339*0fca6ea1SDimitry Andric ExprResult msg = S.ObjC().BuildInstanceMessageImplicit( 1340*0fca6ea1SDimitry Andric InstanceBase, receiverType, GenericLoc, AtIndexSetterSelector, 1341*0fca6ea1SDimitry Andric AtIndexSetter, MultiExprArg(args, 2)); 13420b57cec5SDimitry Andric 13430b57cec5SDimitry Andric if (!msg.isInvalid() && captureSetValueAsResult) { 13440b57cec5SDimitry Andric ObjCMessageExpr *msgExpr = 13450b57cec5SDimitry Andric cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 13460b57cec5SDimitry Andric Expr *arg = msgExpr->getArg(0); 13470b57cec5SDimitry Andric if (CanCaptureValue(arg)) 13480b57cec5SDimitry Andric msgExpr->setArg(0, captureValueAsResult(arg)); 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric return msg; 13520b57cec5SDimitry Andric } 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13550b57cec5SDimitry Andric // MSVC __declspec(property) references 13560b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric MSPropertyRefExpr * 13590b57cec5SDimitry Andric MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) { 13600b57cec5SDimitry Andric CallArgs.insert(CallArgs.begin(), E->getIdx()); 13610b57cec5SDimitry Andric Expr *Base = E->getBase()->IgnoreParens(); 13620b57cec5SDimitry Andric while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) { 13630b57cec5SDimitry Andric CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx()); 13640b57cec5SDimitry Andric Base = MSPropSubscript->getBase()->IgnoreParens(); 13650b57cec5SDimitry Andric } 13660b57cec5SDimitry Andric return cast<MSPropertyRefExpr>(Base); 13670b57cec5SDimitry Andric } 13680b57cec5SDimitry Andric 13690b57cec5SDimitry Andric Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 13700b57cec5SDimitry Andric InstanceBase = capture(RefExpr->getBaseExpr()); 13715f757f3fSDimitry Andric for (Expr *&Arg : CallArgs) 13725f757f3fSDimitry Andric Arg = capture(Arg); 13730b57cec5SDimitry Andric syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { 13740b57cec5SDimitry Andric switch (Idx) { 13750b57cec5SDimitry Andric case 0: 13760b57cec5SDimitry Andric return InstanceBase; 13770b57cec5SDimitry Andric default: 13780b57cec5SDimitry Andric assert(Idx <= CallArgs.size()); 13790b57cec5SDimitry Andric return CallArgs[Idx - 1]; 13800b57cec5SDimitry Andric } 13810b57cec5SDimitry Andric }).rebuild(syntacticBase); 13820b57cec5SDimitry Andric 13830b57cec5SDimitry Andric return syntacticBase; 13840b57cec5SDimitry Andric } 13850b57cec5SDimitry Andric 13860b57cec5SDimitry Andric ExprResult MSPropertyOpBuilder::buildGet() { 13870b57cec5SDimitry Andric if (!RefExpr->getPropertyDecl()->hasGetter()) { 13880b57cec5SDimitry Andric S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property) 13890b57cec5SDimitry Andric << 0 /* getter */ << RefExpr->getPropertyDecl(); 13900b57cec5SDimitry Andric return ExprError(); 13910b57cec5SDimitry Andric } 13920b57cec5SDimitry Andric 13930b57cec5SDimitry Andric UnqualifiedId GetterName; 1394*0fca6ea1SDimitry Andric const IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId(); 13950b57cec5SDimitry Andric GetterName.setIdentifier(II, RefExpr->getMemberLoc()); 13960b57cec5SDimitry Andric CXXScopeSpec SS; 13970b57cec5SDimitry Andric SS.Adopt(RefExpr->getQualifierLoc()); 13980b57cec5SDimitry Andric ExprResult GetterExpr = 13990b57cec5SDimitry Andric S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(), 14000b57cec5SDimitry Andric RefExpr->isArrow() ? tok::arrow : tok::period, SS, 14010b57cec5SDimitry Andric SourceLocation(), GetterName, nullptr); 14020b57cec5SDimitry Andric if (GetterExpr.isInvalid()) { 14030b57cec5SDimitry Andric S.Diag(RefExpr->getMemberLoc(), 14040b57cec5SDimitry Andric diag::err_cannot_find_suitable_accessor) << 0 /* getter */ 14050b57cec5SDimitry Andric << RefExpr->getPropertyDecl(); 14060b57cec5SDimitry Andric return ExprError(); 14070b57cec5SDimitry Andric } 14080b57cec5SDimitry Andric 14090b57cec5SDimitry Andric return S.BuildCallExpr(S.getCurScope(), GetterExpr.get(), 14100b57cec5SDimitry Andric RefExpr->getSourceRange().getBegin(), CallArgs, 14110b57cec5SDimitry Andric RefExpr->getSourceRange().getEnd()); 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, 14150b57cec5SDimitry Andric bool captureSetValueAsResult) { 14160b57cec5SDimitry Andric if (!RefExpr->getPropertyDecl()->hasSetter()) { 14170b57cec5SDimitry Andric S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property) 14180b57cec5SDimitry Andric << 1 /* setter */ << RefExpr->getPropertyDecl(); 14190b57cec5SDimitry Andric return ExprError(); 14200b57cec5SDimitry Andric } 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric UnqualifiedId SetterName; 1423*0fca6ea1SDimitry Andric const IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId(); 14240b57cec5SDimitry Andric SetterName.setIdentifier(II, RefExpr->getMemberLoc()); 14250b57cec5SDimitry Andric CXXScopeSpec SS; 14260b57cec5SDimitry Andric SS.Adopt(RefExpr->getQualifierLoc()); 14270b57cec5SDimitry Andric ExprResult SetterExpr = 14280b57cec5SDimitry Andric S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(), 14290b57cec5SDimitry Andric RefExpr->isArrow() ? tok::arrow : tok::period, SS, 14300b57cec5SDimitry Andric SourceLocation(), SetterName, nullptr); 14310b57cec5SDimitry Andric if (SetterExpr.isInvalid()) { 14320b57cec5SDimitry Andric S.Diag(RefExpr->getMemberLoc(), 14330b57cec5SDimitry Andric diag::err_cannot_find_suitable_accessor) << 1 /* setter */ 14340b57cec5SDimitry Andric << RefExpr->getPropertyDecl(); 14350b57cec5SDimitry Andric return ExprError(); 14360b57cec5SDimitry Andric } 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric SmallVector<Expr*, 4> ArgExprs; 14390b57cec5SDimitry Andric ArgExprs.append(CallArgs.begin(), CallArgs.end()); 14400b57cec5SDimitry Andric ArgExprs.push_back(op); 14410b57cec5SDimitry Andric return S.BuildCallExpr(S.getCurScope(), SetterExpr.get(), 14420b57cec5SDimitry Andric RefExpr->getSourceRange().getBegin(), ArgExprs, 14430b57cec5SDimitry Andric op->getSourceRange().getEnd()); 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric 14460b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14470b57cec5SDimitry Andric // General Sema routines. 14480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14490b57cec5SDimitry Andric 1450*0fca6ea1SDimitry Andric ExprResult SemaPseudoObject::checkRValue(Expr *E) { 14510b57cec5SDimitry Andric Expr *opaqueRef = E->IgnoreParens(); 14520b57cec5SDimitry Andric if (ObjCPropertyRefExpr *refExpr 14530b57cec5SDimitry Andric = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1454*0fca6ea1SDimitry Andric ObjCPropertyOpBuilder builder(SemaRef, refExpr, true); 14550b57cec5SDimitry Andric return builder.buildRValueOperation(E); 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric else if (ObjCSubscriptRefExpr *refExpr 14580b57cec5SDimitry Andric = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1459*0fca6ea1SDimitry Andric ObjCSubscriptOpBuilder builder(SemaRef, refExpr, true); 14600b57cec5SDimitry Andric return builder.buildRValueOperation(E); 14610b57cec5SDimitry Andric } else if (MSPropertyRefExpr *refExpr 14620b57cec5SDimitry Andric = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 1463*0fca6ea1SDimitry Andric MSPropertyOpBuilder builder(SemaRef, refExpr, true); 14640b57cec5SDimitry Andric return builder.buildRValueOperation(E); 14650b57cec5SDimitry Andric } else if (MSPropertySubscriptExpr *RefExpr = 14660b57cec5SDimitry Andric dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { 1467*0fca6ea1SDimitry Andric MSPropertyOpBuilder Builder(SemaRef, RefExpr, true); 14680b57cec5SDimitry Andric return Builder.buildRValueOperation(E); 14690b57cec5SDimitry Andric } else { 14700b57cec5SDimitry Andric llvm_unreachable("unknown pseudo-object kind!"); 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric 14740b57cec5SDimitry Andric /// Check an increment or decrement of a pseudo-object expression. 1475*0fca6ea1SDimitry Andric ExprResult SemaPseudoObject::checkIncDec(Scope *Sc, SourceLocation opcLoc, 14760b57cec5SDimitry Andric UnaryOperatorKind opcode, Expr *op) { 14770b57cec5SDimitry Andric // Do nothing if the operand is dependent. 14780b57cec5SDimitry Andric if (op->isTypeDependent()) 1479*0fca6ea1SDimitry Andric return UnaryOperator::Create( 1480*0fca6ea1SDimitry Andric SemaRef.Context, op, opcode, SemaRef.Context.DependentTy, VK_PRValue, 1481*0fca6ea1SDimitry Andric OK_Ordinary, opcLoc, false, SemaRef.CurFPFeatureOverrides()); 14820b57cec5SDimitry Andric 14830b57cec5SDimitry Andric assert(UnaryOperator::isIncrementDecrementOp(opcode)); 14840b57cec5SDimitry Andric Expr *opaqueRef = op->IgnoreParens(); 14850b57cec5SDimitry Andric if (ObjCPropertyRefExpr *refExpr 14860b57cec5SDimitry Andric = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1487*0fca6ea1SDimitry Andric ObjCPropertyOpBuilder builder(SemaRef, refExpr, false); 14880b57cec5SDimitry Andric return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 14890b57cec5SDimitry Andric } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) { 14900b57cec5SDimitry Andric Diag(opcLoc, diag::err_illegal_container_subscripting_op); 14910b57cec5SDimitry Andric return ExprError(); 14920b57cec5SDimitry Andric } else if (MSPropertyRefExpr *refExpr 14930b57cec5SDimitry Andric = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 1494*0fca6ea1SDimitry Andric MSPropertyOpBuilder builder(SemaRef, refExpr, false); 14950b57cec5SDimitry Andric return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 14960b57cec5SDimitry Andric } else if (MSPropertySubscriptExpr *RefExpr 14970b57cec5SDimitry Andric = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { 1498*0fca6ea1SDimitry Andric MSPropertyOpBuilder Builder(SemaRef, RefExpr, false); 14990b57cec5SDimitry Andric return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 15000b57cec5SDimitry Andric } else { 15010b57cec5SDimitry Andric llvm_unreachable("unknown pseudo-object kind!"); 15020b57cec5SDimitry Andric } 15030b57cec5SDimitry Andric } 15040b57cec5SDimitry Andric 1505*0fca6ea1SDimitry Andric ExprResult SemaPseudoObject::checkAssignment(Scope *S, SourceLocation opcLoc, 15060b57cec5SDimitry Andric BinaryOperatorKind opcode, 15070b57cec5SDimitry Andric Expr *LHS, Expr *RHS) { 15080b57cec5SDimitry Andric // Do nothing if either argument is dependent. 15090b57cec5SDimitry Andric if (LHS->isTypeDependent() || RHS->isTypeDependent()) 1510*0fca6ea1SDimitry Andric return BinaryOperator::Create( 1511*0fca6ea1SDimitry Andric SemaRef.Context, LHS, RHS, opcode, SemaRef.Context.DependentTy, 1512*0fca6ea1SDimitry Andric VK_PRValue, OK_Ordinary, opcLoc, SemaRef.CurFPFeatureOverrides()); 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric // Filter out non-overload placeholder types in the RHS. 15150b57cec5SDimitry Andric if (RHS->getType()->isNonOverloadPlaceholderType()) { 1516*0fca6ea1SDimitry Andric ExprResult result = SemaRef.CheckPlaceholderExpr(RHS); 15170b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 15180b57cec5SDimitry Andric RHS = result.get(); 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric 15210b57cec5SDimitry Andric bool IsSimpleAssign = opcode == BO_Assign; 15220b57cec5SDimitry Andric Expr *opaqueRef = LHS->IgnoreParens(); 15230b57cec5SDimitry Andric if (ObjCPropertyRefExpr *refExpr 15240b57cec5SDimitry Andric = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1525*0fca6ea1SDimitry Andric ObjCPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign); 15260b57cec5SDimitry Andric return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 15270b57cec5SDimitry Andric } else if (ObjCSubscriptRefExpr *refExpr 15280b57cec5SDimitry Andric = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1529*0fca6ea1SDimitry Andric ObjCSubscriptOpBuilder builder(SemaRef, refExpr, IsSimpleAssign); 15300b57cec5SDimitry Andric return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 15310b57cec5SDimitry Andric } else if (MSPropertyRefExpr *refExpr 15320b57cec5SDimitry Andric = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 1533*0fca6ea1SDimitry Andric MSPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign); 15340b57cec5SDimitry Andric return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 15350b57cec5SDimitry Andric } else if (MSPropertySubscriptExpr *RefExpr 15360b57cec5SDimitry Andric = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { 1537*0fca6ea1SDimitry Andric MSPropertyOpBuilder Builder(SemaRef, RefExpr, IsSimpleAssign); 15380b57cec5SDimitry Andric return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 15390b57cec5SDimitry Andric } else { 15400b57cec5SDimitry Andric llvm_unreachable("unknown pseudo-object kind!"); 15410b57cec5SDimitry Andric } 15420b57cec5SDimitry Andric } 15430b57cec5SDimitry Andric 15440b57cec5SDimitry Andric /// Given a pseudo-object reference, rebuild it without the opaque 15450b57cec5SDimitry Andric /// values. Basically, undo the behavior of rebuildAndCaptureObject. 15460b57cec5SDimitry Andric /// This should never operate in-place. 15470b57cec5SDimitry Andric static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { 15480b57cec5SDimitry Andric return Rebuilder(S, 15490b57cec5SDimitry Andric [=](Expr *E, unsigned) -> Expr * { 15500b57cec5SDimitry Andric return cast<OpaqueValueExpr>(E)->getSourceExpr(); 15510b57cec5SDimitry Andric }) 15520b57cec5SDimitry Andric .rebuild(E); 15530b57cec5SDimitry Andric } 15540b57cec5SDimitry Andric 15550b57cec5SDimitry Andric /// Given a pseudo-object expression, recreate what it looks like 15560b57cec5SDimitry Andric /// syntactically without the attendant OpaqueValueExprs. 15570b57cec5SDimitry Andric /// 15580b57cec5SDimitry Andric /// This is a hack which should be removed when TreeTransform is 15590b57cec5SDimitry Andric /// capable of rebuilding a tree without stripping implicit 15600b57cec5SDimitry Andric /// operations. 1561*0fca6ea1SDimitry Andric Expr *SemaPseudoObject::recreateSyntacticForm(PseudoObjectExpr *E) { 15620b57cec5SDimitry Andric Expr *syntax = E->getSyntacticForm(); 15630b57cec5SDimitry Andric if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { 1564*0fca6ea1SDimitry Andric Expr *op = stripOpaqueValuesFromPseudoObjectRef(SemaRef, uop->getSubExpr()); 1565*0fca6ea1SDimitry Andric return UnaryOperator::Create( 1566*0fca6ea1SDimitry Andric SemaRef.Context, op, uop->getOpcode(), uop->getType(), 1567*0fca6ea1SDimitry Andric uop->getValueKind(), uop->getObjectKind(), uop->getOperatorLoc(), 1568*0fca6ea1SDimitry Andric uop->canOverflow(), SemaRef.CurFPFeatureOverrides()); 15690b57cec5SDimitry Andric } else if (CompoundAssignOperator *cop 15700b57cec5SDimitry Andric = dyn_cast<CompoundAssignOperator>(syntax)) { 1571*0fca6ea1SDimitry Andric Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, cop->getLHS()); 15720b57cec5SDimitry Andric Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); 15735ffd83dbSDimitry Andric return CompoundAssignOperator::Create( 1574*0fca6ea1SDimitry Andric SemaRef.Context, lhs, rhs, cop->getOpcode(), cop->getType(), 15755ffd83dbSDimitry Andric cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(), 1576*0fca6ea1SDimitry Andric SemaRef.CurFPFeatureOverrides(), cop->getComputationLHSType(), 15775ffd83dbSDimitry Andric cop->getComputationResultType()); 15785ffd83dbSDimitry Andric 15790b57cec5SDimitry Andric } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { 1580*0fca6ea1SDimitry Andric Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, bop->getLHS()); 15810b57cec5SDimitry Andric Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); 1582*0fca6ea1SDimitry Andric return BinaryOperator::Create(SemaRef.Context, lhs, rhs, bop->getOpcode(), 15830b57cec5SDimitry Andric bop->getType(), bop->getValueKind(), 15845ffd83dbSDimitry Andric bop->getObjectKind(), bop->getOperatorLoc(), 1585*0fca6ea1SDimitry Andric SemaRef.CurFPFeatureOverrides()); 15865ffd83dbSDimitry Andric 15875ffd83dbSDimitry Andric } else if (isa<CallExpr>(syntax)) { 15885ffd83dbSDimitry Andric return syntax; 15890b57cec5SDimitry Andric } else { 15900b57cec5SDimitry Andric assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); 1591*0fca6ea1SDimitry Andric return stripOpaqueValuesFromPseudoObjectRef(SemaRef, syntax); 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric } 1594*0fca6ea1SDimitry Andric 1595*0fca6ea1SDimitry Andric SemaPseudoObject::SemaPseudoObject(Sema &S) : SemaBase(S) {} 1596