1 //===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements semantic analysis for expressions involving
10 // pseudo-object references. Pseudo-objects are conceptual objects
11 // whose storage is entirely abstract and all accesses to which are
12 // translated through some sort of abstraction barrier.
14 // For example, Objective-C objects can have "properties", either
15 // declared or undeclared. A property may be accessed by writing
17 // where 'expr' is an r-value of Objective-C pointer type and 'prop'
18 // is the name of the property. If this expression is used in a context
19 // needing an r-value, it is treated as if it were a message-send
20 // of the associated 'getter' selector, typically:
22 // If it is used as the LHS of a simple assignment, it is treated
23 // as a message-send of the associated 'setter' selector, typically:
24 // [expr setProp: RHS]
25 // If it is used as the LHS of a compound assignment, or the operand
26 // of a unary increment or decrement, both are required; for example,
27 // 'expr.prop *= 100' would be translated to:
28 // [expr setProp: [expr prop] * 100]
30 //===----------------------------------------------------------------------===//
32 #include "clang/Sema/SemaPseudoObject.h"
33 #include "clang/AST/ExprCXX.h"
34 #include "clang/AST/ExprObjC.h"
35 #include "clang/Basic/CharInfo.h"
36 #include "clang/Lex/Preprocessor.h"
37 #include "clang/Sema/Initialization.h"
38 #include "clang/Sema/ScopeInfo.h"
39 #include "clang/Sema/SemaObjC.h"
41 using namespace clang
;
45 // Basically just a very focused copy of TreeTransform.
48 unsigned MSPropertySubscriptCount
;
49 typedef llvm::function_ref
<Expr
*(Expr
*, unsigned)> SpecificRebuilderRefTy
;
50 const SpecificRebuilderRefTy
&SpecificCallback
;
51 Rebuilder(Sema
&S
, const SpecificRebuilderRefTy
&SpecificCallback
)
52 : S(S
), MSPropertySubscriptCount(0),
53 SpecificCallback(SpecificCallback
) {}
55 Expr
*rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr
*refExpr
) {
56 // Fortunately, the constraint that we're rebuilding something
57 // with a base limits the number of cases here.
58 if (refExpr
->isClassReceiver() || refExpr
->isSuperReceiver())
61 if (refExpr
->isExplicitProperty()) {
62 return new (S
.Context
) ObjCPropertyRefExpr(
63 refExpr
->getExplicitProperty(), refExpr
->getType(),
64 refExpr
->getValueKind(), refExpr
->getObjectKind(),
65 refExpr
->getLocation(), SpecificCallback(refExpr
->getBase(), 0));
67 return new (S
.Context
) ObjCPropertyRefExpr(
68 refExpr
->getImplicitPropertyGetter(),
69 refExpr
->getImplicitPropertySetter(), refExpr
->getType(),
70 refExpr
->getValueKind(), refExpr
->getObjectKind(),
71 refExpr
->getLocation(), SpecificCallback(refExpr
->getBase(), 0));
73 Expr
*rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr
*refExpr
) {
74 assert(refExpr
->getBaseExpr());
75 assert(refExpr
->getKeyExpr());
77 return new (S
.Context
) ObjCSubscriptRefExpr(
78 SpecificCallback(refExpr
->getBaseExpr(), 0),
79 SpecificCallback(refExpr
->getKeyExpr(), 1), refExpr
->getType(),
80 refExpr
->getValueKind(), refExpr
->getObjectKind(),
81 refExpr
->getAtIndexMethodDecl(), refExpr
->setAtIndexMethodDecl(),
82 refExpr
->getRBracket());
84 Expr
*rebuildMSPropertyRefExpr(MSPropertyRefExpr
*refExpr
) {
85 assert(refExpr
->getBaseExpr());
87 return new (S
.Context
) MSPropertyRefExpr(
88 SpecificCallback(refExpr
->getBaseExpr(), 0),
89 refExpr
->getPropertyDecl(), refExpr
->isArrow(), refExpr
->getType(),
90 refExpr
->getValueKind(), refExpr
->getQualifierLoc(),
91 refExpr
->getMemberLoc());
93 Expr
*rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr
*refExpr
) {
94 assert(refExpr
->getBase());
95 assert(refExpr
->getIdx());
97 auto *NewBase
= rebuild(refExpr
->getBase());
98 ++MSPropertySubscriptCount
;
99 return new (S
.Context
) MSPropertySubscriptExpr(
101 SpecificCallback(refExpr
->getIdx(), MSPropertySubscriptCount
),
102 refExpr
->getType(), refExpr
->getValueKind(), refExpr
->getObjectKind(),
103 refExpr
->getRBracketLoc());
106 Expr
*rebuild(Expr
*e
) {
107 // Fast path: nothing to look through.
108 if (auto *PRE
= dyn_cast
<ObjCPropertyRefExpr
>(e
))
109 return rebuildObjCPropertyRefExpr(PRE
);
110 if (auto *SRE
= dyn_cast
<ObjCSubscriptRefExpr
>(e
))
111 return rebuildObjCSubscriptRefExpr(SRE
);
112 if (auto *MSPRE
= dyn_cast
<MSPropertyRefExpr
>(e
))
113 return rebuildMSPropertyRefExpr(MSPRE
);
114 if (auto *MSPSE
= dyn_cast
<MSPropertySubscriptExpr
>(e
))
115 return rebuildMSPropertySubscriptExpr(MSPSE
);
117 // Otherwise, we should look through and rebuild anything that
118 // IgnoreParens would.
120 if (ParenExpr
*parens
= dyn_cast
<ParenExpr
>(e
)) {
121 e
= rebuild(parens
->getSubExpr());
122 return new (S
.Context
) ParenExpr(parens
->getLParen(),
127 if (UnaryOperator
*uop
= dyn_cast
<UnaryOperator
>(e
)) {
128 assert(uop
->getOpcode() == UO_Extension
);
129 e
= rebuild(uop
->getSubExpr());
130 return UnaryOperator::Create(
131 S
.Context
, e
, uop
->getOpcode(), uop
->getType(), uop
->getValueKind(),
132 uop
->getObjectKind(), uop
->getOperatorLoc(), uop
->canOverflow(),
133 S
.CurFPFeatureOverrides());
136 if (GenericSelectionExpr
*gse
= dyn_cast
<GenericSelectionExpr
>(e
)) {
137 assert(!gse
->isResultDependent());
138 unsigned resultIndex
= gse
->getResultIndex();
139 unsigned numAssocs
= gse
->getNumAssocs();
141 SmallVector
<Expr
*, 8> assocExprs
;
142 SmallVector
<TypeSourceInfo
*, 8> assocTypes
;
143 assocExprs
.reserve(numAssocs
);
144 assocTypes
.reserve(numAssocs
);
146 for (const GenericSelectionExpr::Association assoc
:
147 gse
->associations()) {
148 Expr
*assocExpr
= assoc
.getAssociationExpr();
149 if (assoc
.isSelected())
150 assocExpr
= rebuild(assocExpr
);
151 assocExprs
.push_back(assocExpr
);
152 assocTypes
.push_back(assoc
.getTypeSourceInfo());
155 if (gse
->isExprPredicate())
156 return GenericSelectionExpr::Create(
157 S
.Context
, gse
->getGenericLoc(), gse
->getControllingExpr(),
158 assocTypes
, assocExprs
, gse
->getDefaultLoc(), gse
->getRParenLoc(),
159 gse
->containsUnexpandedParameterPack(), resultIndex
);
160 return GenericSelectionExpr::Create(
161 S
.Context
, gse
->getGenericLoc(), gse
->getControllingType(),
162 assocTypes
, assocExprs
, gse
->getDefaultLoc(), gse
->getRParenLoc(),
163 gse
->containsUnexpandedParameterPack(), resultIndex
);
166 if (ChooseExpr
*ce
= dyn_cast
<ChooseExpr
>(e
)) {
167 assert(!ce
->isConditionDependent());
169 Expr
*LHS
= ce
->getLHS(), *RHS
= ce
->getRHS();
170 Expr
*&rebuiltExpr
= ce
->isConditionTrue() ? LHS
: RHS
;
171 rebuiltExpr
= rebuild(rebuiltExpr
);
173 return new (S
.Context
)
174 ChooseExpr(ce
->getBuiltinLoc(), ce
->getCond(), LHS
, RHS
,
175 rebuiltExpr
->getType(), rebuiltExpr
->getValueKind(),
176 rebuiltExpr
->getObjectKind(), ce
->getRParenLoc(),
177 ce
->isConditionTrue());
180 llvm_unreachable("bad expression to rebuild!");
184 class PseudoOpBuilder
{
187 unsigned ResultIndex
;
188 SourceLocation GenericLoc
;
190 SmallVector
<Expr
*, 4> Semantics
;
192 PseudoOpBuilder(Sema
&S
, SourceLocation genericLoc
, bool IsUnique
)
193 : S(S
), ResultIndex(PseudoObjectExpr::NoResult
),
194 GenericLoc(genericLoc
), IsUnique(IsUnique
) {}
196 virtual ~PseudoOpBuilder() {}
198 /// Add a normal semantic expression.
199 void addSemanticExpr(Expr
*semantic
) {
200 Semantics
.push_back(semantic
);
203 /// Add the 'result' semantic expression.
204 void addResultSemanticExpr(Expr
*resultExpr
) {
205 assert(ResultIndex
== PseudoObjectExpr::NoResult
);
206 ResultIndex
= Semantics
.size();
207 Semantics
.push_back(resultExpr
);
208 // An OVE is not unique if it is used as the result expression.
209 if (auto *OVE
= dyn_cast
<OpaqueValueExpr
>(Semantics
.back()))
210 OVE
->setIsUnique(false);
213 ExprResult
buildRValueOperation(Expr
*op
);
214 ExprResult
buildAssignmentOperation(Scope
*Sc
,
215 SourceLocation opLoc
,
216 BinaryOperatorKind opcode
,
217 Expr
*LHS
, Expr
*RHS
);
218 ExprResult
buildIncDecOperation(Scope
*Sc
, SourceLocation opLoc
,
219 UnaryOperatorKind opcode
,
222 virtual ExprResult
complete(Expr
*syntacticForm
);
224 OpaqueValueExpr
*capture(Expr
*op
);
225 OpaqueValueExpr
*captureValueAsResult(Expr
*op
);
227 void setResultToLastSemantic() {
228 assert(ResultIndex
== PseudoObjectExpr::NoResult
);
229 ResultIndex
= Semantics
.size() - 1;
230 // An OVE is not unique if it is used as the result expression.
231 if (auto *OVE
= dyn_cast
<OpaqueValueExpr
>(Semantics
.back()))
232 OVE
->setIsUnique(false);
235 /// Return true if assignments have a non-void result.
236 static bool CanCaptureValue(Expr
*exp
) {
237 if (exp
->isGLValue())
239 QualType ty
= exp
->getType();
240 assert(!ty
->isIncompleteType());
241 assert(!ty
->isDependentType());
243 if (const CXXRecordDecl
*ClassDecl
= ty
->getAsCXXRecordDecl())
244 return ClassDecl
->isTriviallyCopyable();
248 virtual Expr
*rebuildAndCaptureObject(Expr
*) = 0;
249 virtual ExprResult
buildGet() = 0;
250 virtual ExprResult
buildSet(Expr
*, SourceLocation
,
251 bool captureSetValueAsResult
) = 0;
252 /// Should the result of an assignment be the formal result of the
253 /// setter call or the value that was passed to the setter?
255 /// Different pseudo-object language features use different language rules
257 /// The default is to use the set value. Currently, this affects the
258 /// behavior of simple assignments, compound assignments, and prefix
259 /// increment and decrement.
260 /// Postfix increment and decrement always use the getter result as the
261 /// expression result.
263 /// If this method returns true, and the set value isn't capturable for
264 /// some reason, the result of the expression will be void.
265 virtual bool captureSetValueAsResult() const { return true; }
268 /// A PseudoOpBuilder for Objective-C \@properties.
269 class ObjCPropertyOpBuilder
: public PseudoOpBuilder
{
270 ObjCPropertyRefExpr
*RefExpr
;
271 ObjCPropertyRefExpr
*SyntacticRefExpr
;
272 OpaqueValueExpr
*InstanceReceiver
;
273 ObjCMethodDecl
*Getter
;
275 ObjCMethodDecl
*Setter
;
276 Selector SetterSelector
;
277 Selector GetterSelector
;
280 ObjCPropertyOpBuilder(Sema
&S
, ObjCPropertyRefExpr
*refExpr
, bool IsUnique
)
281 : PseudoOpBuilder(S
, refExpr
->getLocation(), IsUnique
),
282 RefExpr(refExpr
), SyntacticRefExpr(nullptr),
283 InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {
286 ExprResult
buildRValueOperation(Expr
*op
);
287 ExprResult
buildAssignmentOperation(Scope
*Sc
,
288 SourceLocation opLoc
,
289 BinaryOperatorKind opcode
,
290 Expr
*LHS
, Expr
*RHS
);
291 ExprResult
buildIncDecOperation(Scope
*Sc
, SourceLocation opLoc
,
292 UnaryOperatorKind opcode
,
295 bool tryBuildGetOfReference(Expr
*op
, ExprResult
&result
);
296 bool findSetter(bool warn
=true);
298 void DiagnoseUnsupportedPropertyUse();
300 Expr
*rebuildAndCaptureObject(Expr
*syntacticBase
) override
;
301 ExprResult
buildGet() override
;
302 ExprResult
buildSet(Expr
*op
, SourceLocation
, bool) override
;
303 ExprResult
complete(Expr
*SyntacticForm
) override
;
305 bool isWeakProperty() const;
308 /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
309 class ObjCSubscriptOpBuilder
: public PseudoOpBuilder
{
310 ObjCSubscriptRefExpr
*RefExpr
;
311 OpaqueValueExpr
*InstanceBase
;
312 OpaqueValueExpr
*InstanceKey
;
313 ObjCMethodDecl
*AtIndexGetter
;
314 Selector AtIndexGetterSelector
;
316 ObjCMethodDecl
*AtIndexSetter
;
317 Selector AtIndexSetterSelector
;
320 ObjCSubscriptOpBuilder(Sema
&S
, ObjCSubscriptRefExpr
*refExpr
, bool IsUnique
)
321 : PseudoOpBuilder(S
, refExpr
->getSourceRange().getBegin(), IsUnique
),
322 RefExpr(refExpr
), InstanceBase(nullptr), InstanceKey(nullptr),
323 AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
325 ExprResult
buildRValueOperation(Expr
*op
);
326 ExprResult
buildAssignmentOperation(Scope
*Sc
,
327 SourceLocation opLoc
,
328 BinaryOperatorKind opcode
,
329 Expr
*LHS
, Expr
*RHS
);
330 Expr
*rebuildAndCaptureObject(Expr
*syntacticBase
) override
;
332 bool findAtIndexGetter();
333 bool findAtIndexSetter();
335 ExprResult
buildGet() override
;
336 ExprResult
buildSet(Expr
*op
, SourceLocation
, bool) override
;
339 class MSPropertyOpBuilder
: public PseudoOpBuilder
{
340 MSPropertyRefExpr
*RefExpr
;
341 OpaqueValueExpr
*InstanceBase
;
342 SmallVector
<Expr
*, 4> CallArgs
;
344 MSPropertyRefExpr
*getBaseMSProperty(MSPropertySubscriptExpr
*E
);
347 MSPropertyOpBuilder(Sema
&S
, MSPropertyRefExpr
*refExpr
, bool IsUnique
)
348 : PseudoOpBuilder(S
, refExpr
->getSourceRange().getBegin(), IsUnique
),
349 RefExpr(refExpr
), InstanceBase(nullptr) {}
350 MSPropertyOpBuilder(Sema
&S
, MSPropertySubscriptExpr
*refExpr
, bool IsUnique
)
351 : PseudoOpBuilder(S
, refExpr
->getSourceRange().getBegin(), IsUnique
),
352 InstanceBase(nullptr) {
353 RefExpr
= getBaseMSProperty(refExpr
);
356 Expr
*rebuildAndCaptureObject(Expr
*) override
;
357 ExprResult
buildGet() override
;
358 ExprResult
buildSet(Expr
*op
, SourceLocation
, bool) override
;
359 bool captureSetValueAsResult() const override
{ return false; }
363 /// Capture the given expression in an OpaqueValueExpr.
364 OpaqueValueExpr
*PseudoOpBuilder::capture(Expr
*e
) {
365 // Make a new OVE whose source is the given expression.
366 OpaqueValueExpr
*captured
=
367 new (S
.Context
) OpaqueValueExpr(GenericLoc
, e
->getType(),
368 e
->getValueKind(), e
->getObjectKind(),
371 captured
->setIsUnique(true);
373 // Make sure we bind that in the semantics.
374 addSemanticExpr(captured
);
378 /// Capture the given expression as the result of this pseudo-object
379 /// operation. This routine is safe against expressions which may
380 /// already be captured.
382 /// \returns the captured expression, which will be the
383 /// same as the input if the input was already captured
384 OpaqueValueExpr
*PseudoOpBuilder::captureValueAsResult(Expr
*e
) {
385 assert(ResultIndex
== PseudoObjectExpr::NoResult
);
387 // If the expression hasn't already been captured, just capture it
388 // and set the new semantic
389 if (!isa
<OpaqueValueExpr
>(e
)) {
390 OpaqueValueExpr
*cap
= capture(e
);
391 setResultToLastSemantic();
395 // Otherwise, it must already be one of our semantic expressions;
396 // set ResultIndex to its index.
399 assert(index
< Semantics
.size() &&
400 "captured expression not found in semantics!");
401 if (e
== Semantics
[index
]) break;
404 // An OVE is not unique if it is used as the result expression.
405 cast
<OpaqueValueExpr
>(e
)->setIsUnique(false);
406 return cast
<OpaqueValueExpr
>(e
);
409 /// The routine which creates the final PseudoObjectExpr.
410 ExprResult
PseudoOpBuilder::complete(Expr
*syntactic
) {
411 return PseudoObjectExpr::Create(S
.Context
, syntactic
,
412 Semantics
, ResultIndex
);
415 /// The main skeleton for building an r-value operation.
416 ExprResult
PseudoOpBuilder::buildRValueOperation(Expr
*op
) {
417 Expr
*syntacticBase
= rebuildAndCaptureObject(op
);
419 ExprResult getExpr
= buildGet();
420 if (getExpr
.isInvalid()) return ExprError();
421 addResultSemanticExpr(getExpr
.get());
423 return complete(syntacticBase
);
426 /// The basic skeleton for building a simple or compound
427 /// assignment operation.
429 PseudoOpBuilder::buildAssignmentOperation(Scope
*Sc
, SourceLocation opcLoc
,
430 BinaryOperatorKind opcode
,
431 Expr
*LHS
, Expr
*RHS
) {
432 assert(BinaryOperator::isAssignmentOp(opcode
));
434 Expr
*syntacticLHS
= rebuildAndCaptureObject(LHS
);
435 OpaqueValueExpr
*capturedRHS
= capture(RHS
);
437 // In some very specific cases, semantic analysis of the RHS as an
438 // expression may require it to be rewritten. In these cases, we
439 // cannot safely keep the OVE around. Fortunately, we don't really
440 // need to: we don't use this particular OVE in multiple places, and
441 // no clients rely that closely on matching up expressions in the
442 // semantic expression with expressions from the syntactic form.
443 Expr
*semanticRHS
= capturedRHS
;
444 if (RHS
->hasPlaceholderType() || isa
<InitListExpr
>(RHS
)) {
446 Semantics
.pop_back();
452 if (opcode
== BO_Assign
) {
453 result
= semanticRHS
;
454 syntactic
= BinaryOperator::Create(S
.Context
, syntacticLHS
, capturedRHS
,
455 opcode
, capturedRHS
->getType(),
456 capturedRHS
->getValueKind(), OK_Ordinary
,
457 opcLoc
, S
.CurFPFeatureOverrides());
460 ExprResult opLHS
= buildGet();
461 if (opLHS
.isInvalid()) return ExprError();
463 // Build an ordinary, non-compound operation.
464 BinaryOperatorKind nonCompound
=
465 BinaryOperator::getOpForCompoundAssignment(opcode
);
466 result
= S
.BuildBinOp(Sc
, opcLoc
, nonCompound
, opLHS
.get(), semanticRHS
);
467 if (result
.isInvalid()) return ExprError();
469 syntactic
= CompoundAssignOperator::Create(
470 S
.Context
, syntacticLHS
, capturedRHS
, opcode
, result
.get()->getType(),
471 result
.get()->getValueKind(), OK_Ordinary
, opcLoc
,
472 S
.CurFPFeatureOverrides(), opLHS
.get()->getType(),
473 result
.get()->getType());
476 // The result of the assignment, if not void, is the value set into
478 result
= buildSet(result
.get(), opcLoc
, captureSetValueAsResult());
479 if (result
.isInvalid()) return ExprError();
480 addSemanticExpr(result
.get());
481 if (!captureSetValueAsResult() && !result
.get()->getType()->isVoidType() &&
482 (result
.get()->isTypeDependent() || CanCaptureValue(result
.get())))
483 setResultToLastSemantic();
485 return complete(syntactic
);
488 /// The basic skeleton for building an increment or decrement
491 PseudoOpBuilder::buildIncDecOperation(Scope
*Sc
, SourceLocation opcLoc
,
492 UnaryOperatorKind opcode
,
494 assert(UnaryOperator::isIncrementDecrementOp(opcode
));
496 Expr
*syntacticOp
= rebuildAndCaptureObject(op
);
499 ExprResult result
= buildGet();
500 if (result
.isInvalid()) return ExprError();
502 QualType resultType
= result
.get()->getType();
504 // That's the postfix result.
505 if (UnaryOperator::isPostfix(opcode
) &&
506 (result
.get()->isTypeDependent() || CanCaptureValue(result
.get()))) {
507 result
= capture(result
.get());
508 setResultToLastSemantic();
511 // Add or subtract a literal 1.
512 llvm::APInt
oneV(S
.Context
.getTypeSize(S
.Context
.IntTy
), 1);
513 Expr
*one
= IntegerLiteral::Create(S
.Context
, oneV
, S
.Context
.IntTy
,
516 if (UnaryOperator::isIncrementOp(opcode
)) {
517 result
= S
.BuildBinOp(Sc
, opcLoc
, BO_Add
, result
.get(), one
);
519 result
= S
.BuildBinOp(Sc
, opcLoc
, BO_Sub
, result
.get(), one
);
521 if (result
.isInvalid()) return ExprError();
523 // Store that back into the result. The value stored is the result
524 // of a prefix operation.
525 result
= buildSet(result
.get(), opcLoc
, UnaryOperator::isPrefix(opcode
) &&
526 captureSetValueAsResult());
527 if (result
.isInvalid()) return ExprError();
528 addSemanticExpr(result
.get());
529 if (UnaryOperator::isPrefix(opcode
) && !captureSetValueAsResult() &&
530 !result
.get()->getType()->isVoidType() &&
531 (result
.get()->isTypeDependent() || CanCaptureValue(result
.get())))
532 setResultToLastSemantic();
534 UnaryOperator
*syntactic
=
535 UnaryOperator::Create(S
.Context
, syntacticOp
, opcode
, resultType
,
536 VK_LValue
, OK_Ordinary
, opcLoc
,
537 !resultType
->isDependentType()
538 ? S
.Context
.getTypeSize(resultType
) >=
539 S
.Context
.getTypeSize(S
.Context
.IntTy
)
541 S
.CurFPFeatureOverrides());
542 return complete(syntactic
);
546 //===----------------------------------------------------------------------===//
547 // Objective-C @property and implicit property references
548 //===----------------------------------------------------------------------===//
550 /// Look up a method in the receiver type of an Objective-C property
552 static ObjCMethodDecl
*LookupMethodInReceiverType(Sema
&S
, Selector sel
,
553 const ObjCPropertyRefExpr
*PRE
) {
554 if (PRE
->isObjectReceiver()) {
555 const ObjCObjectPointerType
*PT
=
556 PRE
->getBase()->getType()->castAs
<ObjCObjectPointerType
>();
558 // Special case for 'self' in class method implementations.
559 if (PT
->isObjCClassType() &&
560 S
.ObjC().isSelfExpr(const_cast<Expr
*>(PRE
->getBase()))) {
561 // This cast is safe because isSelfExpr is only true within
563 ObjCMethodDecl
*method
=
564 cast
<ObjCMethodDecl
>(S
.CurContext
->getNonClosureAncestor());
565 return S
.ObjC().LookupMethodInObjectType(
566 sel
, S
.Context
.getObjCInterfaceType(method
->getClassInterface()),
570 return S
.ObjC().LookupMethodInObjectType(sel
, PT
->getPointeeType(), true);
573 if (PRE
->isSuperReceiver()) {
574 if (const ObjCObjectPointerType
*PT
=
575 PRE
->getSuperReceiverType()->getAs
<ObjCObjectPointerType
>())
576 return S
.ObjC().LookupMethodInObjectType(sel
, PT
->getPointeeType(), true);
578 return S
.ObjC().LookupMethodInObjectType(sel
, PRE
->getSuperReceiverType(),
582 assert(PRE
->isClassReceiver() && "Invalid expression");
583 QualType IT
= S
.Context
.getObjCInterfaceType(PRE
->getClassReceiver());
584 return S
.ObjC().LookupMethodInObjectType(sel
, IT
, false);
587 bool ObjCPropertyOpBuilder::isWeakProperty() const {
589 if (RefExpr
->isExplicitProperty()) {
590 const ObjCPropertyDecl
*Prop
= RefExpr
->getExplicitProperty();
591 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak
)
596 T
= Getter
->getReturnType();
601 return T
.getObjCLifetime() == Qualifiers::OCL_Weak
;
604 bool ObjCPropertyOpBuilder::findGetter() {
605 if (Getter
) return true;
607 // For implicit properties, just trust the lookup we already did.
608 if (RefExpr
->isImplicitProperty()) {
609 if ((Getter
= RefExpr
->getImplicitPropertyGetter())) {
610 GetterSelector
= Getter
->getSelector();
614 // Must build the getter selector the hard way.
615 ObjCMethodDecl
*setter
= RefExpr
->getImplicitPropertySetter();
616 assert(setter
&& "both setter and getter are null - cannot happen");
617 const IdentifierInfo
*setterName
=
618 setter
->getSelector().getIdentifierInfoForSlot(0);
619 const IdentifierInfo
*getterName
=
620 &S
.Context
.Idents
.get(setterName
->getName().substr(3));
622 S
.PP
.getSelectorTable().getNullarySelector(getterName
);
627 ObjCPropertyDecl
*prop
= RefExpr
->getExplicitProperty();
628 Getter
= LookupMethodInReceiverType(S
, prop
->getGetterName(), RefExpr
);
629 return (Getter
!= nullptr);
632 /// Try to find the most accurate setter declaration for the property
635 /// \return true if a setter was found, in which case Setter
636 bool ObjCPropertyOpBuilder::findSetter(bool warn
) {
637 // For implicit properties, just trust the lookup we already did.
638 if (RefExpr
->isImplicitProperty()) {
639 if (ObjCMethodDecl
*setter
= RefExpr
->getImplicitPropertySetter()) {
641 SetterSelector
= setter
->getSelector();
644 const IdentifierInfo
*getterName
= RefExpr
->getImplicitPropertyGetter()
646 .getIdentifierInfoForSlot(0);
648 SelectorTable::constructSetterSelector(S
.PP
.getIdentifierTable(),
649 S
.PP
.getSelectorTable(),
655 // For explicit properties, this is more involved.
656 ObjCPropertyDecl
*prop
= RefExpr
->getExplicitProperty();
657 SetterSelector
= prop
->getSetterName();
659 // Do a normal method lookup first.
660 if (ObjCMethodDecl
*setter
=
661 LookupMethodInReceiverType(S
, SetterSelector
, RefExpr
)) {
662 if (setter
->isPropertyAccessor() && warn
)
663 if (const ObjCInterfaceDecl
*IFace
=
664 dyn_cast
<ObjCInterfaceDecl
>(setter
->getDeclContext())) {
665 StringRef thisPropertyName
= prop
->getName();
666 // Try flipping the case of the first character.
667 char front
= thisPropertyName
.front();
668 front
= isLowercase(front
) ? toUppercase(front
) : toLowercase(front
);
669 SmallString
<100> PropertyName
= thisPropertyName
;
670 PropertyName
[0] = front
;
671 const IdentifierInfo
*AltMember
=
672 &S
.PP
.getIdentifierTable().get(PropertyName
);
673 if (ObjCPropertyDecl
*prop1
= IFace
->FindPropertyDeclaration(
674 AltMember
, prop
->getQueryKind()))
675 if (prop
!= prop1
&& (prop1
->getSetterMethodDecl() == setter
)) {
676 S
.Diag(RefExpr
->getExprLoc(), diag::err_property_setter_ambiguous_use
)
677 << prop
<< prop1
<< setter
->getSelector();
678 S
.Diag(prop
->getLocation(), diag::note_property_declare
);
679 S
.Diag(prop1
->getLocation(), diag::note_property_declare
);
686 // That can fail in the somewhat crazy situation that we're
687 // type-checking a message send within the @interface declaration
688 // that declared the @property. But it's not clear that that's
689 // valuable to support.
694 void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
695 if (S
.getCurLexicalContext()->isObjCContainer() &&
696 S
.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl
&&
697 S
.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation
) {
698 if (ObjCPropertyDecl
*prop
= RefExpr
->getExplicitProperty()) {
699 S
.Diag(RefExpr
->getLocation(),
700 diag::err_property_function_in_objc_container
);
701 S
.Diag(prop
->getLocation(), diag::note_property_declare
);
706 /// Capture the base object of an Objective-C property expression.
707 Expr
*ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr
*syntacticBase
) {
708 assert(InstanceReceiver
== nullptr);
710 // If we have a base, capture it in an OVE and rebuild the syntactic
711 // form to use the OVE as its base.
712 if (RefExpr
->isObjectReceiver()) {
713 InstanceReceiver
= capture(RefExpr
->getBase());
714 syntacticBase
= Rebuilder(S
, [=](Expr
*, unsigned) -> Expr
* {
715 return InstanceReceiver
;
716 }).rebuild(syntacticBase
);
719 if (ObjCPropertyRefExpr
*
720 refE
= dyn_cast
<ObjCPropertyRefExpr
>(syntacticBase
->IgnoreParens()))
721 SyntacticRefExpr
= refE
;
723 return syntacticBase
;
726 /// Load from an Objective-C property reference.
727 ExprResult
ObjCPropertyOpBuilder::buildGet() {
730 DiagnoseUnsupportedPropertyUse();
734 if (SyntacticRefExpr
)
735 SyntacticRefExpr
->setIsMessagingGetter();
737 QualType receiverType
= RefExpr
->getReceiverType(S
.Context
);
738 if (!Getter
->isImplicit())
739 S
.DiagnoseUseOfDecl(Getter
, GenericLoc
, nullptr, true);
740 // Build a message-send.
742 if ((Getter
->isInstanceMethod() && !RefExpr
->isClassReceiver()) ||
743 RefExpr
->isObjectReceiver()) {
744 assert(InstanceReceiver
|| RefExpr
->isSuperReceiver());
745 msg
= S
.ObjC().BuildInstanceMessageImplicit(
746 InstanceReceiver
, receiverType
, GenericLoc
, Getter
->getSelector(),
749 msg
= S
.ObjC().BuildClassMessageImplicit(
750 receiverType
, RefExpr
->isSuperReceiver(), GenericLoc
,
751 Getter
->getSelector(), Getter
, {});
756 /// Store to an Objective-C property reference.
758 /// \param captureSetValueAsResult If true, capture the actual
759 /// value being set as the value of the property operation.
760 ExprResult
ObjCPropertyOpBuilder::buildSet(Expr
*op
, SourceLocation opcLoc
,
761 bool captureSetValueAsResult
) {
762 if (!findSetter(false)) {
763 DiagnoseUnsupportedPropertyUse();
767 if (SyntacticRefExpr
)
768 SyntacticRefExpr
->setIsMessagingSetter();
770 QualType receiverType
= RefExpr
->getReceiverType(S
.Context
);
772 // Use assignment constraints when possible; they give us better
773 // diagnostics. "When possible" basically means anything except a
775 if (!S
.getLangOpts().CPlusPlus
|| !op
->getType()->isRecordType()) {
776 QualType paramType
= (*Setter
->param_begin())->getType()
777 .substObjCMemberType(
779 Setter
->getDeclContext(),
780 ObjCSubstitutionContext::Parameter
);
781 if (!S
.getLangOpts().CPlusPlus
|| !paramType
->isRecordType()) {
782 ExprResult opResult
= op
;
783 Sema::AssignConvertType assignResult
784 = S
.CheckSingleAssignmentConstraints(paramType
, opResult
);
785 if (opResult
.isInvalid() ||
786 S
.DiagnoseAssignmentResult(assignResult
, opcLoc
, paramType
,
787 op
->getType(), opResult
.get(),
788 AssignmentAction::Assigning
))
792 assert(op
&& "successful assignment left argument invalid?");
797 Expr
*args
[] = { op
};
799 // Build a message-send.
801 if (!Setter
->isImplicit())
802 S
.DiagnoseUseOfDecl(Setter
, GenericLoc
, nullptr, true);
803 if ((Setter
->isInstanceMethod() && !RefExpr
->isClassReceiver()) ||
804 RefExpr
->isObjectReceiver()) {
805 msg
= S
.ObjC().BuildInstanceMessageImplicit(InstanceReceiver
, receiverType
,
806 GenericLoc
, SetterSelector
,
807 Setter
, MultiExprArg(args
, 1));
809 msg
= S
.ObjC().BuildClassMessageImplicit(
810 receiverType
, RefExpr
->isSuperReceiver(), GenericLoc
, SetterSelector
,
811 Setter
, MultiExprArg(args
, 1));
814 if (!msg
.isInvalid() && captureSetValueAsResult
) {
815 ObjCMessageExpr
*msgExpr
=
816 cast
<ObjCMessageExpr
>(msg
.get()->IgnoreImplicit());
817 Expr
*arg
= msgExpr
->getArg(0);
818 if (CanCaptureValue(arg
))
819 msgExpr
->setArg(0, captureValueAsResult(arg
));
825 /// @property-specific behavior for doing lvalue-to-rvalue conversion.
826 ExprResult
ObjCPropertyOpBuilder::buildRValueOperation(Expr
*op
) {
827 // Explicit properties always have getters, but implicit ones don't.
828 // Check that before proceeding.
829 if (RefExpr
->isImplicitProperty() && !RefExpr
->getImplicitPropertyGetter()) {
830 S
.Diag(RefExpr
->getLocation(), diag::err_getter_not_found
)
831 << RefExpr
->getSourceRange();
835 ExprResult result
= PseudoOpBuilder::buildRValueOperation(op
);
836 if (result
.isInvalid()) return ExprError();
838 if (RefExpr
->isExplicitProperty() && !Getter
->hasRelatedResultType())
839 S
.ObjC().DiagnosePropertyAccessorMismatch(RefExpr
->getExplicitProperty(),
840 Getter
, RefExpr
->getLocation());
842 // As a special case, if the method returns 'id', try to get
843 // a better type from the property.
844 if (RefExpr
->isExplicitProperty() && result
.get()->isPRValue()) {
845 QualType receiverType
= RefExpr
->getReceiverType(S
.Context
);
846 QualType propType
= RefExpr
->getExplicitProperty()
847 ->getUsageType(receiverType
);
848 if (result
.get()->getType()->isObjCIdType()) {
849 if (const ObjCObjectPointerType
*ptr
850 = propType
->getAs
<ObjCObjectPointerType
>()) {
851 if (!ptr
->isObjCIdType())
852 result
= S
.ImpCastExprToType(result
.get(), propType
, CK_BitCast
);
855 if (propType
.getObjCLifetime() == Qualifiers::OCL_Weak
&&
856 !S
.Diags
.isIgnored(diag::warn_arc_repeated_use_of_weak
,
857 RefExpr
->getLocation()))
858 S
.getCurFunction()->markSafeWeakUse(RefExpr
);
864 /// Try to build this as a call to a getter that returns a reference.
866 /// \return true if it was possible, whether or not it actually
868 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr
*op
,
869 ExprResult
&result
) {
870 if (!S
.getLangOpts().CPlusPlus
) return false;
874 // The property has no setter and no getter! This can happen if the type is
875 // invalid. Error have already been reported.
876 result
= ExprError();
880 // Only do this if the getter returns an l-value reference type.
881 QualType resultType
= Getter
->getReturnType();
882 if (!resultType
->isLValueReferenceType()) return false;
884 result
= buildRValueOperation(op
);
888 /// @property-specific behavior for doing assignments.
890 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope
*Sc
,
891 SourceLocation opcLoc
,
892 BinaryOperatorKind opcode
,
893 Expr
*LHS
, Expr
*RHS
) {
894 assert(BinaryOperator::isAssignmentOp(opcode
));
896 // If there's no setter, we have no choice but to try to assign to
897 // the result of the getter.
900 if (tryBuildGetOfReference(LHS
, result
)) {
901 if (result
.isInvalid()) return ExprError();
902 return S
.BuildBinOp(Sc
, opcLoc
, opcode
, result
.get(), RHS
);
905 // Otherwise, it's an error.
906 S
.Diag(opcLoc
, diag::err_nosetter_property_assignment
)
907 << unsigned(RefExpr
->isImplicitProperty())
909 << LHS
->getSourceRange() << RHS
->getSourceRange();
913 // If there is a setter, we definitely want to use it.
915 // Verify that we can do a compound assignment.
916 if (opcode
!= BO_Assign
&& !findGetter()) {
917 S
.Diag(opcLoc
, diag::err_nogetter_property_compound_assignment
)
918 << LHS
->getSourceRange() << RHS
->getSourceRange();
923 PseudoOpBuilder::buildAssignmentOperation(Sc
, opcLoc
, opcode
, LHS
, RHS
);
924 if (result
.isInvalid()) return ExprError();
926 // Various warnings about property assignments in ARC.
927 if (S
.getLangOpts().ObjCAutoRefCount
&& InstanceReceiver
) {
928 S
.ObjC().checkRetainCycles(InstanceReceiver
->getSourceExpr(), RHS
);
929 S
.checkUnsafeExprAssigns(opcLoc
, LHS
, RHS
);
935 /// @property-specific behavior for doing increments and decrements.
937 ObjCPropertyOpBuilder::buildIncDecOperation(Scope
*Sc
, SourceLocation opcLoc
,
938 UnaryOperatorKind opcode
,
940 // If there's no setter, we have no choice but to try to assign to
941 // the result of the getter.
944 if (tryBuildGetOfReference(op
, result
)) {
945 if (result
.isInvalid()) return ExprError();
946 return S
.BuildUnaryOp(Sc
, opcLoc
, opcode
, result
.get());
949 // Otherwise, it's an error.
950 S
.Diag(opcLoc
, diag::err_nosetter_property_incdec
)
951 << unsigned(RefExpr
->isImplicitProperty())
952 << unsigned(UnaryOperator::isDecrementOp(opcode
))
954 << op
->getSourceRange();
958 // If there is a setter, we definitely want to use it.
960 // We also need a getter.
962 assert(RefExpr
->isImplicitProperty());
963 S
.Diag(opcLoc
, diag::err_nogetter_property_incdec
)
964 << unsigned(UnaryOperator::isDecrementOp(opcode
))
966 << op
->getSourceRange();
970 return PseudoOpBuilder::buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
973 ExprResult
ObjCPropertyOpBuilder::complete(Expr
*SyntacticForm
) {
974 if (isWeakProperty() && !S
.isUnevaluatedContext() &&
975 !S
.Diags
.isIgnored(diag::warn_arc_repeated_use_of_weak
,
976 SyntacticForm
->getBeginLoc()))
977 S
.getCurFunction()->recordUseOfWeak(SyntacticRefExpr
,
978 SyntacticRefExpr
->isMessagingGetter());
980 return PseudoOpBuilder::complete(SyntacticForm
);
983 // ObjCSubscript build stuff.
986 /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
988 /// FIXME. Remove this routine if it is proven that no additional
989 /// specifity is needed.
990 ExprResult
ObjCSubscriptOpBuilder::buildRValueOperation(Expr
*op
) {
991 ExprResult result
= PseudoOpBuilder::buildRValueOperation(op
);
992 if (result
.isInvalid()) return ExprError();
996 /// objective-c subscripting-specific behavior for doing assignments.
998 ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope
*Sc
,
999 SourceLocation opcLoc
,
1000 BinaryOperatorKind opcode
,
1001 Expr
*LHS
, Expr
*RHS
) {
1002 assert(BinaryOperator::isAssignmentOp(opcode
));
1003 // There must be a method to do the Index'ed assignment.
1004 if (!findAtIndexSetter())
1007 // Verify that we can do a compound assignment.
1008 if (opcode
!= BO_Assign
&& !findAtIndexGetter())
1012 PseudoOpBuilder::buildAssignmentOperation(Sc
, opcLoc
, opcode
, LHS
, RHS
);
1013 if (result
.isInvalid()) return ExprError();
1015 // Various warnings about objc Index'ed assignments in ARC.
1016 if (S
.getLangOpts().ObjCAutoRefCount
&& InstanceBase
) {
1017 S
.ObjC().checkRetainCycles(InstanceBase
->getSourceExpr(), RHS
);
1018 S
.checkUnsafeExprAssigns(opcLoc
, LHS
, RHS
);
1024 /// Capture the base object of an Objective-C Index'ed expression.
1025 Expr
*ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr
*syntacticBase
) {
1026 assert(InstanceBase
== nullptr);
1028 // Capture base expression in an OVE and rebuild the syntactic
1029 // form to use the OVE as its base expression.
1030 InstanceBase
= capture(RefExpr
->getBaseExpr());
1031 InstanceKey
= capture(RefExpr
->getKeyExpr());
1034 Rebuilder(S
, [=](Expr
*, unsigned Idx
) -> Expr
* {
1037 return InstanceBase
;
1041 llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
1043 }).rebuild(syntacticBase
);
1045 return syntacticBase
;
1048 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
1049 /// objects used as dictionary subscript key objects.
1050 static void CheckKeyForObjCARCConversion(Sema
&S
, QualType ContainerT
,
1052 if (ContainerT
.isNull())
1054 // dictionary subscripting.
1055 // - (id)objectForKeyedSubscript:(id)key;
1056 const IdentifierInfo
*KeyIdents
[] = {
1057 &S
.Context
.Idents
.get("objectForKeyedSubscript")};
1058 Selector GetterSelector
= S
.Context
.Selectors
.getSelector(1, KeyIdents
);
1059 ObjCMethodDecl
*Getter
= S
.ObjC().LookupMethodInObjectType(
1060 GetterSelector
, ContainerT
, true /*instance*/);
1063 QualType T
= Getter
->parameters()[0]->getType();
1064 S
.ObjC().CheckObjCConversion(Key
->getSourceRange(), T
, Key
,
1065 CheckedConversionKind::Implicit
);
1068 bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1072 Expr
*BaseExpr
= RefExpr
->getBaseExpr();
1073 QualType BaseT
= BaseExpr
->getType();
1075 QualType ResultType
;
1076 if (const ObjCObjectPointerType
*PTy
=
1077 BaseT
->getAs
<ObjCObjectPointerType
>()) {
1078 ResultType
= PTy
->getPointeeType();
1080 SemaObjC::ObjCSubscriptKind Res
=
1081 S
.ObjC().CheckSubscriptingKind(RefExpr
->getKeyExpr());
1082 if (Res
== SemaObjC::OS_Error
) {
1083 if (S
.getLangOpts().ObjCAutoRefCount
)
1084 CheckKeyForObjCARCConversion(S
, ResultType
,
1085 RefExpr
->getKeyExpr());
1088 bool arrayRef
= (Res
== SemaObjC::OS_Array
);
1090 if (ResultType
.isNull()) {
1091 S
.Diag(BaseExpr
->getExprLoc(), diag::err_objc_subscript_base_type
)
1092 << BaseExpr
->getType() << arrayRef
;
1096 // dictionary subscripting.
1097 // - (id)objectForKeyedSubscript:(id)key;
1098 const IdentifierInfo
*KeyIdents
[] = {
1099 &S
.Context
.Idents
.get("objectForKeyedSubscript")};
1100 AtIndexGetterSelector
= S
.Context
.Selectors
.getSelector(1, KeyIdents
);
1103 // - (id)objectAtIndexedSubscript:(size_t)index;
1104 const IdentifierInfo
*KeyIdents
[] = {
1105 &S
.Context
.Idents
.get("objectAtIndexedSubscript")};
1107 AtIndexGetterSelector
= S
.Context
.Selectors
.getSelector(1, KeyIdents
);
1110 AtIndexGetter
= S
.ObjC().LookupMethodInObjectType(
1111 AtIndexGetterSelector
, ResultType
, true /*instance*/);
1113 if (!AtIndexGetter
&& S
.getLangOpts().DebuggerObjCLiteral
) {
1114 AtIndexGetter
= ObjCMethodDecl::Create(
1115 S
.Context
, SourceLocation(), SourceLocation(), AtIndexGetterSelector
,
1116 S
.Context
.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,
1117 S
.Context
.getTranslationUnitDecl(), true /*Instance*/,
1118 false /*isVariadic*/,
1119 /*isPropertyAccessor=*/false,
1120 /*isSynthesizedAccessorStub=*/false,
1121 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1122 ObjCImplementationControl::Required
, false);
1123 ParmVarDecl
*Argument
= ParmVarDecl::Create(S
.Context
, AtIndexGetter
,
1124 SourceLocation(), SourceLocation(),
1125 arrayRef
? &S
.Context
.Idents
.get("index")
1126 : &S
.Context
.Idents
.get("key"),
1127 arrayRef
? S
.Context
.UnsignedLongTy
1128 : S
.Context
.getObjCIdType(),
1132 AtIndexGetter
->setMethodParams(S
.Context
, Argument
, {});
1135 if (!AtIndexGetter
) {
1136 if (!BaseT
->isObjCIdType()) {
1137 S
.Diag(BaseExpr
->getExprLoc(), diag::err_objc_subscript_method_not_found
)
1138 << BaseExpr
->getType() << 0 << arrayRef
;
1141 AtIndexGetter
= S
.ObjC().LookupInstanceMethodInGlobalPool(
1142 AtIndexGetterSelector
, RefExpr
->getSourceRange(), true);
1145 if (AtIndexGetter
) {
1146 QualType T
= AtIndexGetter
->parameters()[0]->getType();
1147 if ((arrayRef
&& !T
->isIntegralOrEnumerationType()) ||
1148 (!arrayRef
&& !T
->isObjCObjectPointerType())) {
1149 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1150 arrayRef
? diag::err_objc_subscript_index_type
1151 : diag::err_objc_subscript_key_type
) << T
;
1152 S
.Diag(AtIndexGetter
->parameters()[0]->getLocation(),
1153 diag::note_parameter_type
) << T
;
1156 QualType R
= AtIndexGetter
->getReturnType();
1157 if (!R
->isObjCObjectPointerType()) {
1158 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1159 diag::err_objc_indexing_method_result_type
) << R
<< arrayRef
;
1160 S
.Diag(AtIndexGetter
->getLocation(), diag::note_method_declared_at
) <<
1161 AtIndexGetter
->getDeclName();
1167 bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1171 Expr
*BaseExpr
= RefExpr
->getBaseExpr();
1172 QualType BaseT
= BaseExpr
->getType();
1174 QualType ResultType
;
1175 if (const ObjCObjectPointerType
*PTy
=
1176 BaseT
->getAs
<ObjCObjectPointerType
>()) {
1177 ResultType
= PTy
->getPointeeType();
1180 SemaObjC::ObjCSubscriptKind Res
=
1181 S
.ObjC().CheckSubscriptingKind(RefExpr
->getKeyExpr());
1182 if (Res
== SemaObjC::OS_Error
) {
1183 if (S
.getLangOpts().ObjCAutoRefCount
)
1184 CheckKeyForObjCARCConversion(S
, ResultType
,
1185 RefExpr
->getKeyExpr());
1188 bool arrayRef
= (Res
== SemaObjC::OS_Array
);
1190 if (ResultType
.isNull()) {
1191 S
.Diag(BaseExpr
->getExprLoc(), diag::err_objc_subscript_base_type
)
1192 << BaseExpr
->getType() << arrayRef
;
1197 // dictionary subscripting.
1198 // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1199 const IdentifierInfo
*KeyIdents
[] = {
1200 &S
.Context
.Idents
.get("setObject"),
1201 &S
.Context
.Idents
.get("forKeyedSubscript")};
1202 AtIndexSetterSelector
= S
.Context
.Selectors
.getSelector(2, KeyIdents
);
1205 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1206 const IdentifierInfo
*KeyIdents
[] = {
1207 &S
.Context
.Idents
.get("setObject"),
1208 &S
.Context
.Idents
.get("atIndexedSubscript")};
1209 AtIndexSetterSelector
= S
.Context
.Selectors
.getSelector(2, KeyIdents
);
1211 AtIndexSetter
= S
.ObjC().LookupMethodInObjectType(
1212 AtIndexSetterSelector
, ResultType
, true /*instance*/);
1214 if (!AtIndexSetter
&& S
.getLangOpts().DebuggerObjCLiteral
) {
1215 TypeSourceInfo
*ReturnTInfo
= nullptr;
1216 QualType ReturnType
= S
.Context
.VoidTy
;
1217 AtIndexSetter
= ObjCMethodDecl::Create(
1218 S
.Context
, SourceLocation(), SourceLocation(), AtIndexSetterSelector
,
1219 ReturnType
, ReturnTInfo
, S
.Context
.getTranslationUnitDecl(),
1220 true /*Instance*/, false /*isVariadic*/,
1221 /*isPropertyAccessor=*/false,
1222 /*isSynthesizedAccessorStub=*/false,
1223 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1224 ObjCImplementationControl::Required
, false);
1225 SmallVector
<ParmVarDecl
*, 2> Params
;
1226 ParmVarDecl
*object
= ParmVarDecl::Create(S
.Context
, AtIndexSetter
,
1227 SourceLocation(), SourceLocation(),
1228 &S
.Context
.Idents
.get("object"),
1229 S
.Context
.getObjCIdType(),
1233 Params
.push_back(object
);
1234 ParmVarDecl
*key
= ParmVarDecl::Create(S
.Context
, AtIndexSetter
,
1235 SourceLocation(), SourceLocation(),
1236 arrayRef
? &S
.Context
.Idents
.get("index")
1237 : &S
.Context
.Idents
.get("key"),
1238 arrayRef
? S
.Context
.UnsignedLongTy
1239 : S
.Context
.getObjCIdType(),
1243 Params
.push_back(key
);
1244 AtIndexSetter
->setMethodParams(S
.Context
, Params
, {});
1247 if (!AtIndexSetter
) {
1248 if (!BaseT
->isObjCIdType()) {
1249 S
.Diag(BaseExpr
->getExprLoc(),
1250 diag::err_objc_subscript_method_not_found
)
1251 << BaseExpr
->getType() << 1 << arrayRef
;
1254 AtIndexSetter
= S
.ObjC().LookupInstanceMethodInGlobalPool(
1255 AtIndexSetterSelector
, RefExpr
->getSourceRange(), true);
1259 if (AtIndexSetter
&& arrayRef
) {
1260 QualType T
= AtIndexSetter
->parameters()[1]->getType();
1261 if (!T
->isIntegralOrEnumerationType()) {
1262 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1263 diag::err_objc_subscript_index_type
) << T
;
1264 S
.Diag(AtIndexSetter
->parameters()[1]->getLocation(),
1265 diag::note_parameter_type
) << T
;
1268 T
= AtIndexSetter
->parameters()[0]->getType();
1269 if (!T
->isObjCObjectPointerType()) {
1270 S
.Diag(RefExpr
->getBaseExpr()->getExprLoc(),
1271 diag::err_objc_subscript_object_type
) << T
<< arrayRef
;
1272 S
.Diag(AtIndexSetter
->parameters()[0]->getLocation(),
1273 diag::note_parameter_type
) << T
;
1277 else if (AtIndexSetter
&& !arrayRef
)
1278 for (unsigned i
=0; i
<2; i
++) {
1279 QualType T
= AtIndexSetter
->parameters()[i
]->getType();
1280 if (!T
->isObjCObjectPointerType()) {
1282 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1283 diag::err_objc_subscript_key_type
) << T
;
1285 S
.Diag(RefExpr
->getBaseExpr()->getExprLoc(),
1286 diag::err_objc_subscript_dic_object_type
) << T
;
1287 S
.Diag(AtIndexSetter
->parameters()[i
]->getLocation(),
1288 diag::note_parameter_type
) << T
;
1296 // Get the object at "Index" position in the container.
1297 // [BaseExpr objectAtIndexedSubscript : IndexExpr];
1298 ExprResult
ObjCSubscriptOpBuilder::buildGet() {
1299 if (!findAtIndexGetter())
1302 QualType receiverType
= InstanceBase
->getType();
1304 // Build a message-send.
1306 Expr
*Index
= InstanceKey
;
1309 Expr
*args
[] = { Index
};
1310 assert(InstanceBase
);
1312 S
.DiagnoseUseOfDecl(AtIndexGetter
, GenericLoc
);
1313 msg
= S
.ObjC().BuildInstanceMessageImplicit(
1314 InstanceBase
, receiverType
, GenericLoc
, AtIndexGetterSelector
,
1315 AtIndexGetter
, MultiExprArg(args
, 1));
1319 /// Store into the container the "op" object at "Index"'ed location
1320 /// by building this messaging expression:
1321 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1322 /// \param captureSetValueAsResult If true, capture the actual
1323 /// value being set as the value of the property operation.
1324 ExprResult
ObjCSubscriptOpBuilder::buildSet(Expr
*op
, SourceLocation opcLoc
,
1325 bool captureSetValueAsResult
) {
1326 if (!findAtIndexSetter())
1329 S
.DiagnoseUseOfDecl(AtIndexSetter
, GenericLoc
);
1330 QualType receiverType
= InstanceBase
->getType();
1331 Expr
*Index
= InstanceKey
;
1334 Expr
*args
[] = { op
, Index
};
1336 // Build a message-send.
1337 ExprResult msg
= S
.ObjC().BuildInstanceMessageImplicit(
1338 InstanceBase
, receiverType
, GenericLoc
, AtIndexSetterSelector
,
1339 AtIndexSetter
, MultiExprArg(args
, 2));
1341 if (!msg
.isInvalid() && captureSetValueAsResult
) {
1342 ObjCMessageExpr
*msgExpr
=
1343 cast
<ObjCMessageExpr
>(msg
.get()->IgnoreImplicit());
1344 Expr
*arg
= msgExpr
->getArg(0);
1345 if (CanCaptureValue(arg
))
1346 msgExpr
->setArg(0, captureValueAsResult(arg
));
1352 //===----------------------------------------------------------------------===//
1353 // MSVC __declspec(property) references
1354 //===----------------------------------------------------------------------===//
1357 MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr
*E
) {
1358 CallArgs
.insert(CallArgs
.begin(), E
->getIdx());
1359 Expr
*Base
= E
->getBase()->IgnoreParens();
1360 while (auto *MSPropSubscript
= dyn_cast
<MSPropertySubscriptExpr
>(Base
)) {
1361 CallArgs
.insert(CallArgs
.begin(), MSPropSubscript
->getIdx());
1362 Base
= MSPropSubscript
->getBase()->IgnoreParens();
1364 return cast
<MSPropertyRefExpr
>(Base
);
1367 Expr
*MSPropertyOpBuilder::rebuildAndCaptureObject(Expr
*syntacticBase
) {
1368 InstanceBase
= capture(RefExpr
->getBaseExpr());
1369 for (Expr
*&Arg
: CallArgs
)
1371 syntacticBase
= Rebuilder(S
, [=](Expr
*, unsigned Idx
) -> Expr
* {
1374 return InstanceBase
;
1376 assert(Idx
<= CallArgs
.size());
1377 return CallArgs
[Idx
- 1];
1379 }).rebuild(syntacticBase
);
1381 return syntacticBase
;
1384 ExprResult
MSPropertyOpBuilder::buildGet() {
1385 if (!RefExpr
->getPropertyDecl()->hasGetter()) {
1386 S
.Diag(RefExpr
->getMemberLoc(), diag::err_no_accessor_for_property
)
1387 << 0 /* getter */ << RefExpr
->getPropertyDecl();
1391 UnqualifiedId GetterName
;
1392 const IdentifierInfo
*II
= RefExpr
->getPropertyDecl()->getGetterId();
1393 GetterName
.setIdentifier(II
, RefExpr
->getMemberLoc());
1395 SS
.Adopt(RefExpr
->getQualifierLoc());
1396 ExprResult GetterExpr
=
1397 S
.ActOnMemberAccessExpr(S
.getCurScope(), InstanceBase
, SourceLocation(),
1398 RefExpr
->isArrow() ? tok::arrow
: tok::period
, SS
,
1399 SourceLocation(), GetterName
, nullptr);
1400 if (GetterExpr
.isInvalid()) {
1401 S
.Diag(RefExpr
->getMemberLoc(),
1402 diag::err_cannot_find_suitable_accessor
) << 0 /* getter */
1403 << RefExpr
->getPropertyDecl();
1407 return S
.BuildCallExpr(S
.getCurScope(), GetterExpr
.get(),
1408 RefExpr
->getSourceRange().getBegin(), CallArgs
,
1409 RefExpr
->getSourceRange().getEnd());
1412 ExprResult
MSPropertyOpBuilder::buildSet(Expr
*op
, SourceLocation sl
,
1413 bool captureSetValueAsResult
) {
1414 if (!RefExpr
->getPropertyDecl()->hasSetter()) {
1415 S
.Diag(RefExpr
->getMemberLoc(), diag::err_no_accessor_for_property
)
1416 << 1 /* setter */ << RefExpr
->getPropertyDecl();
1420 UnqualifiedId SetterName
;
1421 const IdentifierInfo
*II
= RefExpr
->getPropertyDecl()->getSetterId();
1422 SetterName
.setIdentifier(II
, RefExpr
->getMemberLoc());
1424 SS
.Adopt(RefExpr
->getQualifierLoc());
1425 ExprResult SetterExpr
=
1426 S
.ActOnMemberAccessExpr(S
.getCurScope(), InstanceBase
, SourceLocation(),
1427 RefExpr
->isArrow() ? tok::arrow
: tok::period
, SS
,
1428 SourceLocation(), SetterName
, nullptr);
1429 if (SetterExpr
.isInvalid()) {
1430 S
.Diag(RefExpr
->getMemberLoc(),
1431 diag::err_cannot_find_suitable_accessor
) << 1 /* setter */
1432 << RefExpr
->getPropertyDecl();
1436 SmallVector
<Expr
*, 4> ArgExprs
;
1437 ArgExprs
.append(CallArgs
.begin(), CallArgs
.end());
1438 ArgExprs
.push_back(op
);
1439 return S
.BuildCallExpr(S
.getCurScope(), SetterExpr
.get(),
1440 RefExpr
->getSourceRange().getBegin(), ArgExprs
,
1441 op
->getSourceRange().getEnd());
1444 //===----------------------------------------------------------------------===//
1445 // General Sema routines.
1446 //===----------------------------------------------------------------------===//
1448 ExprResult
SemaPseudoObject::checkRValue(Expr
*E
) {
1449 Expr
*opaqueRef
= E
->IgnoreParens();
1450 if (ObjCPropertyRefExpr
*refExpr
1451 = dyn_cast
<ObjCPropertyRefExpr
>(opaqueRef
)) {
1452 ObjCPropertyOpBuilder
builder(SemaRef
, refExpr
, true);
1453 return builder
.buildRValueOperation(E
);
1455 else if (ObjCSubscriptRefExpr
*refExpr
1456 = dyn_cast
<ObjCSubscriptRefExpr
>(opaqueRef
)) {
1457 ObjCSubscriptOpBuilder
builder(SemaRef
, refExpr
, true);
1458 return builder
.buildRValueOperation(E
);
1459 } else if (MSPropertyRefExpr
*refExpr
1460 = dyn_cast
<MSPropertyRefExpr
>(opaqueRef
)) {
1461 MSPropertyOpBuilder
builder(SemaRef
, refExpr
, true);
1462 return builder
.buildRValueOperation(E
);
1463 } else if (MSPropertySubscriptExpr
*RefExpr
=
1464 dyn_cast
<MSPropertySubscriptExpr
>(opaqueRef
)) {
1465 MSPropertyOpBuilder
Builder(SemaRef
, RefExpr
, true);
1466 return Builder
.buildRValueOperation(E
);
1468 llvm_unreachable("unknown pseudo-object kind!");
1472 /// Check an increment or decrement of a pseudo-object expression.
1473 ExprResult
SemaPseudoObject::checkIncDec(Scope
*Sc
, SourceLocation opcLoc
,
1474 UnaryOperatorKind opcode
, Expr
*op
) {
1475 // Do nothing if the operand is dependent.
1476 if (op
->isTypeDependent())
1477 return UnaryOperator::Create(
1478 SemaRef
.Context
, op
, opcode
, SemaRef
.Context
.DependentTy
, VK_PRValue
,
1479 OK_Ordinary
, opcLoc
, false, SemaRef
.CurFPFeatureOverrides());
1481 assert(UnaryOperator::isIncrementDecrementOp(opcode
));
1482 Expr
*opaqueRef
= op
->IgnoreParens();
1483 if (ObjCPropertyRefExpr
*refExpr
1484 = dyn_cast
<ObjCPropertyRefExpr
>(opaqueRef
)) {
1485 ObjCPropertyOpBuilder
builder(SemaRef
, refExpr
, false);
1486 return builder
.buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
1487 } else if (isa
<ObjCSubscriptRefExpr
>(opaqueRef
)) {
1488 Diag(opcLoc
, diag::err_illegal_container_subscripting_op
);
1490 } else if (MSPropertyRefExpr
*refExpr
1491 = dyn_cast
<MSPropertyRefExpr
>(opaqueRef
)) {
1492 MSPropertyOpBuilder
builder(SemaRef
, refExpr
, false);
1493 return builder
.buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
1494 } else if (MSPropertySubscriptExpr
*RefExpr
1495 = dyn_cast
<MSPropertySubscriptExpr
>(opaqueRef
)) {
1496 MSPropertyOpBuilder
Builder(SemaRef
, RefExpr
, false);
1497 return Builder
.buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
1499 llvm_unreachable("unknown pseudo-object kind!");
1503 ExprResult
SemaPseudoObject::checkAssignment(Scope
*S
, SourceLocation opcLoc
,
1504 BinaryOperatorKind opcode
,
1505 Expr
*LHS
, Expr
*RHS
) {
1506 // Do nothing if either argument is dependent.
1507 if (LHS
->isTypeDependent() || RHS
->isTypeDependent())
1508 return BinaryOperator::Create(
1509 SemaRef
.Context
, LHS
, RHS
, opcode
, SemaRef
.Context
.DependentTy
,
1510 VK_PRValue
, OK_Ordinary
, opcLoc
, SemaRef
.CurFPFeatureOverrides());
1512 // Filter out non-overload placeholder types in the RHS.
1513 if (RHS
->getType()->isNonOverloadPlaceholderType()) {
1514 ExprResult result
= SemaRef
.CheckPlaceholderExpr(RHS
);
1515 if (result
.isInvalid()) return ExprError();
1519 bool IsSimpleAssign
= opcode
== BO_Assign
;
1520 Expr
*opaqueRef
= LHS
->IgnoreParens();
1521 if (ObjCPropertyRefExpr
*refExpr
1522 = dyn_cast
<ObjCPropertyRefExpr
>(opaqueRef
)) {
1523 ObjCPropertyOpBuilder
builder(SemaRef
, refExpr
, IsSimpleAssign
);
1524 return builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1525 } else if (ObjCSubscriptRefExpr
*refExpr
1526 = dyn_cast
<ObjCSubscriptRefExpr
>(opaqueRef
)) {
1527 ObjCSubscriptOpBuilder
builder(SemaRef
, refExpr
, IsSimpleAssign
);
1528 return builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1529 } else if (MSPropertyRefExpr
*refExpr
1530 = dyn_cast
<MSPropertyRefExpr
>(opaqueRef
)) {
1531 MSPropertyOpBuilder
builder(SemaRef
, refExpr
, IsSimpleAssign
);
1532 return builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1533 } else if (MSPropertySubscriptExpr
*RefExpr
1534 = dyn_cast
<MSPropertySubscriptExpr
>(opaqueRef
)) {
1535 MSPropertyOpBuilder
Builder(SemaRef
, RefExpr
, IsSimpleAssign
);
1536 return Builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1538 llvm_unreachable("unknown pseudo-object kind!");
1542 /// Given a pseudo-object reference, rebuild it without the opaque
1543 /// values. Basically, undo the behavior of rebuildAndCaptureObject.
1544 /// This should never operate in-place.
1545 static Expr
*stripOpaqueValuesFromPseudoObjectRef(Sema
&S
, Expr
*E
) {
1547 [=](Expr
*E
, unsigned) -> Expr
* {
1548 return cast
<OpaqueValueExpr
>(E
)->getSourceExpr();
1553 /// Given a pseudo-object expression, recreate what it looks like
1554 /// syntactically without the attendant OpaqueValueExprs.
1556 /// This is a hack which should be removed when TreeTransform is
1557 /// capable of rebuilding a tree without stripping implicit
1559 Expr
*SemaPseudoObject::recreateSyntacticForm(PseudoObjectExpr
*E
) {
1560 Expr
*syntax
= E
->getSyntacticForm();
1561 if (UnaryOperator
*uop
= dyn_cast
<UnaryOperator
>(syntax
)) {
1562 Expr
*op
= stripOpaqueValuesFromPseudoObjectRef(SemaRef
, uop
->getSubExpr());
1563 return UnaryOperator::Create(
1564 SemaRef
.Context
, op
, uop
->getOpcode(), uop
->getType(),
1565 uop
->getValueKind(), uop
->getObjectKind(), uop
->getOperatorLoc(),
1566 uop
->canOverflow(), SemaRef
.CurFPFeatureOverrides());
1567 } else if (CompoundAssignOperator
*cop
1568 = dyn_cast
<CompoundAssignOperator
>(syntax
)) {
1569 Expr
*lhs
= stripOpaqueValuesFromPseudoObjectRef(SemaRef
, cop
->getLHS());
1570 Expr
*rhs
= cast
<OpaqueValueExpr
>(cop
->getRHS())->getSourceExpr();
1571 return CompoundAssignOperator::Create(
1572 SemaRef
.Context
, lhs
, rhs
, cop
->getOpcode(), cop
->getType(),
1573 cop
->getValueKind(), cop
->getObjectKind(), cop
->getOperatorLoc(),
1574 SemaRef
.CurFPFeatureOverrides(), cop
->getComputationLHSType(),
1575 cop
->getComputationResultType());
1577 } else if (BinaryOperator
*bop
= dyn_cast
<BinaryOperator
>(syntax
)) {
1578 Expr
*lhs
= stripOpaqueValuesFromPseudoObjectRef(SemaRef
, bop
->getLHS());
1579 Expr
*rhs
= cast
<OpaqueValueExpr
>(bop
->getRHS())->getSourceExpr();
1580 return BinaryOperator::Create(SemaRef
.Context
, lhs
, rhs
, bop
->getOpcode(),
1581 bop
->getType(), bop
->getValueKind(),
1582 bop
->getObjectKind(), bop
->getOperatorLoc(),
1583 SemaRef
.CurFPFeatureOverrides());
1585 } else if (isa
<CallExpr
>(syntax
)) {
1588 assert(syntax
->hasPlaceholderType(BuiltinType::PseudoObject
));
1589 return stripOpaqueValuesFromPseudoObjectRef(SemaRef
, syntax
);
1593 SemaPseudoObject::SemaPseudoObject(Sema
&S
) : SemaBase(S
) {}