blob: 67bf742384482f36966199e8abdce079189266cd [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"
Jordan Rose58b6bdc2012-09-28 22:21:30 +000034#include "clang/Sema/ScopeInfo.h"
John McCall3c3b7f92011-10-25 17:37:35 +000035#include "clang/Sema/Initialization.h"
36#include "clang/AST/ExprObjC.h"
37#include "clang/Lex/Preprocessor.h"
Fariborz Jahanianb5b155c2012-05-24 22:48:38 +000038#include "llvm/ADT/SmallString.h"
John McCall3c3b7f92011-10-25 17:37:35 +000039
40using namespace clang;
41using namespace sema;
42
John McCall4b9c2d22011-11-06 09:01:30 +000043namespace {
44 // Basically just a very focused copy of TreeTransform.
45 template <class T> struct Rebuilder {
46 Sema &S;
47 Rebuilder(Sema &S) : S(S) {}
48
49 T &getDerived() { return static_cast<T&>(*this); }
50
51 Expr *rebuild(Expr *e) {
52 // Fast path: nothing to look through.
53 if (typename T::specific_type *specific
54 = dyn_cast<typename T::specific_type>(e))
55 return getDerived().rebuildSpecific(specific);
56
57 // Otherwise, we should look through and rebuild anything that
58 // IgnoreParens would.
59
60 if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
61 e = rebuild(parens->getSubExpr());
62 return new (S.Context) ParenExpr(parens->getLParen(),
63 parens->getRParen(),
64 e);
65 }
66
67 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
68 assert(uop->getOpcode() == UO_Extension);
69 e = rebuild(uop->getSubExpr());
70 return new (S.Context) UnaryOperator(e, uop->getOpcode(),
71 uop->getType(),
72 uop->getValueKind(),
73 uop->getObjectKind(),
74 uop->getOperatorLoc());
75 }
76
77 if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
78 assert(!gse->isResultDependent());
79 unsigned resultIndex = gse->getResultIndex();
80 unsigned numAssocs = gse->getNumAssocs();
81
82 SmallVector<Expr*, 8> assocs(numAssocs);
83 SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
84
85 for (unsigned i = 0; i != numAssocs; ++i) {
86 Expr *assoc = gse->getAssocExpr(i);
87 if (i == resultIndex) assoc = rebuild(assoc);
88 assocs[i] = assoc;
89 assocTypes[i] = gse->getAssocTypeSourceInfo(i);
90 }
91
92 return new (S.Context) GenericSelectionExpr(S.Context,
93 gse->getGenericLoc(),
94 gse->getControllingExpr(),
Benjamin Kramer3b6bef92012-08-24 11:54:20 +000095 assocTypes,
96 assocs,
John McCall4b9c2d22011-11-06 09:01:30 +000097 gse->getDefaultLoc(),
98 gse->getRParenLoc(),
99 gse->containsUnexpandedParameterPack(),
100 resultIndex);
101 }
102
103 llvm_unreachable("bad expression to rebuild!");
104 }
105 };
106
107 struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
108 Expr *NewBase;
109 ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
Benjamin Krameracf9e822011-11-06 09:50:13 +0000110 : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
John McCall4b9c2d22011-11-06 09:01:30 +0000111
112 typedef ObjCPropertyRefExpr specific_type;
113 Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
114 // Fortunately, the constraint that we're rebuilding something
115 // with a base limits the number of cases here.
Eli Friedmana70779f2012-11-29 03:13:49 +0000116 assert(refExpr->isObjectReceiver());
John McCall4b9c2d22011-11-06 09:01:30 +0000117
118 if (refExpr->isExplicitProperty()) {
119 return new (S.Context)
120 ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
121 refExpr->getType(), refExpr->getValueKind(),
122 refExpr->getObjectKind(), refExpr->getLocation(),
123 NewBase);
124 }
125 return new (S.Context)
126 ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
127 refExpr->getImplicitPropertySetter(),
128 refExpr->getType(), refExpr->getValueKind(),
129 refExpr->getObjectKind(),refExpr->getLocation(),
130 NewBase);
131 }
132 };
133
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000134 struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
135 Expr *NewBase;
136 Expr *NewKeyExpr;
137 ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
138 : Rebuilder<ObjCSubscriptRefRebuilder>(S),
139 NewBase(newBase), NewKeyExpr(newKeyExpr) {}
140
141 typedef ObjCSubscriptRefExpr specific_type;
142 Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
143 assert(refExpr->getBaseExpr());
144 assert(refExpr->getKeyExpr());
145
146 return new (S.Context)
147 ObjCSubscriptRefExpr(NewBase,
148 NewKeyExpr,
149 refExpr->getType(), refExpr->getValueKind(),
150 refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
151 refExpr->setAtIndexMethodDecl(),
152 refExpr->getRBracket());
153 }
154 };
155
John McCall4b9c2d22011-11-06 09:01:30 +0000156 class PseudoOpBuilder {
157 public:
158 Sema &S;
159 unsigned ResultIndex;
160 SourceLocation GenericLoc;
161 SmallVector<Expr *, 4> Semantics;
162
163 PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
164 : S(S), ResultIndex(PseudoObjectExpr::NoResult),
165 GenericLoc(genericLoc) {}
166
Matt Beaumont-Gay1aa17212011-11-08 01:53:17 +0000167 virtual ~PseudoOpBuilder() {}
168
John McCall4b9c2d22011-11-06 09:01:30 +0000169 /// Add a normal semantic expression.
170 void addSemanticExpr(Expr *semantic) {
171 Semantics.push_back(semantic);
172 }
173
174 /// Add the 'result' semantic expression.
175 void addResultSemanticExpr(Expr *resultExpr) {
176 assert(ResultIndex == PseudoObjectExpr::NoResult);
177 ResultIndex = Semantics.size();
178 Semantics.push_back(resultExpr);
179 }
180
181 ExprResult buildRValueOperation(Expr *op);
182 ExprResult buildAssignmentOperation(Scope *Sc,
183 SourceLocation opLoc,
184 BinaryOperatorKind opcode,
185 Expr *LHS, Expr *RHS);
186 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
187 UnaryOperatorKind opcode,
188 Expr *op);
189
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000190 virtual ExprResult complete(Expr *syntacticForm);
John McCall4b9c2d22011-11-06 09:01:30 +0000191
192 OpaqueValueExpr *capture(Expr *op);
193 OpaqueValueExpr *captureValueAsResult(Expr *op);
194
195 void setResultToLastSemantic() {
196 assert(ResultIndex == PseudoObjectExpr::NoResult);
197 ResultIndex = Semantics.size() - 1;
198 }
199
200 /// Return true if assignments have a non-void result.
Eli Friedman25f071e2012-11-13 23:16:33 +0000201 bool CanCaptureValueOfType(QualType ty) {
202 assert(!ty->isIncompleteType());
203 assert(!ty->isDependentType());
204
205 if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())
206 return ClassDecl->isTriviallyCopyable();
207 return true;
208 }
John McCall4b9c2d22011-11-06 09:01:30 +0000209
210 virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
211 virtual ExprResult buildGet() = 0;
212 virtual ExprResult buildSet(Expr *, SourceLocation,
213 bool captureSetValueAsResult) = 0;
214 };
215
Dmitri Gribenkoe23fb902012-09-12 17:01:48 +0000216 /// A PseudoOpBuilder for Objective-C \@properties.
John McCall4b9c2d22011-11-06 09:01:30 +0000217 class ObjCPropertyOpBuilder : public PseudoOpBuilder {
218 ObjCPropertyRefExpr *RefExpr;
Argyrios Kyrtzidisb085d892012-03-30 00:19:18 +0000219 ObjCPropertyRefExpr *SyntacticRefExpr;
John McCall4b9c2d22011-11-06 09:01:30 +0000220 OpaqueValueExpr *InstanceReceiver;
221 ObjCMethodDecl *Getter;
222
223 ObjCMethodDecl *Setter;
224 Selector SetterSelector;
Fariborz Jahaniana2c91e72012-04-18 19:13:23 +0000225 Selector GetterSelector;
John McCall4b9c2d22011-11-06 09:01:30 +0000226
227 public:
228 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
229 PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
Argyrios Kyrtzidisb085d892012-03-30 00:19:18 +0000230 SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
John McCall4b9c2d22011-11-06 09:01:30 +0000231 }
232
233 ExprResult buildRValueOperation(Expr *op);
234 ExprResult buildAssignmentOperation(Scope *Sc,
235 SourceLocation opLoc,
236 BinaryOperatorKind opcode,
237 Expr *LHS, Expr *RHS);
238 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
239 UnaryOperatorKind opcode,
240 Expr *op);
241
242 bool tryBuildGetOfReference(Expr *op, ExprResult &result);
Fariborz Jahanianb5b155c2012-05-24 22:48:38 +0000243 bool findSetter(bool warn=true);
John McCall4b9c2d22011-11-06 09:01:30 +0000244 bool findGetter();
245
246 Expr *rebuildAndCaptureObject(Expr *syntacticBase);
247 ExprResult buildGet();
248 ExprResult buildSet(Expr *op, SourceLocation, bool);
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000249 ExprResult complete(Expr *SyntacticForm);
250
251 bool isWeakProperty() const;
John McCall4b9c2d22011-11-06 09:01:30 +0000252 };
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000253
254 /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
255 class ObjCSubscriptOpBuilder : public PseudoOpBuilder {
256 ObjCSubscriptRefExpr *RefExpr;
257 OpaqueValueExpr *InstanceBase;
258 OpaqueValueExpr *InstanceKey;
259 ObjCMethodDecl *AtIndexGetter;
260 Selector AtIndexGetterSelector;
261
262 ObjCMethodDecl *AtIndexSetter;
263 Selector AtIndexSetterSelector;
264
265 public:
266 ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
267 PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
268 RefExpr(refExpr),
269 InstanceBase(0), InstanceKey(0),
270 AtIndexGetter(0), AtIndexSetter(0) { }
271
272 ExprResult buildRValueOperation(Expr *op);
273 ExprResult buildAssignmentOperation(Scope *Sc,
274 SourceLocation opLoc,
275 BinaryOperatorKind opcode,
276 Expr *LHS, Expr *RHS);
277 Expr *rebuildAndCaptureObject(Expr *syntacticBase);
278
279 bool findAtIndexGetter();
280 bool findAtIndexSetter();
281
282 ExprResult buildGet();
283 ExprResult buildSet(Expr *op, SourceLocation, bool);
284 };
285
John McCall4b9c2d22011-11-06 09:01:30 +0000286}
287
288/// Capture the given expression in an OpaqueValueExpr.
289OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
290 // Make a new OVE whose source is the given expression.
291 OpaqueValueExpr *captured =
292 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
Douglas Gregor97df54e2012-02-23 22:17:26 +0000293 e->getValueKind(), e->getObjectKind(),
294 e);
John McCall4b9c2d22011-11-06 09:01:30 +0000295
296 // Make sure we bind that in the semantics.
297 addSemanticExpr(captured);
298 return captured;
299}
300
301/// Capture the given expression as the result of this pseudo-object
302/// operation. This routine is safe against expressions which may
303/// already be captured.
304///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +0000305/// \returns the captured expression, which will be the
John McCall4b9c2d22011-11-06 09:01:30 +0000306/// same as the input if the input was already captured
307OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
308 assert(ResultIndex == PseudoObjectExpr::NoResult);
309
310 // If the expression hasn't already been captured, just capture it
311 // and set the new semantic
312 if (!isa<OpaqueValueExpr>(e)) {
313 OpaqueValueExpr *cap = capture(e);
314 setResultToLastSemantic();
315 return cap;
316 }
317
318 // Otherwise, it must already be one of our semantic expressions;
319 // set ResultIndex to its index.
320 unsigned index = 0;
321 for (;; ++index) {
322 assert(index < Semantics.size() &&
323 "captured expression not found in semantics!");
324 if (e == Semantics[index]) break;
325 }
326 ResultIndex = index;
327 return cast<OpaqueValueExpr>(e);
328}
329
330/// The routine which creates the final PseudoObjectExpr.
331ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
332 return PseudoObjectExpr::Create(S.Context, syntactic,
333 Semantics, ResultIndex);
334}
335
336/// The main skeleton for building an r-value operation.
337ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
338 Expr *syntacticBase = rebuildAndCaptureObject(op);
339
340 ExprResult getExpr = buildGet();
341 if (getExpr.isInvalid()) return ExprError();
342 addResultSemanticExpr(getExpr.take());
343
344 return complete(syntacticBase);
345}
346
347/// The basic skeleton for building a simple or compound
348/// assignment operation.
349ExprResult
350PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
351 BinaryOperatorKind opcode,
352 Expr *LHS, Expr *RHS) {
353 assert(BinaryOperator::isAssignmentOp(opcode));
354
355 Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
356 OpaqueValueExpr *capturedRHS = capture(RHS);
357
358 Expr *syntactic;
359
360 ExprResult result;
361 if (opcode == BO_Assign) {
362 result = capturedRHS;
363 syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
364 opcode, capturedRHS->getType(),
365 capturedRHS->getValueKind(),
Lang Hamesbe9af122012-10-02 04:45:10 +0000366 OK_Ordinary, opcLoc, false);
John McCall4b9c2d22011-11-06 09:01:30 +0000367 } else {
368 ExprResult opLHS = buildGet();
369 if (opLHS.isInvalid()) return ExprError();
370
371 // Build an ordinary, non-compound operation.
372 BinaryOperatorKind nonCompound =
373 BinaryOperator::getOpForCompoundAssignment(opcode);
374 result = S.BuildBinOp(Sc, opcLoc, nonCompound,
375 opLHS.take(), capturedRHS);
376 if (result.isInvalid()) return ExprError();
377
378 syntactic =
379 new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
380 result.get()->getType(),
381 result.get()->getValueKind(),
382 OK_Ordinary,
383 opLHS.get()->getType(),
384 result.get()->getType(),
Lang Hamesbe9af122012-10-02 04:45:10 +0000385 opcLoc, false);
John McCall4b9c2d22011-11-06 09:01:30 +0000386 }
387
388 // The result of the assignment, if not void, is the value set into
389 // the l-value.
Eli Friedman25f071e2012-11-13 23:16:33 +0000390 result = buildSet(result.take(), opcLoc, /*captureSetValueAsResult*/ true);
John McCall4b9c2d22011-11-06 09:01:30 +0000391 if (result.isInvalid()) return ExprError();
392 addSemanticExpr(result.take());
393
394 return complete(syntactic);
395}
396
397/// The basic skeleton for building an increment or decrement
398/// operation.
399ExprResult
400PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
401 UnaryOperatorKind opcode,
402 Expr *op) {
403 assert(UnaryOperator::isIncrementDecrementOp(opcode));
404
405 Expr *syntacticOp = rebuildAndCaptureObject(op);
406
407 // Load the value.
408 ExprResult result = buildGet();
409 if (result.isInvalid()) return ExprError();
410
411 QualType resultType = result.get()->getType();
412
413 // That's the postfix result.
Eli Friedman25f071e2012-11-13 23:16:33 +0000414 if (UnaryOperator::isPostfix(opcode) && CanCaptureValueOfType(resultType)) {
John McCall4b9c2d22011-11-06 09:01:30 +0000415 result = capture(result.take());
416 setResultToLastSemantic();
417 }
418
419 // Add or subtract a literal 1.
420 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
421 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
422 GenericLoc);
423
424 if (UnaryOperator::isIncrementOp(opcode)) {
425 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
426 } else {
427 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
428 }
429 if (result.isInvalid()) return ExprError();
430
431 // Store that back into the result. The value stored is the result
432 // of a prefix operation.
Eli Friedman25f071e2012-11-13 23:16:33 +0000433 result = buildSet(result.take(), opcLoc, UnaryOperator::isPrefix(opcode));
John McCall4b9c2d22011-11-06 09:01:30 +0000434 if (result.isInvalid()) return ExprError();
435 addSemanticExpr(result.take());
436
437 UnaryOperator *syntactic =
438 new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
439 VK_LValue, OK_Ordinary, opcLoc);
440 return complete(syntactic);
441}
442
443
444//===----------------------------------------------------------------------===//
445// Objective-C @property and implicit property references
446//===----------------------------------------------------------------------===//
447
448/// Look up a method in the receiver type of an Objective-C property
449/// reference.
John McCall3c3b7f92011-10-25 17:37:35 +0000450static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
451 const ObjCPropertyRefExpr *PRE) {
John McCall3c3b7f92011-10-25 17:37:35 +0000452 if (PRE->isObjectReceiver()) {
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000453 const ObjCObjectPointerType *PT =
454 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
John McCall4b9c2d22011-11-06 09:01:30 +0000455
456 // Special case for 'self' in class method implementations.
457 if (PT->isObjCClassType() &&
458 S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
459 // This cast is safe because isSelfExpr is only true within
460 // methods.
461 ObjCMethodDecl *method =
462 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
463 return S.LookupMethodInObjectType(sel,
464 S.Context.getObjCInterfaceType(method->getClassInterface()),
465 /*instance*/ false);
466 }
467
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000468 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
John McCall3c3b7f92011-10-25 17:37:35 +0000469 }
470
Benjamin Krameraa9807a2011-10-28 13:21:18 +0000471 if (PRE->isSuperReceiver()) {
472 if (const ObjCObjectPointerType *PT =
473 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
474 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
475
476 return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
477 }
478
479 assert(PRE->isClassReceiver() && "Invalid expression");
480 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
481 return S.LookupMethodInObjectType(sel, IT, false);
John McCall3c3b7f92011-10-25 17:37:35 +0000482}
483
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000484bool ObjCPropertyOpBuilder::isWeakProperty() const {
485 QualType T;
486 if (RefExpr->isExplicitProperty()) {
487 const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();
488 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
489 return true;
490
491 T = Prop->getType();
492 } else if (Getter) {
493 T = Getter->getResultType();
494 } else {
495 return false;
496 }
497
498 return T.getObjCLifetime() == Qualifiers::OCL_Weak;
499}
500
John McCall4b9c2d22011-11-06 09:01:30 +0000501bool ObjCPropertyOpBuilder::findGetter() {
502 if (Getter) return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000503
John McCalldc4df512011-11-07 22:49:50 +0000504 // For implicit properties, just trust the lookup we already did.
505 if (RefExpr->isImplicitProperty()) {
Fariborz Jahaniana2c91e72012-04-18 19:13:23 +0000506 if ((Getter = RefExpr->getImplicitPropertyGetter())) {
507 GetterSelector = Getter->getSelector();
508 return true;
509 }
510 else {
511 // Must build the getter selector the hard way.
512 ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
513 assert(setter && "both setter and getter are null - cannot happen");
514 IdentifierInfo *setterName =
515 setter->getSelector().getIdentifierInfoForSlot(0);
516 const char *compStr = setterName->getNameStart();
517 compStr += 3;
518 IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
519 GetterSelector =
520 S.PP.getSelectorTable().getNullarySelector(getterName);
521 return false;
522
523 }
John McCalldc4df512011-11-07 22:49:50 +0000524 }
525
526 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
527 Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
John McCall4b9c2d22011-11-06 09:01:30 +0000528 return (Getter != 0);
529}
530
531/// Try to find the most accurate setter declaration for the property
532/// reference.
533///
534/// \return true if a setter was found, in which case Setter
Fariborz Jahanianb5b155c2012-05-24 22:48:38 +0000535bool ObjCPropertyOpBuilder::findSetter(bool warn) {
John McCall4b9c2d22011-11-06 09:01:30 +0000536 // For implicit properties, just trust the lookup we already did.
537 if (RefExpr->isImplicitProperty()) {
538 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
539 Setter = setter;
540 SetterSelector = setter->getSelector();
541 return true;
John McCall3c3b7f92011-10-25 17:37:35 +0000542 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000543 IdentifierInfo *getterName =
544 RefExpr->getImplicitPropertyGetter()->getSelector()
545 .getIdentifierInfoForSlot(0);
546 SetterSelector =
547 SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
548 S.PP.getSelectorTable(),
549 getterName);
550 return false;
John McCall3c3b7f92011-10-25 17:37:35 +0000551 }
John McCall4b9c2d22011-11-06 09:01:30 +0000552 }
553
554 // For explicit properties, this is more involved.
555 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
556 SetterSelector = prop->getSetterName();
557
558 // Do a normal method lookup first.
559 if (ObjCMethodDecl *setter =
560 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
Jordan Rose1e4691b2012-10-10 16:42:25 +0000561 if (setter->isPropertyAccessor() && warn)
Fariborz Jahanianb5b155c2012-05-24 22:48:38 +0000562 if (const ObjCInterfaceDecl *IFace =
563 dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
564 const StringRef thisPropertyName(prop->getName());
565 char front = thisPropertyName.front();
566 front = islower(front) ? toupper(front) : tolower(front);
567 SmallString<100> PropertyName = thisPropertyName;
568 PropertyName[0] = front;
569 IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
570 if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
571 if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
Fariborz Jahaniancba0ebc2012-05-26 16:10:06 +0000572 S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
Fariborz Jahanianb5b155c2012-05-24 22:48:38 +0000573 << prop->getName() << prop1->getName() << setter->getSelector();
574 S.Diag(prop->getLocation(), diag::note_property_declare);
575 S.Diag(prop1->getLocation(), diag::note_property_declare);
576 }
577 }
John McCall4b9c2d22011-11-06 09:01:30 +0000578 Setter = setter;
579 return true;
580 }
581
582 // That can fail in the somewhat crazy situation that we're
583 // type-checking a message send within the @interface declaration
584 // that declared the @property. But it's not clear that that's
585 // valuable to support.
586
587 return false;
588}
589
590/// Capture the base object of an Objective-C property expression.
591Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
592 assert(InstanceReceiver == 0);
593
594 // If we have a base, capture it in an OVE and rebuild the syntactic
595 // form to use the OVE as its base.
596 if (RefExpr->isObjectReceiver()) {
597 InstanceReceiver = capture(RefExpr->getBase());
598
599 syntacticBase =
600 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
601 }
602
Argyrios Kyrtzidisb085d892012-03-30 00:19:18 +0000603 if (ObjCPropertyRefExpr *
604 refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
605 SyntacticRefExpr = refE;
606
John McCall4b9c2d22011-11-06 09:01:30 +0000607 return syntacticBase;
608}
609
610/// Load from an Objective-C property reference.
611ExprResult ObjCPropertyOpBuilder::buildGet() {
612 findGetter();
613 assert(Getter);
Argyrios Kyrtzidisb085d892012-03-30 00:19:18 +0000614
615 if (SyntacticRefExpr)
616 SyntacticRefExpr->setIsMessagingGetter();
617
John McCall4b9c2d22011-11-06 09:01:30 +0000618 QualType receiverType;
John McCall4b9c2d22011-11-06 09:01:30 +0000619 if (RefExpr->isClassReceiver()) {
620 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
621 } else if (RefExpr->isSuperReceiver()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000622 receiverType = RefExpr->getSuperReceiverType();
John McCall3c3b7f92011-10-25 17:37:35 +0000623 } else {
John McCall4b9c2d22011-11-06 09:01:30 +0000624 assert(InstanceReceiver);
625 receiverType = InstanceReceiver->getType();
626 }
John McCall3c3b7f92011-10-25 17:37:35 +0000627
John McCall4b9c2d22011-11-06 09:01:30 +0000628 // Build a message-send.
629 ExprResult msg;
630 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
631 assert(InstanceReceiver || RefExpr->isSuperReceiver());
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000632 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
633 GenericLoc, Getter->getSelector(),
634 Getter, MultiExprArg());
John McCall4b9c2d22011-11-06 09:01:30 +0000635 } else {
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000636 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
637 GenericLoc,
638 Getter->getSelector(), Getter,
639 MultiExprArg());
John McCall4b9c2d22011-11-06 09:01:30 +0000640 }
641 return msg;
642}
John McCall3c3b7f92011-10-25 17:37:35 +0000643
John McCall4b9c2d22011-11-06 09:01:30 +0000644/// Store to an Objective-C property reference.
645///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +0000646/// \param captureSetValueAsResult If true, capture the actual
John McCall4b9c2d22011-11-06 09:01:30 +0000647/// value being set as the value of the property operation.
648ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
649 bool captureSetValueAsResult) {
Fariborz Jahanianb5b155c2012-05-24 22:48:38 +0000650 bool hasSetter = findSetter(false);
John McCall4b9c2d22011-11-06 09:01:30 +0000651 assert(hasSetter); (void) hasSetter;
652
Argyrios Kyrtzidisb085d892012-03-30 00:19:18 +0000653 if (SyntacticRefExpr)
654 SyntacticRefExpr->setIsMessagingSetter();
655
John McCall4b9c2d22011-11-06 09:01:30 +0000656 QualType receiverType;
John McCall4b9c2d22011-11-06 09:01:30 +0000657 if (RefExpr->isClassReceiver()) {
658 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
659 } else if (RefExpr->isSuperReceiver()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000660 receiverType = RefExpr->getSuperReceiverType();
661 } else {
662 assert(InstanceReceiver);
663 receiverType = InstanceReceiver->getType();
664 }
665
666 // Use assignment constraints when possible; they give us better
667 // diagnostics. "When possible" basically means anything except a
668 // C++ class type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000669 if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000670 QualType paramType = (*Setter->param_begin())->getType();
David Blaikie4e4d0842012-03-11 07:00:24 +0000671 if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000672 ExprResult opResult = op;
673 Sema::AssignConvertType assignResult
674 = S.CheckSingleAssignmentConstraints(paramType, opResult);
675 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
676 op->getType(), opResult.get(),
677 Sema::AA_Assigning))
678 return ExprError();
679
680 op = opResult.take();
681 assert(op && "successful assignment left argument invalid?");
John McCall3c3b7f92011-10-25 17:37:35 +0000682 }
683 }
684
John McCall4b9c2d22011-11-06 09:01:30 +0000685 // Arguments.
686 Expr *args[] = { op };
John McCall3c3b7f92011-10-25 17:37:35 +0000687
John McCall4b9c2d22011-11-06 09:01:30 +0000688 // Build a message-send.
689 ExprResult msg;
690 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000691 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
692 GenericLoc, SetterSelector, Setter,
693 MultiExprArg(args, 1));
John McCall4b9c2d22011-11-06 09:01:30 +0000694 } else {
Argyrios Kyrtzidis746f5bc2012-01-12 02:34:39 +0000695 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
696 GenericLoc,
697 SetterSelector, Setter,
698 MultiExprArg(args, 1));
John McCall4b9c2d22011-11-06 09:01:30 +0000699 }
700
701 if (!msg.isInvalid() && captureSetValueAsResult) {
702 ObjCMessageExpr *msgExpr =
703 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
704 Expr *arg = msgExpr->getArg(0);
Eli Friedman25f071e2012-11-13 23:16:33 +0000705 if (CanCaptureValueOfType(arg->getType()))
706 msgExpr->setArg(0, captureValueAsResult(arg));
John McCall4b9c2d22011-11-06 09:01:30 +0000707 }
708
709 return msg;
John McCall3c3b7f92011-10-25 17:37:35 +0000710}
711
John McCall4b9c2d22011-11-06 09:01:30 +0000712/// @property-specific behavior for doing lvalue-to-rvalue conversion.
713ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
714 // Explicit properties always have getters, but implicit ones don't.
715 // Check that before proceeding.
Eli Friedmana70779f2012-11-29 03:13:49 +0000716 if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {
John McCall4b9c2d22011-11-06 09:01:30 +0000717 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
Eli Friedmana70779f2012-11-29 03:13:49 +0000718 << RefExpr->getSourceRange();
John McCall3c3b7f92011-10-25 17:37:35 +0000719 return ExprError();
720 }
721
John McCall4b9c2d22011-11-06 09:01:30 +0000722 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
John McCall3c3b7f92011-10-25 17:37:35 +0000723 if (result.isInvalid()) return ExprError();
724
John McCall4b9c2d22011-11-06 09:01:30 +0000725 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
726 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
727 Getter, RefExpr->getLocation());
728
729 // As a special case, if the method returns 'id', try to get
730 // a better type from the property.
731 if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
732 result.get()->getType()->isObjCIdType()) {
733 QualType propType = RefExpr->getExplicitProperty()->getType();
734 if (const ObjCObjectPointerType *ptr
735 = propType->getAs<ObjCObjectPointerType>()) {
736 if (!ptr->isObjCIdType())
737 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
738 }
739 }
740
John McCall3c3b7f92011-10-25 17:37:35 +0000741 return result;
742}
743
John McCall4b9c2d22011-11-06 09:01:30 +0000744/// Try to build this as a call to a getter that returns a reference.
745///
746/// \return true if it was possible, whether or not it actually
747/// succeeded
748bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
749 ExprResult &result) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000750 if (!S.getLangOpts().CPlusPlus) return false;
John McCall4b9c2d22011-11-06 09:01:30 +0000751
752 findGetter();
753 assert(Getter && "property has no setter and no getter!");
754
755 // Only do this if the getter returns an l-value reference type.
756 QualType resultType = Getter->getResultType();
757 if (!resultType->isLValueReferenceType()) return false;
758
759 result = buildRValueOperation(op);
760 return true;
761}
762
763/// @property-specific behavior for doing assignments.
764ExprResult
765ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
766 SourceLocation opcLoc,
767 BinaryOperatorKind opcode,
768 Expr *LHS, Expr *RHS) {
John McCall3c3b7f92011-10-25 17:37:35 +0000769 assert(BinaryOperator::isAssignmentOp(opcode));
John McCall3c3b7f92011-10-25 17:37:35 +0000770
771 // If there's no setter, we have no choice but to try to assign to
772 // the result of the getter.
John McCall4b9c2d22011-11-06 09:01:30 +0000773 if (!findSetter()) {
774 ExprResult result;
775 if (tryBuildGetOfReference(LHS, result)) {
776 if (result.isInvalid()) return ExprError();
777 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000778 }
779
780 // Otherwise, it's an error.
John McCall4b9c2d22011-11-06 09:01:30 +0000781 S.Diag(opcLoc, diag::err_nosetter_property_assignment)
782 << unsigned(RefExpr->isImplicitProperty())
783 << SetterSelector
John McCall3c3b7f92011-10-25 17:37:35 +0000784 << LHS->getSourceRange() << RHS->getSourceRange();
785 return ExprError();
786 }
787
788 // If there is a setter, we definitely want to use it.
789
John McCall4b9c2d22011-11-06 09:01:30 +0000790 // Verify that we can do a compound assignment.
791 if (opcode != BO_Assign && !findGetter()) {
792 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
John McCall3c3b7f92011-10-25 17:37:35 +0000793 << LHS->getSourceRange() << RHS->getSourceRange();
794 return ExprError();
795 }
796
John McCall4b9c2d22011-11-06 09:01:30 +0000797 ExprResult result =
798 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000799 if (result.isInvalid()) return ExprError();
800
John McCall4b9c2d22011-11-06 09:01:30 +0000801 // Various warnings about property assignments in ARC.
David Blaikie4e4d0842012-03-11 07:00:24 +0000802 if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
John McCall4b9c2d22011-11-06 09:01:30 +0000803 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
804 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
805 }
806
John McCall3c3b7f92011-10-25 17:37:35 +0000807 return result;
808}
John McCall4b9c2d22011-11-06 09:01:30 +0000809
810/// @property-specific behavior for doing increments and decrements.
811ExprResult
812ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
813 UnaryOperatorKind opcode,
814 Expr *op) {
815 // If there's no setter, we have no choice but to try to assign to
816 // the result of the getter.
817 if (!findSetter()) {
818 ExprResult result;
819 if (tryBuildGetOfReference(op, result)) {
820 if (result.isInvalid()) return ExprError();
821 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
822 }
823
824 // Otherwise, it's an error.
825 S.Diag(opcLoc, diag::err_nosetter_property_incdec)
826 << unsigned(RefExpr->isImplicitProperty())
827 << unsigned(UnaryOperator::isDecrementOp(opcode))
828 << SetterSelector
829 << op->getSourceRange();
830 return ExprError();
831 }
832
833 // If there is a setter, we definitely want to use it.
834
835 // We also need a getter.
836 if (!findGetter()) {
837 assert(RefExpr->isImplicitProperty());
838 S.Diag(opcLoc, diag::err_nogetter_property_incdec)
839 << unsigned(UnaryOperator::isDecrementOp(opcode))
Fariborz Jahaniana2c91e72012-04-18 19:13:23 +0000840 << GetterSelector
John McCall4b9c2d22011-11-06 09:01:30 +0000841 << op->getSourceRange();
842 return ExprError();
843 }
844
845 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
846}
847
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000848ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
849 if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) {
850 DiagnosticsEngine::Level Level =
851 S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
852 SyntacticForm->getLocStart());
853 if (Level != DiagnosticsEngine::Ignored)
Jordan Rose7a270482012-09-28 22:21:35 +0000854 S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
855 SyntacticRefExpr->isMessagingGetter());
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000856 }
857
858 return PseudoOpBuilder::complete(SyntacticForm);
859}
860
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000861// ObjCSubscript build stuff.
862//
863
864/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
865/// conversion.
866/// FIXME. Remove this routine if it is proven that no additional
867/// specifity is needed.
868ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
869 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
870 if (result.isInvalid()) return ExprError();
871 return result;
872}
873
874/// objective-c subscripting-specific behavior for doing assignments.
875ExprResult
876ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
877 SourceLocation opcLoc,
878 BinaryOperatorKind opcode,
879 Expr *LHS, Expr *RHS) {
880 assert(BinaryOperator::isAssignmentOp(opcode));
881 // There must be a method to do the Index'ed assignment.
882 if (!findAtIndexSetter())
883 return ExprError();
884
885 // Verify that we can do a compound assignment.
886 if (opcode != BO_Assign && !findAtIndexGetter())
887 return ExprError();
888
889 ExprResult result =
890 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
891 if (result.isInvalid()) return ExprError();
892
893 // Various warnings about objc Index'ed assignments in ARC.
David Blaikie4e4d0842012-03-11 07:00:24 +0000894 if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000895 S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
896 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
897 }
898
899 return result;
900}
901
902/// Capture the base object of an Objective-C Index'ed expression.
903Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
904 assert(InstanceBase == 0);
905
906 // Capture base expression in an OVE and rebuild the syntactic
907 // form to use the OVE as its base expression.
908 InstanceBase = capture(RefExpr->getBaseExpr());
909 InstanceKey = capture(RefExpr->getKeyExpr());
910
911 syntacticBase =
912 ObjCSubscriptRefRebuilder(S, InstanceBase,
913 InstanceKey).rebuild(syntacticBase);
914
915 return syntacticBase;
916}
917
918/// CheckSubscriptingKind - This routine decide what type
919/// of indexing represented by "FromE" is being done.
920Sema::ObjCSubscriptKind
921 Sema::CheckSubscriptingKind(Expr *FromE) {
922 // If the expression already has integral or enumeration type, we're golden.
923 QualType T = FromE->getType();
924 if (T->isIntegralOrEnumerationType())
925 return OS_Array;
926
927 // If we don't have a class type in C++, there's no way we can get an
928 // expression of integral or enumeration type.
929 const RecordType *RecordTy = T->getAs<RecordType>();
Fariborz Jahaniana78eca22012-03-28 17:56:49 +0000930 if (!RecordTy && T->isObjCObjectPointerType())
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000931 // All other scalar cases are assumed to be dictionary indexing which
932 // caller handles, with diagnostics if needed.
933 return OS_Dictionary;
Fariborz Jahaniana78eca22012-03-28 17:56:49 +0000934 if (!getLangOpts().CPlusPlus ||
935 !RecordTy || RecordTy->isIncompleteType()) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000936 // No indexing can be done. Issue diagnostics and quit.
Fariborz Jahaniana78eca22012-03-28 17:56:49 +0000937 const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
938 if (isa<StringLiteral>(IndexExpr))
939 Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
940 << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
941 else
942 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
943 << T;
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000944 return OS_Error;
945 }
946
947 // We must have a complete class type.
948 if (RequireCompleteType(FromE->getExprLoc(), T,
Douglas Gregord10099e2012-05-04 16:32:21 +0000949 diag::err_objc_index_incomplete_class_type, FromE))
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000950 return OS_Error;
951
952 // Look for a conversion to an integral, enumeration type, or
953 // objective-C pointer type.
954 UnresolvedSet<4> ViableConversions;
955 UnresolvedSet<4> ExplicitConversions;
Argyrios Kyrtzidis9d295432012-11-28 03:56:09 +0000956 std::pair<CXXRecordDecl::conversion_iterator,
957 CXXRecordDecl::conversion_iterator> Conversions
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000958 = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
959
960 int NoIntegrals=0, NoObjCIdPointers=0;
961 SmallVector<CXXConversionDecl *, 4> ConversionDecls;
962
Argyrios Kyrtzidis9d295432012-11-28 03:56:09 +0000963 for (CXXRecordDecl::conversion_iterator
964 I = Conversions.first, E = Conversions.second; I != E; ++I) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000965 if (CXXConversionDecl *Conversion
966 = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
967 QualType CT = Conversion->getConversionType().getNonReferenceType();
968 if (CT->isIntegralOrEnumerationType()) {
969 ++NoIntegrals;
970 ConversionDecls.push_back(Conversion);
971 }
972 else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
973 ++NoObjCIdPointers;
974 ConversionDecls.push_back(Conversion);
975 }
976 }
977 }
978 if (NoIntegrals ==1 && NoObjCIdPointers == 0)
979 return OS_Array;
980 if (NoIntegrals == 0 && NoObjCIdPointers == 1)
981 return OS_Dictionary;
982 if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
983 // No conversion function was found. Issue diagnostic and return.
984 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
985 << FromE->getType();
986 return OS_Error;
987 }
988 Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
989 << FromE->getType();
990 for (unsigned int i = 0; i < ConversionDecls.size(); i++)
991 Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
992
993 return OS_Error;
994}
995
Fariborz Jahaniandc483052012-08-02 18:03:58 +0000996/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
997/// objects used as dictionary subscript key objects.
998static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
999 Expr *Key) {
1000 if (ContainerT.isNull())
1001 return;
1002 // dictionary subscripting.
1003 // - (id)objectForKeyedSubscript:(id)key;
1004 IdentifierInfo *KeyIdents[] = {
1005 &S.Context.Idents.get("objectForKeyedSubscript")
1006 };
1007 Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1008 ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
1009 true /*instance*/);
1010 if (!Getter)
1011 return;
1012 QualType T = Getter->param_begin()[0]->getType();
1013 S.CheckObjCARCConversion(Key->getSourceRange(),
1014 T, Key, Sema::CCK_ImplicitConversion);
1015}
1016
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001017bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1018 if (AtIndexGetter)
1019 return true;
1020
1021 Expr *BaseExpr = RefExpr->getBaseExpr();
1022 QualType BaseT = BaseExpr->getType();
1023
1024 QualType ResultType;
1025 if (const ObjCObjectPointerType *PTy =
1026 BaseT->getAs<ObjCObjectPointerType>()) {
1027 ResultType = PTy->getPointeeType();
1028 if (const ObjCObjectType *iQFaceTy =
1029 ResultType->getAsObjCQualifiedInterfaceType())
1030 ResultType = iQFaceTy->getBaseType();
1031 }
1032 Sema::ObjCSubscriptKind Res =
1033 S.CheckSubscriptingKind(RefExpr->getKeyExpr());
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001034 if (Res == Sema::OS_Error) {
1035 if (S.getLangOpts().ObjCAutoRefCount)
1036 CheckKeyForObjCARCConversion(S, ResultType,
1037 RefExpr->getKeyExpr());
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001038 return false;
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001039 }
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001040 bool arrayRef = (Res == Sema::OS_Array);
1041
1042 if (ResultType.isNull()) {
1043 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1044 << BaseExpr->getType() << arrayRef;
1045 return false;
1046 }
1047 if (!arrayRef) {
1048 // dictionary subscripting.
1049 // - (id)objectForKeyedSubscript:(id)key;
1050 IdentifierInfo *KeyIdents[] = {
1051 &S.Context.Idents.get("objectForKeyedSubscript")
1052 };
1053 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1054 }
1055 else {
1056 // - (id)objectAtIndexedSubscript:(size_t)index;
1057 IdentifierInfo *KeyIdents[] = {
1058 &S.Context.Idents.get("objectAtIndexedSubscript")
1059 };
1060
1061 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1062 }
1063
1064 AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
1065 true /*instance*/);
1066 bool receiverIdType = (BaseT->isObjCIdType() ||
1067 BaseT->isObjCQualifiedIdType());
1068
David Blaikie4e4d0842012-03-11 07:00:24 +00001069 if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001070 AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1071 SourceLocation(), AtIndexGetterSelector,
1072 S.Context.getObjCIdType() /*ReturnType*/,
1073 0 /*TypeSourceInfo */,
1074 S.Context.getTranslationUnitDecl(),
1075 true /*Instance*/, false/*isVariadic*/,
Jordan Rose1e4691b2012-10-10 16:42:25 +00001076 /*isPropertyAccessor=*/false,
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001077 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1078 ObjCMethodDecl::Required,
1079 false);
1080 ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1081 SourceLocation(), SourceLocation(),
1082 arrayRef ? &S.Context.Idents.get("index")
1083 : &S.Context.Idents.get("key"),
1084 arrayRef ? S.Context.UnsignedLongTy
1085 : S.Context.getObjCIdType(),
1086 /*TInfo=*/0,
1087 SC_None,
1088 SC_None,
1089 0);
1090 AtIndexGetter->setMethodParams(S.Context, Argument,
1091 ArrayRef<SourceLocation>());
1092 }
1093
1094 if (!AtIndexGetter) {
1095 if (!receiverIdType) {
1096 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1097 << BaseExpr->getType() << 0 << arrayRef;
1098 return false;
1099 }
1100 AtIndexGetter =
1101 S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
1102 RefExpr->getSourceRange(),
1103 true, false);
1104 }
1105
1106 if (AtIndexGetter) {
1107 QualType T = AtIndexGetter->param_begin()[0]->getType();
1108 if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1109 (!arrayRef && !T->isObjCObjectPointerType())) {
1110 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1111 arrayRef ? diag::err_objc_subscript_index_type
1112 : diag::err_objc_subscript_key_type) << T;
1113 S.Diag(AtIndexGetter->param_begin()[0]->getLocation(),
1114 diag::note_parameter_type) << T;
1115 return false;
1116 }
1117 QualType R = AtIndexGetter->getResultType();
1118 if (!R->isObjCObjectPointerType()) {
1119 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1120 diag::err_objc_indexing_method_result_type) << R << arrayRef;
1121 S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1122 AtIndexGetter->getDeclName();
1123 }
1124 }
1125 return true;
1126}
1127
1128bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1129 if (AtIndexSetter)
1130 return true;
1131
1132 Expr *BaseExpr = RefExpr->getBaseExpr();
1133 QualType BaseT = BaseExpr->getType();
1134
1135 QualType ResultType;
1136 if (const ObjCObjectPointerType *PTy =
1137 BaseT->getAs<ObjCObjectPointerType>()) {
1138 ResultType = PTy->getPointeeType();
1139 if (const ObjCObjectType *iQFaceTy =
1140 ResultType->getAsObjCQualifiedInterfaceType())
1141 ResultType = iQFaceTy->getBaseType();
1142 }
1143
1144 Sema::ObjCSubscriptKind Res =
1145 S.CheckSubscriptingKind(RefExpr->getKeyExpr());
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001146 if (Res == Sema::OS_Error) {
1147 if (S.getLangOpts().ObjCAutoRefCount)
1148 CheckKeyForObjCARCConversion(S, ResultType,
1149 RefExpr->getKeyExpr());
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001150 return false;
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001151 }
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001152 bool arrayRef = (Res == Sema::OS_Array);
1153
1154 if (ResultType.isNull()) {
1155 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1156 << BaseExpr->getType() << arrayRef;
1157 return false;
1158 }
1159
1160 if (!arrayRef) {
1161 // dictionary subscripting.
1162 // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1163 IdentifierInfo *KeyIdents[] = {
1164 &S.Context.Idents.get("setObject"),
1165 &S.Context.Idents.get("forKeyedSubscript")
1166 };
1167 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1168 }
1169 else {
1170 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1171 IdentifierInfo *KeyIdents[] = {
1172 &S.Context.Idents.get("setObject"),
1173 &S.Context.Idents.get("atIndexedSubscript")
1174 };
1175 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1176 }
1177 AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
1178 true /*instance*/);
1179
1180 bool receiverIdType = (BaseT->isObjCIdType() ||
1181 BaseT->isObjCQualifiedIdType());
1182
David Blaikie4e4d0842012-03-11 07:00:24 +00001183 if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001184 TypeSourceInfo *ResultTInfo = 0;
1185 QualType ReturnType = S.Context.VoidTy;
1186 AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1187 SourceLocation(), AtIndexSetterSelector,
1188 ReturnType,
1189 ResultTInfo,
1190 S.Context.getTranslationUnitDecl(),
1191 true /*Instance*/, false/*isVariadic*/,
Jordan Rose1e4691b2012-10-10 16:42:25 +00001192 /*isPropertyAccessor=*/false,
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001193 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1194 ObjCMethodDecl::Required,
1195 false);
1196 SmallVector<ParmVarDecl *, 2> Params;
1197 ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1198 SourceLocation(), SourceLocation(),
1199 &S.Context.Idents.get("object"),
1200 S.Context.getObjCIdType(),
1201 /*TInfo=*/0,
1202 SC_None,
1203 SC_None,
1204 0);
1205 Params.push_back(object);
1206 ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1207 SourceLocation(), SourceLocation(),
1208 arrayRef ? &S.Context.Idents.get("index")
1209 : &S.Context.Idents.get("key"),
1210 arrayRef ? S.Context.UnsignedLongTy
1211 : S.Context.getObjCIdType(),
1212 /*TInfo=*/0,
1213 SC_None,
1214 SC_None,
1215 0);
1216 Params.push_back(key);
1217 AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
1218 }
1219
1220 if (!AtIndexSetter) {
1221 if (!receiverIdType) {
1222 S.Diag(BaseExpr->getExprLoc(),
1223 diag::err_objc_subscript_method_not_found)
1224 << BaseExpr->getType() << 1 << arrayRef;
1225 return false;
1226 }
1227 AtIndexSetter =
1228 S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
1229 RefExpr->getSourceRange(),
1230 true, false);
1231 }
1232
1233 bool err = false;
1234 if (AtIndexSetter && arrayRef) {
1235 QualType T = AtIndexSetter->param_begin()[1]->getType();
1236 if (!T->isIntegralOrEnumerationType()) {
1237 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1238 diag::err_objc_subscript_index_type) << T;
1239 S.Diag(AtIndexSetter->param_begin()[1]->getLocation(),
1240 diag::note_parameter_type) << T;
1241 err = true;
1242 }
1243 T = AtIndexSetter->param_begin()[0]->getType();
1244 if (!T->isObjCObjectPointerType()) {
1245 S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1246 diag::err_objc_subscript_object_type) << T << arrayRef;
1247 S.Diag(AtIndexSetter->param_begin()[0]->getLocation(),
1248 diag::note_parameter_type) << T;
1249 err = true;
1250 }
1251 }
1252 else if (AtIndexSetter && !arrayRef)
1253 for (unsigned i=0; i <2; i++) {
1254 QualType T = AtIndexSetter->param_begin()[i]->getType();
1255 if (!T->isObjCObjectPointerType()) {
1256 if (i == 1)
1257 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1258 diag::err_objc_subscript_key_type) << T;
1259 else
1260 S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1261 diag::err_objc_subscript_dic_object_type) << T;
1262 S.Diag(AtIndexSetter->param_begin()[i]->getLocation(),
1263 diag::note_parameter_type) << T;
1264 err = true;
1265 }
1266 }
1267
1268 return !err;
1269}
1270
1271// Get the object at "Index" position in the container.
1272// [BaseExpr objectAtIndexedSubscript : IndexExpr];
1273ExprResult ObjCSubscriptOpBuilder::buildGet() {
1274 if (!findAtIndexGetter())
1275 return ExprError();
1276
1277 QualType receiverType = InstanceBase->getType();
1278
1279 // Build a message-send.
1280 ExprResult msg;
1281 Expr *Index = InstanceKey;
1282
1283 // Arguments.
1284 Expr *args[] = { Index };
1285 assert(InstanceBase);
1286 msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1287 GenericLoc,
1288 AtIndexGetterSelector, AtIndexGetter,
1289 MultiExprArg(args, 1));
1290 return msg;
1291}
1292
1293/// Store into the container the "op" object at "Index"'ed location
1294/// by building this messaging expression:
1295/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00001296/// \param captureSetValueAsResult If true, capture the actual
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001297/// value being set as the value of the property operation.
1298ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
1299 bool captureSetValueAsResult) {
1300 if (!findAtIndexSetter())
1301 return ExprError();
1302
1303 QualType receiverType = InstanceBase->getType();
1304 Expr *Index = InstanceKey;
1305
1306 // Arguments.
1307 Expr *args[] = { op, Index };
1308
1309 // Build a message-send.
1310 ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1311 GenericLoc,
1312 AtIndexSetterSelector,
1313 AtIndexSetter,
1314 MultiExprArg(args, 2));
1315
1316 if (!msg.isInvalid() && captureSetValueAsResult) {
1317 ObjCMessageExpr *msgExpr =
1318 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1319 Expr *arg = msgExpr->getArg(0);
Eli Friedman25f071e2012-11-13 23:16:33 +00001320 if (CanCaptureValueOfType(arg->getType()))
1321 msgExpr->setArg(0, captureValueAsResult(arg));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001322 }
1323
1324 return msg;
1325}
1326
John McCall4b9c2d22011-11-06 09:01:30 +00001327//===----------------------------------------------------------------------===//
1328// General Sema routines.
1329//===----------------------------------------------------------------------===//
1330
1331ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
1332 Expr *opaqueRef = E->IgnoreParens();
1333 if (ObjCPropertyRefExpr *refExpr
1334 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1335 ObjCPropertyOpBuilder builder(*this, refExpr);
1336 return builder.buildRValueOperation(E);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001337 }
1338 else if (ObjCSubscriptRefExpr *refExpr
1339 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1340 ObjCSubscriptOpBuilder builder(*this, refExpr);
1341 return builder.buildRValueOperation(E);
John McCall4b9c2d22011-11-06 09:01:30 +00001342 } else {
1343 llvm_unreachable("unknown pseudo-object kind!");
1344 }
1345}
1346
1347/// Check an increment or decrement of a pseudo-object expression.
1348ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
1349 UnaryOperatorKind opcode, Expr *op) {
1350 // Do nothing if the operand is dependent.
1351 if (op->isTypeDependent())
1352 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
1353 VK_RValue, OK_Ordinary, opcLoc);
1354
1355 assert(UnaryOperator::isIncrementDecrementOp(opcode));
1356 Expr *opaqueRef = op->IgnoreParens();
1357 if (ObjCPropertyRefExpr *refExpr
1358 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1359 ObjCPropertyOpBuilder builder(*this, refExpr);
1360 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001361 } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1362 Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1363 return ExprError();
John McCall4b9c2d22011-11-06 09:01:30 +00001364 } else {
1365 llvm_unreachable("unknown pseudo-object kind!");
1366 }
1367}
1368
1369ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
1370 BinaryOperatorKind opcode,
1371 Expr *LHS, Expr *RHS) {
1372 // Do nothing if either argument is dependent.
1373 if (LHS->isTypeDependent() || RHS->isTypeDependent())
1374 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
Lang Hamesbe9af122012-10-02 04:45:10 +00001375 VK_RValue, OK_Ordinary, opcLoc, false);
John McCall4b9c2d22011-11-06 09:01:30 +00001376
1377 // Filter out non-overload placeholder types in the RHS.
John McCall32509f12011-11-15 01:35:18 +00001378 if (RHS->getType()->isNonOverloadPlaceholderType()) {
1379 ExprResult result = CheckPlaceholderExpr(RHS);
1380 if (result.isInvalid()) return ExprError();
1381 RHS = result.take();
John McCall4b9c2d22011-11-06 09:01:30 +00001382 }
1383
1384 Expr *opaqueRef = LHS->IgnoreParens();
1385 if (ObjCPropertyRefExpr *refExpr
1386 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1387 ObjCPropertyOpBuilder builder(*this, refExpr);
1388 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001389 } else if (ObjCSubscriptRefExpr *refExpr
1390 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1391 ObjCSubscriptOpBuilder builder(*this, refExpr);
1392 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
John McCall4b9c2d22011-11-06 09:01:30 +00001393 } else {
1394 llvm_unreachable("unknown pseudo-object kind!");
1395 }
1396}
John McCall01e19be2011-11-30 04:42:31 +00001397
1398/// Given a pseudo-object reference, rebuild it without the opaque
1399/// values. Basically, undo the behavior of rebuildAndCaptureObject.
1400/// This should never operate in-place.
1401static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
1402 Expr *opaqueRef = E->IgnoreParens();
1403 if (ObjCPropertyRefExpr *refExpr
1404 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
Douglas Gregor88507dd2012-04-13 16:05:42 +00001405 // Class and super property references don't have opaque values in them.
1406 if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
1407 return E;
1408
1409 assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
1410 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
1411 return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001412 } else if (ObjCSubscriptRefExpr *refExpr
1413 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1414 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
1415 OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
1416 return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
1417 keyOVE->getSourceExpr()).rebuild(E);
John McCall01e19be2011-11-30 04:42:31 +00001418 } else {
1419 llvm_unreachable("unknown pseudo-object kind!");
1420 }
1421}
1422
1423/// Given a pseudo-object expression, recreate what it looks like
1424/// syntactically without the attendant OpaqueValueExprs.
1425///
1426/// This is a hack which should be removed when TreeTransform is
1427/// capable of rebuilding a tree without stripping implicit
1428/// operations.
1429Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
1430 Expr *syntax = E->getSyntacticForm();
1431 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
1432 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
1433 return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
1434 uop->getValueKind(), uop->getObjectKind(),
1435 uop->getOperatorLoc());
1436 } else if (CompoundAssignOperator *cop
1437 = dyn_cast<CompoundAssignOperator>(syntax)) {
1438 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
1439 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
1440 return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
1441 cop->getType(),
1442 cop->getValueKind(),
1443 cop->getObjectKind(),
1444 cop->getComputationLHSType(),
1445 cop->getComputationResultType(),
Lang Hamesbe9af122012-10-02 04:45:10 +00001446 cop->getOperatorLoc(), false);
John McCall01e19be2011-11-30 04:42:31 +00001447 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
1448 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
1449 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
1450 return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
1451 bop->getType(), bop->getValueKind(),
1452 bop->getObjectKind(),
Lang Hamesbe9af122012-10-02 04:45:10 +00001453 bop->getOperatorLoc(), false);
John McCall01e19be2011-11-30 04:42:31 +00001454 } else {
1455 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
1456 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
1457 }
1458}