Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
//
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.
13
//
14
//  For example, Objective-C objects can have "properties", either
15
//  declared or undeclared.  A property may be accessed by writing
16
//    expr.prop
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:
21
//    [expr prop]
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]
29
//
30
//===----------------------------------------------------------------------===//
31
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"
40
41
using namespace clang;
42
using namespace sema;
43
44
namespace {
45
  // Basically just a very focused copy of TreeTransform.
46
  struct Rebuilder {
47
    Sema &S;
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
0
          SpecificCallback(SpecificCallback) {}
54
55
0
    Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {
56
      // Fortunately, the constraint that we're rebuilding something
57
      // with a base limits the number of cases here.
58
0
      if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
59
0
        return refExpr;
60
61
0
      if (refExpr->isExplicitProperty()) {
62
0
        return new (S.Context) ObjCPropertyRefExpr(
63
0
            refExpr->getExplicitProperty(), refExpr->getType(),
64
0
            refExpr->getValueKind(), refExpr->getObjectKind(),
65
0
            refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
66
0
      }
67
0
      return new (S.Context) ObjCPropertyRefExpr(
68
0
          refExpr->getImplicitPropertyGetter(),
69
0
          refExpr->getImplicitPropertySetter(), refExpr->getType(),
70
0
          refExpr->getValueKind(), refExpr->getObjectKind(),
71
0
          refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
72
0
    }
73
0
    Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {
74
0
      assert(refExpr->getBaseExpr());
75
0
      assert(refExpr->getKeyExpr());
76
77
0
      return new (S.Context) ObjCSubscriptRefExpr(
78
0
          SpecificCallback(refExpr->getBaseExpr(), 0),
79
0
          SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),
80
0
          refExpr->getValueKind(), refExpr->getObjectKind(),
81
0
          refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),
82
0
          refExpr->getRBracket());
83
0
    }
84
0
    Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {
85
0
      assert(refExpr->getBaseExpr());
86
87
0
      return new (S.Context) MSPropertyRefExpr(
88
0
          SpecificCallback(refExpr->getBaseExpr(), 0),
89
0
          refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),
90
0
          refExpr->getValueKind(), refExpr->getQualifierLoc(),
91
0
          refExpr->getMemberLoc());
92
0
    }
93
0
    Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {
94
0
      assert(refExpr->getBase());
95
0
      assert(refExpr->getIdx());
96
97
0
      auto *NewBase = rebuild(refExpr->getBase());
98
0
      ++MSPropertySubscriptCount;
99
0
      return new (S.Context) MSPropertySubscriptExpr(
100
0
          NewBase,
101
0
          SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),
102
0
          refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),
103
0
          refExpr->getRBracketLoc());
104
0
    }
105
106
0
    Expr *rebuild(Expr *e) {
107
      // Fast path: nothing to look through.
108
0
      if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))
109
0
        return rebuildObjCPropertyRefExpr(PRE);
110
0
      if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))
111
0
        return rebuildObjCSubscriptRefExpr(SRE);
112
0
      if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))
113
0
        return rebuildMSPropertyRefExpr(MSPRE);
114
0
      if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))
115
0
        return rebuildMSPropertySubscriptExpr(MSPSE);
116
117
      // Otherwise, we should look through and rebuild anything that
118
      // IgnoreParens would.
119
120
0
      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
121
0
        e = rebuild(parens->getSubExpr());
122
0
        return new (S.Context) ParenExpr(parens->getLParen(),
123
0
                                         parens->getRParen(),
124
0
                                         e);
125
0
      }
126
127
0
      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
128
0
        assert(uop->getOpcode() == UO_Extension);
129
0
        e = rebuild(uop->getSubExpr());
130
0
        return UnaryOperator::Create(
131
0
            S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),
132
0
            uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
133
0
            S.CurFPFeatureOverrides());
134
0
      }
135
136
0
      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
137
0
        assert(!gse->isResultDependent());
138
0
        unsigned resultIndex = gse->getResultIndex();
139
0
        unsigned numAssocs = gse->getNumAssocs();
140
141
0
        SmallVector<Expr *, 8> assocExprs;
142
0
        SmallVector<TypeSourceInfo *, 8> assocTypes;
143
0
        assocExprs.reserve(numAssocs);
144
0
        assocTypes.reserve(numAssocs);
145
146
0
        for (const GenericSelectionExpr::Association assoc :
147
0
             gse->associations()) {
148
0
          Expr *assocExpr = assoc.getAssociationExpr();
149
0
          if (assoc.isSelected())
150
0
            assocExpr = rebuild(assocExpr);
151
0
          assocExprs.push_back(assocExpr);
152
0
          assocTypes.push_back(assoc.getTypeSourceInfo());
153
0
        }
154
155
0
        if (gse->isExprPredicate())
156
0
          return GenericSelectionExpr::Create(
157
0
              S.Context, gse->getGenericLoc(), gse->getControllingExpr(),
158
0
              assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
159
0
              gse->containsUnexpandedParameterPack(), resultIndex);
160
0
        return GenericSelectionExpr::Create(
161
0
            S.Context, gse->getGenericLoc(), gse->getControllingType(),
162
0
            assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
163
0
            gse->containsUnexpandedParameterPack(), resultIndex);
164
0
      }
165
166
0
      if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {
167
0
        assert(!ce->isConditionDependent());
168
169
0
        Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();
170
0
        Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;
171
0
        rebuiltExpr = rebuild(rebuiltExpr);
172
173
0
        return new (S.Context)
174
0
            ChooseExpr(ce->getBuiltinLoc(), ce->getCond(), LHS, RHS,
175
0
                       rebuiltExpr->getType(), rebuiltExpr->getValueKind(),
176
0
                       rebuiltExpr->getObjectKind(), ce->getRParenLoc(),
177
0
                       ce->isConditionTrue());
178
0
      }
179
180
0
      llvm_unreachable("bad expression to rebuild!");
181
0
    }
182
  };
183
184
  class PseudoOpBuilder {
185
  public:
186
    Sema &S;
187
    unsigned ResultIndex;
188
    SourceLocation GenericLoc;
189
    bool IsUnique;
190
    SmallVector<Expr *, 4> Semantics;
191
192
    PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
193
      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
194
0
        GenericLoc(genericLoc), IsUnique(IsUnique) {}
195
196
0
    virtual ~PseudoOpBuilder() {}
197
198
    /// Add a normal semantic expression.
199
0
    void addSemanticExpr(Expr *semantic) {
200
0
      Semantics.push_back(semantic);
201
0
    }
202
203
    /// Add the 'result' semantic expression.
204
0
    void addResultSemanticExpr(Expr *resultExpr) {
205
0
      assert(ResultIndex == PseudoObjectExpr::NoResult);
206
0
      ResultIndex = Semantics.size();
207
0
      Semantics.push_back(resultExpr);
208
      // An OVE is not unique if it is used as the result expression.
209
0
      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
210
0
        OVE->setIsUnique(false);
211
0
    }
212
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,
220
                                    Expr *op);
221
222
    virtual ExprResult complete(Expr *syntacticForm);
223
224
    OpaqueValueExpr *capture(Expr *op);
225
    OpaqueValueExpr *captureValueAsResult(Expr *op);
226
227
0
    void setResultToLastSemantic() {
228
0
      assert(ResultIndex == PseudoObjectExpr::NoResult);
229
0
      ResultIndex = Semantics.size() - 1;
230
      // An OVE is not unique if it is used as the result expression.
231
0
      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
232
0
        OVE->setIsUnique(false);
233
0
    }
234
235
    /// Return true if assignments have a non-void result.
