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