blob: d5f1523f62a45b29ad38ded7ded5448e8d7e3337 [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-Gay1aa17212011-11-08 01:53:17 +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(),
Douglas Gregor97df54e2012-02-23 22:17:26 +0000225 e->getValueKind(), e->getObjectKind(),
226 e);
John McCall4b9c2d22011-11-06 09:01:30 +0000227
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 McCalldc4df512011-11-07 22:49:50 +0000420 // For implicit properties, just trust the lookup we already did.
421 if (RefExpr->isImplicitProperty()) {
422 Getter = RefExpr->getImplicitPropertyGetter();
423 return (Getter != 0);
424 }
425
426 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
427 Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
John McCall4b9c2d22011-11-06 09:01:30 +0000428 return (Getter != 0);
429}
430
431/// Try to find the most accurate setter declaration for the property
432/// reference.
433///
434/// \return true if a setter was found, in which case Setter
435bool ObjCPropertyOpBuilder::findSetter() {
436 // For implicit properties, just trust the lookup we already did.
437 if (RefExpr->isImplicitProperty()) {
438 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
439 Setter = setter;
440 SetterSelector = setter->getSelector();
441 return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000442 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000443 IdentifierInfo *getterName =
444 RefExpr->getImplicitPropertyGetter()->getSelector()
445 .getIdentifierInfoForSlot(0);
446 SetterSelector =
447 SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
448 S.PP.getSelectorTable(),
449 getterName);
450 return false;
John McCall3c3b7f92011-10-25 17:37:35 +0000451 }
John McCall4b9c2d22011-11-06 09:01:30 +0000452 }
453
454 // For explicit properties, this is more involved.
455 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
456 SetterSelector = prop->getSetterName();
457
458 // Do a normal method lookup first.
459 if (ObjCMethodDecl *setter =
460 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
461 Setter = setter;
462 return true;
463 }
464
465 // That can fail in the somewhat crazy situation that we're
466 // type-checking a message send within the @interface declaration
467 // that declared the @property. But it's not clear that that's
468 // valuable to support.
469
470 return false;
471}
472
473/// Capture the base object of an Objective-C property expression.
474Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
475 assert(InstanceReceiver == 0);
476
477 // If we have a base, capture it in an OVE and rebuild the syntactic
478 // form to use the OVE as its base.
479 if (RefExpr->isObjectReceiver()) {
480 InstanceReceiver = capture(RefExpr->getBase());
481
482 syntacticBase =
483 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
484 }
485
486 return syntacticBase;
487}
488
489/// Load from an Objective-C property reference.
490ExprResult ObjCPropertyOpBuilder::buildGet() {
491 findGetter();
492 assert(Getter);
493
494 QualType receiverType;
John McCall4b9c2d22011-11-06 09:01:30 +0000495 if (RefExpr->isClassReceiver()) {
496 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
497 } else if (RefExpr->isSuperReceiver()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000498 receiverType = RefExpr->getSuperReceiverType();
John McCall3c3b7f92011-10-25 17:37:35 +0000499 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000500 assert(InstanceReceiver);
501 receiverType = InstanceReceiver->getType();
502 }
John McCall3c3b7f92011-10-25 17:37:35 +0000503
John McCall4b9c2d22011-11-06 09:01:30 +0000504 // Build a message-send.
505 ExprResult msg;
506 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
507 assert(InstanceReceiver || RefExpr->isSuperReceiver());
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000508 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
509 GenericLoc, Getter->getSelector(),
510 Getter, MultiExprArg());
John McCall4b9c2d22011-11-06 09:01:30 +0000511 } else {
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000512 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
513 GenericLoc,
514 Getter->getSelector(), Getter,
515 MultiExprArg());
John McCall4b9c2d22011-11-06 09:01:30 +0000516 }
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;
John McCall4b9c2d22011-11-06 09:01:30 +0000530 if (RefExpr->isClassReceiver()) {
531 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
532 } else if (RefExpr->isSuperReceiver()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000533 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()) {
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000564 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
565 GenericLoc, SetterSelector, Setter,
566 MultiExprArg(args, 1));
John McCall4b9c2d22011-11-06 09:01:30 +0000567 } else {
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000568 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
569 GenericLoc,
570 SetterSelector, Setter,
571 MultiExprArg(args, 1));
John McCall4b9c2d22011-11-06 09:01:30 +0000572 }
573
574 if (!msg.isInvalid() && captureSetValueAsResult) {
575 ObjCMessageExpr *msgExpr =
576 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
577 Expr *arg = msgExpr->getArg(0);
578 msgExpr->setArg(0, captureValueAsResult(arg));
579 }
580
581 return msg;
John McCall3c3b7f92011-10-25 17:37:35 +0000582}
583
John McCall4b9c2d22011-11-06 09:01:30 +0000584/// @property-specific behavior for doing lvalue-to-rvalue conversion.
585ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
586 // Explicit properties always have getters, but implicit ones don't.
587 // Check that before proceeding.
588 if (RefExpr->isImplicitProperty() &&
589 !RefExpr->getImplicitPropertyGetter()) {
590 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
591 << RefExpr->getBase()->getType();
John McCall3c3b7f92011-10-25 17:37:35 +0000592 return ExprError();
593 }
594
John McCall4b9c2d22011-11-06 09:01:30 +0000595 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
John McCall3c3b7f92011-10-25 17:37:35 +0000596 if (result.isInvalid()) return ExprError();
597
John McCall4b9c2d22011-11-06 09:01:30 +0000598 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
599 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
600 Getter, RefExpr->getLocation());
601
602 // As a special case, if the method returns 'id', try to get
603 // a better type from the property.
604 if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
605 result.get()->getType()->isObjCIdType()) {
606 QualType propType = RefExpr->getExplicitProperty()->getType();
607 if (const ObjCObjectPointerType *ptr
608 = propType->getAs<ObjCObjectPointerType>()) {
609 if (!ptr->isObjCIdType())
610 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
611 }
612 }
613
John McCall3c3b7f92011-10-25 17:37:35 +0000614 return result;
615}
616
John McCall4b9c2d22011-11-06 09:01:30 +0000617/// Try to build this as a call to a getter that returns a reference.
618///
619/// \return true if it was possible, whether or not it actually
620/// succeeded
621bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
622 ExprResult &result) {
623 if (!S.getLangOptions().CPlusPlus) return false;
624
625 findGetter();
626 assert(Getter && "property has no setter and no getter!");
627
628 // Only do this if the getter returns an l-value reference type.
629 QualType resultType = Getter->getResultType();
630 if (!resultType->isLValueReferenceType()) return false;
631
632 result = buildRValueOperation(op);
633 return true;
634}
635
636/// @property-specific behavior for doing assignments.
637ExprResult
638ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
639 SourceLocation opcLoc,
640 BinaryOperatorKind opcode,
641 Expr *LHS, Expr *RHS) {
John McCall3c3b7f92011-10-25 17:37:35 +0000642 assert(BinaryOperator::isAssignmentOp(opcode));
John McCall3c3b7f92011-10-25 17:37:35 +0000643
644 // If there's no setter, we have no choice but to try to assign to
645 // the result of the getter.
John McCall4b9c2d22011-11-06 09:01:30 +0000646 if (!findSetter()) {
647 ExprResult result;
648 if (tryBuildGetOfReference(LHS, result)) {
649 if (result.isInvalid()) return ExprError();
650 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000651 }
652
653 // Otherwise, it's an error.
John McCall4b9c2d22011-11-06 09:01:30 +0000654 S.Diag(opcLoc, diag::err_nosetter_property_assignment)
655 << unsigned(RefExpr->isImplicitProperty())
656 << SetterSelector
John McCall3c3b7f92011-10-25 17:37:35 +0000657 << LHS->getSourceRange() << RHS->getSourceRange();
658 return ExprError();
659 }
660
661 // If there is a setter, we definitely want to use it.
662
John McCall4b9c2d22011-11-06 09:01:30 +0000663 // Verify that we can do a compound assignment.
664 if (opcode != BO_Assign && !findGetter()) {
665 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
John McCall3c3b7f92011-10-25 17:37:35 +0000666 << LHS->getSourceRange() << RHS->getSourceRange();
667 return ExprError();
668 }
669
John McCall4b9c2d22011-11-06 09:01:30 +0000670 ExprResult result =
671 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000672 if (result.isInvalid()) return ExprError();
673
John McCall4b9c2d22011-11-06 09:01:30 +0000674 // Various warnings about property assignments in ARC.
675 if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
676 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
677 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
678 }
679
John McCall3c3b7f92011-10-25 17:37:35 +0000680 return result;
681}
John McCall4b9c2d22011-11-06 09:01:30 +0000682
683/// @property-specific behavior for doing increments and decrements.
684ExprResult
685ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
686 UnaryOperatorKind opcode,
687 Expr *op) {
688 // If there's no setter, we have no choice but to try to assign to
689 // the result of the getter.
690 if (!findSetter()) {
691 ExprResult result;
692 if (tryBuildGetOfReference(op, result)) {
693 if (result.isInvalid()) return ExprError();
694 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
695 }
696
697 // Otherwise, it's an error.
698 S.Diag(opcLoc, diag::err_nosetter_property_incdec)
699 << unsigned(RefExpr->isImplicitProperty())
700 << unsigned(UnaryOperator::isDecrementOp(opcode))
701 << SetterSelector
702 << op->getSourceRange();
703 return ExprError();
704 }
705
706 // If there is a setter, we definitely want to use it.
707
708 // We also need a getter.
709 if (!findGetter()) {
710 assert(RefExpr->isImplicitProperty());
711 S.Diag(opcLoc, diag::err_nogetter_property_incdec)
712 << unsigned(UnaryOperator::isDecrementOp(opcode))
713 << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
714 << op->getSourceRange();
715 return ExprError();
716 }
717
718 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
719}
720
721//===----------------------------------------------------------------------===//
722// General Sema routines.
723//===----------------------------------------------------------------------===//
724
725ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
726 Expr *opaqueRef = E->IgnoreParens();
727 if (ObjCPropertyRefExpr *refExpr
728 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
729 ObjCPropertyOpBuilder builder(*this, refExpr);
730 return builder.buildRValueOperation(E);
731 } else {
732 llvm_unreachable("unknown pseudo-object kind!");
733 }
734}
735
736/// Check an increment or decrement of a pseudo-object expression.
737ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
738 UnaryOperatorKind opcode, Expr *op) {
739 // Do nothing if the operand is dependent.
740 if (op->isTypeDependent())
741 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
742 VK_RValue, OK_Ordinary, opcLoc);
743
744 assert(UnaryOperator::isIncrementDecrementOp(opcode));
745 Expr *opaqueRef = op->IgnoreParens();
746 if (ObjCPropertyRefExpr *refExpr
747 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
748 ObjCPropertyOpBuilder builder(*this, refExpr);
749 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
750 } else {
751 llvm_unreachable("unknown pseudo-object kind!");
752 }
753}
754
755ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
756 BinaryOperatorKind opcode,
757 Expr *LHS, Expr *RHS) {
758 // Do nothing if either argument is dependent.
759 if (LHS->isTypeDependent() || RHS->isTypeDependent())
760 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
761 VK_RValue, OK_Ordinary, opcLoc);
762
763 // Filter out non-overload placeholder types in the RHS.
John McCall32509f12011-11-15 01:35:18 +0000764 if (RHS->getType()->isNonOverloadPlaceholderType()) {
765 ExprResult result = CheckPlaceholderExpr(RHS);
766 if (result.isInvalid()) return ExprError();
767 RHS = result.take();
John McCall4b9c2d22011-11-06 09:01:30 +0000768 }
769
770 Expr *opaqueRef = LHS->IgnoreParens();
771 if (ObjCPropertyRefExpr *refExpr
772 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
773 ObjCPropertyOpBuilder builder(*this, refExpr);
774 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
775 } else {
776 llvm_unreachable("unknown pseudo-object kind!");
777 }
778}
John McCall01e19be2011-11-30 04:42:31 +0000779
780/// Given a pseudo-object reference, rebuild it without the opaque
781/// values. Basically, undo the behavior of rebuildAndCaptureObject.
782/// This should never operate in-place.
783static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
784 Expr *opaqueRef = E->IgnoreParens();
785 if (ObjCPropertyRefExpr *refExpr
786 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
787 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
788 return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
789 } else {
790 llvm_unreachable("unknown pseudo-object kind!");
791 }
792}
793
794/// Given a pseudo-object expression, recreate what it looks like
795/// syntactically without the attendant OpaqueValueExprs.
796///
797/// This is a hack which should be removed when TreeTransform is
798/// capable of rebuilding a tree without stripping implicit
799/// operations.
800Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
801 Expr *syntax = E->getSyntacticForm();
802 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
803 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
804 return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
805 uop->getValueKind(), uop->getObjectKind(),
806 uop->getOperatorLoc());
807 } else if (CompoundAssignOperator *cop
808 = dyn_cast<CompoundAssignOperator>(syntax)) {
809 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
810 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
811 return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
812 cop->getType(),
813 cop->getValueKind(),
814 cop->getObjectKind(),
815 cop->getComputationLHSType(),
816 cop->getComputationResultType(),
817 cop->getOperatorLoc());
818 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
819 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
820 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
821 return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
822 bop->getType(), bop->getValueKind(),
823 bop->getObjectKind(),
824 bop->getOperatorLoc());
825 } else {
826 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
827 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
828 }
829}