• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements semantic analysis for expressions involving
11 //  pseudo-object references.  Pseudo-objects are conceptual objects
12 //  whose storage is entirely abstract and all accesses to which are
13 //  translated through some sort of abstraction barrier.
14 //
15 //  For example, Objective-C objects can have "properties", either
16 //  declared or undeclared.  A property may be accessed by writing
17 //    expr.prop
18 //  where 'expr' is an r-value of Objective-C pointer type and 'prop'
19 //  is the name of the property.  If this expression is used in a context
20 //  needing an r-value, it is treated as if it were a message-send
21 //  of the associated 'getter' selector, typically:
22 //    [expr prop]
23 //  If it is used as the LHS of a simple assignment, it is treated
24 //  as a message-send of the associated 'setter' selector, typically:
25 //    [expr setProp: RHS]
26 //  If it is used as the LHS of a compound assignment, or the operand
27 //  of a unary increment or decrement, both are required;  for example,
28 //  'expr.prop *= 100' would be translated to:
29 //    [expr setProp: [expr prop] * 100]
30 //
31 //===----------------------------------------------------------------------===//
32 
33 #include "clang/Sema/SemaInternal.h"
34 #include "clang/Sema/Initialization.h"
35 #include "clang/AST/ExprObjC.h"
36 #include "clang/Lex/Preprocessor.h"
37 #include "llvm/ADT/SmallString.h"
38 
39 using namespace clang;
40 using namespace sema;
41 
42 namespace {
43   // Basically just a very focused copy of TreeTransform.
44   template <class T> struct Rebuilder {
45     Sema &S;
Rebuilder__anonb6b836840111::Rebuilder46     Rebuilder(Sema &S) : S(S) {}
47 
getDerived__anonb6b836840111::Rebuilder48     T &getDerived() { return static_cast<T&>(*this); }
49 
rebuild__anonb6b836840111::Rebuilder50     Expr *rebuild(Expr *e) {
51       // Fast path: nothing to look through.
52       if (typename T::specific_type *specific
53             = dyn_cast<typename T::specific_type>(e))
54         return getDerived().rebuildSpecific(specific);
55 
56       // Otherwise, we should look through and rebuild anything that
57       // IgnoreParens would.
58 
59       if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
60         e = rebuild(parens->getSubExpr());
61         return new (S.Context) ParenExpr(parens->getLParen(),
62                                          parens->getRParen(),
63                                          e);
64       }
65 
66       if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
67         assert(uop->getOpcode() == UO_Extension);
68         e = rebuild(uop->getSubExpr());
69         return new (S.Context) UnaryOperator(e, uop->getOpcode(),
70                                              uop->getType(),
71                                              uop->getValueKind(),
72                                              uop->getObjectKind(),
73                                              uop->getOperatorLoc());
74       }
75 
76       if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
77         assert(!gse->isResultDependent());
78         unsigned resultIndex = gse->getResultIndex();
79         unsigned numAssocs = gse->getNumAssocs();
80 
81         SmallVector<Expr*, 8> assocs(numAssocs);
82         SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
83 
84         for (unsigned i = 0; i != numAssocs; ++i) {
85           Expr *assoc = gse->getAssocExpr(i);
86           if (i == resultIndex) assoc = rebuild(assoc);
87           assocs[i] = assoc;
88           assocTypes[i] = gse->getAssocTypeSourceInfo(i);
89         }
90 
91         return new (S.Context) GenericSelectionExpr(S.Context,
92                                                     gse->getGenericLoc(),
93                                                     gse->getControllingExpr(),
94                                                     assocTypes,
95                                                     assocs,
96                                                     gse->getDefaultLoc(),
97                                                     gse->getRParenLoc(),
98                                       gse->containsUnexpandedParameterPack(),
99                                                     resultIndex);
100       }
101 
102       llvm_unreachable("bad expression to rebuild!");
103     }
104   };
105 
106   struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
107     Expr *NewBase;
ObjCPropertyRefRebuilder__anonb6b836840111::ObjCPropertyRefRebuilder108     ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
109       : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
110 
111     typedef ObjCPropertyRefExpr specific_type;
rebuildSpecific__anonb6b836840111::ObjCPropertyRefRebuilder112     Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
113       // Fortunately, the constraint that we're rebuilding something
114       // with a base limits the number of cases here.
115       assert(refExpr->getBase());
116 
117       if (refExpr->isExplicitProperty()) {
118         return new (S.Context)
119           ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
120                               refExpr->getType(), refExpr->getValueKind(),
121                               refExpr->getObjectKind(), refExpr->getLocation(),
122                               NewBase);
123       }
124       return new (S.Context)
125         ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
126                             refExpr->getImplicitPropertySetter(),
127                             refExpr->getType(), refExpr->getValueKind(),
128                             refExpr->getObjectKind(),refExpr->getLocation(),
129                             NewBase);
130     }
131   };
132 
133   struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
134     Expr *NewBase;
135     Expr *NewKeyExpr;
ObjCSubscriptRefRebuilder__anonb6b836840111::ObjCSubscriptRefRebuilder136     ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
137     : Rebuilder<ObjCSubscriptRefRebuilder>(S),
138       NewBase(newBase), NewKeyExpr(newKeyExpr) {}
139 
140     typedef ObjCSubscriptRefExpr specific_type;
rebuildSpecific__anonb6b836840111::ObjCSubscriptRefRebuilder141     Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
142       assert(refExpr->getBaseExpr());
143       assert(refExpr->getKeyExpr());
144 
145       return new (S.Context)
146         ObjCSubscriptRefExpr(NewBase,
147                              NewKeyExpr,
148                              refExpr->getType(), refExpr->getValueKind(),
149                              refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
150                              refExpr->setAtIndexMethodDecl(),
151                              refExpr->getRBracket());
152     }
153   };
154 
155   class PseudoOpBuilder {
156   public:
157     Sema &S;
158     unsigned ResultIndex;
159     SourceLocation GenericLoc;
160     SmallVector<Expr *, 4> Semantics;
161 
PseudoOpBuilder(Sema & S,SourceLocation genericLoc)162     PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
163       : S(S), ResultIndex(PseudoObjectExpr::NoResult),
164         GenericLoc(genericLoc) {}
165 
~PseudoOpBuilder()166     virtual ~PseudoOpBuilder() {}
167 
168     /// Add a normal semantic expression.
addSemanticExpr(Expr * semantic)169     void addSemanticExpr(Expr *semantic) {
170       Semantics.push_back(semantic);
171     }
172 
173     /// Add the 'result' semantic expression.
addResultSemanticExpr(Expr * resultExpr)174     void addResultSemanticExpr(Expr *resultExpr) {
175       assert(ResultIndex == PseudoObjectExpr::NoResult);
176       ResultIndex = Semantics.size();
177       Semantics.push_back(resultExpr);
178     }
179 
180     ExprResult buildRValueOperation(Expr *op);
181     ExprResult buildAssignmentOperation(Scope *Sc,
182                                         SourceLocation opLoc,
183                                         BinaryOperatorKind opcode,
184                                         Expr *LHS, Expr *RHS);
185     ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
186                                     UnaryOperatorKind opcode,
187                                     Expr *op);
188 
189     ExprResult complete(Expr *syntacticForm);
190 
191     OpaqueValueExpr *capture(Expr *op);
192     OpaqueValueExpr *captureValueAsResult(Expr *op);
193 
setResultToLastSemantic()194     void setResultToLastSemantic() {
195       assert(ResultIndex == PseudoObjectExpr::NoResult);
196       ResultIndex = Semantics.size() - 1;
197     }
198 
199     /// Return true if assignments have a non-void result.
assignmentsHaveResult()200     virtual bool assignmentsHaveResult() { return true; }
201 
202     virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
203     virtual ExprResult buildGet() = 0;
204     virtual ExprResult buildSet(Expr *, SourceLocation,
205                                 bool captureSetValueAsResult) = 0;
206   };
207 
208   /// A PseudoOpBuilder for Objective-C @properties.
209   class ObjCPropertyOpBuilder : public PseudoOpBuilder {
210     ObjCPropertyRefExpr *RefExpr;
211     ObjCPropertyRefExpr *SyntacticRefExpr;
212     OpaqueValueExpr *InstanceReceiver;
213     ObjCMethodDecl *Getter;
214 
215     ObjCMethodDecl *Setter;
216     Selector SetterSelector;
217     Selector GetterSelector;
218 
219   public:
ObjCPropertyOpBuilder(Sema & S,ObjCPropertyRefExpr * refExpr)220     ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
221       PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
222       SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
223     }
224 
225     ExprResult buildRValueOperation(Expr *op);
226     ExprResult buildAssignmentOperation(Scope *Sc,
227                                         SourceLocation opLoc,
228                                         BinaryOperatorKind opcode,
229                                         Expr *LHS, Expr *RHS);
230     ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
231                                     UnaryOperatorKind opcode,
232                                     Expr *op);
233 
234     bool tryBuildGetOfReference(Expr *op, ExprResult &result);
235     bool findSetter(bool warn=true);
236     bool findGetter();
237 
238     Expr *rebuildAndCaptureObject(Expr *syntacticBase);
239     ExprResult buildGet();
240     ExprResult buildSet(Expr *op, SourceLocation, bool);
241   };
242 
243  /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
244  class ObjCSubscriptOpBuilder : public PseudoOpBuilder {
245    ObjCSubscriptRefExpr *RefExpr;
246    OpaqueValueExpr *InstanceBase;
247    OpaqueValueExpr *InstanceKey;
248    ObjCMethodDecl *AtIndexGetter;
249    Selector AtIndexGetterSelector;
250 
251    ObjCMethodDecl *AtIndexSetter;
252    Selector AtIndexSetterSelector;
253 
254  public:
ObjCSubscriptOpBuilder(Sema & S,ObjCSubscriptRefExpr * refExpr)255     ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
256       PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
257       RefExpr(refExpr),
258     InstanceBase(0), InstanceKey(0),
259     AtIndexGetter(0), AtIndexSetter(0) { }
260 
261    ExprResult buildRValueOperation(Expr *op);
262    ExprResult buildAssignmentOperation(Scope *Sc,
263                                        SourceLocation opLoc,
264                                        BinaryOperatorKind opcode,
265                                        Expr *LHS, Expr *RHS);
266    Expr *rebuildAndCaptureObject(Expr *syntacticBase);
267 
268    bool findAtIndexGetter();
269    bool findAtIndexSetter();
270 
271    ExprResult buildGet();
272    ExprResult buildSet(Expr *op, SourceLocation, bool);
273  };
274 
275 }
276 
277 /// Capture the given expression in an OpaqueValueExpr.
capture(Expr * e)278 OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
279   // Make a new OVE whose source is the given expression.
280   OpaqueValueExpr *captured =
281     new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
282                                     e->getValueKind(), e->getObjectKind(),
283                                     e);
284 
285   // Make sure we bind that in the semantics.
286   addSemanticExpr(captured);
287   return captured;
288 }
289 
290 /// Capture the given expression as the result of this pseudo-object
291 /// operation.  This routine is safe against expressions which may
292 /// already be captured.
293 ///
294 /// \returns the captured expression, which will be the
295 ///   same as the input if the input was already captured
captureValueAsResult(Expr * e)296 OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
297   assert(ResultIndex == PseudoObjectExpr::NoResult);
298 
299   // If the expression hasn't already been captured, just capture it
300   // and set the new semantic
301   if (!isa<OpaqueValueExpr>(e)) {
302     OpaqueValueExpr *cap = capture(e);
303     setResultToLastSemantic();
304     return cap;
305   }
306 
307   // Otherwise, it must already be one of our semantic expressions;
308   // set ResultIndex to its index.
309   unsigned index = 0;
310   for (;; ++index) {
311     assert(index < Semantics.size() &&
312            "captured expression not found in semantics!");
313     if (e == Semantics[index]) break;
314   }
315   ResultIndex = index;
316   return cast<OpaqueValueExpr>(e);
317 }
318 
319 /// The routine which creates the final PseudoObjectExpr.
complete(Expr * syntactic)320 ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
321   return PseudoObjectExpr::Create(S.Context, syntactic,
322                                   Semantics, ResultIndex);
323 }
324 
325 /// The main skeleton for building an r-value operation.
buildRValueOperation(Expr * op)326 ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
327   Expr *syntacticBase = rebuildAndCaptureObject(op);
328 
329   ExprResult getExpr = buildGet();
330   if (getExpr.isInvalid()) return ExprError();
331   addResultSemanticExpr(getExpr.take());
332 
333   return complete(syntacticBase);
334 }
335 
336 /// The basic skeleton for building a simple or compound
337 /// assignment operation.
338 ExprResult
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)339 PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
340                                           BinaryOperatorKind opcode,
341                                           Expr *LHS, Expr *RHS) {
342   assert(BinaryOperator::isAssignmentOp(opcode));
343 
344   Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
345   OpaqueValueExpr *capturedRHS = capture(RHS);
346 
347   Expr *syntactic;
348 
349   ExprResult result;
350   if (opcode == BO_Assign) {
351     result = capturedRHS;
352     syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
353                                                opcode, capturedRHS->getType(),
354                                                capturedRHS->getValueKind(),
355                                                OK_Ordinary, opcLoc);
356   } else {
357     ExprResult opLHS = buildGet();
358     if (opLHS.isInvalid()) return ExprError();
359 
360     // Build an ordinary, non-compound operation.
361     BinaryOperatorKind nonCompound =
362       BinaryOperator::getOpForCompoundAssignment(opcode);
363     result = S.BuildBinOp(Sc, opcLoc, nonCompound,
364                           opLHS.take(), capturedRHS);
365     if (result.isInvalid()) return ExprError();
366 
367     syntactic =
368       new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
369                                              result.get()->getType(),
370                                              result.get()->getValueKind(),
371                                              OK_Ordinary,
372                                              opLHS.get()->getType(),
373                                              result.get()->getType(),
374                                              opcLoc);
375   }
376 
377   // The result of the assignment, if not void, is the value set into
378   // the l-value.
379   result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
380   if (result.isInvalid()) return ExprError();
381   addSemanticExpr(result.take());
382 
383   return complete(syntactic);
384 }
385 
386 /// The basic skeleton for building an increment or decrement
387 /// operation.
388 ExprResult
buildIncDecOperation(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)389 PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
390                                       UnaryOperatorKind opcode,
391                                       Expr *op) {
392   assert(UnaryOperator::isIncrementDecrementOp(opcode));
393 
394   Expr *syntacticOp = rebuildAndCaptureObject(op);
395 
396   // Load the value.
397   ExprResult result = buildGet();
398   if (result.isInvalid()) return ExprError();
399 
400   QualType resultType = result.get()->getType();
401 
402   // That's the postfix result.
403   if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
404     result = capture(result.take());
405     setResultToLastSemantic();
406   }
407 
408   // Add or subtract a literal 1.
409   llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
410   Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
411                                      GenericLoc);
412 
413   if (UnaryOperator::isIncrementOp(opcode)) {
414     result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
415   } else {
416     result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
417   }
418   if (result.isInvalid()) return ExprError();
419 
420   // Store that back into the result.  The value stored is the result
421   // of a prefix operation.
422   result = buildSet(result.take(), opcLoc,
423              UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
424   if (result.isInvalid()) return ExprError();
425   addSemanticExpr(result.take());
426 
427   UnaryOperator *syntactic =
428     new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
429                                   VK_LValue, OK_Ordinary, opcLoc);
430   return complete(syntactic);
431 }
432 
433 
434 //===----------------------------------------------------------------------===//
435 //  Objective-C @property and implicit property references
436 //===----------------------------------------------------------------------===//
437 
438 /// Look up a method in the receiver type of an Objective-C property
439 /// reference.
LookupMethodInReceiverType(Sema & S,Selector sel,const ObjCPropertyRefExpr * PRE)440 static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
441                                             const ObjCPropertyRefExpr *PRE) {
442   if (PRE->isObjectReceiver()) {
443     const ObjCObjectPointerType *PT =
444       PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
445 
446     // Special case for 'self' in class method implementations.
447     if (PT->isObjCClassType() &&
448         S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
449       // This cast is safe because isSelfExpr is only true within
450       // methods.
451       ObjCMethodDecl *method =
452         cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
453       return S.LookupMethodInObjectType(sel,
454                  S.Context.getObjCInterfaceType(method->getClassInterface()),
455                                         /*instance*/ false);
456     }
457 
458     return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
459   }
460 
461   if (PRE->isSuperReceiver()) {
462     if (const ObjCObjectPointerType *PT =
463         PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
464       return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
465 
466     return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
467   }
468 
469   assert(PRE->isClassReceiver() && "Invalid expression");
470   QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
471   return S.LookupMethodInObjectType(sel, IT, false);
472 }
473 
findGetter()474 bool ObjCPropertyOpBuilder::findGetter() {
475   if (Getter) return true;
476 
477   // For implicit properties, just trust the lookup we already did.
478   if (RefExpr->isImplicitProperty()) {
479     if ((Getter = RefExpr->getImplicitPropertyGetter())) {
480       GetterSelector = Getter->getSelector();
481       return true;
482     }
483     else {
484       // Must build the getter selector the hard way.
485       ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
486       assert(setter && "both setter and getter are null - cannot happen");
487       IdentifierInfo *setterName =
488         setter->getSelector().getIdentifierInfoForSlot(0);
489       const char *compStr = setterName->getNameStart();
490       compStr += 3;
491       IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
492       GetterSelector =
493         S.PP.getSelectorTable().getNullarySelector(getterName);
494       return false;
495 
496     }
497   }
498 
499   ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
500   Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
501   return (Getter != 0);
502 }
503 
504 /// Try to find the most accurate setter declaration for the property
505 /// reference.
506 ///
507 /// \return true if a setter was found, in which case Setter
findSetter(bool warn)508 bool ObjCPropertyOpBuilder::findSetter(bool warn) {
509   // For implicit properties, just trust the lookup we already did.
510   if (RefExpr->isImplicitProperty()) {
511     if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
512       Setter = setter;
513       SetterSelector = setter->getSelector();
514       return true;
515     } else {
516       IdentifierInfo *getterName =
517         RefExpr->getImplicitPropertyGetter()->getSelector()
518           .getIdentifierInfoForSlot(0);
519       SetterSelector =
520         SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
521                                            S.PP.getSelectorTable(),
522                                            getterName);
523       return false;
524     }
525   }
526 
527   // For explicit properties, this is more involved.
528   ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
529   SetterSelector = prop->getSetterName();
530 
531   // Do a normal method lookup first.
532   if (ObjCMethodDecl *setter =
533         LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
534     if (setter->isSynthesized() && warn)
535       if (const ObjCInterfaceDecl *IFace =
536           dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
537         const StringRef thisPropertyName(prop->getName());
538         char front = thisPropertyName.front();
539         front = islower(front) ? toupper(front) : tolower(front);
540         SmallString<100> PropertyName = thisPropertyName;
541         PropertyName[0] = front;
542         IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
543         if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
544           if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
545             S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
546               << prop->getName() << prop1->getName() << setter->getSelector();
547             S.Diag(prop->getLocation(), diag::note_property_declare);
548             S.Diag(prop1->getLocation(), diag::note_property_declare);
549           }
550       }
551     Setter = setter;
552     return true;
553   }
554 
555   // That can fail in the somewhat crazy situation that we're
556   // type-checking a message send within the @interface declaration
557   // that declared the @property.  But it's not clear that that's
558   // valuable to support.
559 
560   return false;
561 }
562 
563 /// Capture the base object of an Objective-C property expression.
rebuildAndCaptureObject(Expr * syntacticBase)564 Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
565   assert(InstanceReceiver == 0);
566 
567   // If we have a base, capture it in an OVE and rebuild the syntactic
568   // form to use the OVE as its base.
569   if (RefExpr->isObjectReceiver()) {
570     InstanceReceiver = capture(RefExpr->getBase());
571 
572     syntacticBase =
573       ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
574   }
575 
576   if (ObjCPropertyRefExpr *
577         refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
578     SyntacticRefExpr = refE;
579 
580   return syntacticBase;
581 }
582 
583 /// Load from an Objective-C property reference.
buildGet()584 ExprResult ObjCPropertyOpBuilder::buildGet() {
585   findGetter();
586   assert(Getter);
587 
588   if (SyntacticRefExpr)
589     SyntacticRefExpr->setIsMessagingGetter();
590 
591   QualType receiverType;
592   if (RefExpr->isClassReceiver()) {
593     receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
594   } else if (RefExpr->isSuperReceiver()) {
595     receiverType = RefExpr->getSuperReceiverType();
596   } else {
597     assert(InstanceReceiver);
598     receiverType = InstanceReceiver->getType();
599   }
600 
601   // Build a message-send.
602   ExprResult msg;
603   if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
604     assert(InstanceReceiver || RefExpr->isSuperReceiver());
605     msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
606                                          GenericLoc, Getter->getSelector(),
607                                          Getter, MultiExprArg());
608   } else {
609     msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
610                                       GenericLoc,
611                                       Getter->getSelector(), Getter,
612                                       MultiExprArg());
613   }
614   return msg;
615 }
616 
617 /// Store to an Objective-C property reference.
618 ///
619 /// \param captureSetValueAsResult If true, capture the actual
620 ///   value being set as the value of the property operation.
buildSet(Expr * op,SourceLocation opcLoc,bool captureSetValueAsResult)621 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
622                                            bool captureSetValueAsResult) {
623   bool hasSetter = findSetter(false);
624   assert(hasSetter); (void) hasSetter;
625 
626   if (SyntacticRefExpr)
627     SyntacticRefExpr->setIsMessagingSetter();
628 
629   QualType receiverType;
630   if (RefExpr->isClassReceiver()) {
631     receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
632   } else if (RefExpr->isSuperReceiver()) {
633     receiverType = RefExpr->getSuperReceiverType();
634   } else {
635     assert(InstanceReceiver);
636     receiverType = InstanceReceiver->getType();
637   }
638 
639   // Use assignment constraints when possible; they give us better
640   // diagnostics.  "When possible" basically means anything except a
641   // C++ class type.
642   if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
643     QualType paramType = (*Setter->param_begin())->getType();
644     if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
645       ExprResult opResult = op;
646       Sema::AssignConvertType assignResult
647         = S.CheckSingleAssignmentConstraints(paramType, opResult);
648       if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
649                                      op->getType(), opResult.get(),
650                                      Sema::AA_Assigning))
651         return ExprError();
652 
653       op = opResult.take();
654       assert(op && "successful assignment left argument invalid?");
655     }
656   }
657 
658   // Arguments.
659   Expr *args[] = { op };
660 
661   // Build a message-send.
662   ExprResult msg;
663   if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
664     msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
665                                          GenericLoc, SetterSelector, Setter,
666                                          MultiExprArg(args, 1));
667   } else {
668     msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
669                                       GenericLoc,
670                                       SetterSelector, Setter,
671                                       MultiExprArg(args, 1));
672   }
673 
674   if (!msg.isInvalid() && captureSetValueAsResult) {
675     ObjCMessageExpr *msgExpr =
676       cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
677     Expr *arg = msgExpr->getArg(0);
678     msgExpr->setArg(0, captureValueAsResult(arg));
679   }
680 
681   return msg;
682 }
683 
684 /// @property-specific behavior for doing lvalue-to-rvalue conversion.
buildRValueOperation(Expr * op)685 ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
686   // Explicit properties always have getters, but implicit ones don't.
687   // Check that before proceeding.
688   if (RefExpr->isImplicitProperty() &&
689       !RefExpr->getImplicitPropertyGetter()) {
690     S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
691       << RefExpr->getBase()->getType();
692     return ExprError();
693   }
694 
695   ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
696   if (result.isInvalid()) return ExprError();
697 
698   if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
699     S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
700                                        Getter, RefExpr->getLocation());
701 
702   // As a special case, if the method returns 'id', try to get
703   // a better type from the property.
704   if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
705       result.get()->getType()->isObjCIdType()) {
706     QualType propType = RefExpr->getExplicitProperty()->getType();
707     if (const ObjCObjectPointerType *ptr
708           = propType->getAs<ObjCObjectPointerType>()) {
709       if (!ptr->isObjCIdType())
710         result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
711     }
712   }
713 
714   return result;
715 }
716 
717 /// Try to build this as a call to a getter that returns a reference.
718 ///
719 /// \return true if it was possible, whether or not it actually
720 ///   succeeded
tryBuildGetOfReference(Expr * op,ExprResult & result)721 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
722                                                    ExprResult &result) {
723   if (!S.getLangOpts().CPlusPlus) return false;
724 
725   findGetter();
726   assert(Getter && "property has no setter and no getter!");
727 
728   // Only do this if the getter returns an l-value reference type.
729   QualType resultType = Getter->getResultType();
730   if (!resultType->isLValueReferenceType()) return false;
731 
732   result = buildRValueOperation(op);
733   return true;
734 }
735 
736 /// @property-specific behavior for doing assignments.
737 ExprResult
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)738 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
739                                                 SourceLocation opcLoc,
740                                                 BinaryOperatorKind opcode,
741                                                 Expr *LHS, Expr *RHS) {
742   assert(BinaryOperator::isAssignmentOp(opcode));
743 
744   // If there's no setter, we have no choice but to try to assign to
745   // the result of the getter.
746   if (!findSetter()) {
747     ExprResult result;
748     if (tryBuildGetOfReference(LHS, result)) {
749       if (result.isInvalid()) return ExprError();
750       return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
751     }
752 
753     // Otherwise, it's an error.
754     S.Diag(opcLoc, diag::err_nosetter_property_assignment)
755       << unsigned(RefExpr->isImplicitProperty())
756       << SetterSelector
757       << LHS->getSourceRange() << RHS->getSourceRange();
758     return ExprError();
759   }
760 
761   // If there is a setter, we definitely want to use it.
762 
763   // Verify that we can do a compound assignment.
764   if (opcode != BO_Assign && !findGetter()) {
765     S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
766       << LHS->getSourceRange() << RHS->getSourceRange();
767     return ExprError();
768   }
769 
770   ExprResult result =
771     PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
772   if (result.isInvalid()) return ExprError();
773 
774   // Various warnings about property assignments in ARC.
775   if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
776     S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
777     S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
778   }
779 
780   return result;
781 }
782 
783 /// @property-specific behavior for doing increments and decrements.
784 ExprResult
buildIncDecOperation(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)785 ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
786                                             UnaryOperatorKind opcode,
787                                             Expr *op) {
788   // If there's no setter, we have no choice but to try to assign to
789   // the result of the getter.
790   if (!findSetter()) {
791     ExprResult result;
792     if (tryBuildGetOfReference(op, result)) {
793       if (result.isInvalid()) return ExprError();
794       return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
795     }
796 
797     // Otherwise, it's an error.
798     S.Diag(opcLoc, diag::err_nosetter_property_incdec)
799       << unsigned(RefExpr->isImplicitProperty())
800       << unsigned(UnaryOperator::isDecrementOp(opcode))
801       << SetterSelector
802       << op->getSourceRange();
803     return ExprError();
804   }
805 
806   // If there is a setter, we definitely want to use it.
807 
808   // We also need a getter.
809   if (!findGetter()) {
810     assert(RefExpr->isImplicitProperty());
811     S.Diag(opcLoc, diag::err_nogetter_property_incdec)
812       << unsigned(UnaryOperator::isDecrementOp(opcode))
813       << GetterSelector
814       << op->getSourceRange();
815     return ExprError();
816   }
817 
818   return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
819 }
820 
821 // ObjCSubscript build stuff.
822 //
823 
824 /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
825 /// conversion.
826 /// FIXME. Remove this routine if it is proven that no additional
827 /// specifity is needed.
buildRValueOperation(Expr * op)828 ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
829   ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
830   if (result.isInvalid()) return ExprError();
831   return result;
832 }
833 
834 /// objective-c subscripting-specific  behavior for doing assignments.
835 ExprResult
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)836 ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
837                                                 SourceLocation opcLoc,
838                                                 BinaryOperatorKind opcode,
839                                                 Expr *LHS, Expr *RHS) {
840   assert(BinaryOperator::isAssignmentOp(opcode));
841   // There must be a method to do the Index'ed assignment.
842   if (!findAtIndexSetter())
843     return ExprError();
844 
845   // Verify that we can do a compound assignment.
846   if (opcode != BO_Assign && !findAtIndexGetter())
847     return ExprError();
848 
849   ExprResult result =
850   PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
851   if (result.isInvalid()) return ExprError();
852 
853   // Various warnings about objc Index'ed assignments in ARC.
854   if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
855     S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
856     S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
857   }
858 
859   return result;
860 }
861 
862 /// Capture the base object of an Objective-C Index'ed expression.
rebuildAndCaptureObject(Expr * syntacticBase)863 Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
864   assert(InstanceBase == 0);
865 
866   // Capture base expression in an OVE and rebuild the syntactic
867   // form to use the OVE as its base expression.
868   InstanceBase = capture(RefExpr->getBaseExpr());
869   InstanceKey = capture(RefExpr->getKeyExpr());
870 
871   syntacticBase =
872     ObjCSubscriptRefRebuilder(S, InstanceBase,
873                               InstanceKey).rebuild(syntacticBase);
874 
875   return syntacticBase;
876 }
877 
878 /// CheckSubscriptingKind - This routine decide what type
879 /// of indexing represented by "FromE" is being done.
880 Sema::ObjCSubscriptKind
CheckSubscriptingKind(Expr * FromE)881   Sema::CheckSubscriptingKind(Expr *FromE) {
882   // If the expression already has integral or enumeration type, we're golden.
883   QualType T = FromE->getType();
884   if (T->isIntegralOrEnumerationType())
885     return OS_Array;
886 
887   // If we don't have a class type in C++, there's no way we can get an
888   // expression of integral or enumeration type.
889   const RecordType *RecordTy = T->getAs<RecordType>();
890   if (!RecordTy && T->isObjCObjectPointerType())
891     // All other scalar cases are assumed to be dictionary indexing which
892     // caller handles, with diagnostics if needed.
893     return OS_Dictionary;
894   if (!getLangOpts().CPlusPlus ||
895       !RecordTy || RecordTy->isIncompleteType()) {
896     // No indexing can be done. Issue diagnostics and quit.
897     const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
898     if (isa<StringLiteral>(IndexExpr))
899       Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
900         << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
901     else
902       Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
903         << T;
904     return OS_Error;
905   }
906 
907   // We must have a complete class type.
908   if (RequireCompleteType(FromE->getExprLoc(), T,
909                           diag::err_objc_index_incomplete_class_type, FromE))
910     return OS_Error;
911 
912   // Look for a conversion to an integral, enumeration type, or
913   // objective-C pointer type.
914   UnresolvedSet<4> ViableConversions;
915   UnresolvedSet<4> ExplicitConversions;
916   const UnresolvedSetImpl *Conversions
917     = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
918 
919   int NoIntegrals=0, NoObjCIdPointers=0;
920   SmallVector<CXXConversionDecl *, 4> ConversionDecls;
921 
922   for (UnresolvedSetImpl::iterator I = Conversions->begin(),
923        E = Conversions->end();
924        I != E;
925        ++I) {
926     if (CXXConversionDecl *Conversion
927         = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
928       QualType CT = Conversion->getConversionType().getNonReferenceType();
929       if (CT->isIntegralOrEnumerationType()) {
930         ++NoIntegrals;
931         ConversionDecls.push_back(Conversion);
932       }
933       else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
934         ++NoObjCIdPointers;
935         ConversionDecls.push_back(Conversion);
936       }
937     }
938   }
939   if (NoIntegrals ==1 && NoObjCIdPointers == 0)
940     return OS_Array;
941   if (NoIntegrals == 0 && NoObjCIdPointers == 1)
942     return OS_Dictionary;
943   if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
944     // No conversion function was found. Issue diagnostic and return.
945     Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
946       << FromE->getType();
947     return OS_Error;
948   }
949   Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
950       << FromE->getType();
951   for (unsigned int i = 0; i < ConversionDecls.size(); i++)
952     Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
953 
954   return OS_Error;
955 }
956 
957 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
958 /// objects used as dictionary subscript key objects.
CheckKeyForObjCARCConversion(Sema & S,QualType ContainerT,Expr * Key)959 static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
960                                          Expr *Key) {
961   if (ContainerT.isNull())
962     return;
963   // dictionary subscripting.
964   // - (id)objectForKeyedSubscript:(id)key;
965   IdentifierInfo *KeyIdents[] = {
966     &S.Context.Idents.get("objectForKeyedSubscript")
967   };
968   Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
969   ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
970                                                       true /*instance*/);
971   if (!Getter)
972     return;
973   QualType T = Getter->param_begin()[0]->getType();
974   S.CheckObjCARCConversion(Key->getSourceRange(),
975                          T, Key, Sema::CCK_ImplicitConversion);
976 }
977 
findAtIndexGetter()978 bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
979   if (AtIndexGetter)
980     return true;
981 
982   Expr *BaseExpr = RefExpr->getBaseExpr();
983   QualType BaseT = BaseExpr->getType();
984 
985   QualType ResultType;
986   if (const ObjCObjectPointerType *PTy =
987       BaseT->getAs<ObjCObjectPointerType>()) {
988     ResultType = PTy->getPointeeType();
989     if (const ObjCObjectType *iQFaceTy =
990         ResultType->getAsObjCQualifiedInterfaceType())
991       ResultType = iQFaceTy->getBaseType();
992   }
993   Sema::ObjCSubscriptKind Res =
994     S.CheckSubscriptingKind(RefExpr->getKeyExpr());
995   if (Res == Sema::OS_Error) {
996     if (S.getLangOpts().ObjCAutoRefCount)
997       CheckKeyForObjCARCConversion(S, ResultType,
998                                    RefExpr->getKeyExpr());
999     return false;
1000   }
1001   bool arrayRef = (Res == Sema::OS_Array);
1002 
1003   if (ResultType.isNull()) {
1004     S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1005       << BaseExpr->getType() << arrayRef;
1006     return false;
1007   }
1008   if (!arrayRef) {
1009     // dictionary subscripting.
1010     // - (id)objectForKeyedSubscript:(id)key;
1011     IdentifierInfo *KeyIdents[] = {
1012       &S.Context.Idents.get("objectForKeyedSubscript")
1013     };
1014     AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1015   }
1016   else {
1017     // - (id)objectAtIndexedSubscript:(size_t)index;
1018     IdentifierInfo *KeyIdents[] = {
1019       &S.Context.Idents.get("objectAtIndexedSubscript")
1020     };
1021 
1022     AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1023   }
1024 
1025   AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
1026                                              true /*instance*/);
1027   bool receiverIdType = (BaseT->isObjCIdType() ||
1028                          BaseT->isObjCQualifiedIdType());
1029 
1030   if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
1031     AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1032                            SourceLocation(), AtIndexGetterSelector,
1033                            S.Context.getObjCIdType() /*ReturnType*/,
1034                            0 /*TypeSourceInfo */,
1035                            S.Context.getTranslationUnitDecl(),
1036                            true /*Instance*/, false/*isVariadic*/,
1037                            /*isSynthesized=*/false,
1038                            /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1039                            ObjCMethodDecl::Required,
1040                            false);
1041     ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1042                                                 SourceLocation(), SourceLocation(),
1043                                                 arrayRef ? &S.Context.Idents.get("index")
1044                                                          : &S.Context.Idents.get("key"),
1045                                                 arrayRef ? S.Context.UnsignedLongTy
1046                                                          : S.Context.getObjCIdType(),
1047                                                 /*TInfo=*/0,
1048                                                 SC_None,
1049                                                 SC_None,
1050                                                 0);
1051     AtIndexGetter->setMethodParams(S.Context, Argument,
1052                                    ArrayRef<SourceLocation>());
1053   }
1054 
1055   if (!AtIndexGetter) {
1056     if (!receiverIdType) {
1057       S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1058       << BaseExpr->getType() << 0 << arrayRef;
1059       return false;
1060     }
1061     AtIndexGetter =
1062       S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
1063                                          RefExpr->getSourceRange(),
1064                                          true, false);
1065   }
1066 
1067   if (AtIndexGetter) {
1068     QualType T = AtIndexGetter->param_begin()[0]->getType();
1069     if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1070         (!arrayRef && !T->isObjCObjectPointerType())) {
1071       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1072              arrayRef ? diag::err_objc_subscript_index_type
1073                       : diag::err_objc_subscript_key_type) << T;
1074       S.Diag(AtIndexGetter->param_begin()[0]->getLocation(),
1075              diag::note_parameter_type) << T;
1076       return false;
1077     }
1078     QualType R = AtIndexGetter->getResultType();
1079     if (!R->isObjCObjectPointerType()) {
1080       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1081              diag::err_objc_indexing_method_result_type) << R << arrayRef;
1082       S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1083         AtIndexGetter->getDeclName();
1084     }
1085   }
1086   return true;
1087 }
1088 
findAtIndexSetter()1089 bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1090   if (AtIndexSetter)
1091     return true;
1092 
1093   Expr *BaseExpr = RefExpr->getBaseExpr();
1094   QualType BaseT = BaseExpr->getType();
1095 
1096   QualType ResultType;
1097   if (const ObjCObjectPointerType *PTy =
1098       BaseT->getAs<ObjCObjectPointerType>()) {
1099     ResultType = PTy->getPointeeType();
1100     if (const ObjCObjectType *iQFaceTy =
1101         ResultType->getAsObjCQualifiedInterfaceType())
1102       ResultType = iQFaceTy->getBaseType();
1103   }
1104 
1105   Sema::ObjCSubscriptKind Res =
1106     S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1107   if (Res == Sema::OS_Error) {
1108     if (S.getLangOpts().ObjCAutoRefCount)
1109       CheckKeyForObjCARCConversion(S, ResultType,
1110                                    RefExpr->getKeyExpr());
1111     return false;
1112   }
1113   bool arrayRef = (Res == Sema::OS_Array);
1114 
1115   if (ResultType.isNull()) {
1116     S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1117       << BaseExpr->getType() << arrayRef;
1118     return false;
1119   }
1120 
1121   if (!arrayRef) {
1122     // dictionary subscripting.
1123     // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1124     IdentifierInfo *KeyIdents[] = {
1125       &S.Context.Idents.get("setObject"),
1126       &S.Context.Idents.get("forKeyedSubscript")
1127     };
1128     AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1129   }
1130   else {
1131     // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1132     IdentifierInfo *KeyIdents[] = {
1133       &S.Context.Idents.get("setObject"),
1134       &S.Context.Idents.get("atIndexedSubscript")
1135     };
1136     AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1137   }
1138   AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
1139                                              true /*instance*/);
1140 
1141   bool receiverIdType = (BaseT->isObjCIdType() ||
1142                          BaseT->isObjCQualifiedIdType());
1143 
1144   if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
1145     TypeSourceInfo *ResultTInfo = 0;
1146     QualType ReturnType = S.Context.VoidTy;
1147     AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1148                            SourceLocation(), AtIndexSetterSelector,
1149                            ReturnType,
1150                            ResultTInfo,
1151                            S.Context.getTranslationUnitDecl(),
1152                            true /*Instance*/, false/*isVariadic*/,
1153                            /*isSynthesized=*/false,
1154                            /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1155                            ObjCMethodDecl::Required,
1156                            false);
1157     SmallVector<ParmVarDecl *, 2> Params;
1158     ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1159                                                 SourceLocation(), SourceLocation(),
1160                                                 &S.Context.Idents.get("object"),
1161                                                 S.Context.getObjCIdType(),
1162                                                 /*TInfo=*/0,
1163                                                 SC_None,
1164                                                 SC_None,
1165                                                 0);
1166     Params.push_back(object);
1167     ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1168                                                 SourceLocation(), SourceLocation(),
1169                                                 arrayRef ?  &S.Context.Idents.get("index")
1170                                                          :  &S.Context.Idents.get("key"),
1171                                                 arrayRef ? S.Context.UnsignedLongTy
1172                                                          : S.Context.getObjCIdType(),
1173                                                 /*TInfo=*/0,
1174                                                 SC_None,
1175                                                 SC_None,
1176                                                 0);
1177     Params.push_back(key);
1178     AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
1179   }
1180 
1181   if (!AtIndexSetter) {
1182     if (!receiverIdType) {
1183       S.Diag(BaseExpr->getExprLoc(),
1184              diag::err_objc_subscript_method_not_found)
1185       << BaseExpr->getType() << 1 << arrayRef;
1186       return false;
1187     }
1188     AtIndexSetter =
1189       S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
1190                                          RefExpr->getSourceRange(),
1191                                          true, false);
1192   }
1193 
1194   bool err = false;
1195   if (AtIndexSetter && arrayRef) {
1196     QualType T = AtIndexSetter->param_begin()[1]->getType();
1197     if (!T->isIntegralOrEnumerationType()) {
1198       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1199              diag::err_objc_subscript_index_type) << T;
1200       S.Diag(AtIndexSetter->param_begin()[1]->getLocation(),
1201              diag::note_parameter_type) << T;
1202       err = true;
1203     }
1204     T = AtIndexSetter->param_begin()[0]->getType();
1205     if (!T->isObjCObjectPointerType()) {
1206       S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1207              diag::err_objc_subscript_object_type) << T << arrayRef;
1208       S.Diag(AtIndexSetter->param_begin()[0]->getLocation(),
1209              diag::note_parameter_type) << T;
1210       err = true;
1211     }
1212   }
1213   else if (AtIndexSetter && !arrayRef)
1214     for (unsigned i=0; i <2; i++) {
1215       QualType T = AtIndexSetter->param_begin()[i]->getType();
1216       if (!T->isObjCObjectPointerType()) {
1217         if (i == 1)
1218           S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1219                  diag::err_objc_subscript_key_type) << T;
1220         else
1221           S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1222                  diag::err_objc_subscript_dic_object_type) << T;
1223         S.Diag(AtIndexSetter->param_begin()[i]->getLocation(),
1224                diag::note_parameter_type) << T;
1225         err = true;
1226       }
1227     }
1228 
1229   return !err;
1230 }
1231 
1232 // Get the object at "Index" position in the container.
1233 // [BaseExpr objectAtIndexedSubscript : IndexExpr];
buildGet()1234 ExprResult ObjCSubscriptOpBuilder::buildGet() {
1235   if (!findAtIndexGetter())
1236     return ExprError();
1237 
1238   QualType receiverType = InstanceBase->getType();
1239 
1240   // Build a message-send.
1241   ExprResult msg;
1242   Expr *Index = InstanceKey;
1243 
1244   // Arguments.
1245   Expr *args[] = { Index };
1246   assert(InstanceBase);
1247   msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1248                                        GenericLoc,
1249                                        AtIndexGetterSelector, AtIndexGetter,
1250                                        MultiExprArg(args, 1));
1251   return msg;
1252 }
1253 
1254 /// Store into the container the "op" object at "Index"'ed location
1255 /// by building this messaging expression:
1256 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1257 /// \param captureSetValueAsResult If true, capture the actual
1258 ///   value being set as the value of the property operation.
buildSet(Expr * op,SourceLocation opcLoc,bool captureSetValueAsResult)1259 ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
1260                                            bool captureSetValueAsResult) {
1261   if (!findAtIndexSetter())
1262     return ExprError();
1263 
1264   QualType receiverType = InstanceBase->getType();
1265   Expr *Index = InstanceKey;
1266 
1267   // Arguments.
1268   Expr *args[] = { op, Index };
1269 
1270   // Build a message-send.
1271   ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1272                                                   GenericLoc,
1273                                                   AtIndexSetterSelector,
1274                                                   AtIndexSetter,
1275                                                   MultiExprArg(args, 2));
1276 
1277   if (!msg.isInvalid() && captureSetValueAsResult) {
1278     ObjCMessageExpr *msgExpr =
1279       cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1280     Expr *arg = msgExpr->getArg(0);
1281     msgExpr->setArg(0, captureValueAsResult(arg));
1282   }
1283 
1284   return msg;
1285 }
1286 
1287 //===----------------------------------------------------------------------===//
1288 //  General Sema routines.
1289 //===----------------------------------------------------------------------===//
1290 
checkPseudoObjectRValue(Expr * E)1291 ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
1292   Expr *opaqueRef = E->IgnoreParens();
1293   if (ObjCPropertyRefExpr *refExpr
1294         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1295     ObjCPropertyOpBuilder builder(*this, refExpr);
1296     return builder.buildRValueOperation(E);
1297   }
1298   else if (ObjCSubscriptRefExpr *refExpr
1299            = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1300     ObjCSubscriptOpBuilder builder(*this, refExpr);
1301     return builder.buildRValueOperation(E);
1302   } else {
1303     llvm_unreachable("unknown pseudo-object kind!");
1304   }
1305 }
1306 
1307 /// Check an increment or decrement of a pseudo-object expression.
checkPseudoObjectIncDec(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)1308 ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
1309                                          UnaryOperatorKind opcode, Expr *op) {
1310   // Do nothing if the operand is dependent.
1311   if (op->isTypeDependent())
1312     return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
1313                                        VK_RValue, OK_Ordinary, opcLoc);
1314 
1315   assert(UnaryOperator::isIncrementDecrementOp(opcode));
1316   Expr *opaqueRef = op->IgnoreParens();
1317   if (ObjCPropertyRefExpr *refExpr
1318         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1319     ObjCPropertyOpBuilder builder(*this, refExpr);
1320     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1321   } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1322     Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1323     return ExprError();
1324   } else {
1325     llvm_unreachable("unknown pseudo-object kind!");
1326   }
1327 }
1328 
checkPseudoObjectAssignment(Scope * S,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)1329 ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
1330                                              BinaryOperatorKind opcode,
1331                                              Expr *LHS, Expr *RHS) {
1332   // Do nothing if either argument is dependent.
1333   if (LHS->isTypeDependent() || RHS->isTypeDependent())
1334     return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
1335                                         VK_RValue, OK_Ordinary, opcLoc);
1336 
1337   // Filter out non-overload placeholder types in the RHS.
1338   if (RHS->getType()->isNonOverloadPlaceholderType()) {
1339     ExprResult result = CheckPlaceholderExpr(RHS);
1340     if (result.isInvalid()) return ExprError();
1341     RHS = result.take();
1342   }
1343 
1344   Expr *opaqueRef = LHS->IgnoreParens();
1345   if (ObjCPropertyRefExpr *refExpr
1346         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1347     ObjCPropertyOpBuilder builder(*this, refExpr);
1348     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1349   } else if (ObjCSubscriptRefExpr *refExpr
1350              = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1351     ObjCSubscriptOpBuilder builder(*this, refExpr);
1352     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1353   } else {
1354     llvm_unreachable("unknown pseudo-object kind!");
1355   }
1356 }
1357 
1358 /// Given a pseudo-object reference, rebuild it without the opaque
1359 /// values.  Basically, undo the behavior of rebuildAndCaptureObject.
1360 /// This should never operate in-place.
stripOpaqueValuesFromPseudoObjectRef(Sema & S,Expr * E)1361 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
1362   Expr *opaqueRef = E->IgnoreParens();
1363   if (ObjCPropertyRefExpr *refExpr
1364         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1365     // Class and super property references don't have opaque values in them.
1366     if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
1367       return E;
1368 
1369     assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
1370     OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
1371     return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
1372   } else if (ObjCSubscriptRefExpr *refExpr
1373                = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1374     OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
1375     OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
1376     return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
1377                                      keyOVE->getSourceExpr()).rebuild(E);
1378   } else {
1379     llvm_unreachable("unknown pseudo-object kind!");
1380   }
1381 }
1382 
1383 /// Given a pseudo-object expression, recreate what it looks like
1384 /// syntactically without the attendant OpaqueValueExprs.
1385 ///
1386 /// This is a hack which should be removed when TreeTransform is
1387 /// capable of rebuilding a tree without stripping implicit
1388 /// operations.
recreateSyntacticForm(PseudoObjectExpr * E)1389 Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
1390   Expr *syntax = E->getSyntacticForm();
1391   if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
1392     Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
1393     return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
1394                                        uop->getValueKind(), uop->getObjectKind(),
1395                                        uop->getOperatorLoc());
1396   } else if (CompoundAssignOperator *cop
1397                = dyn_cast<CompoundAssignOperator>(syntax)) {
1398     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
1399     Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
1400     return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
1401                                                 cop->getType(),
1402                                                 cop->getValueKind(),
1403                                                 cop->getObjectKind(),
1404                                                 cop->getComputationLHSType(),
1405                                                 cop->getComputationResultType(),
1406                                                 cop->getOperatorLoc());
1407   } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
1408     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
1409     Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
1410     return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
1411                                         bop->getType(), bop->getValueKind(),
1412                                         bop->getObjectKind(),
1413                                         bop->getOperatorLoc());
1414   } else {
1415     assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
1416     return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
1417   }
1418 }
1419