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/SemaInternal.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 "llvm/ADT/SmallString.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
.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
.LookupMethodInObjectType(sel
,
566 S
.Context
.getObjCInterfaceType(method
->getClassInterface()),
570 return S
.LookupMethodInObjectType(sel
, PT
->getPointeeType(), true);
573 if (PRE
->isSuperReceiver()) {
574 if (const ObjCObjectPointerType
*PT
=
575 PRE
->getSuperReceiverType()->getAs
<ObjCObjectPointerType
>())
576 return S
.LookupMethodInObjectType(sel
, PT
->getPointeeType(), true);
578 return S
.LookupMethodInObjectType(sel
, PRE
->getSuperReceiverType(), false);
581 assert(PRE
->isClassReceiver() && "Invalid expression");
582 QualType IT
= S
.Context
.getObjCInterfaceType(PRE
->getClassReceiver());
583 return S
.LookupMethodInObjectType(sel
, IT
, false);
586 bool ObjCPropertyOpBuilder::isWeakProperty() const {
588 if (RefExpr
->isExplicitProperty()) {
589 const ObjCPropertyDecl
*Prop
= RefExpr
->getExplicitProperty();
590 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak
)
595 T
= Getter
->getReturnType();
600 return T
.getObjCLifetime() == Qualifiers::OCL_Weak
;
603 bool ObjCPropertyOpBuilder::findGetter() {
604 if (Getter
) return true;
606 // For implicit properties, just trust the lookup we already did.
607 if (RefExpr
->isImplicitProperty()) {
608 if ((Getter
= RefExpr
->getImplicitPropertyGetter())) {
609 GetterSelector
= Getter
->getSelector();
613 // Must build the getter selector the hard way.
614 ObjCMethodDecl
*setter
= RefExpr
->getImplicitPropertySetter();
615 assert(setter
&& "both setter and getter are null - cannot happen");
616 IdentifierInfo
*setterName
=
617 setter
->getSelector().getIdentifierInfoForSlot(0);
618 IdentifierInfo
*getterName
=
619 &S
.Context
.Idents
.get(setterName
->getName().substr(3));
621 S
.PP
.getSelectorTable().getNullarySelector(getterName
);
626 ObjCPropertyDecl
*prop
= RefExpr
->getExplicitProperty();
627 Getter
= LookupMethodInReceiverType(S
, prop
->getGetterName(), RefExpr
);
628 return (Getter
!= nullptr);
631 /// Try to find the most accurate setter declaration for the property
634 /// \return true if a setter was found, in which case Setter
635 bool ObjCPropertyOpBuilder::findSetter(bool warn
) {
636 // For implicit properties, just trust the lookup we already did.
637 if (RefExpr
->isImplicitProperty()) {
638 if (ObjCMethodDecl
*setter
= RefExpr
->getImplicitPropertySetter()) {
640 SetterSelector
= setter
->getSelector();
643 IdentifierInfo
*getterName
=
644 RefExpr
->getImplicitPropertyGetter()->getSelector()
645 .getIdentifierInfoForSlot(0);
647 SelectorTable::constructSetterSelector(S
.PP
.getIdentifierTable(),
648 S
.PP
.getSelectorTable(),
654 // For explicit properties, this is more involved.
655 ObjCPropertyDecl
*prop
= RefExpr
->getExplicitProperty();
656 SetterSelector
= prop
->getSetterName();
658 // Do a normal method lookup first.
659 if (ObjCMethodDecl
*setter
=
660 LookupMethodInReceiverType(S
, SetterSelector
, RefExpr
)) {
661 if (setter
->isPropertyAccessor() && warn
)
662 if (const ObjCInterfaceDecl
*IFace
=
663 dyn_cast
<ObjCInterfaceDecl
>(setter
->getDeclContext())) {
664 StringRef thisPropertyName
= prop
->getName();
665 // Try flipping the case of the first character.
666 char front
= thisPropertyName
.front();
667 front
= isLowercase(front
) ? toUppercase(front
) : toLowercase(front
);
668 SmallString
<100> PropertyName
= thisPropertyName
;
669 PropertyName
[0] = front
;
670 IdentifierInfo
*AltMember
= &S
.PP
.getIdentifierTable().get(PropertyName
);
671 if (ObjCPropertyDecl
*prop1
= IFace
->FindPropertyDeclaration(
672 AltMember
, prop
->getQueryKind()))
673 if (prop
!= prop1
&& (prop1
->getSetterMethodDecl() == setter
)) {
674 S
.Diag(RefExpr
->getExprLoc(), diag::err_property_setter_ambiguous_use
)
675 << prop
<< prop1
<< setter
->getSelector();
676 S
.Diag(prop
->getLocation(), diag::note_property_declare
);
677 S
.Diag(prop1
->getLocation(), diag::note_property_declare
);
684 // That can fail in the somewhat crazy situation that we're
685 // type-checking a message send within the @interface declaration
686 // that declared the @property. But it's not clear that that's
687 // valuable to support.
692 void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
693 if (S
.getCurLexicalContext()->isObjCContainer() &&
694 S
.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl
&&
695 S
.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation
) {
696 if (ObjCPropertyDecl
*prop
= RefExpr
->getExplicitProperty()) {
697 S
.Diag(RefExpr
->getLocation(),
698 diag::err_property_function_in_objc_container
);
699 S
.Diag(prop
->getLocation(), diag::note_property_declare
);
704 /// Capture the base object of an Objective-C property expression.
705 Expr
*ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr
*syntacticBase
) {
706 assert(InstanceReceiver
== nullptr);
708 // If we have a base, capture it in an OVE and rebuild the syntactic
709 // form to use the OVE as its base.
710 if (RefExpr
->isObjectReceiver()) {
711 InstanceReceiver
= capture(RefExpr
->getBase());
712 syntacticBase
= Rebuilder(S
, [=](Expr
*, unsigned) -> Expr
* {
713 return InstanceReceiver
;
714 }).rebuild(syntacticBase
);
717 if (ObjCPropertyRefExpr
*
718 refE
= dyn_cast
<ObjCPropertyRefExpr
>(syntacticBase
->IgnoreParens()))
719 SyntacticRefExpr
= refE
;
721 return syntacticBase
;
724 /// Load from an Objective-C property reference.
725 ExprResult
ObjCPropertyOpBuilder::buildGet() {
728 DiagnoseUnsupportedPropertyUse();
732 if (SyntacticRefExpr
)
733 SyntacticRefExpr
->setIsMessagingGetter();
735 QualType receiverType
= RefExpr
->getReceiverType(S
.Context
);
736 if (!Getter
->isImplicit())
737 S
.DiagnoseUseOfDecl(Getter
, GenericLoc
, nullptr, true);
738 // Build a message-send.
740 if ((Getter
->isInstanceMethod() && !RefExpr
->isClassReceiver()) ||
741 RefExpr
->isObjectReceiver()) {
742 assert(InstanceReceiver
|| RefExpr
->isSuperReceiver());
743 msg
= S
.BuildInstanceMessageImplicit(InstanceReceiver
, receiverType
,
744 GenericLoc
, Getter
->getSelector(),
745 Getter
, std::nullopt
);
747 msg
= S
.BuildClassMessageImplicit(receiverType
, RefExpr
->isSuperReceiver(),
748 GenericLoc
, Getter
->getSelector(), Getter
,
754 /// Store to an Objective-C property reference.
756 /// \param captureSetValueAsResult If true, capture the actual
757 /// value being set as the value of the property operation.
758 ExprResult
ObjCPropertyOpBuilder::buildSet(Expr
*op
, SourceLocation opcLoc
,
759 bool captureSetValueAsResult
) {
760 if (!findSetter(false)) {
761 DiagnoseUnsupportedPropertyUse();
765 if (SyntacticRefExpr
)
766 SyntacticRefExpr
->setIsMessagingSetter();
768 QualType receiverType
= RefExpr
->getReceiverType(S
.Context
);
770 // Use assignment constraints when possible; they give us better
771 // diagnostics. "When possible" basically means anything except a
773 if (!S
.getLangOpts().CPlusPlus
|| !op
->getType()->isRecordType()) {
774 QualType paramType
= (*Setter
->param_begin())->getType()
775 .substObjCMemberType(
777 Setter
->getDeclContext(),
778 ObjCSubstitutionContext::Parameter
);
779 if (!S
.getLangOpts().CPlusPlus
|| !paramType
->isRecordType()) {
780 ExprResult opResult
= op
;
781 Sema::AssignConvertType assignResult
782 = S
.CheckSingleAssignmentConstraints(paramType
, opResult
);
783 if (opResult
.isInvalid() ||
784 S
.DiagnoseAssignmentResult(assignResult
, opcLoc
, paramType
,
785 op
->getType(), opResult
.get(),
790 assert(op
&& "successful assignment left argument invalid?");
795 Expr
*args
[] = { op
};
797 // Build a message-send.
799 if (!Setter
->isImplicit())
800 S
.DiagnoseUseOfDecl(Setter
, GenericLoc
, nullptr, true);
801 if ((Setter
->isInstanceMethod() && !RefExpr
->isClassReceiver()) ||
802 RefExpr
->isObjectReceiver()) {
803 msg
= S
.BuildInstanceMessageImplicit(InstanceReceiver
, receiverType
,
804 GenericLoc
, SetterSelector
, Setter
,
805 MultiExprArg(args
, 1));
807 msg
= S
.BuildClassMessageImplicit(receiverType
, RefExpr
->isSuperReceiver(),
809 SetterSelector
, Setter
,
810 MultiExprArg(args
, 1));
813 if (!msg
.isInvalid() && captureSetValueAsResult
) {
814 ObjCMessageExpr
*msgExpr
=
815 cast
<ObjCMessageExpr
>(msg
.get()->IgnoreImplicit());
816 Expr
*arg
= msgExpr
->getArg(0);
817 if (CanCaptureValue(arg
))
818 msgExpr
->setArg(0, captureValueAsResult(arg
));
824 /// @property-specific behavior for doing lvalue-to-rvalue conversion.
825 ExprResult
ObjCPropertyOpBuilder::buildRValueOperation(Expr
*op
) {
826 // Explicit properties always have getters, but implicit ones don't.
827 // Check that before proceeding.
828 if (RefExpr
->isImplicitProperty() && !RefExpr
->getImplicitPropertyGetter()) {
829 S
.Diag(RefExpr
->getLocation(), diag::err_getter_not_found
)
830 << RefExpr
->getSourceRange();
834 ExprResult result
= PseudoOpBuilder::buildRValueOperation(op
);
835 if (result
.isInvalid()) return ExprError();
837 if (RefExpr
->isExplicitProperty() && !Getter
->hasRelatedResultType())
838 S
.DiagnosePropertyAccessorMismatch(RefExpr
->getExplicitProperty(),
839 Getter
, RefExpr
->getLocation());
841 // As a special case, if the method returns 'id', try to get
842 // a better type from the property.
843 if (RefExpr
->isExplicitProperty() && result
.get()->isPRValue()) {
844 QualType receiverType
= RefExpr
->getReceiverType(S
.Context
);
845 QualType propType
= RefExpr
->getExplicitProperty()
846 ->getUsageType(receiverType
);
847 if (result
.get()->getType()->isObjCIdType()) {
848 if (const ObjCObjectPointerType
*ptr
849 = propType
->getAs
<ObjCObjectPointerType
>()) {
850 if (!ptr
->isObjCIdType())
851 result
= S
.ImpCastExprToType(result
.get(), propType
, CK_BitCast
);
854 if (propType
.getObjCLifetime() == Qualifiers::OCL_Weak
&&
855 !S
.Diags
.isIgnored(diag::warn_arc_repeated_use_of_weak
,
856 RefExpr
->getLocation()))
857 S
.getCurFunction()->markSafeWeakUse(RefExpr
);
863 /// Try to build this as a call to a getter that returns a reference.
865 /// \return true if it was possible, whether or not it actually
867 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr
*op
,
868 ExprResult
&result
) {
869 if (!S
.getLangOpts().CPlusPlus
) return false;
873 // The property has no setter and no getter! This can happen if the type is
874 // invalid. Error have already been reported.
875 result
= ExprError();
879 // Only do this if the getter returns an l-value reference type.
880 QualType resultType
= Getter
->getReturnType();
881 if (!resultType
->isLValueReferenceType()) return false;
883 result
= buildRValueOperation(op
);
887 /// @property-specific behavior for doing assignments.
889 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope
*Sc
,
890 SourceLocation opcLoc
,
891 BinaryOperatorKind opcode
,
892 Expr
*LHS
, Expr
*RHS
) {
893 assert(BinaryOperator::isAssignmentOp(opcode
));
895 // If there's no setter, we have no choice but to try to assign to
896 // the result of the getter.
899 if (tryBuildGetOfReference(LHS
, result
)) {
900 if (result
.isInvalid()) return ExprError();
901 return S
.BuildBinOp(Sc
, opcLoc
, opcode
, result
.get(), RHS
);
904 // Otherwise, it's an error.
905 S
.Diag(opcLoc
, diag::err_nosetter_property_assignment
)
906 << unsigned(RefExpr
->isImplicitProperty())
908 << LHS
->getSourceRange() << RHS
->getSourceRange();
912 // If there is a setter, we definitely want to use it.
914 // Verify that we can do a compound assignment.
915 if (opcode
!= BO_Assign
&& !findGetter()) {
916 S
.Diag(opcLoc
, diag::err_nogetter_property_compound_assignment
)
917 << LHS
->getSourceRange() << RHS
->getSourceRange();
922 PseudoOpBuilder::buildAssignmentOperation(Sc
, opcLoc
, opcode
, LHS
, RHS
);
923 if (result
.isInvalid()) return ExprError();
925 // Various warnings about property assignments in ARC.
926 if (S
.getLangOpts().ObjCAutoRefCount
&& InstanceReceiver
) {
927 S
.checkRetainCycles(InstanceReceiver
->getSourceExpr(), RHS
);
928 S
.checkUnsafeExprAssigns(opcLoc
, LHS
, RHS
);
934 /// @property-specific behavior for doing increments and decrements.
936 ObjCPropertyOpBuilder::buildIncDecOperation(Scope
*Sc
, SourceLocation opcLoc
,
937 UnaryOperatorKind opcode
,
939 // If there's no setter, we have no choice but to try to assign to
940 // the result of the getter.
943 if (tryBuildGetOfReference(op
, result
)) {
944 if (result
.isInvalid()) return ExprError();
945 return S
.BuildUnaryOp(Sc
, opcLoc
, opcode
, result
.get());
948 // Otherwise, it's an error.
949 S
.Diag(opcLoc
, diag::err_nosetter_property_incdec
)
950 << unsigned(RefExpr
->isImplicitProperty())
951 << unsigned(UnaryOperator::isDecrementOp(opcode
))
953 << op
->getSourceRange();
957 // If there is a setter, we definitely want to use it.
959 // We also need a getter.
961 assert(RefExpr
->isImplicitProperty());
962 S
.Diag(opcLoc
, diag::err_nogetter_property_incdec
)
963 << unsigned(UnaryOperator::isDecrementOp(opcode
))
965 << op
->getSourceRange();
969 return PseudoOpBuilder::buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
972 ExprResult
ObjCPropertyOpBuilder::complete(Expr
*SyntacticForm
) {
973 if (isWeakProperty() && !S
.isUnevaluatedContext() &&
974 !S
.Diags
.isIgnored(diag::warn_arc_repeated_use_of_weak
,
975 SyntacticForm
->getBeginLoc()))
976 S
.getCurFunction()->recordUseOfWeak(SyntacticRefExpr
,
977 SyntacticRefExpr
->isMessagingGetter());
979 return PseudoOpBuilder::complete(SyntacticForm
);
982 // ObjCSubscript build stuff.
985 /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
987 /// FIXME. Remove this routine if it is proven that no additional
988 /// specifity is needed.
989 ExprResult
ObjCSubscriptOpBuilder::buildRValueOperation(Expr
*op
) {
990 ExprResult result
= PseudoOpBuilder::buildRValueOperation(op
);
991 if (result
.isInvalid()) return ExprError();
995 /// objective-c subscripting-specific behavior for doing assignments.
997 ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope
*Sc
,
998 SourceLocation opcLoc
,
999 BinaryOperatorKind opcode
,
1000 Expr
*LHS
, Expr
*RHS
) {
1001 assert(BinaryOperator::isAssignmentOp(opcode
));
1002 // There must be a method to do the Index'ed assignment.
1003 if (!findAtIndexSetter())
1006 // Verify that we can do a compound assignment.
1007 if (opcode
!= BO_Assign
&& !findAtIndexGetter())
1011 PseudoOpBuilder::buildAssignmentOperation(Sc
, opcLoc
, opcode
, LHS
, RHS
);
1012 if (result
.isInvalid()) return ExprError();
1014 // Various warnings about objc Index'ed assignments in ARC.
1015 if (S
.getLangOpts().ObjCAutoRefCount
&& InstanceBase
) {
1016 S
.checkRetainCycles(InstanceBase
->getSourceExpr(), RHS
);
1017 S
.checkUnsafeExprAssigns(opcLoc
, LHS
, RHS
);
1023 /// Capture the base object of an Objective-C Index'ed expression.
1024 Expr
*ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr
*syntacticBase
) {
1025 assert(InstanceBase
== nullptr);
1027 // Capture base expression in an OVE and rebuild the syntactic
1028 // form to use the OVE as its base expression.
1029 InstanceBase
= capture(RefExpr
->getBaseExpr());
1030 InstanceKey
= capture(RefExpr
->getKeyExpr());
1033 Rebuilder(S
, [=](Expr
*, unsigned Idx
) -> Expr
* {
1036 return InstanceBase
;
1040 llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
1042 }).rebuild(syntacticBase
);
1044 return syntacticBase
;
1047 /// CheckSubscriptingKind - This routine decide what type
1048 /// of indexing represented by "FromE" is being done.
1049 Sema::ObjCSubscriptKind
1050 Sema::CheckSubscriptingKind(Expr
*FromE
) {
1051 // If the expression already has integral or enumeration type, we're golden.
1052 QualType T
= FromE
->getType();
1053 if (T
->isIntegralOrEnumerationType())
1056 // If we don't have a class type in C++, there's no way we can get an
1057 // expression of integral or enumeration type.
1058 const RecordType
*RecordTy
= T
->getAs
<RecordType
>();
1060 (T
->isObjCObjectPointerType() || T
->isVoidPointerType()))
1061 // All other scalar cases are assumed to be dictionary indexing which
1062 // caller handles, with diagnostics if needed.
1063 return OS_Dictionary
;
1064 if (!getLangOpts().CPlusPlus
||
1065 !RecordTy
|| RecordTy
->isIncompleteType()) {
1066 // No indexing can be done. Issue diagnostics and quit.
1067 const Expr
*IndexExpr
= FromE
->IgnoreParenImpCasts();
1068 if (isa
<StringLiteral
>(IndexExpr
))
1069 Diag(FromE
->getExprLoc(), diag::err_objc_subscript_pointer
)
1070 << T
<< FixItHint::CreateInsertion(FromE
->getExprLoc(), "@");
1072 Diag(FromE
->getExprLoc(), diag::err_objc_subscript_type_conversion
)
1077 // We must have a complete class type.
1078 if (RequireCompleteType(FromE
->getExprLoc(), T
,
1079 diag::err_objc_index_incomplete_class_type
, FromE
))
1082 // Look for a conversion to an integral, enumeration type, or
1083 // objective-C pointer type.
1084 int NoIntegrals
=0, NoObjCIdPointers
=0;
1085 SmallVector
<CXXConversionDecl
*, 4> ConversionDecls
;
1087 for (NamedDecl
*D
: cast
<CXXRecordDecl
>(RecordTy
->getDecl())
1088 ->getVisibleConversionFunctions()) {
1089 if (CXXConversionDecl
*Conversion
=
1090 dyn_cast
<CXXConversionDecl
>(D
->getUnderlyingDecl())) {
1091 QualType CT
= Conversion
->getConversionType().getNonReferenceType();
1092 if (CT
->isIntegralOrEnumerationType()) {
1094 ConversionDecls
.push_back(Conversion
);
1096 else if (CT
->isObjCIdType() ||CT
->isBlockPointerType()) {
1098 ConversionDecls
.push_back(Conversion
);
1102 if (NoIntegrals
==1 && NoObjCIdPointers
== 0)
1104 if (NoIntegrals
== 0 && NoObjCIdPointers
== 1)
1105 return OS_Dictionary
;
1106 if (NoIntegrals
== 0 && NoObjCIdPointers
== 0) {
1107 // No conversion function was found. Issue diagnostic and return.
1108 Diag(FromE
->getExprLoc(), diag::err_objc_subscript_type_conversion
)
1109 << FromE
->getType();
1112 Diag(FromE
->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion
)
1113 << FromE
->getType();
1114 for (unsigned int i
= 0; i
< ConversionDecls
.size(); i
++)
1115 Diag(ConversionDecls
[i
]->getLocation(),
1116 diag::note_conv_function_declared_at
);
1121 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
1122 /// objects used as dictionary subscript key objects.
1123 static void CheckKeyForObjCARCConversion(Sema
&S
, QualType ContainerT
,
1125 if (ContainerT
.isNull())
1127 // dictionary subscripting.
1128 // - (id)objectForKeyedSubscript:(id)key;
1129 IdentifierInfo
*KeyIdents
[] = {
1130 &S
.Context
.Idents
.get("objectForKeyedSubscript")
1132 Selector GetterSelector
= S
.Context
.Selectors
.getSelector(1, KeyIdents
);
1133 ObjCMethodDecl
*Getter
= S
.LookupMethodInObjectType(GetterSelector
, ContainerT
,
1137 QualType T
= Getter
->parameters()[0]->getType();
1138 S
.CheckObjCConversion(Key
->getSourceRange(), T
, Key
,
1139 Sema::CCK_ImplicitConversion
);
1142 bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1146 Expr
*BaseExpr
= RefExpr
->getBaseExpr();
1147 QualType BaseT
= BaseExpr
->getType();
1149 QualType ResultType
;
1150 if (const ObjCObjectPointerType
*PTy
=
1151 BaseT
->getAs
<ObjCObjectPointerType
>()) {
1152 ResultType
= PTy
->getPointeeType();
1154 Sema::ObjCSubscriptKind Res
=
1155 S
.CheckSubscriptingKind(RefExpr
->getKeyExpr());
1156 if (Res
== Sema::OS_Error
) {
1157 if (S
.getLangOpts().ObjCAutoRefCount
)
1158 CheckKeyForObjCARCConversion(S
, ResultType
,
1159 RefExpr
->getKeyExpr());
1162 bool arrayRef
= (Res
== Sema::OS_Array
);
1164 if (ResultType
.isNull()) {
1165 S
.Diag(BaseExpr
->getExprLoc(), diag::err_objc_subscript_base_type
)
1166 << BaseExpr
->getType() << arrayRef
;
1170 // dictionary subscripting.
1171 // - (id)objectForKeyedSubscript:(id)key;
1172 IdentifierInfo
*KeyIdents
[] = {
1173 &S
.Context
.Idents
.get("objectForKeyedSubscript")
1175 AtIndexGetterSelector
= S
.Context
.Selectors
.getSelector(1, KeyIdents
);
1178 // - (id)objectAtIndexedSubscript:(size_t)index;
1179 IdentifierInfo
*KeyIdents
[] = {
1180 &S
.Context
.Idents
.get("objectAtIndexedSubscript")
1183 AtIndexGetterSelector
= S
.Context
.Selectors
.getSelector(1, KeyIdents
);
1186 AtIndexGetter
= S
.LookupMethodInObjectType(AtIndexGetterSelector
, ResultType
,
1189 if (!AtIndexGetter
&& S
.getLangOpts().DebuggerObjCLiteral
) {
1190 AtIndexGetter
= ObjCMethodDecl::Create(
1191 S
.Context
, SourceLocation(), SourceLocation(), AtIndexGetterSelector
,
1192 S
.Context
.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,
1193 S
.Context
.getTranslationUnitDecl(), true /*Instance*/,
1194 false /*isVariadic*/,
1195 /*isPropertyAccessor=*/false,
1196 /*isSynthesizedAccessorStub=*/false,
1197 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1198 ObjCImplementationControl::Required
, false);
1199 ParmVarDecl
*Argument
= ParmVarDecl::Create(S
.Context
, AtIndexGetter
,
1200 SourceLocation(), SourceLocation(),
1201 arrayRef
? &S
.Context
.Idents
.get("index")
1202 : &S
.Context
.Idents
.get("key"),
1203 arrayRef
? S
.Context
.UnsignedLongTy
1204 : S
.Context
.getObjCIdType(),
1208 AtIndexGetter
->setMethodParams(S
.Context
, Argument
, std::nullopt
);
1211 if (!AtIndexGetter
) {
1212 if (!BaseT
->isObjCIdType()) {
1213 S
.Diag(BaseExpr
->getExprLoc(), diag::err_objc_subscript_method_not_found
)
1214 << BaseExpr
->getType() << 0 << arrayRef
;
1218 S
.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector
,
1219 RefExpr
->getSourceRange(),
1223 if (AtIndexGetter
) {
1224 QualType T
= AtIndexGetter
->parameters()[0]->getType();
1225 if ((arrayRef
&& !T
->isIntegralOrEnumerationType()) ||
1226 (!arrayRef
&& !T
->isObjCObjectPointerType())) {
1227 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1228 arrayRef
? diag::err_objc_subscript_index_type
1229 : diag::err_objc_subscript_key_type
) << T
;
1230 S
.Diag(AtIndexGetter
->parameters()[0]->getLocation(),
1231 diag::note_parameter_type
) << T
;
1234 QualType R
= AtIndexGetter
->getReturnType();
1235 if (!R
->isObjCObjectPointerType()) {
1236 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1237 diag::err_objc_indexing_method_result_type
) << R
<< arrayRef
;
1238 S
.Diag(AtIndexGetter
->getLocation(), diag::note_method_declared_at
) <<
1239 AtIndexGetter
->getDeclName();
1245 bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1249 Expr
*BaseExpr
= RefExpr
->getBaseExpr();
1250 QualType BaseT
= BaseExpr
->getType();
1252 QualType ResultType
;
1253 if (const ObjCObjectPointerType
*PTy
=
1254 BaseT
->getAs
<ObjCObjectPointerType
>()) {
1255 ResultType
= PTy
->getPointeeType();
1258 Sema::ObjCSubscriptKind Res
=
1259 S
.CheckSubscriptingKind(RefExpr
->getKeyExpr());
1260 if (Res
== Sema::OS_Error
) {
1261 if (S
.getLangOpts().ObjCAutoRefCount
)
1262 CheckKeyForObjCARCConversion(S
, ResultType
,
1263 RefExpr
->getKeyExpr());
1266 bool arrayRef
= (Res
== Sema::OS_Array
);
1268 if (ResultType
.isNull()) {
1269 S
.Diag(BaseExpr
->getExprLoc(), diag::err_objc_subscript_base_type
)
1270 << BaseExpr
->getType() << arrayRef
;
1275 // dictionary subscripting.
1276 // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1277 IdentifierInfo
*KeyIdents
[] = {
1278 &S
.Context
.Idents
.get("setObject"),
1279 &S
.Context
.Idents
.get("forKeyedSubscript")
1281 AtIndexSetterSelector
= S
.Context
.Selectors
.getSelector(2, KeyIdents
);
1284 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1285 IdentifierInfo
*KeyIdents
[] = {
1286 &S
.Context
.Idents
.get("setObject"),
1287 &S
.Context
.Idents
.get("atIndexedSubscript")
1289 AtIndexSetterSelector
= S
.Context
.Selectors
.getSelector(2, KeyIdents
);
1291 AtIndexSetter
= S
.LookupMethodInObjectType(AtIndexSetterSelector
, ResultType
,
1294 if (!AtIndexSetter
&& S
.getLangOpts().DebuggerObjCLiteral
) {
1295 TypeSourceInfo
*ReturnTInfo
= nullptr;
1296 QualType ReturnType
= S
.Context
.VoidTy
;
1297 AtIndexSetter
= ObjCMethodDecl::Create(
1298 S
.Context
, SourceLocation(), SourceLocation(), AtIndexSetterSelector
,
1299 ReturnType
, ReturnTInfo
, S
.Context
.getTranslationUnitDecl(),
1300 true /*Instance*/, false /*isVariadic*/,
1301 /*isPropertyAccessor=*/false,
1302 /*isSynthesizedAccessorStub=*/false,
1303 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1304 ObjCImplementationControl::Required
, false);
1305 SmallVector
<ParmVarDecl
*, 2> Params
;
1306 ParmVarDecl
*object
= ParmVarDecl::Create(S
.Context
, AtIndexSetter
,
1307 SourceLocation(), SourceLocation(),
1308 &S
.Context
.Idents
.get("object"),
1309 S
.Context
.getObjCIdType(),
1313 Params
.push_back(object
);
1314 ParmVarDecl
*key
= ParmVarDecl::Create(S
.Context
, AtIndexSetter
,
1315 SourceLocation(), SourceLocation(),
1316 arrayRef
? &S
.Context
.Idents
.get("index")
1317 : &S
.Context
.Idents
.get("key"),
1318 arrayRef
? S
.Context
.UnsignedLongTy
1319 : S
.Context
.getObjCIdType(),
1323 Params
.push_back(key
);
1324 AtIndexSetter
->setMethodParams(S
.Context
, Params
, std::nullopt
);
1327 if (!AtIndexSetter
) {
1328 if (!BaseT
->isObjCIdType()) {
1329 S
.Diag(BaseExpr
->getExprLoc(),
1330 diag::err_objc_subscript_method_not_found
)
1331 << BaseExpr
->getType() << 1 << arrayRef
;
1335 S
.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector
,
1336 RefExpr
->getSourceRange(),
1341 if (AtIndexSetter
&& arrayRef
) {
1342 QualType T
= AtIndexSetter
->parameters()[1]->getType();
1343 if (!T
->isIntegralOrEnumerationType()) {
1344 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1345 diag::err_objc_subscript_index_type
) << T
;
1346 S
.Diag(AtIndexSetter
->parameters()[1]->getLocation(),
1347 diag::note_parameter_type
) << T
;
1350 T
= AtIndexSetter
->parameters()[0]->getType();
1351 if (!T
->isObjCObjectPointerType()) {
1352 S
.Diag(RefExpr
->getBaseExpr()->getExprLoc(),
1353 diag::err_objc_subscript_object_type
) << T
<< arrayRef
;
1354 S
.Diag(AtIndexSetter
->parameters()[0]->getLocation(),
1355 diag::note_parameter_type
) << T
;
1359 else if (AtIndexSetter
&& !arrayRef
)
1360 for (unsigned i
=0; i
<2; i
++) {
1361 QualType T
= AtIndexSetter
->parameters()[i
]->getType();
1362 if (!T
->isObjCObjectPointerType()) {
1364 S
.Diag(RefExpr
->getKeyExpr()->getExprLoc(),
1365 diag::err_objc_subscript_key_type
) << T
;
1367 S
.Diag(RefExpr
->getBaseExpr()->getExprLoc(),
1368 diag::err_objc_subscript_dic_object_type
) << T
;
1369 S
.Diag(AtIndexSetter
->parameters()[i
]->getLocation(),
1370 diag::note_parameter_type
) << T
;
1378 // Get the object at "Index" position in the container.
1379 // [BaseExpr objectAtIndexedSubscript : IndexExpr];
1380 ExprResult
ObjCSubscriptOpBuilder::buildGet() {
1381 if (!findAtIndexGetter())
1384 QualType receiverType
= InstanceBase
->getType();
1386 // Build a message-send.
1388 Expr
*Index
= InstanceKey
;
1391 Expr
*args
[] = { Index
};
1392 assert(InstanceBase
);
1394 S
.DiagnoseUseOfDecl(AtIndexGetter
, GenericLoc
);
1395 msg
= S
.BuildInstanceMessageImplicit(InstanceBase
, receiverType
,
1397 AtIndexGetterSelector
, AtIndexGetter
,
1398 MultiExprArg(args
, 1));
1402 /// Store into the container the "op" object at "Index"'ed location
1403 /// by building this messaging expression:
1404 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1405 /// \param captureSetValueAsResult If true, capture the actual
1406 /// value being set as the value of the property operation.
1407 ExprResult
ObjCSubscriptOpBuilder::buildSet(Expr
*op
, SourceLocation opcLoc
,
1408 bool captureSetValueAsResult
) {
1409 if (!findAtIndexSetter())
1412 S
.DiagnoseUseOfDecl(AtIndexSetter
, GenericLoc
);
1413 QualType receiverType
= InstanceBase
->getType();
1414 Expr
*Index
= InstanceKey
;
1417 Expr
*args
[] = { op
, Index
};
1419 // Build a message-send.
1420 ExprResult msg
= S
.BuildInstanceMessageImplicit(InstanceBase
, receiverType
,
1422 AtIndexSetterSelector
,
1424 MultiExprArg(args
, 2));
1426 if (!msg
.isInvalid() && captureSetValueAsResult
) {
1427 ObjCMessageExpr
*msgExpr
=
1428 cast
<ObjCMessageExpr
>(msg
.get()->IgnoreImplicit());
1429 Expr
*arg
= msgExpr
->getArg(0);
1430 if (CanCaptureValue(arg
))
1431 msgExpr
->setArg(0, captureValueAsResult(arg
));
1437 //===----------------------------------------------------------------------===//
1438 // MSVC __declspec(property) references
1439 //===----------------------------------------------------------------------===//
1442 MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr
*E
) {
1443 CallArgs
.insert(CallArgs
.begin(), E
->getIdx());
1444 Expr
*Base
= E
->getBase()->IgnoreParens();
1445 while (auto *MSPropSubscript
= dyn_cast
<MSPropertySubscriptExpr
>(Base
)) {
1446 CallArgs
.insert(CallArgs
.begin(), MSPropSubscript
->getIdx());
1447 Base
= MSPropSubscript
->getBase()->IgnoreParens();
1449 return cast
<MSPropertyRefExpr
>(Base
);
1452 Expr
*MSPropertyOpBuilder::rebuildAndCaptureObject(Expr
*syntacticBase
) {
1453 InstanceBase
= capture(RefExpr
->getBaseExpr());
1454 for (Expr
*&Arg
: CallArgs
)
1456 syntacticBase
= Rebuilder(S
, [=](Expr
*, unsigned Idx
) -> Expr
* {
1459 return InstanceBase
;
1461 assert(Idx
<= CallArgs
.size());
1462 return CallArgs
[Idx
- 1];
1464 }).rebuild(syntacticBase
);
1466 return syntacticBase
;
1469 ExprResult
MSPropertyOpBuilder::buildGet() {
1470 if (!RefExpr
->getPropertyDecl()->hasGetter()) {
1471 S
.Diag(RefExpr
->getMemberLoc(), diag::err_no_accessor_for_property
)
1472 << 0 /* getter */ << RefExpr
->getPropertyDecl();
1476 UnqualifiedId GetterName
;
1477 IdentifierInfo
*II
= RefExpr
->getPropertyDecl()->getGetterId();
1478 GetterName
.setIdentifier(II
, RefExpr
->getMemberLoc());
1480 SS
.Adopt(RefExpr
->getQualifierLoc());
1481 ExprResult GetterExpr
=
1482 S
.ActOnMemberAccessExpr(S
.getCurScope(), InstanceBase
, SourceLocation(),
1483 RefExpr
->isArrow() ? tok::arrow
: tok::period
, SS
,
1484 SourceLocation(), GetterName
, nullptr);
1485 if (GetterExpr
.isInvalid()) {
1486 S
.Diag(RefExpr
->getMemberLoc(),
1487 diag::err_cannot_find_suitable_accessor
) << 0 /* getter */
1488 << RefExpr
->getPropertyDecl();
1492 return S
.BuildCallExpr(S
.getCurScope(), GetterExpr
.get(),
1493 RefExpr
->getSourceRange().getBegin(), CallArgs
,
1494 RefExpr
->getSourceRange().getEnd());
1497 ExprResult
MSPropertyOpBuilder::buildSet(Expr
*op
, SourceLocation sl
,
1498 bool captureSetValueAsResult
) {
1499 if (!RefExpr
->getPropertyDecl()->hasSetter()) {
1500 S
.Diag(RefExpr
->getMemberLoc(), diag::err_no_accessor_for_property
)
1501 << 1 /* setter */ << RefExpr
->getPropertyDecl();
1505 UnqualifiedId SetterName
;
1506 IdentifierInfo
*II
= RefExpr
->getPropertyDecl()->getSetterId();
1507 SetterName
.setIdentifier(II
, RefExpr
->getMemberLoc());
1509 SS
.Adopt(RefExpr
->getQualifierLoc());
1510 ExprResult SetterExpr
=
1511 S
.ActOnMemberAccessExpr(S
.getCurScope(), InstanceBase
, SourceLocation(),
1512 RefExpr
->isArrow() ? tok::arrow
: tok::period
, SS
,
1513 SourceLocation(), SetterName
, nullptr);
1514 if (SetterExpr
.isInvalid()) {
1515 S
.Diag(RefExpr
->getMemberLoc(),
1516 diag::err_cannot_find_suitable_accessor
) << 1 /* setter */
1517 << RefExpr
->getPropertyDecl();
1521 SmallVector
<Expr
*, 4> ArgExprs
;
1522 ArgExprs
.append(CallArgs
.begin(), CallArgs
.end());
1523 ArgExprs
.push_back(op
);
1524 return S
.BuildCallExpr(S
.getCurScope(), SetterExpr
.get(),
1525 RefExpr
->getSourceRange().getBegin(), ArgExprs
,
1526 op
->getSourceRange().getEnd());
1529 //===----------------------------------------------------------------------===//
1530 // General Sema routines.
1531 //===----------------------------------------------------------------------===//
1533 ExprResult
Sema::checkPseudoObjectRValue(Expr
*E
) {
1534 Expr
*opaqueRef
= E
->IgnoreParens();
1535 if (ObjCPropertyRefExpr
*refExpr
1536 = dyn_cast
<ObjCPropertyRefExpr
>(opaqueRef
)) {
1537 ObjCPropertyOpBuilder
builder(*this, refExpr
, true);
1538 return builder
.buildRValueOperation(E
);
1540 else if (ObjCSubscriptRefExpr
*refExpr
1541 = dyn_cast
<ObjCSubscriptRefExpr
>(opaqueRef
)) {
1542 ObjCSubscriptOpBuilder
builder(*this, refExpr
, true);
1543 return builder
.buildRValueOperation(E
);
1544 } else if (MSPropertyRefExpr
*refExpr
1545 = dyn_cast
<MSPropertyRefExpr
>(opaqueRef
)) {
1546 MSPropertyOpBuilder
builder(*this, refExpr
, true);
1547 return builder
.buildRValueOperation(E
);
1548 } else if (MSPropertySubscriptExpr
*RefExpr
=
1549 dyn_cast
<MSPropertySubscriptExpr
>(opaqueRef
)) {
1550 MSPropertyOpBuilder
Builder(*this, RefExpr
, true);
1551 return Builder
.buildRValueOperation(E
);
1553 llvm_unreachable("unknown pseudo-object kind!");
1557 /// Check an increment or decrement of a pseudo-object expression.
1558 ExprResult
Sema::checkPseudoObjectIncDec(Scope
*Sc
, SourceLocation opcLoc
,
1559 UnaryOperatorKind opcode
, Expr
*op
) {
1560 // Do nothing if the operand is dependent.
1561 if (op
->isTypeDependent())
1562 return UnaryOperator::Create(Context
, op
, opcode
, Context
.DependentTy
,
1563 VK_PRValue
, OK_Ordinary
, opcLoc
, false,
1564 CurFPFeatureOverrides());
1566 assert(UnaryOperator::isIncrementDecrementOp(opcode
));
1567 Expr
*opaqueRef
= op
->IgnoreParens();
1568 if (ObjCPropertyRefExpr
*refExpr
1569 = dyn_cast
<ObjCPropertyRefExpr
>(opaqueRef
)) {
1570 ObjCPropertyOpBuilder
builder(*this, refExpr
, false);
1571 return builder
.buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
1572 } else if (isa
<ObjCSubscriptRefExpr
>(opaqueRef
)) {
1573 Diag(opcLoc
, diag::err_illegal_container_subscripting_op
);
1575 } else if (MSPropertyRefExpr
*refExpr
1576 = dyn_cast
<MSPropertyRefExpr
>(opaqueRef
)) {
1577 MSPropertyOpBuilder
builder(*this, refExpr
, false);
1578 return builder
.buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
1579 } else if (MSPropertySubscriptExpr
*RefExpr
1580 = dyn_cast
<MSPropertySubscriptExpr
>(opaqueRef
)) {
1581 MSPropertyOpBuilder
Builder(*this, RefExpr
, false);
1582 return Builder
.buildIncDecOperation(Sc
, opcLoc
, opcode
, op
);
1584 llvm_unreachable("unknown pseudo-object kind!");
1588 ExprResult
Sema::checkPseudoObjectAssignment(Scope
*S
, SourceLocation opcLoc
,
1589 BinaryOperatorKind opcode
,
1590 Expr
*LHS
, Expr
*RHS
) {
1591 // Do nothing if either argument is dependent.
1592 if (LHS
->isTypeDependent() || RHS
->isTypeDependent())
1593 return BinaryOperator::Create(Context
, LHS
, RHS
, opcode
,
1594 Context
.DependentTy
, VK_PRValue
, OK_Ordinary
,
1595 opcLoc
, CurFPFeatureOverrides());
1597 // Filter out non-overload placeholder types in the RHS.
1598 if (RHS
->getType()->isNonOverloadPlaceholderType()) {
1599 ExprResult result
= CheckPlaceholderExpr(RHS
);
1600 if (result
.isInvalid()) return ExprError();
1604 bool IsSimpleAssign
= opcode
== BO_Assign
;
1605 Expr
*opaqueRef
= LHS
->IgnoreParens();
1606 if (ObjCPropertyRefExpr
*refExpr
1607 = dyn_cast
<ObjCPropertyRefExpr
>(opaqueRef
)) {
1608 ObjCPropertyOpBuilder
builder(*this, refExpr
, IsSimpleAssign
);
1609 return builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1610 } else if (ObjCSubscriptRefExpr
*refExpr
1611 = dyn_cast
<ObjCSubscriptRefExpr
>(opaqueRef
)) {
1612 ObjCSubscriptOpBuilder
builder(*this, refExpr
, IsSimpleAssign
);
1613 return builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1614 } else if (MSPropertyRefExpr
*refExpr
1615 = dyn_cast
<MSPropertyRefExpr
>(opaqueRef
)) {
1616 MSPropertyOpBuilder
builder(*this, refExpr
, IsSimpleAssign
);
1617 return builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1618 } else if (MSPropertySubscriptExpr
*RefExpr
1619 = dyn_cast
<MSPropertySubscriptExpr
>(opaqueRef
)) {
1620 MSPropertyOpBuilder
Builder(*this, RefExpr
, IsSimpleAssign
);
1621 return Builder
.buildAssignmentOperation(S
, opcLoc
, opcode
, LHS
, RHS
);
1623 llvm_unreachable("unknown pseudo-object kind!");
1627 /// Given a pseudo-object reference, rebuild it without the opaque
1628 /// values. Basically, undo the behavior of rebuildAndCaptureObject.
1629 /// This should never operate in-place.
1630 static Expr
*stripOpaqueValuesFromPseudoObjectRef(Sema
&S
, Expr
*E
) {
1632 [=](Expr
*E
, unsigned) -> Expr
* {
1633 return cast
<OpaqueValueExpr
>(E
)->getSourceExpr();
1638 /// Given a pseudo-object expression, recreate what it looks like
1639 /// syntactically without the attendant OpaqueValueExprs.
1641 /// This is a hack which should be removed when TreeTransform is
1642 /// capable of rebuilding a tree without stripping implicit
1644 Expr
*Sema::recreateSyntacticForm(PseudoObjectExpr
*E
) {
1645 Expr
*syntax
= E
->getSyntacticForm();
1646 if (UnaryOperator
*uop
= dyn_cast
<UnaryOperator
>(syntax
)) {
1647 Expr
*op
= stripOpaqueValuesFromPseudoObjectRef(*this, uop
->getSubExpr());
1648 return UnaryOperator::Create(Context
, op
, uop
->getOpcode(), uop
->getType(),
1649 uop
->getValueKind(), uop
->getObjectKind(),
1650 uop
->getOperatorLoc(), uop
->canOverflow(),
1651 CurFPFeatureOverrides());
1652 } else if (CompoundAssignOperator
*cop
1653 = dyn_cast
<CompoundAssignOperator
>(syntax
)) {
1654 Expr
*lhs
= stripOpaqueValuesFromPseudoObjectRef(*this, cop
->getLHS());
1655 Expr
*rhs
= cast
<OpaqueValueExpr
>(cop
->getRHS())->getSourceExpr();
1656 return CompoundAssignOperator::Create(
1657 Context
, lhs
, rhs
, cop
->getOpcode(), cop
->getType(),
1658 cop
->getValueKind(), cop
->getObjectKind(), cop
->getOperatorLoc(),
1659 CurFPFeatureOverrides(), cop
->getComputationLHSType(),
1660 cop
->getComputationResultType());
1662 } else if (BinaryOperator
*bop
= dyn_cast
<BinaryOperator
>(syntax
)) {
1663 Expr
*lhs
= stripOpaqueValuesFromPseudoObjectRef(*this, bop
->getLHS());
1664 Expr
*rhs
= cast
<OpaqueValueExpr
>(bop
->getRHS())->getSourceExpr();
1665 return BinaryOperator::Create(Context
, lhs
, rhs
, bop
->getOpcode(),
1666 bop
->getType(), bop
->getValueKind(),
1667 bop
->getObjectKind(), bop
->getOperatorLoc(),
1668 CurFPFeatureOverrides());
1670 } else if (isa
<CallExpr
>(syntax
)) {
1673 assert(syntax
->hasPlaceholderType(BuiltinType::PseudoObject
));
1674 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax
);