1594 lines · cpp
1//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements semantic analysis for expressions involving10// pseudo-object references. Pseudo-objects are conceptual objects11// whose storage is entirely abstract and all accesses to which are12// translated through some sort of abstraction barrier.13//14// For example, Objective-C objects can have "properties", either15// declared or undeclared. A property may be accessed by writing16// expr.prop17// where 'expr' is an r-value of Objective-C pointer type and 'prop'18// is the name of the property. If this expression is used in a context19// needing an r-value, it is treated as if it were a message-send20// of the associated 'getter' selector, typically:21// [expr prop]22// If it is used as the LHS of a simple assignment, it is treated23// as a message-send of the associated 'setter' selector, typically:24// [expr setProp: RHS]25// If it is used as the LHS of a compound assignment, or the operand26// of a unary increment or decrement, both are required; for example,27// 'expr.prop *= 100' would be translated to:28// [expr setProp: [expr prop] * 100]29//30//===----------------------------------------------------------------------===//31 32#include "clang/Sema/SemaPseudoObject.h"33#include "clang/AST/ExprCXX.h"34#include "clang/AST/ExprObjC.h"35#include "clang/Basic/CharInfo.h"36#include "clang/Lex/Preprocessor.h"37#include "clang/Sema/Initialization.h"38#include "clang/Sema/ScopeInfo.h"39#include "clang/Sema/SemaObjC.h"40 41using namespace clang;42using namespace sema;43 44namespace {45 // Basically just a very focused copy of TreeTransform.46 struct Rebuilder {47 Sema &S;48 unsigned MSPropertySubscriptCount;49 typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;50 const SpecificRebuilderRefTy &SpecificCallback;51 Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)52 : S(S), MSPropertySubscriptCount(0),53 SpecificCallback(SpecificCallback) {}54 55 Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {56 // Fortunately, the constraint that we're rebuilding something57 // with a base limits the number of cases here.58 if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())59 return refExpr;60 61 if (refExpr->isExplicitProperty()) {62 return new (S.Context) ObjCPropertyRefExpr(63 refExpr->getExplicitProperty(), refExpr->getType(),64 refExpr->getValueKind(), refExpr->getObjectKind(),65 refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));66 }67 return new (S.Context) ObjCPropertyRefExpr(68 refExpr->getImplicitPropertyGetter(),69 refExpr->getImplicitPropertySetter(), refExpr->getType(),70 refExpr->getValueKind(), refExpr->getObjectKind(),71 refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));72 }73 Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {74 assert(refExpr->getBaseExpr());75 assert(refExpr->getKeyExpr());76 77 return new (S.Context) ObjCSubscriptRefExpr(78 SpecificCallback(refExpr->getBaseExpr(), 0),79 SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),80 refExpr->getValueKind(), refExpr->getObjectKind(),81 refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),82 refExpr->getRBracket());83 }84 Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {85 assert(refExpr->getBaseExpr());86 87 return new (S.Context) MSPropertyRefExpr(88 SpecificCallback(refExpr->getBaseExpr(), 0),89 refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),90 refExpr->getValueKind(), refExpr->getQualifierLoc(),91 refExpr->getMemberLoc());92 }93 Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {94 assert(refExpr->getBase());95 assert(refExpr->getIdx());96 97 auto *NewBase = rebuild(refExpr->getBase());98 ++MSPropertySubscriptCount;99 return new (S.Context) MSPropertySubscriptExpr(100 NewBase,101 SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),102 refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),103 refExpr->getRBracketLoc());104 }105 106 Expr *rebuild(Expr *e) {107 // Fast path: nothing to look through.108 if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))109 return rebuildObjCPropertyRefExpr(PRE);110 if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))111 return rebuildObjCSubscriptRefExpr(SRE);112 if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))113 return rebuildMSPropertyRefExpr(MSPRE);114 if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))115 return rebuildMSPropertySubscriptExpr(MSPSE);116 117 // Otherwise, we should look through and rebuild anything that118 // IgnoreParens would.119 120 if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {121 e = rebuild(parens->getSubExpr());122 return new (S.Context) ParenExpr(parens->getLParen(),123 parens->getRParen(),124 e);125 }126 127 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {128 assert(uop->getOpcode() == UO_Extension);129 e = rebuild(uop->getSubExpr());130 return UnaryOperator::Create(131 S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),132 uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),133 S.CurFPFeatureOverrides());134 }135 136 if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {137 assert(!gse->isResultDependent());138 unsigned resultIndex = gse->getResultIndex();139 unsigned numAssocs = gse->getNumAssocs();140 141 SmallVector<Expr *, 8> assocExprs;142 SmallVector<TypeSourceInfo *, 8> assocTypes;143 assocExprs.reserve(numAssocs);144 assocTypes.reserve(numAssocs);145 146 for (const GenericSelectionExpr::Association assoc :147 gse->associations()) {148 Expr *assocExpr = assoc.getAssociationExpr();149 if (assoc.isSelected())150 assocExpr = rebuild(assocExpr);151 assocExprs.push_back(assocExpr);152 assocTypes.push_back(assoc.getTypeSourceInfo());153 }154 155 if (gse->isExprPredicate())156 return GenericSelectionExpr::Create(157 S.Context, gse->getGenericLoc(), gse->getControllingExpr(),158 assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),159 gse->containsUnexpandedParameterPack(), resultIndex);160 return GenericSelectionExpr::Create(161 S.Context, gse->getGenericLoc(), gse->getControllingType(),162 assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),163 gse->containsUnexpandedParameterPack(), resultIndex);164 }165 166 if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {167 assert(!ce->isConditionDependent());168 169 Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();170 Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;171 rebuiltExpr = rebuild(rebuiltExpr);172 173 return new (S.Context)174 ChooseExpr(ce->getBuiltinLoc(), ce->getCond(), LHS, RHS,175 rebuiltExpr->getType(), rebuiltExpr->getValueKind(),176 rebuiltExpr->getObjectKind(), ce->getRParenLoc(),177 ce->isConditionTrue());178 }179 180 llvm_unreachable("bad expression to rebuild!");181 }182 };183 184 class PseudoOpBuilder {185 public:186 Sema &S;187 unsigned ResultIndex;188 SourceLocation GenericLoc;189 bool IsUnique;190 SmallVector<Expr *, 4> Semantics;191 192 PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)193 : S(S), ResultIndex(PseudoObjectExpr::NoResult),194 GenericLoc(genericLoc), IsUnique(IsUnique) {}195 196 virtual ~PseudoOpBuilder() {}197 198 /// Add a normal semantic expression.199 void addSemanticExpr(Expr *semantic) {200 Semantics.push_back(semantic);201 }202 203 /// Add the 'result' semantic expression.204 void addResultSemanticExpr(Expr *resultExpr) {205 assert(ResultIndex == PseudoObjectExpr::NoResult);206 ResultIndex = Semantics.size();207 Semantics.push_back(resultExpr);208 // An OVE is not unique if it is used as the result expression.209 if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))210 OVE->setIsUnique(false);211 }212 213 ExprResult buildRValueOperation(Expr *op);214 ExprResult buildAssignmentOperation(Scope *Sc,215 SourceLocation opLoc,216 BinaryOperatorKind opcode,217 Expr *LHS, Expr *RHS);218 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,219 UnaryOperatorKind opcode,220 Expr *op);221 222 virtual ExprResult complete(Expr *syntacticForm);223 224 OpaqueValueExpr *capture(Expr *op);225 OpaqueValueExpr *captureValueAsResult(Expr *op);226 227 void setResultToLastSemantic() {228 assert(ResultIndex == PseudoObjectExpr::NoResult);229 ResultIndex = Semantics.size() - 1;230 // An OVE is not unique if it is used as the result expression.231 if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))232 OVE->setIsUnique(false);233 }234 235 /// Return true if assignments have a non-void result.236 static bool CanCaptureValue(Expr *exp) {237 if (exp->isGLValue())238 return true;239 QualType ty = exp->getType();240 assert(!ty->isIncompleteType());241 assert(!ty->isDependentType());242 243 if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())244 return ClassDecl->isTriviallyCopyable();245 return true;246 }247 248 virtual Expr *rebuildAndCaptureObject(Expr *) = 0;249 virtual ExprResult buildGet() = 0;250 virtual ExprResult buildSet(Expr *, SourceLocation,251 bool captureSetValueAsResult) = 0;252 /// Should the result of an assignment be the formal result of the253 /// setter call or the value that was passed to the setter?254 ///255 /// Different pseudo-object language features use different language rules256 /// for this.257 /// The default is to use the set value. Currently, this affects the258 /// behavior of simple assignments, compound assignments, and prefix259 /// increment and decrement.260 /// Postfix increment and decrement always use the getter result as the261 /// expression result.262 ///263 /// If this method returns true, and the set value isn't capturable for264 /// some reason, the result of the expression will be void.265 virtual bool captureSetValueAsResult() const { return true; }266 };267 268 /// A PseudoOpBuilder for Objective-C \@properties.269 class ObjCPropertyOpBuilder : public PseudoOpBuilder {270 ObjCPropertyRefExpr *RefExpr;271 ObjCPropertyRefExpr *SyntacticRefExpr;272 OpaqueValueExpr *InstanceReceiver;273 ObjCMethodDecl *Getter;274 275 ObjCMethodDecl *Setter;276 Selector SetterSelector;277 Selector GetterSelector;278 279 public:280 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)281 : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),282 RefExpr(refExpr), SyntacticRefExpr(nullptr),283 InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {284 }285 286 ExprResult buildRValueOperation(Expr *op);287 ExprResult buildAssignmentOperation(Scope *Sc,288 SourceLocation opLoc,289 BinaryOperatorKind opcode,290 Expr *LHS, Expr *RHS);291 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,292 UnaryOperatorKind opcode,293 Expr *op);294 295 bool tryBuildGetOfReference(Expr *op, ExprResult &result);296 bool findSetter(bool warn=true);297 bool findGetter();298 void DiagnoseUnsupportedPropertyUse();299 300 Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;301 ExprResult buildGet() override;302 ExprResult buildSet(Expr *op, SourceLocation, bool) override;303 ExprResult complete(Expr *SyntacticForm) override;304 305 bool isWeakProperty() const;306 };307 308 /// A PseudoOpBuilder for Objective-C array/dictionary indexing.309 class ObjCSubscriptOpBuilder : public PseudoOpBuilder {310 ObjCSubscriptRefExpr *RefExpr;311 OpaqueValueExpr *InstanceBase;312 OpaqueValueExpr *InstanceKey;313 ObjCMethodDecl *AtIndexGetter;314 Selector AtIndexGetterSelector;315 316 ObjCMethodDecl *AtIndexSetter;317 Selector AtIndexSetterSelector;318 319 public:320 ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)321 : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),322 RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),323 AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}324 325 ExprResult buildRValueOperation(Expr *op);326 ExprResult buildAssignmentOperation(Scope *Sc,327 SourceLocation opLoc,328 BinaryOperatorKind opcode,329 Expr *LHS, Expr *RHS);330 Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;331 332 bool findAtIndexGetter();333 bool findAtIndexSetter();334 335 ExprResult buildGet() override;336 ExprResult buildSet(Expr *op, SourceLocation, bool) override;337 };338 339 class MSPropertyOpBuilder : public PseudoOpBuilder {340 MSPropertyRefExpr *RefExpr;341 OpaqueValueExpr *InstanceBase;342 SmallVector<Expr *, 4> CallArgs;343 344 MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);345 346 public:347 MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)348 : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),349 RefExpr(refExpr), InstanceBase(nullptr) {}350 MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)351 : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),352 InstanceBase(nullptr) {353 RefExpr = getBaseMSProperty(refExpr);354 }355 356 Expr *rebuildAndCaptureObject(Expr *) override;357 ExprResult buildGet() override;358 ExprResult buildSet(Expr *op, SourceLocation, bool) override;359 bool captureSetValueAsResult() const override { return false; }360 };361}362 363/// Capture the given expression in an OpaqueValueExpr.364OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {365 // Make a new OVE whose source is the given expression.366 OpaqueValueExpr *captured =367 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),368 e->getValueKind(), e->getObjectKind(),369 e);370 if (IsUnique)371 captured->setIsUnique(true);372 373 // Make sure we bind that in the semantics.374 addSemanticExpr(captured);375 return captured;376}377 378/// Capture the given expression as the result of this pseudo-object379/// operation. This routine is safe against expressions which may380/// already be captured.381///382/// \returns the captured expression, which will be the383/// same as the input if the input was already captured384OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {385 assert(ResultIndex == PseudoObjectExpr::NoResult);386 387 // If the expression hasn't already been captured, just capture it388 // and set the new semantic389 if (!isa<OpaqueValueExpr>(e)) {390 OpaqueValueExpr *cap = capture(e);391 setResultToLastSemantic();392 return cap;393 }394 395 // Otherwise, it must already be one of our semantic expressions;396 // set ResultIndex to its index.397 unsigned index = 0;398 for (;; ++index) {399 assert(index < Semantics.size() &&400 "captured expression not found in semantics!");401 if (e == Semantics[index]) break;402 }403 ResultIndex = index;404 // An OVE is not unique if it is used as the result expression.405 cast<OpaqueValueExpr>(e)->setIsUnique(false);406 return cast<OpaqueValueExpr>(e);407}408 409/// The routine which creates the final PseudoObjectExpr.410ExprResult PseudoOpBuilder::complete(Expr *syntactic) {411 return PseudoObjectExpr::Create(S.Context, syntactic,412 Semantics, ResultIndex);413}414 415/// The main skeleton for building an r-value operation.416ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {417 Expr *syntacticBase = rebuildAndCaptureObject(op);418 419 ExprResult getExpr = buildGet();420 if (getExpr.isInvalid()) return ExprError();421 addResultSemanticExpr(getExpr.get());422 423 return complete(syntacticBase);424}425 426/// The basic skeleton for building a simple or compound427/// assignment operation.428ExprResult429PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,430 BinaryOperatorKind opcode,431 Expr *LHS, Expr *RHS) {432 assert(BinaryOperator::isAssignmentOp(opcode));433 434 Expr *syntacticLHS = rebuildAndCaptureObject(LHS);435 OpaqueValueExpr *capturedRHS = capture(RHS);436 437 // In some very specific cases, semantic analysis of the RHS as an438 // expression may require it to be rewritten. In these cases, we439 // cannot safely keep the OVE around. Fortunately, we don't really440 // need to: we don't use this particular OVE in multiple places, and441 // no clients rely that closely on matching up expressions in the442 // semantic expression with expressions from the syntactic form.443 Expr *semanticRHS = capturedRHS;444 if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) {445 semanticRHS = RHS;446 Semantics.pop_back();447 }448 449 Expr *syntactic;450 451 ExprResult result;452 if (opcode == BO_Assign) {453 result = semanticRHS;454 syntactic = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS,455 opcode, capturedRHS->getType(),456 capturedRHS->getValueKind(), OK_Ordinary,457 opcLoc, S.CurFPFeatureOverrides());458 459 } else {460 ExprResult opLHS = buildGet();461 if (opLHS.isInvalid()) return ExprError();462 463 // Build an ordinary, non-compound operation.464 BinaryOperatorKind nonCompound =465 BinaryOperator::getOpForCompoundAssignment(opcode);466 result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);467 if (result.isInvalid()) return ExprError();468 469 syntactic = CompoundAssignOperator::Create(470 S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),471 result.get()->getValueKind(), OK_Ordinary, opcLoc,472 S.CurFPFeatureOverrides(), opLHS.get()->getType(),473 result.get()->getType());474 }475 476 // The result of the assignment, if not void, is the value set into477 // the l-value.478 result = buildSet(result.get(), opcLoc, captureSetValueAsResult());479 if (result.isInvalid()) return ExprError();480 addSemanticExpr(result.get());481 if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&482 (result.get()->isTypeDependent() || CanCaptureValue(result.get())))483 setResultToLastSemantic();484 485 return complete(syntactic);486}487 488/// The basic skeleton for building an increment or decrement489/// operation.490ExprResult491PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,492 UnaryOperatorKind opcode,493 Expr *op) {494 assert(UnaryOperator::isIncrementDecrementOp(opcode));495 496 Expr *syntacticOp = rebuildAndCaptureObject(op);497 498 // Load the value.499 ExprResult result = buildGet();500 if (result.isInvalid()) return ExprError();501 502 QualType resultType = result.get()->getType();503 504 // That's the postfix result.505 if (UnaryOperator::isPostfix(opcode) &&506 (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {507 result = capture(result.get());508 setResultToLastSemantic();509 }510 511 // Add or subtract a literal 1.512 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);513 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,514 GenericLoc);515 516 if (UnaryOperator::isIncrementOp(opcode)) {517 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one);518 } else {519 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one);520 }521 if (result.isInvalid()) return ExprError();522 523 // Store that back into the result. The value stored is the result524 // of a prefix operation.525 result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&526 captureSetValueAsResult());527 if (result.isInvalid()) return ExprError();528 addSemanticExpr(result.get());529 if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&530 !result.get()->getType()->isVoidType() &&531 (result.get()->isTypeDependent() || CanCaptureValue(result.get())))532 setResultToLastSemantic();533 534 UnaryOperator *syntactic =535 UnaryOperator::Create(S.Context, syntacticOp, opcode, resultType,536 VK_LValue, OK_Ordinary, opcLoc,537 !resultType->isDependentType()538 ? S.Context.getTypeSize(resultType) >=539 S.Context.getTypeSize(S.Context.IntTy)540 : false,541 S.CurFPFeatureOverrides());542 return complete(syntactic);543}544 545 546//===----------------------------------------------------------------------===//547// Objective-C @property and implicit property references548//===----------------------------------------------------------------------===//549 550/// Look up a method in the receiver type of an Objective-C property551/// reference.552static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,553 const ObjCPropertyRefExpr *PRE) {554 if (PRE->isObjectReceiver()) {555 const ObjCObjectPointerType *PT =556 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();557 558 // Special case for 'self' in class method implementations.559 if (PT->isObjCClassType() &&560 S.ObjC().isSelfExpr(const_cast<Expr *>(PRE->getBase()))) {561 // This cast is safe because isSelfExpr is only true within562 // methods.563 ObjCMethodDecl *method =564 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());565 return S.ObjC().LookupMethodInObjectType(566 sel, S.Context.getObjCInterfaceType(method->getClassInterface()),567 /*instance*/ false);568 }569 570 return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);571 }572 573 if (PRE->isSuperReceiver()) {574 if (const ObjCObjectPointerType *PT =575 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())576 return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);577 578 return S.ObjC().LookupMethodInObjectType(sel, PRE->getSuperReceiverType(),579 false);580 }581 582 assert(PRE->isClassReceiver() && "Invalid expression");583 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());584 return S.ObjC().LookupMethodInObjectType(sel, IT, false);585}586 587bool ObjCPropertyOpBuilder::isWeakProperty() const {588 QualType T;589 if (RefExpr->isExplicitProperty()) {590 const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();591 if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)592 return true;593 594 T = Prop->getType();595 } else if (Getter) {596 T = Getter->getReturnType();597 } else {598 return false;599 }600 601 return T.getObjCLifetime() == Qualifiers::OCL_Weak;602}603 604bool ObjCPropertyOpBuilder::findGetter() {605 if (Getter) return true;606 607 // For implicit properties, just trust the lookup we already did.608 if (RefExpr->isImplicitProperty()) {609 if ((Getter = RefExpr->getImplicitPropertyGetter())) {610 GetterSelector = Getter->getSelector();611 return true;612 }613 else {614 // Must build the getter selector the hard way.615 ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();616 assert(setter && "both setter and getter are null - cannot happen");617 const IdentifierInfo *setterName =618 setter->getSelector().getIdentifierInfoForSlot(0);619 const IdentifierInfo *getterName =620 &S.Context.Idents.get(setterName->getName().substr(3));621 GetterSelector =622 S.PP.getSelectorTable().getNullarySelector(getterName);623 return false;624 }625 }626 627 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();628 Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);629 return (Getter != nullptr);630}631 632/// Try to find the most accurate setter declaration for the property633/// reference.634///635/// \return true if a setter was found, in which case Setter636bool ObjCPropertyOpBuilder::findSetter(bool warn) {637 // For implicit properties, just trust the lookup we already did.638 if (RefExpr->isImplicitProperty()) {639 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {640 Setter = setter;641 SetterSelector = setter->getSelector();642 return true;643 } else {644 const IdentifierInfo *getterName = RefExpr->getImplicitPropertyGetter()645 ->getSelector()646 .getIdentifierInfoForSlot(0);647 SetterSelector =648 SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),649 S.PP.getSelectorTable(),650 getterName);651 return false;652 }653 }654 655 // For explicit properties, this is more involved.656 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();657 SetterSelector = prop->getSetterName();658 659 // Do a normal method lookup first.660 if (ObjCMethodDecl *setter =661 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {662 if (setter->isPropertyAccessor() && warn)663 if (const ObjCInterfaceDecl *IFace =664 dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {665 StringRef thisPropertyName = prop->getName();666 // Try flipping the case of the first character.667 char front = thisPropertyName.front();668 front = isLowercase(front) ? toUppercase(front) : toLowercase(front);669 SmallString<100> PropertyName = thisPropertyName;670 PropertyName[0] = front;671 const IdentifierInfo *AltMember =672 &S.PP.getIdentifierTable().get(PropertyName);673 if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(674 AltMember, prop->getQueryKind()))675 if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {676 S.Diag(RefExpr->getExprLoc(), diag::err_property_setter_ambiguous_use)677 << prop << prop1 << setter->getSelector();678 S.Diag(prop->getLocation(), diag::note_property_declare);679 S.Diag(prop1->getLocation(), diag::note_property_declare);680 }681 }682 Setter = setter;683 return true;684 }685 686 // That can fail in the somewhat crazy situation that we're687 // type-checking a message send within the @interface declaration688 // that declared the @property. But it's not clear that that's689 // valuable to support.690 691 return false;692}693 694void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {695 if (S.getCurLexicalContext()->isObjCContainer() &&696 S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&697 S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {698 if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {699 S.Diag(RefExpr->getLocation(),700 diag::err_property_function_in_objc_container);701 S.Diag(prop->getLocation(), diag::note_property_declare);702 }703 }704}705 706/// Capture the base object of an Objective-C property expression.707Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {708 assert(InstanceReceiver == nullptr);709 710 // If we have a base, capture it in an OVE and rebuild the syntactic711 // form to use the OVE as its base.712 if (RefExpr->isObjectReceiver()) {713 InstanceReceiver = capture(RefExpr->getBase());714 syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {715 return InstanceReceiver;716 }).rebuild(syntacticBase);717 }718 719 if (ObjCPropertyRefExpr *720 refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))721 SyntacticRefExpr = refE;722 723 return syntacticBase;724}725 726/// Load from an Objective-C property reference.727ExprResult ObjCPropertyOpBuilder::buildGet() {728 findGetter();729 if (!Getter) {730 DiagnoseUnsupportedPropertyUse();731 return ExprError();732 }733 734 if (SyntacticRefExpr)735 SyntacticRefExpr->setIsMessagingGetter();736 737 QualType receiverType = RefExpr->getReceiverType(S.Context);738 if (!Getter->isImplicit())739 S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);740 // Build a message-send.741 ExprResult msg;742 if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||743 RefExpr->isObjectReceiver()) {744 assert(InstanceReceiver || RefExpr->isSuperReceiver());745 msg = S.ObjC().BuildInstanceMessageImplicit(746 InstanceReceiver, receiverType, GenericLoc, Getter->getSelector(),747 Getter, {});748 } else {749 msg = S.ObjC().BuildClassMessageImplicit(750 receiverType, RefExpr->isSuperReceiver(), GenericLoc,751 Getter->getSelector(), Getter, {});752 }753 return msg;754}755 756/// Store to an Objective-C property reference.757///758/// \param captureSetValueAsResult If true, capture the actual759/// value being set as the value of the property operation.760ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,761 bool captureSetValueAsResult) {762 if (!findSetter(false)) {763 DiagnoseUnsupportedPropertyUse();764 return ExprError();765 }766 767 if (SyntacticRefExpr)768 SyntacticRefExpr->setIsMessagingSetter();769 770 QualType receiverType = RefExpr->getReceiverType(S.Context);771 772 // Use assignment constraints when possible; they give us better773 // diagnostics. "When possible" basically means anything except a774 // C++ class type.775 if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {776 QualType paramType = (*Setter->param_begin())->getType()777 .substObjCMemberType(778 receiverType,779 Setter->getDeclContext(),780 ObjCSubstitutionContext::Parameter);781 if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {782 ExprResult opResult = op;783 AssignConvertType assignResult =784 S.CheckSingleAssignmentConstraints(paramType, opResult);785 if (opResult.isInvalid() ||786 S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,787 op->getType(), opResult.get(),788 AssignmentAction::Assigning))789 return ExprError();790 791 op = opResult.get();792 assert(op && "successful assignment left argument invalid?");793 }794 }795 796 // Arguments.797 Expr *args[] = { op };798 799 // Build a message-send.800 ExprResult msg;801 if (!Setter->isImplicit())802 S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);803 if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||804 RefExpr->isObjectReceiver()) {805 msg = S.ObjC().BuildInstanceMessageImplicit(InstanceReceiver, receiverType,806 GenericLoc, SetterSelector,807 Setter, MultiExprArg(args, 1));808 } else {809 msg = S.ObjC().BuildClassMessageImplicit(810 receiverType, RefExpr->isSuperReceiver(), GenericLoc, SetterSelector,811 Setter, MultiExprArg(args, 1));812 }813 814 if (!msg.isInvalid() && captureSetValueAsResult) {815 ObjCMessageExpr *msgExpr =816 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());817 Expr *arg = msgExpr->getArg(0);818 if (CanCaptureValue(arg))819 msgExpr->setArg(0, captureValueAsResult(arg));820 }821 822 return msg;823}824 825/// @property-specific behavior for doing lvalue-to-rvalue conversion.826ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {827 // Explicit properties always have getters, but implicit ones don't.828 // Check that before proceeding.829 if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {830 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)831 << RefExpr->getSourceRange();832 return ExprError();833 }834 835 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);836 if (result.isInvalid()) return ExprError();837 838 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())839 S.ObjC().DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),840 Getter, RefExpr->getLocation());841 842 // As a special case, if the method returns 'id', try to get843 // a better type from the property.844 if (RefExpr->isExplicitProperty() && result.get()->isPRValue()) {845 QualType receiverType = RefExpr->getReceiverType(S.Context);846 QualType propType = RefExpr->getExplicitProperty()847 ->getUsageType(receiverType);848 if (result.get()->getType()->isObjCIdType()) {849 if (const ObjCObjectPointerType *ptr850 = propType->getAs<ObjCObjectPointerType>()) {851 if (!ptr->isObjCIdType())852 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);853 }854 }855 if (propType.getObjCLifetime() == Qualifiers::OCL_Weak &&856 !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,857 RefExpr->getLocation()))858 S.getCurFunction()->markSafeWeakUse(RefExpr);859 }860 861 return result;862}863 864/// Try to build this as a call to a getter that returns a reference.865///866/// \return true if it was possible, whether or not it actually867/// succeeded868bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,869 ExprResult &result) {870 if (!S.getLangOpts().CPlusPlus) return false;871 872 findGetter();873 if (!Getter) {874 // The property has no setter and no getter! This can happen if the type is875 // invalid. Error have already been reported.876 result = ExprError();877 return true;878 }879 880 // Only do this if the getter returns an l-value reference type.881 QualType resultType = Getter->getReturnType();882 if (!resultType->isLValueReferenceType()) return false;883 884 result = buildRValueOperation(op);885 return true;886}887 888/// @property-specific behavior for doing assignments.889ExprResult890ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,891 SourceLocation opcLoc,892 BinaryOperatorKind opcode,893 Expr *LHS, Expr *RHS) {894 assert(BinaryOperator::isAssignmentOp(opcode));895 896 // If there's no setter, we have no choice but to try to assign to897 // the result of the getter.898 if (!findSetter()) {899 ExprResult result;900 if (tryBuildGetOfReference(LHS, result)) {901 if (result.isInvalid()) return ExprError();902 return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS);903 }904 905 // Otherwise, it's an error.906 S.Diag(opcLoc, diag::err_nosetter_property_assignment)907 << unsigned(RefExpr->isImplicitProperty())908 << SetterSelector909 << LHS->getSourceRange() << RHS->getSourceRange();910 return ExprError();911 }912 913 // If there is a setter, we definitely want to use it.914 915 // Verify that we can do a compound assignment.916 if (opcode != BO_Assign && !findGetter()) {917 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)918 << LHS->getSourceRange() << RHS->getSourceRange();919 return ExprError();920 }921 922 ExprResult result =923 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);924 if (result.isInvalid()) return ExprError();925 926 // Various warnings about property assignments in ARC.927 if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {928 S.ObjC().checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);929 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);930 }931 932 return result;933}934 935/// @property-specific behavior for doing increments and decrements.936ExprResult937ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,938 UnaryOperatorKind opcode,939 Expr *op) {940 // If there's no setter, we have no choice but to try to assign to941 // the result of the getter.942 if (!findSetter()) {943 ExprResult result;944 if (tryBuildGetOfReference(op, result)) {945 if (result.isInvalid()) return ExprError();946 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get());947 }948 949 // Otherwise, it's an error.950 S.Diag(opcLoc, diag::err_nosetter_property_incdec)951 << unsigned(RefExpr->isImplicitProperty())952 << unsigned(UnaryOperator::isDecrementOp(opcode))953 << SetterSelector954 << op->getSourceRange();955 return ExprError();956 }957 958 // If there is a setter, we definitely want to use it.959 960 // We also need a getter.961 if (!findGetter()) {962 assert(RefExpr->isImplicitProperty());963 S.Diag(opcLoc, diag::err_nogetter_property_incdec)964 << unsigned(UnaryOperator::isDecrementOp(opcode))965 << GetterSelector966 << op->getSourceRange();967 return ExprError();968 }969 970 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);971}972 973ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {974 if (isWeakProperty() && !S.isUnevaluatedContext() &&975 !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,976 SyntacticForm->getBeginLoc()))977 S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,978 SyntacticRefExpr->isMessagingGetter());979 980 return PseudoOpBuilder::complete(SyntacticForm);981}982 983// ObjCSubscript build stuff.984//985 986/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue987/// conversion.988/// FIXME. Remove this routine if it is proven that no additional989/// specifity is needed.990ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {991 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);992 if (result.isInvalid()) return ExprError();993 return result;994}995 996/// objective-c subscripting-specific behavior for doing assignments.997ExprResult998ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,999 SourceLocation opcLoc,1000 BinaryOperatorKind opcode,1001 Expr *LHS, Expr *RHS) {1002 assert(BinaryOperator::isAssignmentOp(opcode));1003 // There must be a method to do the Index'ed assignment.1004 if (!findAtIndexSetter())1005 return ExprError();1006 1007 // Verify that we can do a compound assignment.1008 if (opcode != BO_Assign && !findAtIndexGetter())1009 return ExprError();1010 1011 ExprResult result =1012 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);1013 if (result.isInvalid()) return ExprError();1014 1015 // Various warnings about objc Index'ed assignments in ARC.1016 if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {1017 S.ObjC().checkRetainCycles(InstanceBase->getSourceExpr(), RHS);1018 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);1019 }1020 1021 return result;1022}1023 1024/// Capture the base object of an Objective-C Index'ed expression.1025Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {1026 assert(InstanceBase == nullptr);1027 1028 // Capture base expression in an OVE and rebuild the syntactic1029 // form to use the OVE as its base expression.1030 InstanceBase = capture(RefExpr->getBaseExpr());1031 InstanceKey = capture(RefExpr->getKeyExpr());1032 1033 syntacticBase =1034 Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {1035 switch (Idx) {1036 case 0:1037 return InstanceBase;1038 case 1:1039 return InstanceKey;1040 default:1041 llvm_unreachable("Unexpected index for ObjCSubscriptExpr");1042 }1043 }).rebuild(syntacticBase);1044 1045 return syntacticBase;1046}1047 1048/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF1049/// objects used as dictionary subscript key objects.1050static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,1051 Expr *Key) {1052 if (ContainerT.isNull())1053 return;1054 // dictionary subscripting.1055 // - (id)objectForKeyedSubscript:(id)key;1056 const IdentifierInfo *KeyIdents[] = {1057 &S.Context.Idents.get("objectForKeyedSubscript")};1058 Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);1059 ObjCMethodDecl *Getter = S.ObjC().LookupMethodInObjectType(1060 GetterSelector, ContainerT, true /*instance*/);1061 if (!Getter)1062 return;1063 QualType T = Getter->parameters()[0]->getType();1064 S.ObjC().CheckObjCConversion(Key->getSourceRange(), T, Key,1065 CheckedConversionKind::Implicit);1066}1067 1068bool ObjCSubscriptOpBuilder::findAtIndexGetter() {1069 if (AtIndexGetter)1070 return true;1071 1072 Expr *BaseExpr = RefExpr->getBaseExpr();1073 QualType BaseT = BaseExpr->getType();1074 1075 QualType ResultType;1076 if (const ObjCObjectPointerType *PTy =1077 BaseT->getAs<ObjCObjectPointerType>()) {1078 ResultType = PTy->getPointeeType();1079 }1080 SemaObjC::ObjCSubscriptKind Res =1081 S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());1082 if (Res == SemaObjC::OS_Error) {1083 if (S.getLangOpts().ObjCAutoRefCount)1084 CheckKeyForObjCARCConversion(S, ResultType,1085 RefExpr->getKeyExpr());1086 return false;1087 }1088 bool arrayRef = (Res == SemaObjC::OS_Array);1089 1090 if (ResultType.isNull()) {1091 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)1092 << BaseExpr->getType() << arrayRef;1093 return false;1094 }1095 if (!arrayRef) {1096 // dictionary subscripting.1097 // - (id)objectForKeyedSubscript:(id)key;1098 const IdentifierInfo *KeyIdents[] = {1099 &S.Context.Idents.get("objectForKeyedSubscript")};1100 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);1101 }1102 else {1103 // - (id)objectAtIndexedSubscript:(size_t)index;1104 const IdentifierInfo *KeyIdents[] = {1105 &S.Context.Idents.get("objectAtIndexedSubscript")};1106 1107 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);1108 }1109 1110 AtIndexGetter = S.ObjC().LookupMethodInObjectType(1111 AtIndexGetterSelector, ResultType, true /*instance*/);1112 1113 if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {1114 AtIndexGetter = ObjCMethodDecl::Create(1115 S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector,1116 S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,1117 S.Context.getTranslationUnitDecl(), true /*Instance*/,1118 false /*isVariadic*/,1119 /*isPropertyAccessor=*/false,1120 /*isSynthesizedAccessorStub=*/false,1121 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,1122 ObjCImplementationControl::Required, false);1123 ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,1124 SourceLocation(), SourceLocation(),1125 arrayRef ? &S.Context.Idents.get("index")1126 : &S.Context.Idents.get("key"),1127 arrayRef ? S.Context.UnsignedLongTy1128 : S.Context.getObjCIdType(),1129 /*TInfo=*/nullptr,1130 SC_None,1131 nullptr);1132 AtIndexGetter->setMethodParams(S.Context, Argument, {});1133 }1134 1135 if (!AtIndexGetter) {1136 if (!BaseT->isObjCIdType()) {1137 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)1138 << BaseExpr->getType() << 0 << arrayRef;1139 return false;1140 }1141 AtIndexGetter = S.ObjC().LookupInstanceMethodInGlobalPool(1142 AtIndexGetterSelector, RefExpr->getSourceRange(), true);1143 }1144 1145 if (AtIndexGetter) {1146 QualType T = AtIndexGetter->parameters()[0]->getType();1147 if ((arrayRef && !T->isIntegralOrEnumerationType()) ||1148 (!arrayRef && !T->isObjCObjectPointerType())) {1149 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1150 arrayRef ? diag::err_objc_subscript_index_type1151 : diag::err_objc_subscript_key_type) << T;1152 S.Diag(AtIndexGetter->parameters()[0]->getLocation(),1153 diag::note_parameter_type) << T;1154 return false;1155 }1156 QualType R = AtIndexGetter->getReturnType();1157 if (!R->isObjCObjectPointerType()) {1158 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1159 diag::err_objc_indexing_method_result_type) << R << arrayRef;1160 S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<1161 AtIndexGetter->getDeclName();1162 }1163 }1164 return true;1165}1166 1167bool ObjCSubscriptOpBuilder::findAtIndexSetter() {1168 if (AtIndexSetter)1169 return true;1170 1171 Expr *BaseExpr = RefExpr->getBaseExpr();1172 QualType BaseT = BaseExpr->getType();1173 1174 QualType ResultType;1175 if (const ObjCObjectPointerType *PTy =1176 BaseT->getAs<ObjCObjectPointerType>()) {1177 ResultType = PTy->getPointeeType();1178 }1179 1180 SemaObjC::ObjCSubscriptKind Res =1181 S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());1182 if (Res == SemaObjC::OS_Error) {1183 if (S.getLangOpts().ObjCAutoRefCount)1184 CheckKeyForObjCARCConversion(S, ResultType,1185 RefExpr->getKeyExpr());1186 return false;1187 }1188 bool arrayRef = (Res == SemaObjC::OS_Array);1189 1190 if (ResultType.isNull()) {1191 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)1192 << BaseExpr->getType() << arrayRef;1193 return false;1194 }1195 1196 if (!arrayRef) {1197 // dictionary subscripting.1198 // - (void)setObject:(id)object forKeyedSubscript:(id)key;1199 const IdentifierInfo *KeyIdents[] = {1200 &S.Context.Idents.get("setObject"),1201 &S.Context.Idents.get("forKeyedSubscript")};1202 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);1203 }1204 else {1205 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;1206 const IdentifierInfo *KeyIdents[] = {1207 &S.Context.Idents.get("setObject"),1208 &S.Context.Idents.get("atIndexedSubscript")};1209 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);1210 }1211 AtIndexSetter = S.ObjC().LookupMethodInObjectType(1212 AtIndexSetterSelector, ResultType, true /*instance*/);1213 1214 if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {1215 TypeSourceInfo *ReturnTInfo = nullptr;1216 QualType ReturnType = S.Context.VoidTy;1217 AtIndexSetter = ObjCMethodDecl::Create(1218 S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,1219 ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),1220 true /*Instance*/, false /*isVariadic*/,1221 /*isPropertyAccessor=*/false,1222 /*isSynthesizedAccessorStub=*/false,1223 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,1224 ObjCImplementationControl::Required, false);1225 SmallVector<ParmVarDecl *, 2> Params;1226 ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,1227 SourceLocation(), SourceLocation(),1228 &S.Context.Idents.get("object"),1229 S.Context.getObjCIdType(),1230 /*TInfo=*/nullptr,1231 SC_None,1232 nullptr);1233 Params.push_back(object);1234 ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,1235 SourceLocation(), SourceLocation(),1236 arrayRef ? &S.Context.Idents.get("index")1237 : &S.Context.Idents.get("key"),1238 arrayRef ? S.Context.UnsignedLongTy1239 : S.Context.getObjCIdType(),1240 /*TInfo=*/nullptr,1241 SC_None,1242 nullptr);1243 Params.push_back(key);1244 AtIndexSetter->setMethodParams(S.Context, Params, {});1245 }1246 1247 if (!AtIndexSetter) {1248 if (!BaseT->isObjCIdType()) {1249 S.Diag(BaseExpr->getExprLoc(),1250 diag::err_objc_subscript_method_not_found)1251 << BaseExpr->getType() << 1 << arrayRef;1252 return false;1253 }1254 AtIndexSetter = S.ObjC().LookupInstanceMethodInGlobalPool(1255 AtIndexSetterSelector, RefExpr->getSourceRange(), true);1256 }1257 1258 bool err = false;1259 if (AtIndexSetter && arrayRef) {1260 QualType T = AtIndexSetter->parameters()[1]->getType();1261 if (!T->isIntegralOrEnumerationType()) {1262 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1263 diag::err_objc_subscript_index_type) << T;1264 S.Diag(AtIndexSetter->parameters()[1]->getLocation(),1265 diag::note_parameter_type) << T;1266 err = true;1267 }1268 T = AtIndexSetter->parameters()[0]->getType();1269 if (!T->isObjCObjectPointerType()) {1270 S.Diag(RefExpr->getBaseExpr()->getExprLoc(),1271 diag::err_objc_subscript_object_type) << T << arrayRef;1272 S.Diag(AtIndexSetter->parameters()[0]->getLocation(),1273 diag::note_parameter_type) << T;1274 err = true;1275 }1276 }1277 else if (AtIndexSetter && !arrayRef)1278 for (unsigned i=0; i <2; i++) {1279 QualType T = AtIndexSetter->parameters()[i]->getType();1280 if (!T->isObjCObjectPointerType()) {1281 if (i == 1)1282 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1283 diag::err_objc_subscript_key_type) << T;1284 else1285 S.Diag(RefExpr->getBaseExpr()->getExprLoc(),1286 diag::err_objc_subscript_dic_object_type) << T;1287 S.Diag(AtIndexSetter->parameters()[i]->getLocation(),1288 diag::note_parameter_type) << T;1289 err = true;1290 }1291 }1292 1293 return !err;1294}1295 1296// Get the object at "Index" position in the container.1297// [BaseExpr objectAtIndexedSubscript : IndexExpr];1298ExprResult ObjCSubscriptOpBuilder::buildGet() {1299 if (!findAtIndexGetter())1300 return ExprError();1301 1302 QualType receiverType = InstanceBase->getType();1303 1304 // Build a message-send.1305 ExprResult msg;1306 Expr *Index = InstanceKey;1307 1308 // Arguments.1309 Expr *args[] = { Index };1310 assert(InstanceBase);1311 if (AtIndexGetter)1312 S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);1313 msg = S.ObjC().BuildInstanceMessageImplicit(1314 InstanceBase, receiverType, GenericLoc, AtIndexGetterSelector,1315 AtIndexGetter, MultiExprArg(args, 1));1316 return msg;1317}1318 1319/// Store into the container the "op" object at "Index"'ed location1320/// by building this messaging expression:1321/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;1322/// \param captureSetValueAsResult If true, capture the actual1323/// value being set as the value of the property operation.1324ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,1325 bool captureSetValueAsResult) {1326 if (!findAtIndexSetter())1327 return ExprError();1328 if (AtIndexSetter)1329 S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);1330 QualType receiverType = InstanceBase->getType();1331 Expr *Index = InstanceKey;1332 1333 // Arguments.1334 Expr *args[] = { op, Index };1335 1336 // Build a message-send.1337 ExprResult msg = S.ObjC().BuildInstanceMessageImplicit(1338 InstanceBase, receiverType, GenericLoc, AtIndexSetterSelector,1339 AtIndexSetter, MultiExprArg(args, 2));1340 1341 if (!msg.isInvalid() && captureSetValueAsResult) {1342 ObjCMessageExpr *msgExpr =1343 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());1344 Expr *arg = msgExpr->getArg(0);1345 if (CanCaptureValue(arg))1346 msgExpr->setArg(0, captureValueAsResult(arg));1347 }1348 1349 return msg;1350}1351 1352//===----------------------------------------------------------------------===//1353// MSVC __declspec(property) references1354//===----------------------------------------------------------------------===//1355 1356MSPropertyRefExpr *1357MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {1358 CallArgs.insert(CallArgs.begin(), E->getIdx());1359 Expr *Base = E->getBase()->IgnoreParens();1360 while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {1361 CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());1362 Base = MSPropSubscript->getBase()->IgnoreParens();1363 }1364 return cast<MSPropertyRefExpr>(Base);1365}1366 1367Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {1368 InstanceBase = capture(RefExpr->getBaseExpr());1369 for (Expr *&Arg : CallArgs)1370 Arg = capture(Arg);1371 syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {1372 switch (Idx) {1373 case 0:1374 return InstanceBase;1375 default:1376 assert(Idx <= CallArgs.size());1377 return CallArgs[Idx - 1];1378 }1379 }).rebuild(syntacticBase);1380 1381 return syntacticBase;1382}1383 1384ExprResult MSPropertyOpBuilder::buildGet() {1385 if (!RefExpr->getPropertyDecl()->hasGetter()) {1386 S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)1387 << 0 /* getter */ << RefExpr->getPropertyDecl();1388 return ExprError();1389 }1390 1391 UnqualifiedId GetterName;1392 const IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();1393 GetterName.setIdentifier(II, RefExpr->getMemberLoc());1394 CXXScopeSpec SS;1395 SS.Adopt(RefExpr->getQualifierLoc());1396 ExprResult GetterExpr =1397 S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),1398 RefExpr->isArrow() ? tok::arrow : tok::period, SS,1399 SourceLocation(), GetterName, nullptr);1400 if (GetterExpr.isInvalid()) {1401 S.Diag(RefExpr->getMemberLoc(),1402 diag::err_cannot_find_suitable_accessor) << 0 /* getter */1403 << RefExpr->getPropertyDecl();1404 return ExprError();1405 }1406 1407 return S.BuildCallExpr(S.getCurScope(), GetterExpr.get(),1408 RefExpr->getSourceRange().getBegin(), CallArgs,1409 RefExpr->getSourceRange().getEnd());1410}1411 1412ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,1413 bool captureSetValueAsResult) {1414 if (!RefExpr->getPropertyDecl()->hasSetter()) {1415 S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)1416 << 1 /* setter */ << RefExpr->getPropertyDecl();1417 return ExprError();1418 }1419 1420 UnqualifiedId SetterName;1421 const IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();1422 SetterName.setIdentifier(II, RefExpr->getMemberLoc());1423 CXXScopeSpec SS;1424 SS.Adopt(RefExpr->getQualifierLoc());1425 ExprResult SetterExpr =1426 S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),1427 RefExpr->isArrow() ? tok::arrow : tok::period, SS,1428 SourceLocation(), SetterName, nullptr);1429 if (SetterExpr.isInvalid()) {1430 S.Diag(RefExpr->getMemberLoc(),1431 diag::err_cannot_find_suitable_accessor) << 1 /* setter */1432 << RefExpr->getPropertyDecl();1433 return ExprError();1434 }1435 1436 SmallVector<Expr*, 4> ArgExprs;1437 ArgExprs.append(CallArgs.begin(), CallArgs.end());1438 ArgExprs.push_back(op);1439 return S.BuildCallExpr(S.getCurScope(), SetterExpr.get(),1440 RefExpr->getSourceRange().getBegin(), ArgExprs,1441 op->getSourceRange().getEnd());1442}1443 1444//===----------------------------------------------------------------------===//1445// General Sema routines.1446//===----------------------------------------------------------------------===//1447 1448ExprResult SemaPseudoObject::checkRValue(Expr *E) {1449 Expr *opaqueRef = E->IgnoreParens();1450 if (ObjCPropertyRefExpr *refExpr1451 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {1452 ObjCPropertyOpBuilder builder(SemaRef, refExpr, true);1453 return builder.buildRValueOperation(E);1454 }1455 else if (ObjCSubscriptRefExpr *refExpr1456 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {1457 ObjCSubscriptOpBuilder builder(SemaRef, refExpr, true);1458 return builder.buildRValueOperation(E);1459 } else if (MSPropertyRefExpr *refExpr1460 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {1461 MSPropertyOpBuilder builder(SemaRef, refExpr, true);1462 return builder.buildRValueOperation(E);1463 } else if (MSPropertySubscriptExpr *RefExpr =1464 dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {1465 MSPropertyOpBuilder Builder(SemaRef, RefExpr, true);1466 return Builder.buildRValueOperation(E);1467 } else {1468 llvm_unreachable("unknown pseudo-object kind!");1469 }1470}1471 1472/// Check an increment or decrement of a pseudo-object expression.1473ExprResult SemaPseudoObject::checkIncDec(Scope *Sc, SourceLocation opcLoc,1474 UnaryOperatorKind opcode, Expr *op) {1475 // Do nothing if the operand is dependent.1476 if (op->isTypeDependent())1477 return UnaryOperator::Create(1478 SemaRef.Context, op, opcode, SemaRef.Context.DependentTy, VK_PRValue,1479 OK_Ordinary, opcLoc, false, SemaRef.CurFPFeatureOverrides());1480 1481 assert(UnaryOperator::isIncrementDecrementOp(opcode));1482 Expr *opaqueRef = op->IgnoreParens();1483 if (ObjCPropertyRefExpr *refExpr1484 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {1485 ObjCPropertyOpBuilder builder(SemaRef, refExpr, false);1486 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);1487 } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {1488 Diag(opcLoc, diag::err_illegal_container_subscripting_op);1489 return ExprError();1490 } else if (MSPropertyRefExpr *refExpr1491 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {1492 MSPropertyOpBuilder builder(SemaRef, refExpr, false);1493 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);1494 } else if (MSPropertySubscriptExpr *RefExpr1495 = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {1496 MSPropertyOpBuilder Builder(SemaRef, RefExpr, false);1497 return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);1498 } else {1499 llvm_unreachable("unknown pseudo-object kind!");1500 }1501}1502 1503ExprResult SemaPseudoObject::checkAssignment(Scope *S, SourceLocation opcLoc,1504 BinaryOperatorKind opcode,1505 Expr *LHS, Expr *RHS) {1506 // Do nothing if either argument is dependent.1507 if (LHS->isTypeDependent() || RHS->isTypeDependent())1508 return BinaryOperator::Create(1509 SemaRef.Context, LHS, RHS, opcode, SemaRef.Context.DependentTy,1510 VK_PRValue, OK_Ordinary, opcLoc, SemaRef.CurFPFeatureOverrides());1511 1512 // Filter out non-overload placeholder types in the RHS.1513 if (RHS->getType()->isNonOverloadPlaceholderType()) {1514 ExprResult result = SemaRef.CheckPlaceholderExpr(RHS);1515 if (result.isInvalid()) return ExprError();1516 RHS = result.get();1517 }1518 1519 bool IsSimpleAssign = opcode == BO_Assign;1520 Expr *opaqueRef = LHS->IgnoreParens();1521 if (ObjCPropertyRefExpr *refExpr1522 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {1523 ObjCPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);1524 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1525 } else if (ObjCSubscriptRefExpr *refExpr1526 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {1527 ObjCSubscriptOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);1528 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1529 } else if (MSPropertyRefExpr *refExpr1530 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {1531 MSPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);1532 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1533 } else if (MSPropertySubscriptExpr *RefExpr1534 = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {1535 MSPropertyOpBuilder Builder(SemaRef, RefExpr, IsSimpleAssign);1536 return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1537 } else {1538 llvm_unreachable("unknown pseudo-object kind!");1539 }1540}1541 1542/// Given a pseudo-object reference, rebuild it without the opaque1543/// values. Basically, undo the behavior of rebuildAndCaptureObject.1544/// This should never operate in-place.1545static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {1546 return Rebuilder(S,1547 [=](Expr *E, unsigned) -> Expr * {1548 return cast<OpaqueValueExpr>(E)->getSourceExpr();1549 })1550 .rebuild(E);1551}1552 1553/// Given a pseudo-object expression, recreate what it looks like1554/// syntactically without the attendant OpaqueValueExprs.1555///1556/// This is a hack which should be removed when TreeTransform is1557/// capable of rebuilding a tree without stripping implicit1558/// operations.1559Expr *SemaPseudoObject::recreateSyntacticForm(PseudoObjectExpr *E) {1560 Expr *syntax = E->getSyntacticForm();1561 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {1562 Expr *op = stripOpaqueValuesFromPseudoObjectRef(SemaRef, uop->getSubExpr());1563 return UnaryOperator::Create(1564 SemaRef.Context, op, uop->getOpcode(), uop->getType(),1565 uop->getValueKind(), uop->getObjectKind(), uop->getOperatorLoc(),1566 uop->canOverflow(), SemaRef.CurFPFeatureOverrides());1567 } else if (CompoundAssignOperator *cop1568 = dyn_cast<CompoundAssignOperator>(syntax)) {1569 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, cop->getLHS());1570 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();1571 return CompoundAssignOperator::Create(1572 SemaRef.Context, lhs, rhs, cop->getOpcode(), cop->getType(),1573 cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),1574 SemaRef.CurFPFeatureOverrides(), cop->getComputationLHSType(),1575 cop->getComputationResultType());1576 1577 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {1578 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, bop->getLHS());1579 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();1580 return BinaryOperator::Create(SemaRef.Context, lhs, rhs, bop->getOpcode(),1581 bop->getType(), bop->getValueKind(),1582 bop->getObjectKind(), bop->getOperatorLoc(),1583 SemaRef.CurFPFeatureOverrides());1584 1585 } else if (isa<CallExpr>(syntax)) {1586 return syntax;1587 } else {1588 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));1589 return stripOpaqueValuesFromPseudoObjectRef(SemaRef, syntax);1590 }1591}1592 1593SemaPseudoObject::SemaPseudoObject(Sema &S) : SemaBase(S) {}1594