Coverage Report

Created: 2020-02-25 14:32

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