blob: b3ed145b155c14aa24f822f122ac629775158474 [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 McCall4b9c2d22011-11-06 09:01:30 +0000421 Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr);
422 return (Getter != 0);
423}
424
425/// Try to find the most accurate setter declaration for the property
426/// reference.
427///
428/// \return true if a setter was found, in which case Setter
429bool ObjCPropertyOpBuilder::findSetter() {
430 // For implicit properties, just trust the lookup we already did.
431 if (RefExpr->isImplicitProperty()) {
432 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
433 Setter = setter;
434 SetterSelector = setter->getSelector();
435 return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000436 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000437 IdentifierInfo *getterName =
438 RefExpr->getImplicitPropertyGetter()->getSelector()
439 .getIdentifierInfoForSlot(0);
440 SetterSelector =
441 SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
442 S.PP.getSelectorTable(),
443 getterName);
444 return false;
John McCall3c3b7f92011-10-25 17:37:35 +0000445 }
John McCall4b9c2d22011-11-06 09:01:30 +0000446 }
447
448 // For explicit properties, this is more involved.
449 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
450 SetterSelector = prop->getSetterName();
451
452 // Do a normal method lookup first.
453 if (ObjCMethodDecl *setter =
454 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
455 Setter = setter;
456 return true;
457 }
458
459 // That can fail in the somewhat crazy situation that we're
460 // type-checking a message send within the @interface declaration
461 // that declared the @property. But it's not clear that that's
462 // valuable to support.
463
464 return false;
465}
466
467/// Capture the base object of an Objective-C property expression.
468Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
469 assert(InstanceReceiver == 0);
470
471 // If we have a base, capture it in an OVE and rebuild the syntactic
472 // form to use the OVE as its base.
473 if (RefExpr->isObjectReceiver()) {
474 InstanceReceiver = capture(RefExpr->getBase());
475
476 syntacticBase =
477 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
478 }
479
480 return syntacticBase;
481}
482
483/// Load from an Objective-C property reference.
484ExprResult ObjCPropertyOpBuilder::buildGet() {
485 findGetter();
486 assert(Getter);
487
488 QualType receiverType;
489 SourceLocation superLoc;
490 if (RefExpr->isClassReceiver()) {
491 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
492 } else if (RefExpr->isSuperReceiver()) {
493 superLoc = RefExpr->getReceiverLocation();
494 receiverType = RefExpr->getSuperReceiverType();
John McCall3c3b7f92011-10-25 17:37:35 +0000495 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000496 assert(InstanceReceiver);
497 receiverType = InstanceReceiver->getType();
498 }
John McCall3c3b7f92011-10-25 17:37:35 +0000499
John McCall4b9c2d22011-11-06 09:01:30 +0000500 // Build a message-send.
501 ExprResult msg;
502 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
503 assert(InstanceReceiver || RefExpr->isSuperReceiver());
504 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
505 Getter->getSelector(), Getter,
506 GenericLoc, GenericLoc, GenericLoc,
507 MultiExprArg());
508 } else {
509 TypeSourceInfo *receiverTypeInfo = 0;
510 if (!RefExpr->isSuperReceiver())
511 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
John McCall3c3b7f92011-10-25 17:37:35 +0000512
John McCall4b9c2d22011-11-06 09:01:30 +0000513 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
514 Getter->getSelector(), Getter,
515 GenericLoc, GenericLoc, GenericLoc,
516 MultiExprArg());
517 }
518 return msg;
519}
John McCall3c3b7f92011-10-25 17:37:35 +0000520
John McCall4b9c2d22011-11-06 09:01:30 +0000521/// Store to an Objective-C property reference.
522///
523/// \param bindSetValueAsResult - If true, capture the actual
524/// value being set as the value of the property operation.
525ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
526 bool captureSetValueAsResult) {
527 bool hasSetter = findSetter();
528 assert(hasSetter); (void) hasSetter;
529
530 QualType receiverType;
531 SourceLocation superLoc;
532 if (RefExpr->isClassReceiver()) {
533 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
534 } else if (RefExpr->isSuperReceiver()) {
535 superLoc = RefExpr->getReceiverLocation();
536 receiverType = RefExpr->getSuperReceiverType();
537 } else {
538 assert(InstanceReceiver);
539 receiverType = InstanceReceiver->getType();
540 }
541
542 // Use assignment constraints when possible; they give us better
543 // diagnostics. "When possible" basically means anything except a
544 // C++ class type.
545 if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {
546 QualType paramType = (*Setter->param_begin())->getType();
547 if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {
548 ExprResult opResult = op;
549 Sema::AssignConvertType assignResult
550 = S.CheckSingleAssignmentConstraints(paramType, opResult);
551 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
552 op->getType(), opResult.get(),
553 Sema::AA_Assigning))
554 return ExprError();
555
556 op = opResult.take();
557 assert(op && "successful assignment left argument invalid?");
John McCall3c3b7f92011-10-25 17:37:35 +0000558 }
559 }
560
John McCall4b9c2d22011-11-06 09:01:30 +0000561 // Arguments.
562 Expr *args[] = { op };
John McCall3c3b7f92011-10-25 17:37:35 +0000563
John McCall4b9c2d22011-11-06 09:01:30 +0000564 // Build a message-send.
565 ExprResult msg;
566 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
567 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
568 SetterSelector, Setter,
569 GenericLoc, GenericLoc, GenericLoc,
570 MultiExprArg(args, 1));
571 } else {
572 TypeSourceInfo *receiverTypeInfo = 0;
573 if (!RefExpr->isSuperReceiver())
574 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
575
576 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
577 SetterSelector, Setter,
578 GenericLoc, GenericLoc, GenericLoc,
579 MultiExprArg(args, 1));
580 }
581
582 if (!msg.isInvalid() && captureSetValueAsResult) {
583 ObjCMessageExpr *msgExpr =
584 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
585 Expr *arg = msgExpr->getArg(0);
586 msgExpr->setArg(0, captureValueAsResult(arg));
587 }
588
589 return msg;
John McCall3c3b7f92011-10-25 17:37:35 +0000590}
591
John McCall4b9c2d22011-11-06 09:01:30 +0000592/// @property-specific behavior for doing lvalue-to-rvalue conversion.
593ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
594 // Explicit properties always have getters, but implicit ones don't.
595 // Check that before proceeding.
596 if (RefExpr->isImplicitProperty() &&
597 !RefExpr->getImplicitPropertyGetter()) {
598 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
599 << RefExpr->getBase()->getType();
John McCall3c3b7f92011-10-25 17:37:35 +0000600 return ExprError();
601 }
602
John McCall4b9c2d22011-11-06 09:01:30 +0000603 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
John McCall3c3b7f92011-10-25 17:37:35 +0000604 if (result.isInvalid()) return ExprError();
605
John McCall4b9c2d22011-11-06 09:01:30 +0000606 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
607 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
608 Getter, RefExpr->getLocation());
609
610 // As a special case, if the method returns 'id', try to get
611 // a better type from the property.
612 if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
613 result.get()->getType()->isObjCIdType()) {
614 QualType propType = RefExpr->getExplicitProperty()->getType();
615 if (const ObjCObjectPointerType *ptr
616 = propType->getAs<ObjCObjectPointerType>()) {
617 if (!ptr->isObjCIdType())
618 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
619 }
620 }
621
John McCall3c3b7f92011-10-25 17:37:35 +0000622 return result;
623}
624
John McCall4b9c2d22011-11-06 09:01:30 +0000625/// Try to build this as a call to a getter that returns a reference.
626///
627/// \return true if it was possible, whether or not it actually
628/// succeeded
629bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
630 ExprResult &result) {
631 if (!S.getLangOptions().CPlusPlus) return false;
632
633 findGetter();
634 assert(Getter && "property has no setter and no getter!");
635
636 // Only do this if the getter returns an l-value reference type.
637 QualType resultType = Getter->getResultType();
638 if (!resultType->isLValueReferenceType()) return false;
639
640 result = buildRValueOperation(op);
641 return true;
642}
643
644/// @property-specific behavior for doing assignments.
645ExprResult
646ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
647 SourceLocation opcLoc,
648 BinaryOperatorKind opcode,
649 Expr *LHS, Expr *RHS) {
John McCall3c3b7f92011-10-25 17:37:35 +0000650 assert(BinaryOperator::isAssignmentOp(opcode));
John McCall3c3b7f92011-10-25 17:37:35 +0000651
652 // If there's no setter, we have no choice but to try to assign to
653 // the result of the getter.
John McCall4b9c2d22011-11-06 09:01:30 +0000654 if (!findSetter()) {
655 ExprResult result;
656 if (tryBuildGetOfReference(LHS, result)) {
657 if (result.isInvalid()) return ExprError();
658 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000659 }
660
661 // Otherwise, it's an error.
John McCall4b9c2d22011-11-06 09:01:30 +0000662 S.Diag(opcLoc, diag::err_nosetter_property_assignment)
663 << unsigned(RefExpr->isImplicitProperty())
664 << SetterSelector
John McCall3c3b7f92011-10-25 17:37:35 +0000665 << LHS->getSourceRange() << RHS->getSourceRange();
666 return ExprError();
667 }
668
669 // If there is a setter, we definitely want to use it.
670
John McCall4b9c2d22011-11-06 09:01:30 +0000671 // Verify that we can do a compound assignment.
672 if (opcode != BO_Assign && !findGetter()) {
673 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
John McCall3c3b7f92011-10-25 17:37:35 +0000674 << LHS->getSourceRange() << RHS->getSourceRange();
675 return ExprError();
676 }
677
John McCall4b9c2d22011-11-06 09:01:30 +0000678 ExprResult result =
679 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000680 if (result.isInvalid()) return ExprError();
681
John McCall4b9c2d22011-11-06 09:01:30 +0000682 // Various warnings about property assignments in ARC.
683 if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
684 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
685 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
686 }
687
John McCall3c3b7f92011-10-25 17:37:35 +0000688 return result;
689}
John McCall4b9c2d22011-11-06 09:01:30 +0000690
691/// @property-specific behavior for doing increments and decrements.
692ExprResult
693ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
694 UnaryOperatorKind opcode,
695 Expr *op) {
696 // If there's no setter, we have no choice but to try to assign to
697 // the result of the getter.
698 if (!findSetter()) {
699 ExprResult result;
700 if (tryBuildGetOfReference(op, result)) {
701 if (result.isInvalid()) return ExprError();
702 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
703 }
704
705 // Otherwise, it's an error.
706 S.Diag(opcLoc, diag::err_nosetter_property_incdec)
707 << unsigned(RefExpr->isImplicitProperty())
708 << unsigned(UnaryOperator::isDecrementOp(opcode))
709 << SetterSelector
710 << op->getSourceRange();
711 return ExprError();
712 }
713
714 // If there is a setter, we definitely want to use it.
715
716 // We also need a getter.
717 if (!findGetter()) {
718 assert(RefExpr->isImplicitProperty());
719 S.Diag(opcLoc, diag::err_nogetter_property_incdec)
720 << unsigned(UnaryOperator::isDecrementOp(opcode))
721 << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
722 << op->getSourceRange();
723 return ExprError();
724 }
725
726 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
727}
728
729//===----------------------------------------------------------------------===//
730// General Sema routines.
731//===----------------------------------------------------------------------===//
732
733ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
734 Expr *opaqueRef = E->IgnoreParens();
735 if (ObjCPropertyRefExpr *refExpr
736 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
737 ObjCPropertyOpBuilder builder(*this, refExpr);
738 return builder.buildRValueOperation(E);
739 } else {
740 llvm_unreachable("unknown pseudo-object kind!");
741 }
742}
743
744/// Check an increment or decrement of a pseudo-object expression.
745ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
746 UnaryOperatorKind opcode, Expr *op) {
747 // Do nothing if the operand is dependent.
748 if (op->isTypeDependent())
749 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
750 VK_RValue, OK_Ordinary, opcLoc);
751
752 assert(UnaryOperator::isIncrementDecrementOp(opcode));
753 Expr *opaqueRef = op->IgnoreParens();
754 if (ObjCPropertyRefExpr *refExpr
755 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
756 ObjCPropertyOpBuilder builder(*this, refExpr);
757 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
758 } else {
759 llvm_unreachable("unknown pseudo-object kind!");
760 }
761}
762
763ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
764 BinaryOperatorKind opcode,
765 Expr *LHS, Expr *RHS) {
766 // Do nothing if either argument is dependent.
767 if (LHS->isTypeDependent() || RHS->isTypeDependent())
768 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
769 VK_RValue, OK_Ordinary, opcLoc);
770
771 // Filter out non-overload placeholder types in the RHS.
772 if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
773 if (PTy->getKind() != BuiltinType::Overload) {
774 ExprResult result = CheckPlaceholderExpr(RHS);
775 if (result.isInvalid()) return ExprError();
776 RHS = result.take();
777 }
778 }
779
780 Expr *opaqueRef = LHS->IgnoreParens();
781 if (ObjCPropertyRefExpr *refExpr
782 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
783 ObjCPropertyOpBuilder builder(*this, refExpr);
784 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
785 } else {
786 llvm_unreachable("unknown pseudo-object kind!");
787 }
788}