236
0
    static bool CanCaptureValue(Expr *exp) {
237
0
      if (exp->isGLValue())
238
0
        return true;
239
0
      QualType ty = exp->getType();
240
0
      assert(!ty->isIncompleteType());
241
0
      assert(!ty->isDependentType());
242
243
0
      if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())
244
0
        return ClassDecl->isTriviallyCopyable();
245
0
      return true;
246
0
    }
247
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?
254
    ///
255
    /// Different pseudo-object language features use different language rules
256
    /// for this.
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.
262
    ///
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
0
    virtual bool captureSetValueAsResult() const { return true; }
266
  };
267
268
  /// A PseudoOpBuilder for Objective-C \@properties.
269
  class ObjCPropertyOpBuilder : public PseudoOpBuilder {
270
    ObjCPropertyRefExpr *RefExpr;
271
    ObjCPropertyRefExpr *SyntacticRefExpr;
272
    OpaqueValueExpr *InstanceReceiver;
273
    ObjCMethodDecl *Getter;
274
275
    ObjCMethodDecl *Setter;
276
    Selector SetterSelector;
277
    Selector GetterSelector;
278
279
  public:
280
    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)
281
        : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),
282
          RefExpr(refExpr), SyntacticRefExpr(nullptr),
283
0
          InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {
284
0
    }
285
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,
293
                                    Expr *op);
294
295
    bool tryBuildGetOfReference(Expr *op, ExprResult &result);
296
    bool findSetter(bool warn=true);
297
    bool findGetter();
298
    void DiagnoseUnsupportedPropertyUse();
299
300
    Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
301
    ExprResult buildGet() override;
302
    ExprResult buildSet(Expr *op, SourceLocation, bool) override;
303
    ExprResult complete(Expr *SyntacticForm) override;
304
305
    bool isWeakProperty() const;
306
  };
307
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;
315
316
   ObjCMethodDecl *AtIndexSetter;
317
   Selector AtIndexSetterSelector;
318
319
 public:
320
   ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)
321
       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
322
         RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),
323
0
         AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
324
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;
331
332
   bool findAtIndexGetter();
333
   bool findAtIndexSetter();
334
335
   ExprResult buildGet() override;
336
   ExprResult buildSet(Expr *op, SourceLocation, bool) override;
337
 };
338
339
 class MSPropertyOpBuilder : public PseudoOpBuilder {
340
   MSPropertyRefExpr *RefExpr;
341
   OpaqueValueExpr *InstanceBase;
342
   SmallVector<Expr *, 4> CallArgs;
343
344
   MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
345
346
 public:
347
   MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
348
       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
349
0
         RefExpr(refExpr), InstanceBase(nullptr) {}
350
   MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)
351
       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
352
0
         InstanceBase(nullptr) {
353
0
     RefExpr = getBaseMSProperty(refExpr);
354
0
   }
355
356
   Expr *rebuildAndCaptureObject(Expr *) override;
357
   ExprResult buildGet() override;
358
   ExprResult buildSet(Expr *op, SourceLocation, bool) override;
359
0
   bool captureSetValueAsResult() const override { return false; }
360
 };
361
}
362
363
/// Capture the given expression in an OpaqueValueExpr.
364
0
OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
365
  // Make a new OVE whose source is the given expression.
366
0
  OpaqueValueExpr *captured =
367
0
    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
368
0
                                    e->getValueKind(), e->getObjectKind(),
369
0
                                    e);
370
0
  if (IsUnique)
371
0
    captured->setIsUnique(true);
372
373
  // Make sure we bind that in the semantics.
374
0
  addSemanticExpr(captured);
375
0
  return captured;
376
0
}
377
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.
381
///
382
/// \returns the captured expression, which will be the
383
///   same as the input if the input was already captured
384
0
OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
385
0
  assert(ResultIndex == PseudoObjectExpr::NoResult);
386
387
  // If the expression hasn't already been captured, just capture it
388
  // and set the new semantic
389
0
  if (!isa<OpaqueValueExpr>(e)) {
390
0
    OpaqueValueExpr *cap = capture(e);
391
0
    setResultToLastSemantic();
392
0
    return cap;
393
0
  }
394
395
  // Otherwise, it must already be one of our semantic expressions;
396
  // set ResultIndex to its index.
397
0
  unsigned index = 0;
398
0
  for (;; ++index) {
399
0
    assert(index < Semantics.size() &&
400
0
           "captured expression not found in semantics!");
401
0
    if (e == Semantics[index]) break;
402
0
  }
403
0
  ResultIndex = index;
404
  // An OVE is not unique if it is used as the result expression.
405
0
  cast<OpaqueValueExpr>(e)->setIsUnique(false);
406
0
  return cast<OpaqueValueExpr>(e);
407
0
}
408
409
/// The routine which creates the final PseudoObjectExpr.
410
0
ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
411
0
  return PseudoObjectExpr::Create(S.Context, syntactic,
412
0
                                  Semantics, ResultIndex);
413
0
}
414
415
/// The main skeleton for building an r-value operation.
416
0
ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
417
0
  Expr *syntacticBase = rebuildAndCaptureObject(op);
418
419
0
  ExprResult getExpr = buildGet();
420
0
  if (getExpr.isInvalid()) return ExprError();
421
0
  addResultSemanticExpr(getExpr.get());
422
423
0
  return complete(syntacticBase);
424
0
}
425
426
/// The basic skeleton for building a simple or compound
427
/// assignment operation.
428
ExprResult
429
PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
430
                                          BinaryOperatorKind opcode,
431
0
                                          Expr *LHS, Expr *RHS) {
432
0
  assert(BinaryOperator::isAssignmentOp(opcode));
433
434
0
  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
435
0
  OpaqueValueExpr *capturedRHS = capture(RHS);
436
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
0
  Expr *semanticRHS = capturedRHS;
444
0
  if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) {
445
0
    semanticRHS = RHS;
446
0
    Semantics.pop_back();
447
0
  }
448
449
0
  Expr *syntactic;
450
451
0
  ExprResult result;
452
0
  if (opcode == BO_Assign) {
453
0
    result = semanticRHS;
454
0
    syntactic = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS,
455
0
                                       opcode, capturedRHS->getType(),
456
0
                                       capturedRHS->getValueKind(), OK_Ordinary,
457
0
                                       opcLoc, S.CurFPFeatureOverrides());
458
459
0
  } else {
460
0
    ExprResult opLHS = buildGet();
461
0
    if (opLHS.isInvalid()) return ExprError();
462
463
    // Build an ordinary, non-compound operation.
464
0
    BinaryOperatorKind nonCompound =
465
0
      BinaryOperator::getOpForCompoundAssignment(opcode);
466
0
    result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);
467
0
    if (result.isInvalid()) return ExprError();
468
469
0
    syntactic = CompoundAssignOperator::Create(
470
0
        S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),
471
0
        result.get()->getValueKind(), OK_Ordinary, opcLoc,
472
0
        S.CurFPFeatureOverrides(), opLHS.get()->getType(),
473
0
        result.get()->getType());
474
0
  }
475
476
  // The result of the assignment, if not void, is the value set into
477
  // the l-value.
478
0
  result = buildSet(result.get(), opcLoc, captureSetValueAsResult());
479
0
  if (result.isInvalid()) return ExprError();
480
0
  addSemanticExpr(result.get());
481
0
  if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&
482
0
      (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
483
0
    setResultToLastSemantic();
484
485
0
  return complete(syntactic);
486
0
}
487
488
/// The basic skeleton for building an increment or decrement
489
/// operation.
490
ExprResult
491
PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
492
                                      UnaryOperatorKind opcode,
