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;
Rebuilder__anonb581425c0111::Rebuilder530b57cec5SDimitry Andric Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)
540b57cec5SDimitry Andric : S(S), MSPropertySubscriptCount(0),
550b57cec5SDimitry Andric SpecificCallback(SpecificCallback) {}
560b57cec5SDimitry Andric
rebuildObjCPropertyRefExpr__anonb581425c0111::Rebuilder570b57cec5SDimitry 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 }
rebuildObjCSubscriptRefExpr__anonb581425c0111::Rebuilder750b57cec5SDimitry 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 }
rebuildMSPropertyRefExpr__anonb581425c0111::Rebuilder860b57cec5SDimitry 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 }
rebuildMSPropertySubscriptExpr__anonb581425c0111::Rebuilder950b57cec5SDimitry 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
rebuild__anonb581425c0111::Rebuilder1080b57cec5SDimitry 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
PseudoOpBuilder(Sema & S,SourceLocation genericLoc,bool IsUnique)1940b57cec5SDimitry Andric PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
1950b57cec5SDimitry Andric : S(S), ResultIndex(PseudoObjectExpr::NoResult),
1960b57cec5SDimitry Andric GenericLoc(genericLoc), IsUnique(IsUnique) {}
1970b57cec5SDimitry Andric
~PseudoOpBuilder()1980b57cec5SDimitry Andric virtual ~PseudoOpBuilder() {}
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric /// Add a normal semantic expression.
addSemanticExpr(Expr * semantic)2010b57cec5SDimitry Andric void addSemanticExpr(Expr *semantic) {
2020b57cec5SDimitry Andric Semantics.push_back(semantic);
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric /// Add the 'result' semantic expression.
addResultSemanticExpr(Expr * resultExpr)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
setResultToLastSemantic()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.
CanCaptureValue(Expr * exp)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.
captureSetValueAsResult() const2670b57cec5SDimitry 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:
ObjCPropertyOpBuilder(Sema & S,ObjCPropertyRefExpr * refExpr,bool IsUnique)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:
ObjCSubscriptOpBuilder(Sema & S,ObjCSubscriptRefExpr * refExpr,bool IsUnique)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:
MSPropertyOpBuilder(Sema & S,MSPropertyRefExpr * refExpr,bool IsUnique)3490b57cec5SDimitry Andric MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
3500b57cec5SDimitry Andric : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
3510b57cec5SDimitry Andric RefExpr(refExpr), InstanceBase(nullptr) {}
MSPropertyOpBuilder(Sema & S,MSPropertySubscriptExpr * refExpr,bool IsUnique)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;
captureSetValueAsResult() const3610b57cec5SDimitry Andric bool captureSetValueAsResult() const override { return false; }
3620b57cec5SDimitry Andric };
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric /// Capture the given expression in an OpaqueValueExpr.
capture(Expr * e)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
captureValueAsResult(Expr * e)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.
complete(Expr * syntactic)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.
buildRValueOperation(Expr * op)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
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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
buildIncDecOperation(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)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.
LookupMethodInReceiverType(Sema & S,Selector sel,const ObjCPropertyRefExpr * PRE)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
isWeakProperty() const5890b57cec5SDimitry 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
findGetter()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
findSetter(bool warn)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
DiagnoseUnsupportedPropertyUse()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.
rebuildAndCaptureObject(Expr * syntacticBase)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.
buildGet()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.
buildSet(Expr * op,SourceLocation opcLoc,bool captureSetValueAsResult)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.
buildRValueOperation(Expr * op)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
tryBuildGetOfReference(Expr * op,ExprResult & result)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
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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
buildIncDecOperation(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)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
complete(Expr * SyntacticForm)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.
buildRValueOperation(Expr * op)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
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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.
rebuildAndCaptureObject(Expr * syntacticBase)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.
CheckKeyForObjCARCConversion(Sema & S,QualType ContainerT,Expr * Key)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
findAtIndexGetter()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
findAtIndexSetter()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];
buildGet()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.
buildSet(Expr * op,SourceLocation opcLoc,bool captureSetValueAsResult)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 *
getBaseMSProperty(MSPropertySubscriptExpr * E)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
rebuildAndCaptureObject(Expr * syntacticBase)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
buildGet()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
buildSet(Expr * op,SourceLocation sl,bool captureSetValueAsResult)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
checkRValue(Expr * E)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.
checkIncDec(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)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
checkAssignment(Scope * S,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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.
stripOpaqueValuesFromPseudoObjectRef(Sema & S,Expr * E)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.
recreateSyntacticForm(PseudoObjectExpr * E)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
SemaPseudoObject(Sema & S)1595*0fca6ea1SDimitry Andric SemaPseudoObject::SemaPseudoObject(Sema &S) : SemaBase(S) {}
1596