blob: b8497e5f0285f52f64942512ec08118fe79676cb [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
Matt Beaumont-Gay90f93d42011-11-07 17:16:31 +0000144 virtual ~PseudoOpBuilder() {}
145
John McCall4b9c2d22011-11-06 09:01:30 +0000146 /// Add a normal semantic expression.
147 void addSemanticExpr(Expr *semantic) {
148 Semantics.push_back(semantic);
149 }
150
151 /// Add the 'result' semantic expression.
152 void addResultSemanticExpr(Expr *resultExpr) {
153 assert(ResultIndex == PseudoObjectExpr::NoResult);
154 ResultIndex = Semantics.size();
155 Semantics.push_back(resultExpr);
156 }
157
158 ExprResult buildRValueOperation(Expr *op);
159 ExprResult buildAssignmentOperation(Scope *Sc,
160 SourceLocation opLoc,
161 BinaryOperatorKind opcode,
162 Expr *LHS, Expr *RHS);
163 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
164 UnaryOperatorKind opcode,
165 Expr *op);
166
167 ExprResult complete(Expr *syntacticForm);
168
169 OpaqueValueExpr *capture(Expr *op);
170 OpaqueValueExpr *captureValueAsResult(Expr *op);
171
172 void setResultToLastSemantic() {
173 assert(ResultIndex == PseudoObjectExpr::NoResult);
174 ResultIndex = Semantics.size() - 1;
175 }
176
177 /// Return true if assignments have a non-void result.
178 virtual bool assignmentsHaveResult() { return true; }
179
180 virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
181 virtual ExprResult buildGet() = 0;
182 virtual ExprResult buildSet(Expr *, SourceLocation,
183 bool captureSetValueAsResult) = 0;
184 };
185
186 /// A PseudoOpBuilder for Objective-C @properties.
187 class ObjCPropertyOpBuilder : public PseudoOpBuilder {
188 ObjCPropertyRefExpr *RefExpr;
189 OpaqueValueExpr *InstanceReceiver;
190 ObjCMethodDecl *Getter;
191
192 ObjCMethodDecl *Setter;
193 Selector SetterSelector;
194
195 public:
196 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
197 PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
198 InstanceReceiver(0), Getter(0), Setter(0) {
199 }
200
201 ExprResult buildRValueOperation(Expr *op);
202 ExprResult buildAssignmentOperation(Scope *Sc,
203 SourceLocation opLoc,
204 BinaryOperatorKind opcode,
205 Expr *LHS, Expr *RHS);
206 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
207 UnaryOperatorKind opcode,
208 Expr *op);
209
210 bool tryBuildGetOfReference(Expr *op, ExprResult &result);
211 bool findSetter();
212 bool findGetter();
213
214 Expr *rebuildAndCaptureObject(Expr *syntacticBase);
215 ExprResult buildGet();
216 ExprResult buildSet(Expr *op, SourceLocation, bool);
217 };
218}
219
220/// Capture the given expression in an OpaqueValueExpr.
221OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
222 // Make a new OVE whose source is the given expression.
223 OpaqueValueExpr *captured =
224 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
225 e->getValueKind());
226 captured->setSourceExpr(e);
227
228 // Make sure we bind that in the semantics.
229 addSemanticExpr(captured);
230 return captured;
231}
232
233/// Capture the given expression as the result of this pseudo-object
234/// operation. This routine is safe against expressions which may
235/// already be captured.
236///
237/// \param Returns the captured expression, which will be the
238/// same as the input if the input was already captured
239OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
240 assert(ResultIndex == PseudoObjectExpr::NoResult);
241
242 // If the expression hasn't already been captured, just capture it
243 // and set the new semantic
244 if (!isa<OpaqueValueExpr>(e)) {
245 OpaqueValueExpr *cap = capture(e);
246 setResultToLastSemantic();
247 return cap;
248 }
249
250 // Otherwise, it must already be one of our semantic expressions;
251 // set ResultIndex to its index.
252 unsigned index = 0;
253 for (;; ++index) {
254 assert(index < Semantics.size() &&
255 "captured expression not found in semantics!");
256 if (e == Semantics[index]) break;
257 }
258 ResultIndex = index;
259 return cast<OpaqueValueExpr>(e);
260}
261
262/// The routine which creates the final PseudoObjectExpr.
263ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
264 return PseudoObjectExpr::Create(S.Context, syntactic,
265 Semantics, ResultIndex);
266}
267
268/// The main skeleton for building an r-value operation.
269ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
270 Expr *syntacticBase = rebuildAndCaptureObject(op);
271
272 ExprResult getExpr = buildGet();
273 if (getExpr.isInvalid()) return ExprError();
274 addResultSemanticExpr(getExpr.take());
275
276 return complete(syntacticBase);
277}
278
279/// The basic skeleton for building a simple or compound
280/// assignment operation.
281ExprResult
282PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
283 BinaryOperatorKind opcode,
284 Expr *LHS, Expr *RHS) {
285 assert(BinaryOperator::isAssignmentOp(opcode));
286
287 Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
288 OpaqueValueExpr *capturedRHS = capture(RHS);
289
290 Expr *syntactic;
291
292 ExprResult result;
293 if (opcode == BO_Assign) {
294 result = capturedRHS;
295 syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
296 opcode, capturedRHS->getType(),
297 capturedRHS->getValueKind(),
298 OK_Ordinary, opcLoc);
299 } else {
300 ExprResult opLHS = buildGet();
301 if (opLHS.isInvalid()) return ExprError();
302
303 // Build an ordinary, non-compound operation.
304 BinaryOperatorKind nonCompound =
305 BinaryOperator::getOpForCompoundAssignment(opcode);
306 result = S.BuildBinOp(Sc, opcLoc, nonCompound,
307 opLHS.take(), capturedRHS);
308 if (result.isInvalid()) return ExprError();
309
310 syntactic =
311 new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
312 result.get()->getType(),
313 result.get()->getValueKind(),
314 OK_Ordinary,
315 opLHS.get()->getType(),
316 result.get()->getType(),
317 opcLoc);
318 }
319
320 // The result of the assignment, if not void, is the value set into
321 // the l-value.
322 result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
323 if (result.isInvalid()) return ExprError();
324 addSemanticExpr(result.take());
325
326 return complete(syntactic);
327}
328
329/// The basic skeleton for building an increment or decrement
330/// operation.
331ExprResult
332PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
333 UnaryOperatorKind opcode,
334 Expr *op) {
335 assert(UnaryOperator::isIncrementDecrementOp(opcode));
336
337 Expr *syntacticOp = rebuildAndCaptureObject(op);
338
339 // Load the value.
340 ExprResult result = buildGet();
341 if (result.isInvalid()) return ExprError();
342
343 QualType resultType = result.get()->getType();
344
345 // That's the postfix result.
346 if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
347 result = capture(result.take());
348 setResultToLastSemantic();
349 }
350
351 // Add or subtract a literal 1.
352 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
353 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
354 GenericLoc);
355
356 if (UnaryOperator::isIncrementOp(opcode)) {
357 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
358 } else {
359 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
360 }
361 if (result.isInvalid()) return ExprError();
362
363 // Store that back into the result. The value stored is the result
364 // of a prefix operation.
365 result = buildSet(result.take(), opcLoc,
366 UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
367 if (result.isInvalid()) return ExprError();
368 addSemanticExpr(result.take());
369
370 UnaryOperator *syntactic =
371 new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
372 VK_LValue, OK_Ordinary, opcLoc);
373 return complete(syntactic);
374}
375
376
377//===----------------------------------------------------------------------===//
378// Objective-C @property and implicit property references
379//===----------------------------------------------------------------------===//
380
381/// Look up a method in the receiver type of an Objective-C property
382/// reference.
John McCall3c3b7f92011-10-25 17:37:35 +0000383static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
384 const ObjCPropertyRefExpr *PRE) {
John McCall3c3b7f92011-10-25 17:37:35 +0000385 if (PRE->isObjectReceiver()) {
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000386 const ObjCObjectPointerType *PT =
387 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
John McCall4b9c2d22011-11-06 09:01:30 +0000388
389 // Special case for 'self' in class method implementations.
390 if (PT->isObjCClassType() &&
391 S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
392 // This cast is safe because isSelfExpr is only true within
393 // methods.
394 ObjCMethodDecl *method =
395 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
396 return S.LookupMethodInObjectType(sel,
397 S.Context.getObjCInterfaceType(method->getClassInterface()),
398 /*instance*/ false);
399 }
400
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000401 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
John McCall3c3b7f92011-10-25 17:37:35 +0000402 }
403
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000404 if (PRE->isSuperReceiver()) {
405 if (const ObjCObjectPointerType *PT =
406 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
407 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
408
409 return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
410 }
411
412 assert(PRE->isClassReceiver() && "Invalid expression");
413 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
414 return S.LookupMethodInObjectType(sel, IT, false);
John McCall3c3b7f92011-10-25 17:37:35 +0000415}
416
John McCall4b9c2d22011-11-06 09:01:30 +0000417bool ObjCPropertyOpBuilder::findGetter() {
418 if (Getter) return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000419
John McCall4b9c2d22011-11-06 09:01:30 +0000420 Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr);
421 return (Getter != 0);
422}
423
424/// Try to find the most accurate setter declaration for the property
425/// reference.
426///
427/// \return true if a setter was found, in which case Setter
428bool ObjCPropertyOpBuilder::findSetter() {
429 // For implicit properties, just trust the lookup we already did.
430 if (RefExpr->isImplicitProperty()) {
431 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
432 Setter = setter;
433 SetterSelector = setter->getSelector();
434 return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000435 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000436 IdentifierInfo *getterName =
437 RefExpr->getImplicitPropertyGetter()->getSelector()
438 .getIdentifierInfoForSlot(0);
439 SetterSelector =
440 SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
441 S.PP.getSelectorTable(),
442 getterName);
443 return false;
John McCall3c3b7f92011-10-25 17:37:35 +0000444 }
John McCall4b9c2d22011-11-06 09:01:30 +0000445 }
446
447 // For explicit properties, this is more involved.
448 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
449 SetterSelector = prop->getSetterName();
450
451 // Do a normal method lookup first.
452 if (ObjCMethodDecl *setter =
453 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
454 Setter = setter;
455 return true;
456 }
457
458 // That can fail in the somewhat crazy situation that we're
459 // type-checking a message send within the @interface declaration
460 // that declared the @property. But it's not clear that that's
461 // valuable to support.
462
463 return false;
464}
465
466/// Capture the base object of an Objective-C property expression.
467Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
468 assert(InstanceReceiver == 0);
469
470 // If we have a base, capture it in an OVE and rebuild the syntactic
471 // form to use the OVE as its base.
472 if (RefExpr->isObjectReceiver()) {
473 InstanceReceiver = capture(RefExpr->getBase());
474
475 syntacticBase =
476 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
477 }
478
479 return syntacticBase;
480}
481
482/// Load from an Objective-C property reference.
483ExprResult ObjCPropertyOpBuilder::buildGet() {
484 findGetter();
485 assert(Getter);
486
487 QualType receiverType;
488 SourceLocation superLoc;
489 if (RefExpr->isClassReceiver()) {
490 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
491 } else if (RefExpr->isSuperReceiver()) {
492 superLoc = RefExpr->getReceiverLocation();
493 receiverType = RefExpr->getSuperReceiverType();
John McCall3c3b7f92011-10-25 17:37:35 +0000494 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000495 assert(InstanceReceiver);
496 receiverType = InstanceReceiver->getType();
497 }
John McCall3c3b7f92011-10-25 17:37:35 +0000498
John McCall4b9c2d22011-11-06 09:01:30 +0000499 // Build a message-send.
500 ExprResult msg;
501 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
502 assert(InstanceReceiver || RefExpr->isSuperReceiver());
503 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
504 Getter->getSelector(), Getter,
505 GenericLoc, GenericLoc, GenericLoc,
506 MultiExprArg());
507 } else {
508 TypeSourceInfo *receiverTypeInfo = 0;
509 if (!RefExpr->isSuperReceiver())
510 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
John McCall3c3b7f92011-10-25 17:37:35 +0000511
John McCall4b9c2d22011-11-06 09:01:30 +0000512 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
513 Getter->getSelector(), Getter,
514 GenericLoc, GenericLoc, GenericLoc,
515 MultiExprArg());
516 }
517 return msg;
518}
John McCall3c3b7f92011-10-25 17:37:35 +0000519
John McCall4b9c2d22011-11-06 09:01:30 +0000520/// Store to an Objective-C property reference.
521///
522/// \param bindSetValueAsResult - If true, capture the actual
523/// value being set as the value of the property operation.
524ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
525 bool captureSetValueAsResult) {
526 bool hasSetter = findSetter();
527 assert(hasSetter); (void) hasSetter;
528
529 QualType receiverType;
530 SourceLocation superLoc;
531 if (RefExpr->isClassReceiver()) {
532 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
533 } else if (RefExpr->isSuperReceiver()) {
534 superLoc = RefExpr->getReceiverLocation();
535 receiverType = RefExpr->getSuperReceiverType();
536 } else {
537 assert(InstanceReceiver);
538 receiverType = InstanceReceiver->getType();
539 }
540
541 // Use assignment constraints when possible; they give us better
542 // diagnostics. "When possible" basically means anything except a
543 // C++ class type.
544 if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {
545 QualType paramType = (*Setter->param_begin())->getType();
546 if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {
547 ExprResult opResult = op;
548 Sema::AssignConvertType assignResult
549 = S.CheckSingleAssignmentConstraints(paramType, opResult);
550 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
551 op->getType(), opResult.get(),
552 Sema::AA_Assigning))
553 return ExprError();
554
555 op = opResult.take();
556 assert(op && "successful assignment left argument invalid?");
John McCall3c3b7f92011-10-25 17:37:35 +0000557 }
558 }
559
John McCall4b9c2d22011-11-06 09:01:30 +0000560 // Arguments.
561 Expr *args[] = { op };
John McCall3c3b7f92011-10-25 17:37:35 +0000562
John McCall4b9c2d22011-11-06 09:01:30 +0000563 // Build a message-send.
564 ExprResult msg;
565 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
566 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
567 SetterSelector, Setter,
568 GenericLoc, GenericLoc, GenericLoc,
569 MultiExprArg(args, 1));
570 } else {
571 TypeSourceInfo *receiverTypeInfo = 0;
572 if (!RefExpr->isSuperReceiver())
573 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
574
575 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
576 SetterSelector, Setter,
577 GenericLoc, GenericLoc, GenericLoc,
578 MultiExprArg(args, 1));
579 }
580
581 if (!msg.isInvalid() && captureSetValueAsResult) {
582 ObjCMessageExpr *msgExpr =
583 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
584 Expr *arg = msgExpr->getArg(0);
585 msgExpr->setArg(0, captureValueAsResult(arg));
586 }
587
588 return msg;
John McCall3c3b7f92011-10-25 17:37:35 +0000589}
590
John McCall4b9c2d22011-11-06 09:01:30 +0000591/// @property-specific behavior for doing lvalue-to-rvalue conversion.
592ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
593 // Explicit properties always have getters, but implicit ones don't.
594 // Check that before proceeding.
595 if (RefExpr->isImplicitProperty() &&
596 !RefExpr->getImplicitPropertyGetter()) {
597 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
598 << RefExpr->getBase()->getType();
John McCall3c3b7f92011-10-25 17:37:35 +0000599 return ExprError();
600 }
601
John McCall4b9c2d22011-11-06 09:01:30 +0000602 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
John McCall3c3b7f92011-10-25 17:37:35 +0000603 if (result.isInvalid()) return ExprError();
604
John McCall4b9c2d22011-11-06 09:01:30 +0000605 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
606 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
607 Getter, RefExpr->getLocation());
608
609 // As a special case, if the method returns 'id', try to get
610 // a better type from the property.
611 if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
612 result.get()->getType()->isObjCIdType()) {
613 QualType propType = RefExpr->getExplicitProperty()->getType();
614 if (const ObjCObjectPointerType *ptr
615 = propType->getAs<ObjCObjectPointerType>()) {
616 if (!ptr->isObjCIdType())
617 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
618 }
619 }
620
John McCall3c3b7f92011-10-25 17:37:35 +0000621 return result;
622}
623
John McCall4b9c2d22011-11-06 09:01:30 +0000624/// Try to build this as a call to a getter that returns a reference.
625///
626/// \return true if it was possible, whether or not it actually
627/// succeeded
628bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
629 ExprResult &result) {
630 if (!S.getLangOptions().CPlusPlus) return false;
631
632 findGetter();
633 assert(Getter && "property has no setter and no getter!");
634
635 // Only do this if the getter returns an l-value reference type.
636 QualType resultType = Getter->getResultType();
637 if (!resultType->isLValueReferenceType()) return false;
638
639 result = buildRValueOperation(op);
640 return true;
641}
642
643/// @property-specific behavior for doing assignments.
644ExprResult
645ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
646 SourceLocation opcLoc,
647 BinaryOperatorKind opcode,
648 Expr *LHS, Expr *RHS) {
John McCall3c3b7f92011-10-25 17:37:35 +0000649 assert(BinaryOperator::isAssignmentOp(opcode));
John McCall3c3b7f92011-10-25 17:37:35 +0000650
651 // If there's no setter, we have no choice but to try to assign to
652 // the result of the getter.
John McCall4b9c2d22011-11-06 09:01:30 +0000653 if (!findSetter()) {
654 ExprResult result;
655 if (tryBuildGetOfReference(LHS, result)) {
656 if (result.isInvalid()) return ExprError();
657 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000658 }
659
660 // Otherwise, it's an error.
John McCall4b9c2d22011-11-06 09:01:30 +0000661 S.Diag(opcLoc, diag::err_nosetter_property_assignment)
662 << unsigned(RefExpr->isImplicitProperty())
663 << SetterSelector
John McCall3c3b7f92011-10-25 17:37:35 +0000664 << LHS->getSourceRange() << RHS->getSourceRange();
665 return ExprError();
666 }
667
668 // If there is a setter, we definitely want to use it.
669
John McCall4b9c2d22011-11-06 09:01:30 +0000670 // Verify that we can do a compound assignment.
671 if (opcode != BO_Assign && !findGetter()) {
672 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
John McCall3c3b7f92011-10-25 17:37:35 +0000673 << LHS->getSourceRange() << RHS->getSourceRange();
674 return ExprError();
675 }
676
John McCall4b9c2d22011-11-06 09:01:30 +0000677 ExprResult result =
678 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000679 if (result.isInvalid()) return ExprError();
680
John McCall4b9c2d22011-11-06 09:01:30 +0000681 // Various warnings about property assignments in ARC.
682 if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
683 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
684 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
685 }
686
John McCall3c3b7f92011-10-25 17:37:35 +0000687 return result;
688}
John McCall4b9c2d22011-11-06 09:01:30 +0000689
690/// @property-specific behavior for doing increments and decrements.
691ExprResult
692ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
693 UnaryOperatorKind opcode,
694 Expr *op) {
695 // If there's no setter, we have no choice but to try to assign to
696 // the result of the getter.
697 if (!findSetter()) {
698 ExprResult result;
699 if (tryBuildGetOfReference(op, result)) {
700 if (result.isInvalid()) return ExprError();
701 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
702 }
703
704 // Otherwise, it's an error.
705 S.Diag(opcLoc, diag::err_nosetter_property_incdec)
706 << unsigned(RefExpr->isImplicitProperty())
707 << unsigned(UnaryOperator::isDecrementOp(opcode))
708 << SetterSelector
709 << op->getSourceRange();
710 return ExprError();
711 }
712
713 // If there is a setter, we definitely want to use it.
714
715 // We also need a getter.
716 if (!findGetter()) {
717 assert(RefExpr->isImplicitProperty());
718 S.Diag(opcLoc, diag::err_nogetter_property_incdec)
719 << unsigned(UnaryOperator::isDecrementOp(opcode))
720 << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
721 << op->getSourceRange();
722 return ExprError();
723 }
724
725 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
726}
727
728//===----------------------------------------------------------------------===//
729// General Sema routines.
730//===----------------------------------------------------------------------===//
731
732ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
733 Expr *opaqueRef = E->IgnoreParens();
734 if (ObjCPropertyRefExpr *refExpr
735 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
736 ObjCPropertyOpBuilder builder(*this, refExpr);
737 return builder.buildRValueOperation(E);
738 } else {
739 llvm_unreachable("unknown pseudo-object kind!");
740 }
741}
742
743/// Check an increment or decrement of a pseudo-object expression.
744ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
745 UnaryOperatorKind opcode, Expr *op) {
746 // Do nothing if the operand is dependent.
747 if (op->isTypeDependent())
748 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
749 VK_RValue, OK_Ordinary, opcLoc);
750
751 assert(UnaryOperator::isIncrementDecrementOp(opcode));
752 Expr *opaqueRef = op->IgnoreParens();
753 if (ObjCPropertyRefExpr *refExpr
754 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
755 ObjCPropertyOpBuilder builder(*this, refExpr);
756 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
757 } else {
758 llvm_unreachable("unknown pseudo-object kind!");
759 }
760}
761
762ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
763 BinaryOperatorKind opcode,
764 Expr *LHS, Expr *RHS) {
765 // Do nothing if either argument is dependent.
766 if (LHS->isTypeDependent() || RHS->isTypeDependent())
767 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
768 VK_RValue, OK_Ordinary, opcLoc);
769
770 // Filter out non-overload placeholder types in the RHS.
771 if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
772 if (PTy->getKind() != BuiltinType::Overload) {
773 ExprResult result = CheckPlaceholderExpr(RHS);
774 if (result.isInvalid()) return ExprError();
775 RHS = result.take();
776 }
777 }
778
779 Expr *opaqueRef = LHS->IgnoreParens();
780 if (ObjCPropertyRefExpr *refExpr
781 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
782 ObjCPropertyOpBuilder builder(*this, refExpr);
783 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
784 } else {
785 llvm_unreachable("unknown pseudo-object kind!");
786 }
787}