493
0
                                      Expr *op) {
494
0
  assert(UnaryOperator::isIncrementDecrementOp(opcode));
495
496
0
  Expr *syntacticOp = rebuildAndCaptureObject(op);
497
498
  // Load the value.
499
0
  ExprResult result = buildGet();
500
0
  if (result.isInvalid()) return ExprError();
501
502
0
  QualType resultType = result.get()->getType();
503
504
  // That's the postfix result.
505
0
  if (UnaryOperator::isPostfix(opcode) &&
506
0
      (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {
507
0
    result = capture(result.get());
508
0
    setResultToLastSemantic();
509
0
  }
510
511
  // Add or subtract a literal 1.
512
0
  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
513
0
  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
514
0
                                     GenericLoc);
515
516
0
  if (UnaryOperator::isIncrementOp(opcode)) {
517
0
    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one);
518
0
  } else {
519
0
    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one);
520
0
  }
521
0
  if (result.isInvalid()) return ExprError();
522
523
  // Store that back into the result.  The value stored is the result
524
  // of a prefix operation.
525
0
  result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&
526
0
                                              captureSetValueAsResult());
527
0
  if (result.isInvalid()) return ExprError();
528
0
  addSemanticExpr(result.get());
529
0
  if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&
530
0
      !result.get()->getType()->isVoidType() &&
531
0
      (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
532
0
    setResultToLastSemantic();
533
534
0
  UnaryOperator *syntactic =
535
0
      UnaryOperator::Create(S.Context, syntacticOp, opcode, resultType,
536
0
                            VK_LValue, OK_Ordinary, opcLoc,
537
0
                            !resultType->isDependentType()
538
0
                                ? S.Context.getTypeSize(resultType) >=
539
0
                                      S.Context.getTypeSize(S.Context.IntTy)
540
0
                                : false,
541
0
                            S.CurFPFeatureOverrides());
542
0
  return complete(syntactic);
543
0
}
544
545
546
//===----------------------------------------------------------------------===//
547
//  Objective-C @property and implicit property references
548
//===----------------------------------------------------------------------===//
549
550
/// Look up a method in the receiver type of an Objective-C property
551
/// reference.
552
static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
553
0
                                            const ObjCPropertyRefExpr *PRE) {
554
0
  if (PRE->isObjectReceiver()) {
555
0
    const ObjCObjectPointerType *PT =
556
0
      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
557
558
    // Special case for 'self' in class method implementations.
559
0
    if (PT->isObjCClassType() &&
560
0
        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
561
      // This cast is safe because isSelfExpr is only true within
562
      // methods.
563
0
      ObjCMethodDecl *method =
564
0
        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
565
0
      return S.LookupMethodInObjectType(sel,
566
0
                 S.Context.getObjCInterfaceType(method->getClassInterface()),
567
0
                                        /*instance*/ false);
568
0
    }
569
570
0
    return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
571
0
  }
572
573
0
  if (PRE->isSuperReceiver()) {
574
0
    if (const ObjCObjectPointerType *PT =
575
0
        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
576
0
      return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
577
578
0
    return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
579
0
  }
580
581
0
  assert(PRE->isClassReceiver() && "Invalid expression");
582
0
  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
583
0
  return S.LookupMethodInObjectType(sel, IT, false);
584
0
}
585
586
0
bool ObjCPropertyOpBuilder::isWeakProperty() const {
587
0
  QualType T;
588
0
  if (RefExpr->isExplicitProperty()) {
589
0
    const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();
590
0
    if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
591
0
      return true;
592
593
0
    T = Prop->getType();
594
0
  } else if (Getter) {
595
0
    T = Getter->getReturnType();
596
0
  } else {
597
0
    return false;
598
0
  }
599
600
0
  return T.getObjCLifetime() == Qualifiers::OCL_Weak;
601
0
}
602
603
0
bool ObjCPropertyOpBuilder::findGetter() {
604
0
  if (Getter) return true;
605
606
  // For implicit properties, just trust the lookup we already did.
607
0
  if (RefExpr->isImplicitProperty()) {
608
0
    if ((Getter = RefExpr->getImplicitPropertyGetter())) {
609
0
      GetterSelector = Getter->getSelector();
610
0
      return true;
611
0
    }
612
0
    else {
613
      // Must build the getter selector the hard way.
614
0
      ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
615
0
      assert(setter && "both setter and getter are null - cannot happen");
616
0
      IdentifierInfo *setterName =
617
0
        setter->getSelector().getIdentifierInfoForSlot(0);
618
0
      IdentifierInfo *getterName =
619
0
          &S.Context.Idents.get(setterName->getName().substr(3));
620
0
      GetterSelector =
621
0
        S.PP.getSelectorTable().getNullarySelector(getterName);
622
0
      return false;
623
0
    }
624
0
  }
625
626
0
  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
627
0
  Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
628
0
  return (Getter != nullptr);
629
0
}
630
631
/// Try to find the most accurate setter declaration for the property
632
/// reference.
633
///
634
/// \return true if a setter was found, in which case Setter
635
0
bool ObjCPropertyOpBuilder::findSetter(bool warn) {
636
  // For implicit properties, just trust the lookup we already did.
637
0
  if (RefExpr->isImplicitProperty()) {
638
0
    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
639
0
      Setter = setter;
640
0
      SetterSelector = setter->getSelector();
641
0
      return true;
642
0
    } else {
643
0
      IdentifierInfo *getterName =
644
0
        RefExpr->getImplicitPropertyGetter()->getSelector()
645
0
          .getIdentifierInfoForSlot(0);
646
0
      SetterSelector =
647
0
        SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
648
0
                                               S.PP.getSelectorTable(),
649
0
                                               getterName);
650
0
      return false;
651
0
    }
652
0
  }
653
654
  // For explicit properties, this is more involved.
655
0
  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
656
0
  SetterSelector = prop->getSetterName();
657
658
  // Do a normal method lookup first.
659
0
  if (ObjCMethodDecl *setter =
660
0
        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
661
0
    if (setter->isPropertyAccessor() && warn)
662
0
      if (const ObjCInterfaceDecl *IFace =
663
0
          dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
664
0
        StringRef thisPropertyName = prop->getName();
665
        // Try flipping the case of the first character.
666
0
        char front = thisPropertyName.front();
667
0
        front = isLowercase(front) ? toUppercase(front) : toLowercase(front);
668
0
        SmallString<100> PropertyName = thisPropertyName;
669
0
        PropertyName[0] = front;
670
0
        IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
671
0
        if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(
672
0
                AltMember, prop->getQueryKind()))
673
0
          if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
674
0
            S.Diag(RefExpr->getExprLoc(), diag::err_property_setter_ambiguous_use)
675
0
              << prop << prop1 << setter->getSelector();
676
0
            S.Diag(prop->getLocation(), diag::note_property_declare);
677
0
            S.Diag(prop1->getLocation(), diag::note_property_declare);
678
0
          }
679
0
      }
680
0
    Setter = setter;
681
0
    return true;
682
0
  }
683
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.
688
689
0
  return false;
690
0
}
691
692
0
void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
693
0
  if (S.getCurLexicalContext()->isObjCContainer() &&
694
0
      S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&
695
0
      S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {
696
0
    if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {
697
0
        S.Diag(RefExpr->getLocation(),
698
0
               diag::err_property_function_in_objc_container);
699
0
        S.Diag(prop->getLocation(), diag::note_property_declare);
700
0
    }
701
0
  }
702
0
}
703
704
/// Capture the base object of an Objective-C property expression.
705
0
Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
706
0
  assert(InstanceReceiver == nullptr);
707
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
0
  if (RefExpr->isObjectReceiver()) {
711
0
    InstanceReceiver = capture(RefExpr->getBase());
712
0
    syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
713
0
                      return InstanceReceiver;
714
0
                    }).rebuild(syntacticBase);
