blob: 74d0818b0e4b359ff4972cc40228506a92f84251 [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.
116 assert(refExpr->getBase());
117
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.
716 if (RefExpr->isImplicitProperty() &&
717 !RefExpr->getImplicitPropertyGetter()) {
718 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
719 << RefExpr->getBase()->getType();
John McCall3c3b7f92011-10-25 17:37:35 +0000720 return ExprError();
721 }
722
John McCall4b9c2d22011-11-06 09:01:30 +0000723 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
John McCall3c3b7f92011-10-25 17:37:35 +0000724 if (result.isInvalid()) return ExprError();
725
John McCall4b9c2d22011-11-06 09:01:30 +0000726 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
727 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
728 Getter, RefExpr->getLocation());
729
730 // As a special case, if the method returns 'id', try to get
731 // a better type from the property.
732 if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
733 result.get()->getType()->isObjCIdType()) {
734 QualType propType = RefExpr->getExplicitProperty()->getType();
735 if (const ObjCObjectPointerType *ptr
736 = propType->getAs<ObjCObjectPointerType>()) {
737 if (!ptr->isObjCIdType())
738 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
739 }
740 }
741
John McCall3c3b7f92011-10-25 17:37:35 +0000742 return result;
743}
744
John McCall4b9c2d22011-11-06 09:01:30 +0000745/// Try to build this as a call to a getter that returns a reference.
746///
747/// \return true if it was possible, whether or not it actually
748/// succeeded
749bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
750 ExprResult &result) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000751 if (!S.getLangOpts().CPlusPlus) return false;
John McCall4b9c2d22011-11-06 09:01:30 +0000752
753 findGetter();
754 assert(Getter && "property has no setter and no getter!");
755
756 // Only do this if the getter returns an l-value reference type.
757 QualType resultType = Getter->getResultType();
758 if (!resultType->isLValueReferenceType()) return false;
759
760 result = buildRValueOperation(op);
761 return true;
762}
763
764/// @property-specific behavior for doing assignments.
765ExprResult
766ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
767 SourceLocation opcLoc,
768 BinaryOperatorKind opcode,
769 Expr *LHS, Expr *RHS) {
John McCall3c3b7f92011-10-25 17:37:35 +0000770 assert(BinaryOperator::isAssignmentOp(opcode));
John McCall3c3b7f92011-10-25 17:37:35 +0000771
772 // If there's no setter, we have no choice but to try to assign to
773 // the result of the getter.
John McCall4b9c2d22011-11-06 09:01:30 +0000774 if (!findSetter()) {
775 ExprResult result;
776 if (tryBuildGetOfReference(LHS, result)) {
777 if (result.isInvalid()) return ExprError();
778 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000779 }
780
781 // Otherwise, it's an error.
John McCall4b9c2d22011-11-06 09:01:30 +0000782 S.Diag(opcLoc, diag::err_nosetter_property_assignment)
783 << unsigned(RefExpr->isImplicitProperty())
784 << SetterSelector
John McCall3c3b7f92011-10-25 17:37:35 +0000785 << LHS->getSourceRange() << RHS->getSourceRange();
786 return ExprError();
787 }
788
789 // If there is a setter, we definitely want to use it.
790
John McCall4b9c2d22011-11-06 09:01:30 +0000791 // Verify that we can do a compound assignment.
792 if (opcode != BO_Assign && !findGetter()) {
793 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
John McCall3c3b7f92011-10-25 17:37:35 +0000794 << LHS->getSourceRange() << RHS->getSourceRange();
795 return ExprError();
796 }
797
John McCall4b9c2d22011-11-06 09:01:30 +0000798 ExprResult result =
799 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
John McCall3c3b7f92011-10-25 17:37:35 +0000800 if (result.isInvalid()) return ExprError();
801
John McCall4b9c2d22011-11-06 09:01:30 +0000802 // Various warnings about property assignments in ARC.
David Blaikie4e4d0842012-03-11 07:00:24 +0000803 if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
John McCall4b9c2d22011-11-06 09:01:30 +0000804 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
805 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
806 }
807
John McCall3c3b7f92011-10-25 17:37:35 +0000808 return result;
809}
John McCall4b9c2d22011-11-06 09:01:30 +0000810
811/// @property-specific behavior for doing increments and decrements.
812ExprResult
813ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
814 UnaryOperatorKind opcode,
815 Expr *op) {
816 // If there's no setter, we have no choice but to try to assign to
817 // the result of the getter.
818 if (!findSetter()) {
819 ExprResult result;
820 if (tryBuildGetOfReference(op, result)) {
821 if (result.isInvalid()) return ExprError();
822 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
823 }
824
825 // Otherwise, it's an error.
826 S.Diag(opcLoc, diag::err_nosetter_property_incdec)
827 << unsigned(RefExpr->isImplicitProperty())
828 << unsigned(UnaryOperator::isDecrementOp(opcode))
829 << SetterSelector
830 << op->getSourceRange();
831 return ExprError();
832 }
833
834 // If there is a setter, we definitely want to use it.
835
836 // We also need a getter.
837 if (!findGetter()) {
838 assert(RefExpr->isImplicitProperty());
839 S.Diag(opcLoc, diag::err_nogetter_property_incdec)
840 << unsigned(UnaryOperator::isDecrementOp(opcode))
Fariborz Jahaniana2c91e72012-04-18 19:13:23 +0000841 << GetterSelector
John McCall4b9c2d22011-11-06 09:01:30 +0000842 << op->getSourceRange();
843 return ExprError();
844 }
845
846 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
847}
848
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000849ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
850 if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) {
851 DiagnosticsEngine::Level Level =
852 S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
853 SyntacticForm->getLocStart());
854 if (Level != DiagnosticsEngine::Ignored)
Jordan Rose7a270482012-09-28 22:21:35 +0000855 S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
856 SyntacticRefExpr->isMessagingGetter());
Jordan Rose58b6bdc2012-09-28 22:21:30 +0000857 }
858
859 return PseudoOpBuilder::complete(SyntacticForm);
860}
861
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000862// ObjCSubscript build stuff.
863//
864
865/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
866/// conversion.
867/// FIXME. Remove this routine if it is proven that no additional
868/// specifity is needed.
869ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
870 ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
871 if (result.isInvalid()) return ExprError();
872 return result;
873}
874
875/// objective-c subscripting-specific behavior for doing assignments.
876ExprResult
877ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
878 SourceLocation opcLoc,
879 BinaryOperatorKind opcode,
880 Expr *LHS, Expr *RHS) {
881 assert(BinaryOperator::isAssignmentOp(opcode));
882 // There must be a method to do the Index'ed assignment.
883 if (!findAtIndexSetter())
884 return ExprError();
885
886 // Verify that we can do a compound assignment.
887 if (opcode != BO_Assign && !findAtIndexGetter())
888 return ExprError();
889
890 ExprResult result =
891 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
892 if (result.isInvalid()) return ExprError();
893
894 // Various warnings about objc Index'ed assignments in ARC.
David Blaikie4e4d0842012-03-11 07:00:24 +0000895 if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000896 S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
897 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
898 }
899
900 return result;
901}
902
903/// Capture the base object of an Objective-C Index'ed expression.
904Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
905 assert(InstanceBase == 0);
906
907 // Capture base expression in an OVE and rebuild the syntactic
908 // form to use the OVE as its base expression.
909 InstanceBase = capture(RefExpr->getBaseExpr());
910 InstanceKey = capture(RefExpr->getKeyExpr());
911
912 syntacticBase =
913 ObjCSubscriptRefRebuilder(S, InstanceBase,
914 InstanceKey).rebuild(syntacticBase);
915
916 return syntacticBase;
917}
918
919/// CheckSubscriptingKind - This routine decide what type
920/// of indexing represented by "FromE" is being done.
921Sema::ObjCSubscriptKind
922 Sema::CheckSubscriptingKind(Expr *FromE) {
923 // If the expression already has integral or enumeration type, we're golden.
924 QualType T = FromE->getType();
925 if (T->isIntegralOrEnumerationType())
926 return OS_Array;
927
928 // If we don't have a class type in C++, there's no way we can get an
929 // expression of integral or enumeration type.
930 const RecordType *RecordTy = T->getAs<RecordType>();
Fariborz Jahaniana78eca22012-03-28 17:56:49 +0000931 if (!RecordTy && T->isObjCObjectPointerType())
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000932 // All other scalar cases are assumed to be dictionary indexing which
933 // caller handles, with diagnostics if needed.
934 return OS_Dictionary;
Fariborz Jahaniana78eca22012-03-28 17:56:49 +0000935 if (!getLangOpts().CPlusPlus ||
936 !RecordTy || RecordTy->isIncompleteType()) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000937 // No indexing can be done. Issue diagnostics and quit.
Fariborz Jahaniana78eca22012-03-28 17:56:49 +0000938 const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
939 if (isa<StringLiteral>(IndexExpr))
940 Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
941 << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
942 else
943 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
944 << T;
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000945 return OS_Error;
946 }
947
948 // We must have a complete class type.
949 if (RequireCompleteType(FromE->getExprLoc(), T,
Douglas Gregord10099e2012-05-04 16:32:21 +0000950 diag::err_objc_index_incomplete_class_type, FromE))
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000951 return OS_Error;
952
953 // Look for a conversion to an integral, enumeration type, or
954 // objective-C pointer type.
955 UnresolvedSet<4> ViableConversions;
956 UnresolvedSet<4> ExplicitConversions;
Argyrios Kyrtzidis9d295432012-11-28 03:56:09 +0000957 std::pair<CXXRecordDecl::conversion_iterator,
958 CXXRecordDecl::conversion_iterator> Conversions
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000959 = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
960
961 int NoIntegrals=0, NoObjCIdPointers=0;
962 SmallVector<CXXConversionDecl *, 4> ConversionDecls;
963
Argyrios Kyrtzidis9d295432012-11-28 03:56:09 +0000964 for (CXXRecordDecl::conversion_iterator
965 I = Conversions.first, E = Conversions.second; I != E; ++I) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000966 if (CXXConversionDecl *Conversion
967 = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
968 QualType CT = Conversion->getConversionType().getNonReferenceType();
969 if (CT->isIntegralOrEnumerationType()) {
970 ++NoIntegrals;
971 ConversionDecls.push_back(Conversion);
972 }
973 else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
974 ++NoObjCIdPointers;
975 ConversionDecls.push_back(Conversion);
976 }
977 }
978 }
979 if (NoIntegrals ==1 && NoObjCIdPointers == 0)
980 return OS_Array;
981 if (NoIntegrals == 0 && NoObjCIdPointers == 1)
982 return OS_Dictionary;
983 if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
984 // No conversion function was found. Issue diagnostic and return.
985 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
986 << FromE->getType();
987 return OS_Error;
988 }
989 Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
990 << FromE->getType();
991 for (unsigned int i = 0; i < ConversionDecls.size(); i++)
992 Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
993
994 return OS_Error;
995}
996
Fariborz Jahaniandc483052012-08-02 18:03:58 +0000997/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
998/// objects used as dictionary subscript key objects.
999static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
1000 Expr *Key) {
1001 if (ContainerT.isNull())
1002 return;
1003 // dictionary subscripting.
1004 // - (id)objectForKeyedSubscript:(id)key;
1005 IdentifierInfo *KeyIdents[] = {
1006 &S.Context.Idents.get("objectForKeyedSubscript")
1007 };
1008 Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1009 ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
1010 true /*instance*/);
1011 if (!Getter)
1012 return;
1013 QualType T = Getter->param_begin()[0]->getType();
1014 S.CheckObjCARCConversion(Key->getSourceRange(),
1015 T, Key, Sema::CCK_ImplicitConversion);
1016}
1017
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001018bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1019 if (AtIndexGetter)
1020 return true;
1021
1022 Expr *BaseExpr = RefExpr->getBaseExpr();
1023 QualType BaseT = BaseExpr->getType();
1024
1025 QualType ResultType;
1026 if (const ObjCObjectPointerType *PTy =
1027 BaseT->getAs<ObjCObjectPointerType>()) {
1028 ResultType = PTy->getPointeeType();
1029 if (const ObjCObjectType *iQFaceTy =
1030 ResultType->getAsObjCQualifiedInterfaceType())
1031 ResultType = iQFaceTy->getBaseType();
1032 }
1033 Sema::ObjCSubscriptKind Res =
1034 S.CheckSubscriptingKind(RefExpr->getKeyExpr());
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001035 if (Res == Sema::OS_Error) {
1036 if (S.getLangOpts().ObjCAutoRefCount)
1037 CheckKeyForObjCARCConversion(S, ResultType,
1038 RefExpr->getKeyExpr());
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001039 return false;
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001040 }
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001041 bool arrayRef = (Res == Sema::OS_Array);
1042
1043 if (ResultType.isNull()) {
1044 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1045 << BaseExpr->getType() << arrayRef;
1046 return false;
1047 }
1048 if (!arrayRef) {
1049 // dictionary subscripting.
1050 // - (id)objectForKeyedSubscript:(id)key;
1051 IdentifierInfo *KeyIdents[] = {
1052 &S.Context.Idents.get("objectForKeyedSubscript")
1053 };
1054 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1055 }
1056 else {
1057 // - (id)objectAtIndexedSubscript:(size_t)index;
1058 IdentifierInfo *KeyIdents[] = {
1059 &S.Context.Idents.get("objectAtIndexedSubscript")
1060 };
1061
1062 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1063 }
1064
1065 AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
1066 true /*instance*/);
1067 bool receiverIdType = (BaseT->isObjCIdType() ||
1068 BaseT->isObjCQualifiedIdType());
1069
David Blaikie4e4d0842012-03-11 07:00:24 +00001070 if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001071 AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1072 SourceLocation(), AtIndexGetterSelector,
1073 S.Context.getObjCIdType() /*ReturnType*/,
1074 0 /*TypeSourceInfo */,
1075 S.Context.getTranslationUnitDecl(),
1076 true /*Instance*/, false/*isVariadic*/,
Jordan Rose1e4691b2012-10-10 16:42:25 +00001077 /*isPropertyAccessor=*/false,
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001078 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1079 ObjCMethodDecl::Required,
1080 false);
1081 ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1082 SourceLocation(), SourceLocation(),
1083 arrayRef ? &S.Context.Idents.get("index")
1084 : &S.Context.Idents.get("key"),
1085 arrayRef ? S.Context.UnsignedLongTy
1086 : S.Context.getObjCIdType(),
1087 /*TInfo=*/0,
1088 SC_None,
1089 SC_None,
1090 0);
1091 AtIndexGetter->setMethodParams(S.Context, Argument,
1092 ArrayRef<SourceLocation>());
1093 }
1094
1095 if (!AtIndexGetter) {
1096 if (!receiverIdType) {
1097 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1098 << BaseExpr->getType() << 0 << arrayRef;
1099 return false;
1100 }
1101 AtIndexGetter =
1102 S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
1103 RefExpr->getSourceRange(),
1104 true, false);
1105 }
1106
1107 if (AtIndexGetter) {
1108 QualType T = AtIndexGetter->param_begin()[0]->getType();
1109 if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1110 (!arrayRef && !T->isObjCObjectPointerType())) {
1111 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1112 arrayRef ? diag::err_objc_subscript_index_type
1113 : diag::err_objc_subscript_key_type) << T;
1114 S.Diag(AtIndexGetter->param_begin()[0]->getLocation(),
1115 diag::note_parameter_type) << T;
1116 return false;
1117 }
1118 QualType R = AtIndexGetter->getResultType();
1119 if (!R->isObjCObjectPointerType()) {
1120 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1121 diag::err_objc_indexing_method_result_type) << R << arrayRef;
1122 S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1123 AtIndexGetter->getDeclName();
1124 }
1125 }
1126 return true;
1127}
1128
1129bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1130 if (AtIndexSetter)
1131 return true;
1132
1133 Expr *BaseExpr = RefExpr->getBaseExpr();
1134 QualType BaseT = BaseExpr->getType();
1135
1136 QualType ResultType;
1137 if (const ObjCObjectPointerType *PTy =
1138 BaseT->getAs<ObjCObjectPointerType>()) {
1139 ResultType = PTy->getPointeeType();
1140 if (const ObjCObjectType *iQFaceTy =
1141 ResultType->getAsObjCQualifiedInterfaceType())
1142 ResultType = iQFaceTy->getBaseType();
1143 }
1144
1145 Sema::ObjCSubscriptKind Res =
1146 S.CheckSubscriptingKind(RefExpr->getKeyExpr());
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001147 if (Res == Sema::OS_Error) {
1148 if (S.getLangOpts().ObjCAutoRefCount)
1149 CheckKeyForObjCARCConversion(S, ResultType,
1150 RefExpr->getKeyExpr());
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001151 return false;
Fariborz Jahaniandc483052012-08-02 18:03:58 +00001152 }
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001153 bool arrayRef = (Res == Sema::OS_Array);
1154
1155 if (ResultType.isNull()) {
1156 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1157 << BaseExpr->getType() << arrayRef;
1158 return false;
1159 }
1160
1161 if (!arrayRef) {
1162 // dictionary subscripting.
1163 // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1164 IdentifierInfo *KeyIdents[] = {
1165 &S.Context.Idents.get("setObject"),
1166 &S.Context.Idents.get("forKeyedSubscript")
1167 };
1168 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1169 }
1170 else {
1171 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1172 IdentifierInfo *KeyIdents[] = {
1173 &S.Context.Idents.get("setObject"),
1174 &S.Context.Idents.get("atIndexedSubscript")
1175 };
1176 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1177 }
1178 AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
1179 true /*instance*/);
1180
1181 bool receiverIdType = (BaseT->isObjCIdType() ||
1182 BaseT->isObjCQualifiedIdType());
1183
David Blaikie4e4d0842012-03-11 07:00:24 +00001184 if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001185 TypeSourceInfo *ResultTInfo = 0;
1186 QualType ReturnType = S.Context.VoidTy;
1187 AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1188 SourceLocation(), AtIndexSetterSelector,
1189 ReturnType,
1190 ResultTInfo,
1191 S.Context.getTranslationUnitDecl(),
1192 true /*Instance*/, false/*isVariadic*/,
Jordan Rose1e4691b2012-10-10 16:42:25 +00001193 /*isPropertyAccessor=*/false,
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001194 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1195 ObjCMethodDecl::Required,
1196 false);
1197 SmallVector<ParmVarDecl *, 2> Params;
1198 ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1199 SourceLocation(), SourceLocation(),
1200 &S.Context.Idents.get("object"),
1201 S.Context.getObjCIdType(),
1202 /*TInfo=*/0,
1203 SC_None,
1204 SC_None,
1205 0);
1206 Params.push_back(object);
1207 ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1208 SourceLocation(), SourceLocation(),
1209 arrayRef ? &S.Context.Idents.get("index")
1210 : &S.Context.Idents.get("key"),
1211 arrayRef ? S.Context.UnsignedLongTy
1212 : S.Context.getObjCIdType(),
1213 /*TInfo=*/0,
1214 SC_None,
1215 SC_None,
1216 0);
1217 Params.push_back(key);
1218 AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
1219 }
1220
1221 if (!AtIndexSetter) {
1222 if (!receiverIdType) {
1223 S.Diag(BaseExpr->getExprLoc(),
1224 diag::err_objc_subscript_method_not_found)
1225 << BaseExpr->getType() << 1 << arrayRef;
1226 return false;
1227 }
1228 AtIndexSetter =
1229 S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
1230 RefExpr->getSourceRange(),
1231 true, false);
1232 }
1233
1234 bool err = false;
1235 if (AtIndexSetter && arrayRef) {
1236 QualType T = AtIndexSetter->param_begin()[1]->getType();
1237 if (!T->isIntegralOrEnumerationType()) {
1238 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1239 diag::err_objc_subscript_index_type) << T;
1240 S.Diag(AtIndexSetter->param_begin()[1]->getLocation(),
1241 diag::note_parameter_type) << T;
1242 err = true;
1243 }
1244 T = AtIndexSetter->param_begin()[0]->getType();
1245 if (!T->isObjCObjectPointerType()) {
1246 S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1247 diag::err_objc_subscript_object_type) << T << arrayRef;
1248 S.Diag(AtIndexSetter->param_begin()[0]->getLocation(),
1249 diag::note_parameter_type) << T;
1250 err = true;
1251 }
1252 }
1253 else if (AtIndexSetter && !arrayRef)
1254 for (unsigned i=0; i <2; i++) {
1255 QualType T = AtIndexSetter->param_begin()[i]->getType();
1256 if (!T->isObjCObjectPointerType()) {
1257 if (i == 1)
1258 S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1259 diag::err_objc_subscript_key_type) << T;
1260 else
1261 S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1262 diag::err_objc_subscript_dic_object_type) << T;
1263 S.Diag(AtIndexSetter->param_begin()[i]->getLocation(),
1264 diag::note_parameter_type) << T;
1265 err = true;
1266 }
1267 }
1268
1269 return !err;
1270}
1271
1272// Get the object at "Index" position in the container.
1273// [BaseExpr objectAtIndexedSubscript : IndexExpr];
1274ExprResult ObjCSubscriptOpBuilder::buildGet() {
1275 if (!findAtIndexGetter())
1276 return ExprError();
1277
1278 QualType receiverType = InstanceBase->getType();
1279
1280 // Build a message-send.
1281 ExprResult msg;
1282 Expr *Index = InstanceKey;
1283
1284 // Arguments.
1285 Expr *args[] = { Index };
1286 assert(InstanceBase);
1287 msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1288 GenericLoc,
1289 AtIndexGetterSelector, AtIndexGetter,
1290 MultiExprArg(args, 1));
1291 return msg;
1292}
1293
1294/// Store into the container the "op" object at "Index"'ed location
1295/// by building this messaging expression:
1296/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00001297/// \param captureSetValueAsResult If true, capture the actual
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001298/// value being set as the value of the property operation.
1299ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
1300 bool captureSetValueAsResult) {
1301 if (!findAtIndexSetter())
1302 return ExprError();
1303
1304 QualType receiverType = InstanceBase->getType();
1305 Expr *Index = InstanceKey;
1306
1307 // Arguments.
1308 Expr *args[] = { op, Index };
1309
1310 // Build a message-send.
1311 ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1312 GenericLoc,
1313 AtIndexSetterSelector,
1314 AtIndexSetter,
1315 MultiExprArg(args, 2));
1316
1317 if (!msg.isInvalid() && captureSetValueAsResult) {
1318 ObjCMessageExpr *msgExpr =
1319 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1320 Expr *arg = msgExpr->getArg(0);
Eli Friedman25f071e2012-11-13 23:16:33 +00001321 if (CanCaptureValueOfType(arg->getType()))
1322 msgExpr->setArg(0, captureValueAsResult(arg));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001323 }
1324
1325 return msg;
1326}
1327
John McCall4b9c2d22011-11-06 09:01:30 +00001328//===----------------------------------------------------------------------===//
1329// General Sema routines.
1330//===----------------------------------------------------------------------===//
1331
1332ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
1333 Expr *opaqueRef = E->IgnoreParens();
1334 if (ObjCPropertyRefExpr *refExpr
1335 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1336 ObjCPropertyOpBuilder builder(*this, refExpr);
1337 return builder.buildRValueOperation(E);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001338 }
1339 else if (ObjCSubscriptRefExpr *refExpr
1340 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1341 ObjCSubscriptOpBuilder builder(*this, refExpr);
1342 return builder.buildRValueOperation(E);
John McCall4b9c2d22011-11-06 09:01:30 +00001343 } else {
1344 llvm_unreachable("unknown pseudo-object kind!");
1345 }
1346}
1347
1348/// Check an increment or decrement of a pseudo-object expression.
1349ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
1350 UnaryOperatorKind opcode, Expr *op) {
1351 // Do nothing if the operand is dependent.
1352 if (op->isTypeDependent())
1353 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
1354 VK_RValue, OK_Ordinary, opcLoc);
1355
1356 assert(UnaryOperator::isIncrementDecrementOp(opcode));
1357 Expr *opaqueRef = op->IgnoreParens();
1358 if (ObjCPropertyRefExpr *refExpr
1359 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1360 ObjCPropertyOpBuilder builder(*this, refExpr);
1361 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001362 } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1363 Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1364 return ExprError();
John McCall4b9c2d22011-11-06 09:01:30 +00001365 } else {
1366 llvm_unreachable("unknown pseudo-object kind!");
1367 }
1368}
1369
1370ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
1371 BinaryOperatorKind opcode,
1372 Expr *LHS, Expr *RHS) {
1373 // Do nothing if either argument is dependent.
1374 if (LHS->isTypeDependent() || RHS->isTypeDependent())
1375 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
Lang Hamesbe9af122012-10-02 04:45:10 +00001376 VK_RValue, OK_Ordinary, opcLoc, false);
John McCall4b9c2d22011-11-06 09:01:30 +00001377
1378 // Filter out non-overload placeholder types in the RHS.
John McCall32509f12011-11-15 01:35:18 +00001379 if (RHS->getType()->isNonOverloadPlaceholderType()) {
1380 ExprResult result = CheckPlaceholderExpr(RHS);
1381 if (result.isInvalid()) return ExprError();
1382 RHS = result.take();
John McCall4b9c2d22011-11-06 09:01:30 +00001383 }
1384
1385 Expr *opaqueRef = LHS->IgnoreParens();
1386 if (ObjCPropertyRefExpr *refExpr
1387 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1388 ObjCPropertyOpBuilder builder(*this, refExpr);
1389 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001390 } else if (ObjCSubscriptRefExpr *refExpr
1391 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1392 ObjCSubscriptOpBuilder builder(*this, refExpr);
1393 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
John McCall4b9c2d22011-11-06 09:01:30 +00001394 } else {
1395 llvm_unreachable("unknown pseudo-object kind!");
1396 }
1397}
John McCall01e19be2011-11-30 04:42:31 +00001398
1399/// Given a pseudo-object reference, rebuild it without the opaque
1400/// values. Basically, undo the behavior of rebuildAndCaptureObject.
1401/// This should never operate in-place.
1402static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
1403 Expr *opaqueRef = E->IgnoreParens();
1404 if (ObjCPropertyRefExpr *refExpr
1405 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
Douglas Gregor88507dd2012-04-13 16:05:42 +00001406 // Class and super property references don't have opaque values in them.
1407 if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
1408 return E;
1409
1410 assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
1411 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
1412 return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001413 } else if (ObjCSubscriptRefExpr *refExpr
1414 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1415 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
1416 OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
1417 return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
1418 keyOVE->getSourceExpr()).rebuild(E);
John McCall01e19be2011-11-30 04:42:31 +00001419 } else {
1420 llvm_unreachable("unknown pseudo-object kind!");
1421 }
1422}
1423
1424/// Given a pseudo-object expression, recreate what it looks like
1425/// syntactically without the attendant OpaqueValueExprs.
1426///
1427/// This is a hack which should be removed when TreeTransform is
1428/// capable of rebuilding a tree without stripping implicit
1429/// operations.
1430Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
1431 Expr *syntax = E->getSyntacticForm();
1432 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
1433 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
1434 return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
1435 uop->getValueKind(), uop->getObjectKind(),
1436 uop->getOperatorLoc());
1437 } else if (CompoundAssignOperator *cop
1438 = dyn_cast<CompoundAssignOperator>(syntax)) {
1439 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
1440 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
1441 return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
1442 cop->getType(),
1443 cop->getValueKind(),
1444 cop->getObjectKind(),
1445 cop->getComputationLHSType(),
1446 cop->getComputationResultType(),
Lang Hamesbe9af122012-10-02 04:45:10 +00001447 cop->getOperatorLoc(), false);
John McCall01e19be2011-11-30 04:42:31 +00001448 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
1449 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
1450 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
1451 return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
1452 bop->getType(), bop->getValueKind(),
1453 bop->getObjectKind(),
Lang Hamesbe9af122012-10-02 04:45:10 +00001454 bop->getOperatorLoc(), false);
John McCall01e19be2011-11-30 04:42:31 +00001455 } else {
1456 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
1457 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
1458 }
1459}