blob: cf43fcad0553d1f6a3e603373190e163db269184 [file] [log] [blame]
John McCall3c3b7f92011-10-25 17:37:35 +00001//===--- 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
38using namespace clang;
39using namespace sema;
40
John McCall4b9c2d22011-11-06 09:01:30 +000041namespace {
42 // Basically just a very focused copy of TreeTransform.
43 template <class T> struct Rebuilder {
44 Sema &S;
45 Rebuilder(Sema &S) : S(S) {}
46
47 T &getDerived() { return static_cast<T&>(*this); }
48
49 Expr *rebuild(Expr *e) {
50 // Fast path: nothing to look through.
51 if (typename T::specific_type *specific
52 = dyn_cast<typename T::specific_type>(e))
53 return getDerived().rebuildSpecific(specific);
54
55 // Otherwise, we should look through and rebuild anything that
56 // IgnoreParens would.
57
58 if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
59 e = rebuild(parens->getSubExpr());
60 return new (S.Context) ParenExpr(parens->getLParen(),
61 parens->getRParen(),
62 e);
63 }
64
65 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
66 assert(uop->getOpcode() == UO_Extension);
67 e = rebuild(uop->getSubExpr());
68 return new (S.Context) UnaryOperator(e, uop->getOpcode(),
69 uop->getType(),
70 uop->getValueKind(),
71 uop->getObjectKind(),
72 uop->getOperatorLoc());
73 }
74
75 if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
76 assert(!gse->isResultDependent());
77 unsigned resultIndex = gse->getResultIndex();
78 unsigned numAssocs = gse->getNumAssocs();
79
80 SmallVector<Expr*, 8> assocs(numAssocs);
81 SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
82
83 for (unsigned i = 0; i != numAssocs; ++i) {
84 Expr *assoc = gse->getAssocExpr(i);
85 if (i == resultIndex) assoc = rebuild(assoc);
86 assocs[i] = assoc;
87 assocTypes[i] = gse->getAssocTypeSourceInfo(i);
88 }
89
90 return new (S.Context) GenericSelectionExpr(S.Context,
91 gse->getGenericLoc(),
92 gse->getControllingExpr(),
93 assocTypes.data(),
94 assocs.data(),
95 numAssocs,
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;
108 ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
Benjamin Krameracf9e822011-11-06 09:50:13 +0000109 : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
John McCall4b9c2d22011-11-06 09:01:30 +0000110
111 typedef ObjCPropertyRefExpr specific_type;
112 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 class PseudoOpBuilder {
134 public:
135 Sema &S;
136 unsigned ResultIndex;
137 SourceLocation GenericLoc;
138 SmallVector<Expr *, 4> Semantics;
139
140 PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
141 : S(S), ResultIndex(PseudoObjectExpr::NoResult),
142 GenericLoc(genericLoc) {}
143
144 /// Add a normal semantic expression.
145 void addSemanticExpr(Expr *semantic) {
146 Semantics.push_back(semantic);
147 }
148
149 /// Add the 'result' semantic expression.
150 void addResultSemanticExpr(Expr *resultExpr) {
151 assert(ResultIndex == PseudoObjectExpr::NoResult);
152 ResultIndex = Semantics.size();
153 Semantics.push_back(resultExpr);
154 }
155
156 ExprResult buildRValueOperation(Expr *op);
157 ExprResult buildAssignmentOperation(Scope *Sc,
158 SourceLocation opLoc,
159 BinaryOperatorKind opcode,
160 Expr *LHS, Expr *RHS);
161 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
162 UnaryOperatorKind opcode,
163 Expr *op);
164
165 ExprResult complete(Expr *syntacticForm);
166
167 OpaqueValueExpr *capture(Expr *op);
168 OpaqueValueExpr *captureValueAsResult(Expr *op);
169
170 void setResultToLastSemantic() {
171 assert(ResultIndex == PseudoObjectExpr::NoResult);
172 ResultIndex = Semantics.size() - 1;
173 }
174
175 /// Return true if assignments have a non-void result.
176 virtual bool assignmentsHaveResult() { return true; }
177
178 virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
179 virtual ExprResult buildGet() = 0;
180 virtual ExprResult buildSet(Expr *, SourceLocation,
181 bool captureSetValueAsResult) = 0;
Matt Beaumont-Gay8cacea52011-11-07 18:30:47 +0000182
183 protected:
184 ~PseudoOpBuilder() {}
John McCall4b9c2d22011-11-06 09:01:30 +0000185 };
186
187 /// A PseudoOpBuilder for Objective-C @properties.
188 class ObjCPropertyOpBuilder : public PseudoOpBuilder {
189 ObjCPropertyRefExpr *RefExpr;
190 OpaqueValueExpr *InstanceReceiver;
191 ObjCMethodDecl *Getter;
192
193 ObjCMethodDecl *Setter;
194 Selector SetterSelector;
195
196 public:
197 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
198 PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
199 InstanceReceiver(0), Getter(0), Setter(0) {
200 }
201
202 ExprResult buildRValueOperation(Expr *op);
203 ExprResult buildAssignmentOperation(Scope *Sc,
204 SourceLocation opLoc,
205 BinaryOperatorKind opcode,
206 Expr *LHS, Expr *RHS);
207 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
208 UnaryOperatorKind opcode,
209 Expr *op);
210
211 bool tryBuildGetOfReference(Expr *op, ExprResult &result);
212 bool findSetter();
213 bool findGetter();
214
215 Expr *rebuildAndCaptureObject(Expr *syntacticBase);
216 ExprResult buildGet();
217 ExprResult buildSet(Expr *op, SourceLocation, bool);
218 };
219}
220
221/// Capture the given expression in an OpaqueValueExpr.
222OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
223 // Make a new OVE whose source is the given expression.
224 OpaqueValueExpr *captured =
225 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
226 e->getValueKind());
227 captured->setSourceExpr(e);
228
229 // Make sure we bind that in the semantics.
230 addSemanticExpr(captured);
231 return captured;
232}
233
234/// Capture the given expression as the result of this pseudo-object
235/// operation. This routine is safe against expressions which may
236/// already be captured.
237///
238/// \param Returns the captured expression, which will be the
239/// same as the input if the input was already captured
240OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
241 assert(ResultIndex == PseudoObjectExpr::NoResult);
242
243 // If the expression hasn't already been captured, just capture it
244 // and set the new semantic
245 if (!isa<OpaqueValueExpr>(e)) {
246 OpaqueValueExpr *cap = capture(e);
247 setResultToLastSemantic();
248 return cap;
249 }
250
251 // Otherwise, it must already be one of our semantic expressions;
252 // set ResultIndex to its index.
253 unsigned index = 0;
254 for (;; ++index) {
255 assert(index < Semantics.size() &&
256 "captured expression not found in semantics!");
257 if (e == Semantics[index]) break;
258 }
259 ResultIndex = index;
260 return cast<OpaqueValueExpr>(e);
261}
262
263/// The routine which creates the final PseudoObjectExpr.
264ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
265 return PseudoObjectExpr::Create(S.Context, syntactic,
266 Semantics, ResultIndex);
267}
268
269/// The main skeleton for building an r-value operation.
270ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
271 Expr *syntacticBase = rebuildAndCaptureObject(op);
272
273 ExprResult getExpr = buildGet();
274 if (getExpr.isInvalid()) return ExprError();
275 addResultSemanticExpr(getExpr.take());
276
277 return complete(syntacticBase);
278}
279
280/// The basic skeleton for building a simple or compound
281/// assignment operation.
282ExprResult
283PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
284 BinaryOperatorKind opcode,
285 Expr *LHS, Expr *RHS) {
286 assert(BinaryOperator::isAssignmentOp(opcode));
287
288 Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
289 OpaqueValueExpr *capturedRHS = capture(RHS);
290
291 Expr *syntactic;
292
293 ExprResult result;
294 if (opcode == BO_Assign) {
295 result = capturedRHS;
296 syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
297 opcode, capturedRHS->getType(),
298 capturedRHS->getValueKind(),
299 OK_Ordinary, opcLoc);
300 } else {
301 ExprResult opLHS = buildGet();
302 if (opLHS.isInvalid()) return ExprError();
303
304 // Build an ordinary, non-compound operation.
305 BinaryOperatorKind nonCompound =
306 BinaryOperator::getOpForCompoundAssignment(opcode);
307 result = S.BuildBinOp(Sc, opcLoc, nonCompound,
308 opLHS.take(), capturedRHS);
309 if (result.isInvalid()) return ExprError();
310
311 syntactic =
312 new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
313 result.get()->getType(),
314 result.get()->getValueKind(),
315 OK_Ordinary,
316 opLHS.get()->getType(),
317 result.get()->getType(),
318 opcLoc);
319 }
320
321 // The result of the assignment, if not void, is the value set into
322 // the l-value.
323 result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
324 if (result.isInvalid()) return ExprError();
325 addSemanticExpr(result.take());
326
327 return complete(syntactic);
328}
329
330/// The basic skeleton for building an increment or decrement
331/// operation.
332ExprResult
333PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
334 UnaryOperatorKind opcode,
335 Expr *op) {
336 assert(UnaryOperator::isIncrementDecrementOp(opcode));
337
338 Expr *syntacticOp = rebuildAndCaptureObject(op);
339
340 // Load the value.
341 ExprResult result = buildGet();
342 if (result.isInvalid()) return ExprError();
343
344 QualType resultType = result.get()->getType();
345
346 // That's the postfix result.
347 if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
348 result = capture(result.take());
349 setResultToLastSemantic();
350 }
351
352 // Add or subtract a literal 1.
353 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
354 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
355 GenericLoc);
356
357 if (UnaryOperator::isIncrementOp(opcode)) {
358 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
359 } else {
360 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
361 }
362 if (result.isInvalid()) return ExprError();
363
364 // Store that back into the result. The value stored is the result
365 // of a prefix operation.
366 result = buildSet(result.take(), opcLoc,
367 UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
368 if (result.isInvalid()) return ExprError();
369 addSemanticExpr(result.take());
370
371 UnaryOperator *syntactic =
372 new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
373 VK_LValue, OK_Ordinary, opcLoc);
374 return complete(syntactic);
375}
376
377
378//===----------------------------------------------------------------------===//
379// Objective-C @property and implicit property references
380//===----------------------------------------------------------------------===//
381
382/// Look up a method in the receiver type of an Objective-C property
383/// reference.
John McCall3c3b7f92011-10-25 17:37:35 +0000384static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
385 const ObjCPropertyRefExpr *PRE) {
John McCall3c3b7f92011-10-25 17:37:35 +0000386 if (PRE->isObjectReceiver()) {
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000387 const ObjCObjectPointerType *PT =
388 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
John McCall4b9c2d22011-11-06 09:01:30 +0000389
390 // Special case for 'self' in class method implementations.
391 if (PT->isObjCClassType() &&
392 S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
393 // This cast is safe because isSelfExpr is only true within
394 // methods.
395 ObjCMethodDecl *method =
396 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
397 return S.LookupMethodInObjectType(sel,
398 S.Context.getObjCInterfaceType(method->getClassInterface()),
399 /*instance*/ false);
400 }
401
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000402 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
John McCall3c3b7f92011-10-25 17:37:35 +0000403 }
404
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000405 if (PRE->isSuperReceiver()) {
406 if (const ObjCObjectPointerType *PT =
407 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
408 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
409
410 return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
411 }
412
413 assert(PRE->isClassReceiver() && "Invalid expression");
414 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
415 return S.LookupMethodInObjectType(sel, IT, false);
John McCall3c3b7f92011-10-25 17:37:35 +0000416}
417
John McCall4b9c2d22011-11-06 09:01:30 +0000418bool ObjCPropertyOpBuilder::findGetter() {
419 if (Getter) return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000420
John McCalldc4df512011-11-07 22:49:50 +0000421 // For implicit properties, just trust the lookup we already did.
422 if (RefExpr->isImplicitProperty()) {
423 Getter = RefExpr->getImplicitPropertyGetter();
424 return (Getter != 0);
425 }
426
427 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
428 Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
John McCall4b9c2d22011-11-06 09:01:30 +0000429 return (Getter != 0);
430}
431
432/// Try to find the most accurate setter declaration for the property
433/// reference.
434///
435/// \return true if a setter was found, in which case Setter
436bool ObjCPropertyOpBuilder::findSetter() {
437 // For implicit properties, just trust the lookup we already did.
438 if (RefExpr->isImplicitProperty()) {
439 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
440 Setter = setter;
441 SetterSelector = setter->getSelector();
442 return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000443 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000444 IdentifierInfo *getterName =
445 RefExpr->getImplicitPropertyGetter()->getSelector()
446 .getIdentifierInfoForSlot(0);
447 SetterSelector =
448 SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
449 S.PP.getSelectorTable(),
450 getterName);
451 return false;
John McCall3c3b7f92011-10-25 17:37:35 +0000452 }
John McCall4b9c2d22011-11-06 09:01:30 +0000453 }
454
455 // For explicit properties, this is more involved.
456 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
457 SetterSelector = prop->getSetterName();
458
459 // Do a normal method lookup first.
460 if (ObjCMethodDecl *setter =
461 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
462 Setter = setter;
463 return true;
464 }
465
466 // That can fail in the somewhat crazy situation that we're
467 // type-checking a message send within the @interface declaration
468 // that declared the @property. But it's not clear that that's
469 // valuable to support.
470
471 return false;
472}
473
474/// Capture the base object of an Objective-C property expression.
475Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
476 assert(InstanceReceiver == 0);
477
478 // If we have a base, capture it in an OVE and rebuild the syntactic
479 // form to use the OVE as its base.
480 if (RefExpr->isObjectReceiver()) {
481 InstanceReceiver = capture(RefExpr->getBase());
482
483 syntacticBase =
484 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
485 }
486
487 return syntacticBase;
488}
489
490/// Load from an Objective-C property reference.
491ExprResult ObjCPropertyOpBuilder::buildGet() {
492 findGetter();
493 assert(Getter);
494
495 QualType receiverType;
496 SourceLocation superLoc;
497 if (RefExpr->isClassReceiver()) {
498 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
499 } else if (RefExpr->isSuperReceiver()) {
500 superLoc = RefExpr->getReceiverLocation();
501 receiverType = RefExpr->getSuperReceiverType();
John McCall3c3b7f92011-10-25 17:37:35 +0000502 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000503 assert(InstanceReceiver);
504 receiverType = InstanceReceiver->getType();
505 }
John McCall3c3b7f92011-10-25 17:37:35 +0000506
John McCall4b9c2d22011-11-06 09:01:30 +0000507 // Build a message-send.
508 ExprResult msg;
509 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
510 assert(InstanceReceiver || RefExpr->isSuperReceiver());
511 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
512 Getter->getSelector(), Getter,
513 GenericLoc, GenericLoc, GenericLoc,
514 MultiExprArg());
515 } else {
516 TypeSourceInfo *receiverTypeInfo = 0;
517 if (!RefExpr->isSuperReceiver())
518 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
John McCall3c3b7f92011-10-25 17:37:35 +0000519
John McCall4b9c2d22011-11-06 09:01:30 +0000520 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
521 Getter->getSelector(), Getter,
522 GenericLoc, GenericLoc, GenericLoc,
523 MultiExprArg());
524 }
525 return msg;
526}
John McCall3c3b7f92011-10-25 17:37:35 +0000527
John McCall4b9c2d22011-11-06 09:01:30 +0000528/// Store to an Objective-C property reference.
529///
530/// \param bindSetValueAsResult - If true, capture the actual
531/// value being set as the value of the property operation.
532ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
533 bool captureSetValueAsResult) {
534 bool hasSetter = findSetter();
535 assert(hasSetter); (void) hasSetter;
536
537 QualType receiverType;
538 SourceLocation superLoc;
539 if (RefExpr->isClassReceiver()) {
540 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
541 } else if (RefExpr->isSuperReceiver()) {
542 superLoc = RefExpr->getReceiverLocation();
543 receiverType = RefExpr->getSuperReceiverType();
544 } else {
545 assert(InstanceReceiver);
546 receiverType = InstanceReceiver->getType();
547 }
548
549 // Use assignment constraints when possible; they give us better
550 // diagnostics. "When possible" basically means anything except a
551 // C++ class type.
552 if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {
553 QualType paramType = (*Setter->param_begin())->getType();
554 if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {
555 ExprResult opResult = op;
556 Sema::AssignConvertType assignResult
557 = S.CheckSingleAssignmentConstraints(paramType, opResult);
558 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
559 op->getType(), opResult.get(),
560 Sema::AA_Assigning))
561 return ExprError();
562
563 op = opResult.take();
564 assert(op && "successful assignment left argument invalid?");
John McCall3c3b7f92011-10-25 17:37:35 +0000565 }
566 }
567
John McCall4b9c2d22011-11-06 09:01:30 +0000568 // Arguments.
569 Expr *args[] = { op };
John McCall3c3b7f92011-10-25 17:37:35 +0000570
John McCall4b9c2d22011-11-06 09:01:30 +0000571 // Build a message-send.
572 ExprResult msg;
573 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
574 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
575 SetterSelector, Setter,
576 GenericLoc, GenericLoc, GenericLoc,
577 MultiExprArg(args, 1));
578 } else {
579 TypeSourceInfo *receiverTypeInfo = 0;
580 if (!RefExpr->isSuperReceiver())
581 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
582
583 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
584 SetterSelector, Setter,
585 GenericLoc, GenericLoc, GenericLoc,
586 MultiExprArg(args, 1));
587 }
588
589 if (!msg.isInvalid() && captureSetValueAsResult) {
590 ObjCMessageExpr *msgExpr =
591 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
592 Expr *arg = msgExpr->getArg(0);
593 msgExpr->setArg(0, captureValueAsResult(arg));
594 }
595
596 return msg;
John McCall3c3b7f92011-10-25 17:37:35 +0000597}
598
John McCall4b9c2d22011-11-06 09:01:30 +0000599/// @property-specific behavior for doing lvalue-to-rvalue conversion.
600ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
601 // Explicit properties always have getters, but implicit ones don't.
602 // Check that before proceeding.
603 if (RefExpr->isImplicitProperty() &&
604 !RefExpr->getImplicitPropertyGetter()) {
605 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
606 << RefExpr->getBase()->getType();
John McCall3c3b7f92011-10-25 17:37:35 +0000607 return ExprError();
608 }
609
John McCall4b9c2d22011-11-06 09:01:30 +0000610 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
John McCall3c3b7f92011-10-25 17:37:35 +0000611 if (result.isInvalid()) return ExprError();
612
John McCall4b9c2d22011-11-06 09:01:30 +0000613 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
614 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
615 Getter, RefExpr->getLocation());
616
617 // As a special case, if the method returns 'id', try to get
618 // a better type from the property.
619 if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
620 result.get()->getType()->isObjCIdType()) {
621 QualType propType = RefExpr->getExplicitProperty()->getType();
622 if (const ObjCObjectPointerType *ptr
623 = propType->getAs<ObjCObjectPointerType>()) {
624 if (!ptr->isObjCIdType())
625 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
626 }
627 }
628
John McCall3c3b7f92011-10-25 17:37:35 +0000629 return result;
630}
631
John McCall4b9c2d22011-11-06 09:01:30 +0000632/// Try to build this as a call to a getter that returns a reference.
633///
634/// \return true if it was possible, whether or not it actually
635/// succeeded
636bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
637 ExprResult &result) {
638 if (!S.getLangOptions().CPlusPlus) return false;
639
640 findGetter();
641 assert(Getter && "property has no setter and no getter!");
642
643 // Only do this if the getter returns an l-value reference type.
644 QualType resultType = Getter->getResultType();
645 if (!resultType->isLValueReferenceType()) return false;
646
647 result = buildRValueOperation(op);
648 return true;
649}
650
651/// @property-specific behavior for doing assignments.
652ExprResult
653ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
654 SourceLocation opcLoc,
655 BinaryOperatorKind opcode,
656 Expr *LHS, Expr *RHS) {
John McCall3c3b7f92011-10-25 17:37:35 +0000657 assert(BinaryOperator::isAssignmentOp(opcode));
John McCall3c3b7f92011-10-25 17:37:35 +0000658
659 // If there's no setter, we have no choice but to try to assign to
660 // the result of the getter.
John McCall4b9c2d22011-11-06 09:01:30 +0000661 if (!findSetter()) {
662 ExprResult result;
663 if (tryBuildGetOfReference(LHS, result)) {
664 if (result.isInvalid()) return ExprError();
665 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000666 }
667
668 // Otherwise, it's an error.
John McCall4b9c2d22011-11-06 09:01:30 +0000669 S.Diag(opcLoc, diag::err_nosetter_property_assignment)
670 << unsigned(RefExpr->isImplicitProperty())
671 << SetterSelector
John McCall3c3b7f92011-10-25 17:37:35 +0000672 << LHS->getSourceRange() << RHS->getSourceRange();
673 return ExprError();
674 }
675
676 // If there is a setter, we definitely want to use it.
677
John McCall4b9c2d22011-11-06 09:01:30 +0000678 // Verify that we can do a compound assignment.
679 if (opcode != BO_Assign && !findGetter()) {
680 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
John McCall3c3b7f92011-10-25 17:37:35 +0000681 << LHS->getSourceRange() << RHS->getSourceRange();
682 return ExprError();
683 }
684
John McCall4b9c2d22011-11-06 09:01:30 +0000685 ExprResult result =
686 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000687 if (result.isInvalid()) return ExprError();
688
John McCall4b9c2d22011-11-06 09:01:30 +0000689 // Various warnings about property assignments in ARC.
690 if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
691 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
692 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
693 }
694
John McCall3c3b7f92011-10-25 17:37:35 +0000695 return result;
696}
John McCall4b9c2d22011-11-06 09:01:30 +0000697
698/// @property-specific behavior for doing increments and decrements.
699ExprResult
700ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
701 UnaryOperatorKind opcode,
702 Expr *op) {
703 // If there's no setter, we have no choice but to try to assign to
704 // the result of the getter.
705 if (!findSetter()) {
706 ExprResult result;
707 if (tryBuildGetOfReference(op, result)) {
708 if (result.isInvalid()) return ExprError();
709 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
710 }
711
712 // Otherwise, it's an error.
713 S.Diag(opcLoc, diag::err_nosetter_property_incdec)
714 << unsigned(RefExpr->isImplicitProperty())
715 << unsigned(UnaryOperator::isDecrementOp(opcode))
716 << SetterSelector
717 << op->getSourceRange();
718 return ExprError();
719 }
720
721 // If there is a setter, we definitely want to use it.
722
723 // We also need a getter.
724 if (!findGetter()) {
725 assert(RefExpr->isImplicitProperty());
726 S.Diag(opcLoc, diag::err_nogetter_property_incdec)
727 << unsigned(UnaryOperator::isDecrementOp(opcode))
728 << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
729 << op->getSourceRange();
730 return ExprError();
731 }
732
733 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
734}
735
736//===----------------------------------------------------------------------===//
737// General Sema routines.
738//===----------------------------------------------------------------------===//
739
740ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
741 Expr *opaqueRef = E->IgnoreParens();
742 if (ObjCPropertyRefExpr *refExpr
743 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
744 ObjCPropertyOpBuilder builder(*this, refExpr);
745 return builder.buildRValueOperation(E);
746 } else {
747 llvm_unreachable("unknown pseudo-object kind!");
748 }
749}
750
751/// Check an increment or decrement of a pseudo-object expression.
752ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
753 UnaryOperatorKind opcode, Expr *op) {
754 // Do nothing if the operand is dependent.
755 if (op->isTypeDependent())
756 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
757 VK_RValue, OK_Ordinary, opcLoc);
758
759 assert(UnaryOperator::isIncrementDecrementOp(opcode));
760 Expr *opaqueRef = op->IgnoreParens();
761 if (ObjCPropertyRefExpr *refExpr
762 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
763 ObjCPropertyOpBuilder builder(*this, refExpr);
764 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
765 } else {
766 llvm_unreachable("unknown pseudo-object kind!");
767 }
768}
769
770ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
771 BinaryOperatorKind opcode,
772 Expr *LHS, Expr *RHS) {
773 // Do nothing if either argument is dependent.
774 if (LHS->isTypeDependent() || RHS->isTypeDependent())
775 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
776 VK_RValue, OK_Ordinary, opcLoc);
777
778 // Filter out non-overload placeholder types in the RHS.
779 if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
780 if (PTy->getKind() != BuiltinType::Overload) {
781 ExprResult result = CheckPlaceholderExpr(RHS);
782 if (result.isInvalid()) return ExprError();
783 RHS = result.take();
784 }
785 }
786
787 Expr *opaqueRef = LHS->IgnoreParens();
788 if (ObjCPropertyRefExpr *refExpr
789 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
790 ObjCPropertyOpBuilder builder(*this, refExpr);
791 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
792 } else {
793 llvm_unreachable("unknown pseudo-object kind!");
794 }
795}