715
0
  }
716
717
0
  if (ObjCPropertyRefExpr *
718
0
        refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
719
0
    SyntacticRefExpr = refE;
720
721
0
  return syntacticBase;
722
0
}
723
724
/// Load from an Objective-C property reference.
725
0
ExprResult ObjCPropertyOpBuilder::buildGet() {
726
0
  findGetter();
727
0
  if (!Getter) {
728
0
    DiagnoseUnsupportedPropertyUse();
729
0
    return ExprError();
730
0
  }
731
732
0
  if (SyntacticRefExpr)
733
0
    SyntacticRefExpr->setIsMessagingGetter();
734
735
0
  QualType receiverType = RefExpr->getReceiverType(S.Context);
736
0
  if (!Getter->isImplicit())
737
0
    S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
738
  // Build a message-send.
739
0
  ExprResult msg;
740
0
  if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
741
0
      RefExpr->isObjectReceiver()) {
742
0
    assert(InstanceReceiver || RefExpr->isSuperReceiver());
743
0
    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
744
0
                                         GenericLoc, Getter->getSelector(),
745
0
                                         Getter, std::nullopt);
746
0
  } else {
747
0
    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
748
0
                                      GenericLoc, Getter->getSelector(), Getter,
749
0
                                      std::nullopt);
750
0
  }
751
0
  return msg;
752
0
}
753
754
/// Store to an Objective-C property reference.
755
///
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
0
                                           bool captureSetValueAsResult) {
760
0
  if (!findSetter(false)) {
761
0
    DiagnoseUnsupportedPropertyUse();
762
0
    return ExprError();
763
0
  }
764
765
0
  if (SyntacticRefExpr)
766
0
    SyntacticRefExpr->setIsMessagingSetter();
767
768
0
  QualType receiverType = RefExpr->getReceiverType(S.Context);
769
770
  // Use assignment constraints when possible; they give us better
771
  // diagnostics.  "When possible" basically means anything except a
772
  // C++ class type.
773
0
  if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
774
0
    QualType paramType = (*Setter->param_begin())->getType()
775
0
                           .substObjCMemberType(
776
0
                             receiverType,
777
0
                             Setter->getDeclContext(),
778
0
                             ObjCSubstitutionContext::Parameter);
779
0
    if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
780
0
      ExprResult opResult = op;
781
0
      Sema::AssignConvertType assignResult
782
0
        = S.CheckSingleAssignmentConstraints(paramType, opResult);
783
0
      if (opResult.isInvalid() ||
784
0
          S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
785
0
                                     op->getType(), opResult.get(),
786
0
                                     Sema::AA_Assigning))
787
0
        return ExprError();
788
789
0
      op = opResult.get();
790
0
      assert(op && "successful assignment left argument invalid?");
791
0
    }
792
0
  }
793
794
  // Arguments.
795
0
  Expr *args[] = { op };
796
797
  // Build a message-send.
798
0
  ExprResult msg;
799
0
  if (!Setter->isImplicit())
800
0
    S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);
801
0
  if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
802
0
      RefExpr->isObjectReceiver()) {
803
0
    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
804
0
                                         GenericLoc, SetterSelector, Setter,
805
0
                                         MultiExprArg(args, 1));
806
0
  } else {
807
0
    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
808
0
                                      GenericLoc,
809
0
                                      SetterSelector, Setter,
810
0
                                      MultiExprArg(args, 1));
811
0
  }
812
813
0
  if (!msg.isInvalid() && captureSetValueAsResult) {
814
0
    ObjCMessageExpr *msgExpr =
815
0
      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
816
0
    Expr *arg = msgExpr->getArg(0);
817
0
    if (CanCaptureValue(arg))
818
0
      msgExpr->setArg(0, captureValueAsResult(arg));
819
0
  }
820
821
0
  return msg;
822
0
}
823
824
/// @property-specific behavior for doing lvalue-to-rvalue conversion.
825
0
ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
826
  // Explicit properties always have getters, but implicit ones don't.
827
  // Check that before proceeding.
828
0
  if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {
829
0
    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
830
0
        << RefExpr->getSourceRange();
831
0
    return ExprError();
832
0
  }
833
834
0
  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
835
0
  if (result.isInvalid()) return ExprError();
836
837
0
  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
838
0
    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
839
0
                                       Getter, RefExpr->getLocation());
840
841
  // As a special case, if the method returns 'id', try to get
842
  // a better type from the property.
843
0
  if (RefExpr->isExplicitProperty() && result.get()->isPRValue()) {
844
0
    QualType receiverType = RefExpr->getReceiverType(S.Context);
845
0
    QualType propType = RefExpr->getExplicitProperty()
846
0
                          ->getUsageType(receiverType);
847
0
    if (result.get()->getType()->isObjCIdType()) {
848
0
      if (const ObjCObjectPointerType *ptr
849
0
            = propType->getAs<ObjCObjectPointerType>()) {
850
0
        if (!ptr->isObjCIdType())
851
0
          result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
852
0
      }
853
0
    }
854
0
    if (propType.getObjCLifetime() == Qualifiers::OCL_Weak &&
855
0
        !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
856
0
                           RefExpr->getLocation()))
857
0
      S.getCurFunction()->markSafeWeakUse(RefExpr);
858
0
  }
859
860
0
  return result;
861
0
}
862
863
/// Try to build this as a call to a getter that returns a reference.
864
///
865
/// \return true if it was possible, whether or not it actually
866
///   succeeded
867
bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
868
0
                                                   ExprResult &result) {
869
0
  if (!S.getLangOpts().CPlusPlus) return false;
870
871
0
  findGetter();
872
0
  if (!Getter) {
873
    // The property has no setter and no getter! This can happen if the type is
874
    // invalid. Error have already been reported.
875
0
    result = ExprError();
876
0
    return true;
877
0
  }
878
879
  // Only do this if the getter returns an l-value reference type.
880
0
  QualType resultType = Getter->getReturnType();
881
0
  if (!resultType->isLValueReferenceType()) return false;
882
883
0
  result = buildRValueOperation(op);
884
0
  return true;
885
0
}
886
887
/// @property-specific behavior for doing assignments.
888
ExprResult
889
ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
890
                                                SourceLocation opcLoc,
891
                                                BinaryOperatorKind opcode,
892
0
                                                Expr *LHS, Expr *RHS) {
893
0
  assert(BinaryOperator::isAssignmentOp(opcode));
894
895
  // If there's no setter, we have no choice but to try to assign to
896
  // the result of the getter.
897
0
  if (!findSetter()) {
898
0
    ExprResult result;
899
0
    if (tryBuildGetOfReference(LHS, result)) {
900
0
      if (result.isInvalid()) return ExprError();
901
0
      return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS);
902
0
    }
903
904
    // Otherwise, it's an error.
905
0
    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
906
0
      << unsigned(RefExpr->isImplicitProperty())
907
0
      << SetterSelector
908
0
      << LHS->getSourceRange() << RHS->getSourceRange();
909
0
    return ExprError();
910
0
  }
911
912
  // If there is a setter, we definitely want to use it.
913
914
  // Verify that we can do a compound assignment.
915
0
  if (opcode != BO_Assign && !findGetter()) {
916
0
    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
917
0
      << LHS->getSourceRange() << RHS->getSourceRange();
918
0
    return ExprError();
919
0
  }
920
921
0
  ExprResult result =
922
0
    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
923
0
  if (result.isInvalid()) return ExprError();
924
925
  // Various warnings about property assignments in ARC.
926
0
  if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
927
0
    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
928
0
    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
