Coverage Report

Created: 2020-09-15 12:33

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