929
0
  }
930
931
0
  return result;
932
0
}
933
934
/// @property-specific behavior for doing increments and decrements.
935
ExprResult
936
ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
937
                                            UnaryOperatorKind opcode,
938
0
                                            Expr *op) {
939
  // If there's no setter, we have no choice but to try to assign to
940
  // the result of the getter.
941
0
  if (!findSetter()) {
942
0
    ExprResult result;
943
0
    if (tryBuildGetOfReference(op, result)) {
944
0
      if (result.isInvalid()) return ExprError();
945
0
      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get());
946
0
    }
947
948
    // Otherwise, it's an error.
949
0
    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
950
0
      << unsigned(RefExpr->isImplicitProperty())
951
0
      << unsigned(UnaryOperator::isDecrementOp(opcode))
952
0
      << SetterSelector
953
0
      << op->getSourceRange();
954
0
    return ExprError();
955
0
  }
956
957
  // If there is a setter, we definitely want to use it.
958
959
  // We also need a getter.
960
0
  if (!findGetter()) {
961
0
    assert(RefExpr->isImplicitProperty());
962
0
    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
963
0
      << unsigned(UnaryOperator::isDecrementOp(opcode))
964
0
      << GetterSelector
965
0
      << op->getSourceRange();
966
0
    return ExprError();
967
0
  }
968
969
0
  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
970
0
}
971
972
0
ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
973
0
  if (isWeakProperty() && !S.isUnevaluatedContext() &&
974
0
      !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
975
0
                         SyntacticForm->getBeginLoc()))
976
0
    S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
977
0
                                        SyntacticRefExpr->isMessagingGetter());
978
979
0
  return PseudoOpBuilder::complete(SyntacticForm);
980
0
}
981
982
// ObjCSubscript build stuff.
983
//
984
985
/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
986
/// conversion.
987
/// FIXME. Remove this routine if it is proven that no additional
988
/// specifity is needed.
989
0
ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
990
0
  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
991
0
  if (result.isInvalid()) return ExprError();
992
0
  return result;
993
0
}
994
995
/// objective-c subscripting-specific  behavior for doing assignments.
996
ExprResult
997
ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
998
                                                SourceLocation opcLoc,
999
                                                BinaryOperatorKind opcode,
1000
0
                                                Expr *LHS, Expr *RHS) {
1001
0
  assert(BinaryOperator::isAssignmentOp(opcode));
1002
  // There must be a method to do the Index'ed assignment.
1003
0
  if (!findAtIndexSetter())
1004
0
    return ExprError();
1005
1006
  // Verify that we can do a compound assignment.
1007
0
  if (opcode != BO_Assign && !findAtIndexGetter())
1008
0
    return ExprError();
1009
1010
0
  ExprResult result =
1011
0
  PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
1012
0
  if (result.isInvalid()) return ExprError();
1013
1014
  // Various warnings about objc Index'ed assignments in ARC.
1015
0
  if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
1016
0
    S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
1017
0
    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
1018
0
  }
1019
1020
0
  return result;
1021
0
}
1022
1023
/// Capture the base object of an Objective-C Index'ed expression.
1024
0
Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
1025
0
  assert(InstanceBase == nullptr);
1026
1027
  // Capture base expression in an OVE and rebuild the syntactic
1028
  // form to use the OVE as its base expression.
1029
0
  InstanceBase = capture(RefExpr->getBaseExpr());
1030
0
  InstanceKey = capture(RefExpr->getKeyExpr());
1031
1032
0
  syntacticBase =
1033
0
      Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
1034
0
        switch (Idx) {
1035
0
        case 0:
1036
0
          return InstanceBase;
1037
0
        case 1:
1038
0
          return InstanceKey;
1039
0
        default:
1040
0
          llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
1041
0
        }
1042
0
      }).rebuild(syntacticBase);
1043
1044
0
  return syntacticBase;
1045
0
}
1046
1047
/// CheckSubscriptingKind - This routine decide what type
1048
/// of indexing represented by "FromE" is being done.
1049
Sema::ObjCSubscriptKind
1050
0
  Sema::CheckSubscriptingKind(Expr *FromE) {
1051
  // If the expression already has integral or enumeration type, we're golden.
1052
0
  QualType T = FromE->getType();
1053
0
  if (T->isIntegralOrEnumerationType())
1054
0
    return OS_Array;
1055
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
0
  const RecordType *RecordTy = T->getAs<RecordType>();
1059
0
  if (!RecordTy &&
1060
0
      (T->isObjCObjectPointerType() || T->isVoidPointerType()))
1061
    // All other scalar cases are assumed to be dictionary indexing which
1062
    // caller handles, with diagnostics if needed.
1063
0
    return OS_Dictionary;
1064
0
  if (!getLangOpts().CPlusPlus ||
1065
0
      !RecordTy || RecordTy->isIncompleteType()) {
1066
    // No indexing can be done. Issue diagnostics and quit.
1067
0
    const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
1068
0
    if (isa<StringLiteral>(IndexExpr))
1069
0
      Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
1070
0
        << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
1071
0
    else
1072
0
      Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
1073
0
        << T;
1074
0
    return OS_Error;
1075
0
  }
1076
1077
  // We must have a complete class type.
1078
0
  if (RequireCompleteType(FromE->getExprLoc(), T,
1079
0
                          diag::err_objc_index_incomplete_class_type, FromE))
1080
0
    return OS_Error;
1081
1082
  // Look for a conversion to an integral, enumeration type, or
1083
  // objective-C pointer type.
1084
0
  int NoIntegrals=0, NoObjCIdPointers=0;
1085
0
  SmallVector<CXXConversionDecl *, 4> ConversionDecls;
1086
1087
0
  for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
1088
0
                          ->getVisibleConversionFunctions()) {
1089
0
    if (CXXConversionDecl *Conversion =
1090
0
            dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
1091
0
      QualType CT = Conversion->getConversionType().getNonReferenceType();
1092
0
      if (CT->isIntegralOrEnumerationType()) {
1093
0
        ++NoIntegrals;
1094
0
        ConversionDecls.push_back(Conversion);
1095
0
      }
1096
0
      else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
1097
0
        ++NoObjCIdPointers;
1098
0
        ConversionDecls.push_back(Conversion);
1099
0
      }
1100
0
    }
1101
0
  }
1102
0
  if (NoIntegrals ==1 && NoObjCIdPointers == 0)
1103
0
    return OS_Array;
1104
0
  if (NoIntegrals == 0 && NoObjCIdPointers == 1)
1105
0
    return OS_Dictionary;
1106
0
  if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
1107
    // No conversion function was found. Issue diagnostic and return.
1108
0
    Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
1109
0
      << FromE->getType();
1110
0
    return OS_Error;
1111
0
  }
1112
0
  Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
1113
0
      << FromE->getType();
1114
0
  for (unsigned int i = 0; i < ConversionDecls.size(); i++)
1115
0
    Diag(ConversionDecls[i]->getLocation(),
1116
0
         diag::note_conv_function_declared_at);
1117
1118
0
  return OS_Error;
1119
0
}
1120
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,
1124
0
                                         Expr *Key) {
1125
0
  if (ContainerT.isNull())
1126
0
    return;
1127
  // dictionary subscripting.
1128
  // - (id)objectForKeyedSubscript:(id)key;
1129
0
  IdentifierInfo *KeyIdents[] = {
1130
0
    &S.Context.Idents.get("objectForKeyedSubscript")
1131
0
  };
1132
0
  Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1133
0
  ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
1134
0
                                                      true /*instance*/);
1135
0
  if (!Getter)
1136
0
    return;
1137
0
  QualType T = Getter->parameters()[0]->getType();
1138
0
  S.CheckObjCConversion(Key->getSourceRange(), T, Key,
1139
0
                        Sema::CCK_ImplicitConversion);
1140
0
}
1141
1142
0
bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1143
0
  if (AtIndexGetter)
1144
0
    return true;
1145
1146
0
  Expr *BaseExpr = RefExpr->getBaseExpr();
1147
0
  QualType BaseT = BaseExpr->getType();
1148
1149
0
  QualType ResultType;
1150
0
  if (const ObjCObjectPointerType *PTy =
1151
0
      BaseT->getAs<ObjCObjectPointerType>()) {
1152
0
    ResultType = PTy->getPointeeType();
1153
0
  }
1154
0
  Sema::ObjCSubscriptKind Res =
1155
0
    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1156
0
  if (Res == Sema::OS_Error) {
1157
0
    if (S.getLangOpts().ObjCAutoRefCount)
1158
0
      CheckKeyForObjCARCConversion(S, ResultType,
1159
0
                                   RefExpr->getKeyExpr());
1160
0
    return false;
1161
0
  }
1162
0
  bool arrayRef = (Res == Sema::OS_Array);
1163
1164
0
  if (ResultType.isNull()) {
1165
0
    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1166
0
      << BaseExpr->getType() << arrayRef;
1167
0
    return false;
1168
0
  }
1169
0
  if (!arrayRef) {
1170
    // dictionary subscripting.
1171
    // - (id)objectForKeyedSubscript:(id)key;
1172
0
    IdentifierInfo *KeyIdents[] = {
1173
0
      &S.Context.Idents.get("objectForKeyedSubscript")
1174
0
    };
1175
0
    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1176
0
  }
1177
0
  else {
1178
    // - (id)objectAtIndexedSubscript:(size_t)index;
1179
0
    IdentifierInfo *KeyIdents[] = {
1180
0
      &S.Context.Idents.get("objectAtIndexedSubscript")
1181
0
    };
1182
1183
0
    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1184
0
  }
1185
1186
0
  AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
1187
0
                                             true /*instance*/);
1188
1189
0
  if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
1190
0
    AtIndexGetter = ObjCMethodDecl::Create(
1191
0
        S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector,
1192
0
        S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,
1193
0
        S.Context.getTranslationUnitDecl(), true /*Instance*/,
1194
0
        false /*isVariadic*/,
1195
0
        /*isPropertyAccessor=*/false,
1196
0
        /*isSynthesizedAccessorStub=*/false,
1197
0
        /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1198
0
        ObjCImplementationControl::Required, false);
1199
0
    ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1200
0
                                                SourceLocation(), SourceLocation(),
1201
0
                                                arrayRef ? &S.Context.Idents.get("index")
1202
0
                                                         : &S.Context.Idents.get("key"),
1203
0
                                                arrayRef ? S.Context.UnsignedLongTy
1204
0
                                                         : S.Context.getObjCIdType(),
1205
0
                                                /*TInfo=*/nullptr,
1206
0
                                                SC_None,
1207
0
                                                nullptr);
1208
0
    AtIndexGetter->setMethodParams(S.Context, Argument, std::nullopt);
1209
0
  }
1210
1211
0
  if (!AtIndexGetter) {
1212
0
    if (!BaseT->isObjCIdType()) {
1213
0
      S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1214
0
      << BaseExpr->getType() << 0 << arrayRef;
1215
0
      return false;
1216
0
    }
1217
0
    AtIndexGetter =
1218
0
      S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
1219
0
                                         RefExpr->getSourceRange(),
1220
0
                                         true);
1221
0
  }
1222
1223
0
  if (AtIndexGetter) {
1224
0
    QualType T = AtIndexGetter->parameters()[0]->getType();
1225
0
    if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1226
0
        (!arrayRef && !T->isObjCObjectPointerType())) {
1227
0
      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1228
0
             arrayRef ? diag::err_objc_subscript_index_type
1229
0
                      : diag::err_objc_subscript_key_type) << T;
1230
0
      S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
1231
0
             diag::note_parameter_type) << T;
1232
0
      return false;
1233
0
    }
1234
0
    QualType R = AtIndexGetter->getReturnType();
1235
0
    if (!R->isObjCObjectPointerType()) {
1236
0
      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1237
0
             diag::err_objc_indexing_method_result_type) << R << arrayRef;
1238
0
      S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1239
0
        AtIndexGetter->getDeclName();
1240
0
    }
1241
0
  }
1242
0
  return true;
1243
0
}
1244
1245
0
bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1246
0
  if (AtIndexSetter)
1247
0
    return true;
1248
1249
0
  Expr *BaseExpr = RefExpr->getBaseExpr();
1250
0
  QualType BaseT = BaseExpr->getType();
1251
1252
0
  QualType ResultType;
1253
0
  if (const ObjCObjectPointerType *PTy =
1254
0
      BaseT->getAs<ObjCObjectPointerType>()) {
1255
0
    ResultType = PTy->getPointeeType();
1256
0
  }
1257
1258
0
  Sema::ObjCSubscriptKind Res =
1259
0
    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1260
0
  if (Res == Sema::OS_Error) {
1261
0
    if (S.getLangOpts().ObjCAutoRefCount)
1262
0
      CheckKeyForObjCARCConversion(S, ResultType,
1263
0
                                   RefExpr->getKeyExpr());
1264
0
    return false;
1265
0
  }
1266
0
  bool arrayRef = (Res == Sema::OS_Array);
1267
1268
0
  if (ResultType.isNull()) {
1269
0
    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1270
0
      << BaseExpr->getType() << arrayRef;
1271
0
    return false;
1272
0
  }
1273
1274
0
  if (!arrayRef) {
1275
    // dictionary subscripting.
1276
    // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1277
0
    IdentifierInfo *KeyIdents[] = {
1278
0
      &S.Context.Idents.get("setObject"),
1279
0
      &S.Context.Idents.get("forKeyedSubscript")
1280
0
    };
1281
0
    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1282
0
  }
1283
0
  else {
1284
    // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1285
0
    IdentifierInfo *KeyIdents[] = {
1286
0
      &S.Context.Idents.get("setObject"),
1287
0
      &S.Context.Idents.get("atIndexedSubscript")
1288
0
    };
1289
0
    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1290
0
  }
1291
0
  AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
1292
0
                                             true /*instance*/);
1293
1294
0
  if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
1295
0
    TypeSourceInfo *ReturnTInfo = nullptr;
1296
0
    QualType ReturnType = S.Context.VoidTy;
1297
0
    AtIndexSetter = ObjCMethodDecl::Create(
1298
0
        S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
1299
0
        ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
1300
0
        true /*Instance*/, false /*isVariadic*/,
1301
0
        /*isPropertyAccessor=*/false,
1302
0
        /*isSynthesizedAccessorStub=*/false,
1303
0
        /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1304
0
        ObjCImplementationControl::Required, false);
1305
0
    SmallVector<ParmVarDecl *, 2> Params;
1306
0
    ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1307
0
                                                SourceLocation(), SourceLocation(),
1308
0
                                                &S.Context.Idents.get("object"),
1309
0
                                                S.Context.getObjCIdType(),
1310
0
                                                /*TInfo=*/nullptr,
1311
0
                                                SC_None,
1312
0
                                                nullptr);
1313
0
    Params.push_back(object);
1314
0
    ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1315
0
                                                SourceLocation(), SourceLocation(),
1316
0
                                                arrayRef ?  &S.Context.Idents.get("index")
1317
0
                                                         :  &S.Context.Idents.get("key"),
1318
0
                                                arrayRef ? S.Context.UnsignedLongTy
1319
0
                                                         : S.Context.getObjCIdType(),
1320
0
                                                /*TInfo=*/nullptr,
1321
0
                                                SC_None,
1322
0
                                                nullptr);
1323
0
    Params.push_back(key);
1324
0
    AtIndexSetter->setMethodParams(S.Context, Params, std::nullopt);
1325
0
  }
1326
1327
0
  if (!AtIndexSetter) {
1328
0
    if (!BaseT->isObjCIdType()) {
1329
0
      S.Diag(BaseExpr->getExprLoc(),
1330
0
             diag::err_objc_subscript_method_not_found)
1331
0
      << BaseExpr->getType() << 1 << arrayRef;
1332
0
      return false;
1333
0
    }
1334
0
    AtIndexSetter =
1335
0
      S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
1336
0
                                         RefExpr->getSourceRange(),
1337
0
                                         true);
1338
0
  }
1339
1340
0
  bool err = false;
1341
0
  if (AtIndexSetter && arrayRef) {
1342
0
    QualType T = AtIndexSetter->parameters()[1]->getType();
1343
0
    if (!T->isIntegralOrEnumerationType()) {
1344
0
      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1345
0
             diag::err_objc_subscript_index_type) << T;
1346
0
      S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
1347
0
             diag::note_parameter_type) << T;
1348
0
      err = true;
1349
0
    }
1350
0
    T = AtIndexSetter->parameters()[0]->getType();
1351
0
    if (!T->isObjCObjectPointerType()) {
1352
0
      S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1353
0
             diag::err_objc_subscript_object_type) << T << arrayRef;
1354
0
      S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
1355
0
             diag::note_parameter_type) << T;
1356
0
      err = true;
1357
0
    }
1358
0
  }
1359
0
  else if (AtIndexSetter && !arrayRef)
1360
0
    for (unsigned i=0; i <2; i++) {
1361
0
      QualType T = AtIndexSetter->parameters()[i]->getType();
1362
0
      if (!T->isObjCObjectPointerType()) {
1363
0
        if (i == 1)
1364
0
          S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1365
0
                 diag::err_objc_subscript_key_type) << T;
1366
0
        else
1367
0
          S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1368
0
                 diag::err_objc_subscript_dic_object_type) << T;
1369
0
        S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
1370
0
               diag::note_parameter_type) << T;
1371
0
        err = true;
1372
0
      }
1373
0
    }
1374
1375
0
  return !err;
1376
0
}
1377
1378
// Get the object at "Index" position in the container.
1379
// [BaseExpr objectAtIndexedSubscript : IndexExpr];
1380
0
ExprResult ObjCSubscriptOpBuilder::buildGet() {
1381
0
  if (!findAtIndexGetter())
1382
0
    return ExprError();
1383
1384
0
  QualType receiverType = InstanceBase->getType();
1385
1386
  // Build a message-send.
1387
0
  ExprResult msg;
1388
0
  Expr *Index = InstanceKey;
1389
1390
  // Arguments.
1391
0
  Expr *args[] = { Index };
1392
0
  assert(InstanceBase);
1393
0
  if (AtIndexGetter)
1394
0
    S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);
1395
0
  msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1396
0
                                       GenericLoc,
1397
0
                                       AtIndexGetterSelector, AtIndexGetter,
1398
0
                                       MultiExprArg(args, 1));
1399
0
  return msg;
1400
0
}
1401
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
0
                                           bool captureSetValueAsResult) {
1409
0
  if (!findAtIndexSetter())
1410
0
    return ExprError();
1411
0
  if (AtIndexSetter)
1412
0
    S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);
1413
0
  QualType receiverType = InstanceBase->getType();
1414
0
  Expr *Index = InstanceKey;
1415
1416
  // Arguments.
1417
0
  Expr *args[] = { op, Index };
1418
1419
  // Build a message-send.
1420
0
  ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1421
0
                                                  GenericLoc,
1422
0
                                                  AtIndexSetterSelector,
1423
0
                                                  AtIndexSetter,
1424
0
                                                  MultiExprArg(args, 2));
1425
1426
0
  if (!msg.isInvalid() && captureSetValueAsResult) {
1427
0
    ObjCMessageExpr *msgExpr =
1428
0
      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1429
0
    Expr *arg = msgExpr->getArg(0);
1430
0
    if (CanCaptureValue(arg))
1431
0
      msgExpr->setArg(0, captureValueAsResult(arg));
1432
0
  }
1433
1434
0
  return msg;
1435
0
}
1436
1437
//===----------------------------------------------------------------------===//
1438
//  MSVC __declspec(property) references
1439
//===----------------------------------------------------------------------===//
1440
1441
MSPropertyRefExpr *
1442
0
MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
1443
0
  CallArgs.insert(CallArgs.begin(), E->getIdx());
1444
0
  Expr *Base = E->getBase()->IgnoreParens();
1445
0
  while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
1446
0
    CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
1447
0
    Base = MSPropSubscript->getBase()->IgnoreParens();
1448
0
  }
1449
0
  return cast<MSPropertyRefExpr>(Base);
1450
0
}
1451
1452
0
Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
1453
0
  InstanceBase = capture(RefExpr->getBaseExpr());
1454
0
  for (Expr *&Arg : CallArgs)
1455
0
    Arg = capture(Arg);
1456
0
  syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
1457
0
                    switch (Idx) {
1458
0
                    case 0:
1459
0
                      return InstanceBase;
1460
0
                    default:
1461
0
                      assert(Idx <= CallArgs.size());
1462
0
                      return CallArgs[Idx - 1];
1463
0
                    }
1464
0
                  }).rebuild(syntacticBase);
1465
1466
0
  return syntacticBase;
1467
0
}
1468
1469
0
ExprResult MSPropertyOpBuilder::buildGet() {
1470
0
  if (!RefExpr->getPropertyDecl()->hasGetter()) {
1471
0
    S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
1472
0
      << 0 /* getter */ << RefExpr->getPropertyDecl();
1473
0
    return ExprError();
1474
0
  }
1475
1476
0
  UnqualifiedId GetterName;
1477
0
  IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();
1478
0
  GetterName.setIdentifier(II, RefExpr->getMemberLoc());
1479
0
  CXXScopeSpec SS;
1480
0
  SS.Adopt(RefExpr->getQualifierLoc());
1481
0
  ExprResult GetterExpr =
1482
0
      S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
1483
0
                              RefExpr->isArrow() ? tok::arrow : tok::period, SS,
1484
0
                              SourceLocation(), GetterName, nullptr);
1485
0
  if (GetterExpr.isInvalid()) {
1486
0
    S.Diag(RefExpr->getMemberLoc(),
1487
0
           diag::err_cannot_find_suitable_accessor) << 0 /* getter */
1488
0
      << RefExpr->getPropertyDecl();
1489
0
    return ExprError();
1490
0
  }
1491
1492
0
  return S.BuildCallExpr(S.getCurScope(), GetterExpr.get(),
1493
0
                         RefExpr->getSourceRange().getBegin(), CallArgs,
1494
0
                         RefExpr->getSourceRange().getEnd());
1495
0
}
1496
1497
ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
1498
0
                                         bool captureSetValueAsResult) {
1499
0
  if (!RefExpr->getPropertyDecl()->hasSetter()) {
1500
0
    S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
1501
0
      << 1 /* setter */ << RefExpr->getPropertyDecl();
1502
0
    return ExprError();
1503
0
  }
1504
1505
0
  UnqualifiedId SetterName;
1506
0
  IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();
1507
0
  SetterName.setIdentifier(II, RefExpr->getMemberLoc());
1508
0
  CXXScopeSpec SS;
1509
0
  SS.Adopt(RefExpr->getQualifierLoc());
1510
0
  ExprResult SetterExpr =
1511
0
      S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
1512
0
                              RefExpr->isArrow() ? tok::arrow : tok::period, SS,
1513
0
                              SourceLocation(), SetterName, nullptr);
1514
0
  if (SetterExpr.isInvalid()) {
1515
0
    S.Diag(RefExpr->getMemberLoc(),
1516
0
           diag::err_cannot_find_suitable_accessor) << 1 /* setter */
1517
0
      << RefExpr->getPropertyDecl();
1518
0
    return ExprError();
1519
0
  }
1520
1521
0
  SmallVector<Expr*, 4> ArgExprs;
1522
0
  ArgExprs.append(CallArgs.begin(), CallArgs.end());
1523
0
  ArgExprs.push_back(op);
1524
0
  return S.BuildCallExpr(S.getCurScope(), SetterExpr.get(),
1525
0
                         RefExpr->getSourceRange().getBegin(), ArgExprs,
1526
0
                         op->getSourceRange().getEnd());
1527
0
}
1528
1529
//===----------------------------------------------------------------------===//
1530
//  General Sema routines.
1531
//===----------------------------------------------------------------------===//
1532
1533
0
ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
1534
0
  Expr *opaqueRef = E->IgnoreParens();
1535
0
  if (ObjCPropertyRefExpr *refExpr
1536
0
        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1537
0
    ObjCPropertyOpBuilder builder(*this, refExpr, true);
1538
0
    return builder.buildRValueOperation(E);
1539
0
  }
1540
0
  else if (ObjCSubscriptRefExpr *refExpr
1541
0
           = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1542
0
    ObjCSubscriptOpBuilder builder(*this, refExpr, true);
1543
0
    return builder.buildRValueOperation(E);
1544
0
  } else if (MSPropertyRefExpr *refExpr
1545
0
             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
1546
0
    MSPropertyOpBuilder builder(*this, refExpr, true);
1547
0
    return builder.buildRValueOperation(E);
1548
0
  } else if (MSPropertySubscriptExpr *RefExpr =
1549
0
                 dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
1550
0
    MSPropertyOpBuilder Builder(*this, RefExpr, true);
1551
0
    return Builder.buildRValueOperation(E);
1552
0
  } else {
1553
0
    llvm_unreachable("unknown pseudo-object kind!");
1554
0
  }
1555
0
}
1556
1557
/// Check an increment or decrement of a pseudo-object expression.
1558
ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
1559
0
                                         UnaryOperatorKind opcode, Expr *op) {
1560
  // Do nothing if the operand is dependent.
1561
0
  if (op->isTypeDependent())
1562
0
    return UnaryOperator::Create(Context, op, opcode, Context.DependentTy,
1563
0
                                 VK_PRValue, OK_Ordinary, opcLoc, false,
1564
0
                                 CurFPFeatureOverrides());
1565
1566
0
  assert(UnaryOperator::isIncrementDecrementOp(opcode));
1567
0
  Expr *opaqueRef = op->IgnoreParens();
1568
0
  if (ObjCPropertyRefExpr *refExpr
1569
0
        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1570
0
    ObjCPropertyOpBuilder builder(*this, refExpr, false);
1571
0
    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1572
0
  } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1573
0
    Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1574
0
    return ExprError();
1575
0
  } else if (MSPropertyRefExpr *refExpr
1576
0
             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
1577
0
    MSPropertyOpBuilder builder(*this, refExpr, false);
1578
0
    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1579
0
  } else if (MSPropertySubscriptExpr *RefExpr
1580
0
             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
1581
0
    MSPropertyOpBuilder Builder(*this, RefExpr, false);
1582
0
    return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1583
0
  } else {
1584
0
    llvm_unreachable("unknown pseudo-object kind!");
1585
0
  }
1586
0
}
1587
1588
ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
1589
                                             BinaryOperatorKind opcode,
1590
0
                                             Expr *LHS, Expr *RHS) {
1591
  // Do nothing if either argument is dependent.
1592
0
  if (LHS->isTypeDependent() || RHS->isTypeDependent())
1593
0
    return BinaryOperator::Create(Context, LHS, RHS, opcode,
1594
0
                                  Context.DependentTy, VK_PRValue, OK_Ordinary,
1595
0
                                  opcLoc, CurFPFeatureOverrides());
1596
1597
  // Filter out non-overload placeholder types in the RHS.
1598
0
  if (RHS->getType()->isNonOverloadPlaceholderType()) {
1599
0
    ExprResult result = CheckPlaceholderExpr(RHS);
1600
0
    if (result.isInvalid()) return ExprError();
1601
0
    RHS = result.get();
1602
0
  }
1603
1604
0
  bool IsSimpleAssign = opcode == BO_Assign;
1605
0
  Expr *opaqueRef = LHS->IgnoreParens();
1606
0
  if (ObjCPropertyRefExpr *refExpr
1607
0
        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1608
0
    ObjCPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
1609
0
    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1610
0
  } else if (ObjCSubscriptRefExpr *refExpr
1611
0
             = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1612
0
    ObjCSubscriptOpBuilder builder(*this, refExpr, IsSimpleAssign);
1613
0
    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1614
0
  } else if (MSPropertyRefExpr *refExpr
1615
0
             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
1616
0
      MSPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
1617
0
      return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1618
0
  } else if (MSPropertySubscriptExpr *RefExpr
1619
0
             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
1620
0
      MSPropertyOpBuilder Builder(*this, RefExpr, IsSimpleAssign);
1621
0
      return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1622
0
  } else {
1623
0
    llvm_unreachable("unknown pseudo-object kind!");
1624
0
  }
1625
0
}
1626
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
0
static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
1631
0
  return Rebuilder(S,
1632
0
                   [=](Expr *E, unsigned) -> Expr * {
1633
0
                     return cast<OpaqueValueExpr>(E)->getSourceExpr();
1634
0
                   })
1635
0
      .rebuild(E);
1636
0
}
1637
1638
/// Given a pseudo-object expression, recreate what it looks like
1639
/// syntactically without the attendant OpaqueValueExprs.
1640
///
1641
/// This is a hack which should be removed when TreeTransform is
1642
/// capable of rebuilding a tree without stripping implicit
1643
/// operations.
1644
0
Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
1645
0
  Expr *syntax = E->getSyntacticForm();
1646
0
  if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
1647
0
    Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
1648
0
    return UnaryOperator::Create(Context, op, uop->getOpcode(), uop->getType(),
1649
0
                                 uop->getValueKind(), uop->getObjectKind(),
1650
0
                                 uop->getOperatorLoc(), uop->canOverflow(),
1651
0
                                 CurFPFeatureOverrides());
1652
0
  } else if (CompoundAssignOperator *cop
1653
0
               = dyn_cast<CompoundAssignOperator>(syntax)) {
1654
0
    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
1655
0
    Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
1656
0
    return CompoundAssignOperator::Create(
1657
0
        Context, lhs, rhs, cop->getOpcode(), cop->getType(),
1658
0
        cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),
1659
0
        CurFPFeatureOverrides(), cop->getComputationLHSType(),
1660
0
        cop->getComputationResultType());
1661
1662
0
  } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
1663
0
    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
1664
0
    Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
1665
0
    return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(),
1666
0
                                  bop->getType(), bop->getValueKind(),
1667
0
                                  bop->getObjectKind(), bop->getOperatorLoc(),
1668
0
                                  CurFPFeatureOverrides());
1669
1670
0
  } else if (isa<CallExpr>(syntax)) {
1671
0
    return syntax;
1672
0
  } else {
1673
0
    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
1674
0
    return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
1675
0
  }
1676
0
}