소스 검색

[CodeGen] Ignore OpaqueValueExprs that are unique references to their
source expressions when iterating over a PseudoObjectExpr's semantic
subexpression list.

Previously the loop in emitPseudoObjectExpr would emit the IR for each
OpaqueValueExpr that was in a PseudoObjectExpr's semantic-form
expression list and use the result when the OpaqueValueExpr later
appeared in other expressions. This caused an assertion failure when
AggExprEmitter tried to copy the result of an OpaqueValueExpr and the
copied type didn't have trivial copy/move constructors or assignment
operators.

This patch adds flag IsUnique to OpaqueValueExpr which indicates it is a
unique reference to its source expression (it is not used in multiple
places). The loop in emitPseudoObjectExpr ignores OpaqueValueExprs that
are unique and CodeGen visitors simply traverse the source expressions
of such OpaqueValueExprs.

rdar://problem/34363596

Differential Revision: https://reviews.llvm.org/D39562

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@327939 91177308-0d34-0410-b5e6-96231b3b80d8

Akira Hatanaka 7 년 전
부모
커밋
3797638dfd

+ 9 - 0
include/clang/AST/Expr.h

@@ -883,6 +883,7 @@ public:
            (SourceExpr && SourceExpr->isInstantiationDependent()),
            (SourceExpr && SourceExpr->isInstantiationDependent()),
            false),
            false),
       SourceExpr(SourceExpr), Loc(Loc) {
       SourceExpr(SourceExpr), Loc(Loc) {
+    setIsUnique(false);
   }
   }
 
 
   /// Given an expression which invokes a copy constructor --- i.e.  a
   /// Given an expression which invokes a copy constructor --- i.e.  a
@@ -925,6 +926,14 @@ public:
   /// place.
   /// place.
   Expr *getSourceExpr() const { return SourceExpr; }
   Expr *getSourceExpr() const { return SourceExpr; }
 
 
+  void setIsUnique(bool V) {
+    assert((!V || SourceExpr) &&
+           "unique OVEs are expected to have source expressions");
+    OpaqueValueExprBits.IsUnique = V;
+  }
+
+  bool isUnique() const { return OpaqueValueExprBits.IsUnique; }
+
   static bool classof(const Stmt *T) {
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OpaqueValueExprClass;
     return T->getStmtClass() == OpaqueValueExprClass;
   }
   }

+ 11 - 0
include/clang/AST/Stmt.h

@@ -237,6 +237,16 @@ protected:
     unsigned ResultIndex : 32 - 8 - NumExprBits;
     unsigned ResultIndex : 32 - 8 - NumExprBits;
   };
   };
 
 
+  class OpaqueValueExprBitfields {
+    friend class OpaqueValueExpr;
+
+    unsigned : NumExprBits;
+
+    /// The OVE is a unique semantic reference to its source expressio if this
+    /// bit is set to true.
+    unsigned IsUnique : 1;
+  };
+
   class ObjCIndirectCopyRestoreExprBitfields {
   class ObjCIndirectCopyRestoreExprBitfields {
     friend class ObjCIndirectCopyRestoreExpr;
     friend class ObjCIndirectCopyRestoreExpr;
 
 
@@ -294,6 +304,7 @@ protected:
     CallExprBitfields CallExprBits;
     CallExprBitfields CallExprBits;
     ExprWithCleanupsBitfields ExprWithCleanupsBits;
     ExprWithCleanupsBitfields ExprWithCleanupsBits;
     PseudoObjectExprBitfields PseudoObjectExprBits;
     PseudoObjectExprBitfields PseudoObjectExprBits;
+    OpaqueValueExprBitfields OpaqueValueExprBits;
     ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
     ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
     InitListExprBitfields InitListExprBits;
     InitListExprBitfields InitListExprBits;
     TypeTraitExprBitfields TypeTraitExprBits;
     TypeTraitExprBitfields TypeTraitExprBits;

+ 35 - 1
lib/CodeGen/CGExpr.cpp

@@ -4167,7 +4167,35 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
 
 
 LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
 LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
   assert(OpaqueValueMappingData::shouldBindAsLValue(e));
   assert(OpaqueValueMappingData::shouldBindAsLValue(e));
-  return getOpaqueLValueMapping(e);
+  return getOrCreateOpaqueLValueMapping(e);
+}
+
+LValue
+CodeGenFunction::getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e) {
+  assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+  llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+      it = OpaqueLValues.find(e);
+
+  if (it != OpaqueLValues.end())
+    return it->second;
+
+  assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
+  return EmitLValue(e->getSourceExpr());
+}
+
+RValue
+CodeGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) {
+  assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+
+  llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+      it = OpaqueRValues.find(e);
+
+  if (it != OpaqueRValues.end())
+    return it->second;
+
+  assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
+  return EmitAnyExpr(e->getSourceExpr());
 }
 }
 
 
 RValue CodeGenFunction::EmitRValueForField(LValue LV,
 RValue CodeGenFunction::EmitRValueForField(LValue LV,
@@ -4719,6 +4747,12 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
     // If this semantic expression is an opaque value, bind it
     // If this semantic expression is an opaque value, bind it
     // to the result of its source expression.
     // to the result of its source expression.
     if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
     if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
+      // Skip unique OVEs.
+      if (ov->isUnique()) {
+        assert(ov != resultExpr &&
+               "A unique OVE cannot be used as the result expression");
+        continue;
+      }
 
 
       // If this is the result expression, we may need to evaluate
       // If this is the result expression, we may need to evaluate
       // directly into the slot.
       // directly into the slot.

+ 5 - 1
lib/CodeGen/CGExprAgg.cpp

@@ -630,7 +630,11 @@ void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){
 }
 }
 
 
 void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
 void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
-  EmitFinalDestCopy(e->getType(), CGF.getOpaqueLValueMapping(e));
+  // If this is a unique OVE, just visit its source expression.
+  if (e->isUnique())
+    Visit(e->getSourceExpr());
+  else
+    EmitFinalDestCopy(e->getType(), CGF.getOrCreateOpaqueLValueMapping(e));
 }
 }
 
 
 void
 void

+ 3 - 2
lib/CodeGen/CGExprComplex.cpp

@@ -155,8 +155,9 @@ public:
   }
   }
   ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
     if (E->isGLValue())
     if (E->isGLValue())
-      return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
-    return CGF.getOpaqueRValueMapping(E).getComplexVal();
+      return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
+                              E->getExprLoc());
+    return CGF.getOrCreateOpaqueRValueMapping(E).getComplexVal();
   }
   }
 
 
   ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
   ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {

+ 3 - 2
lib/CodeGen/CGExprScalar.cpp

@@ -422,10 +422,11 @@ public:
 
 
   Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
     if (E->isGLValue())
     if (E->isGLValue())
-      return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
+      return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
+                              E->getExprLoc());
 
 
     // Otherwise, assume the mapping is the scalar directly.
     // Otherwise, assume the mapping is the scalar directly.
-    return CGF.getOpaqueRValueMapping(E).getScalarVal();
+    return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
   }
   }
 
 
   Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
   Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,

+ 6 - 20
lib/CodeGen/CodeGenFunction.h

@@ -2148,27 +2148,13 @@ public:
     return it->second;
     return it->second;
   }
   }
 
 
-  /// getOpaqueLValueMapping - Given an opaque value expression (which
-  /// must be mapped to an l-value), return its mapping.
-  const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
-    assert(OpaqueValueMapping::shouldBindAsLValue(e));
-
-    llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
-      it = OpaqueLValues.find(e);
-    assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
-    return it->second;
-  }
-
-  /// getOpaqueRValueMapping - Given an opaque value expression (which
-  /// must be mapped to an r-value), return its mapping.
-  const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
-    assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+  /// Given an opaque value expression, return its LValue mapping if it exists,
+  /// otherwise create one.
+  LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e);
 
 
-    llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
-      it = OpaqueRValues.find(e);
-    assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
-    return it->second;
-  }
+  /// Given an opaque value expression, return its RValue mapping if it exists,
+  /// otherwise create one.
+  RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e);
 
 
   /// Get the index of the current ArrayInitLoopExpr, if any.
   /// Get the index of the current ArrayInitLoopExpr, if any.
   llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }
   llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }

+ 39 - 28
lib/Sema/SemaPseudoObject.cpp

@@ -190,11 +190,12 @@ namespace {
     Sema &S;
     Sema &S;
     unsigned ResultIndex;
     unsigned ResultIndex;
     SourceLocation GenericLoc;
     SourceLocation GenericLoc;
+    bool IsUnique;
     SmallVector<Expr *, 4> Semantics;
     SmallVector<Expr *, 4> Semantics;
 
 
-    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
+    PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
       : S(S), ResultIndex(PseudoObjectExpr::NoResult),
       : S(S), ResultIndex(PseudoObjectExpr::NoResult),
-        GenericLoc(genericLoc) {}
+        GenericLoc(genericLoc), IsUnique(IsUnique) {}
 
 
     virtual ~PseudoOpBuilder() {}
     virtual ~PseudoOpBuilder() {}
 
 
@@ -208,6 +209,9 @@ namespace {
       assert(ResultIndex == PseudoObjectExpr::NoResult);
       assert(ResultIndex == PseudoObjectExpr::NoResult);
       ResultIndex = Semantics.size();
       ResultIndex = Semantics.size();
       Semantics.push_back(resultExpr);
       Semantics.push_back(resultExpr);
+      // An OVE is not unique if it is used as the result expression.
+      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+        OVE->setIsUnique(false);
     }
     }
 
 
     ExprResult buildRValueOperation(Expr *op);
     ExprResult buildRValueOperation(Expr *op);
@@ -227,6 +231,9 @@ namespace {
     void setResultToLastSemantic() {
     void setResultToLastSemantic() {
       assert(ResultIndex == PseudoObjectExpr::NoResult);
       assert(ResultIndex == PseudoObjectExpr::NoResult);
       ResultIndex = Semantics.size() - 1;
       ResultIndex = Semantics.size() - 1;
+      // An OVE is not unique if it is used as the result expression.
+      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+        OVE->setIsUnique(false);
     }
     }
 
 
     /// Return true if assignments have a non-void result.
     /// Return true if assignments have a non-void result.
@@ -274,10 +281,10 @@ namespace {
     Selector GetterSelector;
     Selector GetterSelector;
 
 
   public:
   public:
-    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
-      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
-      SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
-      Setter(nullptr) {
+    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)
+        : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),
+          RefExpr(refExpr), SyntacticRefExpr(nullptr),
+          InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {
     }
     }
 
 
     ExprResult buildRValueOperation(Expr *op);
     ExprResult buildRValueOperation(Expr *op);
@@ -314,11 +321,10 @@ namespace {
    Selector AtIndexSetterSelector;
    Selector AtIndexSetterSelector;
   
   
  public:
  public:
-    ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
-      PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), 
-      RefExpr(refExpr),
-      InstanceBase(nullptr), InstanceKey(nullptr),
-      AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
+   ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)
+       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+         RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),
+         AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
 
 
    ExprResult buildRValueOperation(Expr *op);
    ExprResult buildRValueOperation(Expr *op);
    ExprResult buildAssignmentOperation(Scope *Sc,
    ExprResult buildAssignmentOperation(Scope *Sc,
@@ -342,11 +348,11 @@ namespace {
    MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
    MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
 
 
  public:
  public:
-   MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
-     PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
-     RefExpr(refExpr), InstanceBase(nullptr) {}
-   MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
-       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+   MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
+       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+         RefExpr(refExpr), InstanceBase(nullptr) {}
+   MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)
+       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
          InstanceBase(nullptr) {
          InstanceBase(nullptr) {
      RefExpr = getBaseMSProperty(refExpr);
      RefExpr = getBaseMSProperty(refExpr);
    }
    }
@@ -365,7 +371,9 @@ OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
     new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
     new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
                                     e->getValueKind(), e->getObjectKind(),
                                     e->getValueKind(), e->getObjectKind(),
                                     e);
                                     e);
-  
+  if (IsUnique)
+    captured->setIsUnique(true);
+
   // Make sure we bind that in the semantics.
   // Make sure we bind that in the semantics.
   addSemanticExpr(captured);
   addSemanticExpr(captured);
   return captured;
   return captured;
@@ -397,6 +405,8 @@ OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
     if (e == Semantics[index]) break;
     if (e == Semantics[index]) break;
   }
   }
   ResultIndex = index;
   ResultIndex = index;
+  // An OVE is not unique if it is used as the result expression.
+  cast<OpaqueValueExpr>(e)->setIsUnique(false);
   return cast<OpaqueValueExpr>(e);
   return cast<OpaqueValueExpr>(e);
 }
 }
 
 
@@ -1528,20 +1538,20 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
   Expr *opaqueRef = E->IgnoreParens();
   Expr *opaqueRef = E->IgnoreParens();
   if (ObjCPropertyRefExpr *refExpr
   if (ObjCPropertyRefExpr *refExpr
         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
-    ObjCPropertyOpBuilder builder(*this, refExpr);
+    ObjCPropertyOpBuilder builder(*this, refExpr, true);
     return builder.buildRValueOperation(E);
     return builder.buildRValueOperation(E);
   }
   }
   else if (ObjCSubscriptRefExpr *refExpr
   else if (ObjCSubscriptRefExpr *refExpr
            = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
            = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
-    ObjCSubscriptOpBuilder builder(*this, refExpr);
+    ObjCSubscriptOpBuilder builder(*this, refExpr, true);
     return builder.buildRValueOperation(E);
     return builder.buildRValueOperation(E);
   } else if (MSPropertyRefExpr *refExpr
   } else if (MSPropertyRefExpr *refExpr
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
-    MSPropertyOpBuilder builder(*this, refExpr);
+    MSPropertyOpBuilder builder(*this, refExpr, true);
     return builder.buildRValueOperation(E);
     return builder.buildRValueOperation(E);
   } else if (MSPropertySubscriptExpr *RefExpr =
   } else if (MSPropertySubscriptExpr *RefExpr =
                  dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
                  dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
-    MSPropertyOpBuilder Builder(*this, RefExpr);
+    MSPropertyOpBuilder Builder(*this, RefExpr, true);
     return Builder.buildRValueOperation(E);
     return Builder.buildRValueOperation(E);
   } else {
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
     llvm_unreachable("unknown pseudo-object kind!");
@@ -1560,18 +1570,18 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
   Expr *opaqueRef = op->IgnoreParens();
   Expr *opaqueRef = op->IgnoreParens();
   if (ObjCPropertyRefExpr *refExpr
   if (ObjCPropertyRefExpr *refExpr
         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
-    ObjCPropertyOpBuilder builder(*this, refExpr);
+    ObjCPropertyOpBuilder builder(*this, refExpr, false);
     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
   } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
     Diag(opcLoc, diag::err_illegal_container_subscripting_op);
     Diag(opcLoc, diag::err_illegal_container_subscripting_op);
     return ExprError();
     return ExprError();
   } else if (MSPropertyRefExpr *refExpr
   } else if (MSPropertyRefExpr *refExpr
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
-    MSPropertyOpBuilder builder(*this, refExpr);
+    MSPropertyOpBuilder builder(*this, refExpr, false);
     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   } else if (MSPropertySubscriptExpr *RefExpr
   } else if (MSPropertySubscriptExpr *RefExpr
              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
-    MSPropertyOpBuilder Builder(*this, RefExpr);
+    MSPropertyOpBuilder Builder(*this, RefExpr, false);
     return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
     return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   } else {
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
     llvm_unreachable("unknown pseudo-object kind!");
@@ -1594,22 +1604,23 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
     RHS = result.get();
     RHS = result.get();
   }
   }
 
 
+  bool IsSimpleAssign = opcode == BO_Assign;
   Expr *opaqueRef = LHS->IgnoreParens();
   Expr *opaqueRef = LHS->IgnoreParens();
   if (ObjCPropertyRefExpr *refExpr
   if (ObjCPropertyRefExpr *refExpr
         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
-    ObjCPropertyOpBuilder builder(*this, refExpr);
+    ObjCPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else if (ObjCSubscriptRefExpr *refExpr
   } else if (ObjCSubscriptRefExpr *refExpr
              = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
              = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
-    ObjCSubscriptOpBuilder builder(*this, refExpr);
+    ObjCSubscriptOpBuilder builder(*this, refExpr, IsSimpleAssign);
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else if (MSPropertyRefExpr *refExpr
   } else if (MSPropertyRefExpr *refExpr
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
-      MSPropertyOpBuilder builder(*this, refExpr);
+      MSPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
       return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
       return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else if (MSPropertySubscriptExpr *RefExpr
   } else if (MSPropertySubscriptExpr *RefExpr
              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
-      MSPropertyOpBuilder Builder(*this, RefExpr);
+      MSPropertyOpBuilder Builder(*this, RefExpr, IsSimpleAssign);
       return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
       return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else {
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
     llvm_unreachable("unknown pseudo-object kind!");

+ 1 - 0
lib/Serialization/ASTReaderStmt.cpp

@@ -1667,6 +1667,7 @@ void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
   VisitExpr(E);
   E->SourceExpr = Record.readSubExpr();
   E->SourceExpr = Record.readSubExpr();
   E->Loc = ReadSourceLocation();
   E->Loc = ReadSourceLocation();
+  E->setIsUnique(Record.readInt());
 }
 }
 
 
 void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
 void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {

+ 1 - 0
lib/Serialization/ASTWriterStmt.cpp

@@ -1699,6 +1699,7 @@ void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
   VisitExpr(E);
   Record.AddStmt(E->getSourceExpr());
   Record.AddStmt(E->getSourceExpr());
   Record.AddSourceLocation(E->getLocation());
   Record.AddSourceLocation(E->getLocation());
+  Record.push_back(E->isUnique());
   Code = serialization::EXPR_OPAQUE_VALUE;
   Code = serialization::EXPR_OPAQUE_VALUE;
 }
 }
 
 

+ 1 - 1
test/CodeGenCXX/ms-property.cpp

@@ -75,11 +75,11 @@ int main(int argc, char **argv) {
   // CHECK: call void @"??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
   // CHECK: call void @"??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
   foo(argc, (int)argv[0][0]);
   foo(argc, (int)argv[0][0]);
   // CHECK: [[P2:%.+]] = load %class.St*, %class.St** %
   // CHECK: [[P2:%.+]] = load %class.St*, %class.St** %
-  // CHECK: [[T_X:%.+]] = call i32 @"?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}})
   // CHECK: [[P1:%.+]] = load %class.S*, %class.S** %
   // CHECK: [[P1:%.+]] = load %class.S*, %class.S** %
   // CHECK: [[P1_X_22_33:%.+]] = call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33)
   // CHECK: [[P1_X_22_33:%.+]] = call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33)
   // CHECK: [[CAST:%.+]] = sitofp i32 [[P1_X_22_33]] to double
   // CHECK: [[CAST:%.+]] = sitofp i32 [[P1_X_22_33]] to double
   // CHECK: [[ARGC:%.+]] = load i32, i32* %
   // CHECK: [[ARGC:%.+]] = load i32, i32* %
+  // CHECK: [[T_X:%.+]] = call i32 @"?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}})
   // CHECK: [[CAST2:%.+]] = trunc i32 [[T_X]] to i8
   // CHECK: [[CAST2:%.+]] = trunc i32 [[T_X]] to i8
   // CHECK: call void @"?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]])
   // CHECK: call void @"?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]])
   p2->y[t.X][argc] =  p1->x[22][33];
   p2->y[t.X][argc] =  p1->x[22][33];

+ 4 - 4
test/CodeGenObjC/objc-container-subscripting-1.m

@@ -25,8 +25,8 @@ int main() {
 // CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
 // CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
 
 
   val = (array[10] = oldObject);
   val = (array[10] = oldObject);
-// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
-// CHECK-NEXT: [[FOUR:%.*]] = load i8*, i8** [[oldObject:%.*]], align 8
+// CHECK:      [[FOUR:%.*]] = load i8*, i8** [[oldObject:%.*]], align 8
+// CHECK-NEXT: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
 // CHECK-NEXT: [[FIVE:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2
 // CHECK-NEXT: [[FIVE:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2
 // CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
 // CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
 // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
 // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
@@ -45,9 +45,9 @@ int main() {
 
 
 
 
   val = (dictionary[key] = newObject);
   val = (dictionary[key] = newObject);
-// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
+// CHECK:       [[FOURTEEN:%.*]] = load i8*, i8** [[NEWOBJECT:%.*]], align 8
+// CHECK-NEXT:  [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
 // CHECK-NEXT:  [[THIRTEEN:%.*]] = load i8*, i8** [[KEY]], align 8
 // CHECK-NEXT:  [[THIRTEEN:%.*]] = load i8*, i8** [[KEY]], align 8
-// CHECK-NEXT:  [[FOURTEEN:%.*]] = load i8*, i8** [[NEWOBJECT:%.*]], align 8
 // CHECK-NEXT:  [[SIXTEEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.6
 // CHECK-NEXT:  [[SIXTEEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.6
 // CHECK-NEXT:  [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
 // CHECK-NEXT:  [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
 // CHECK-NEXT:  call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])
 // CHECK-NEXT:  call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])

+ 39 - 0
test/CodeGenObjCXX/property-dot-copy-elision.mm

@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++1z -fobjc-arc -o - %s | FileCheck %s
+
+struct S0 {
+  id f;
+};
+
+struct S1 {
+  S1();
+  S1(S0);
+  id f;
+};
+
+@interface C
+@property S1 f;
+@end
+@implementation C
+@end
+
+// CHECK-LABEL: define void @_Z5test0P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: %[[AGG_TMP_1:.*]] = alloca %[[STRUCT_S0:.*]], align
+// CHECK: call void @_ZN2S0C1Ev(%[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void @_ZN2S1C1E2S0(%[[STRUCT_S1]]* %[[AGG_TMP]], %[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[AGG_TMP]])
+
+void test0(C *c) {
+  c.f = S0();
+}
+
+// CHECK: define void @_Z5test1P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: call void @_ZN2S1C1Ev(%[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+
+void test1(C *c) {
+  c.f = S1();
+}

+ 4 - 4
test/CodeGenObjCXX/property-objects.mm

@@ -119,11 +119,11 @@ void testB1(B *b) {
 // CHECK:    define void @_Z6testB0P1B([[B:%.*]]*
 // CHECK:    define void @_Z6testB0P1B([[B:%.*]]*
 // CHECK:      [[BVAR:%.*]] = alloca [[B]]*, align 8
 // CHECK:      [[BVAR:%.*]] = alloca [[B]]*, align 8
 // CHECK:      [[TEMP:%.*]] = alloca [[B0:%.*]], align 8
 // CHECK:      [[TEMP:%.*]] = alloca [[B0:%.*]], align 8
-// CHECK:      load [[B]]*, [[B]]** [[BVAR]]
-// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0
+// CHECK:      [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0
 // CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv()
 // CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv()
 // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64
 // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64
 // CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8
 // CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8
+// CHECK:      load [[B]]*, [[B]]** [[BVAR]]
 // CHECK-NOT:  call
 // CHECK-NOT:  call
 // CHECK:      call void @llvm.memcpy
 // CHECK:      call void @llvm.memcpy
 // CHECK-NOT:  call
 // CHECK-NOT:  call
@@ -161,12 +161,12 @@ void testB2(B *b) {
 
 
 // CHECK:    define void @_Z6testB2P1B([[B]]*
 // CHECK:    define void @_Z6testB2P1B([[B]]*
 // CHECK:      [[BVAR:%.*]] = alloca [[B]]*, align 8
 // CHECK:      [[BVAR:%.*]] = alloca [[B]]*, align 8
-// CHECK:      load [[B]]*, [[B]]** [[BVAR]]
-// CHECK-NOT:  call
+// CHECK:      call void @llvm.dbg.declare(
 // CHECK:      call void @_ZN2B3C1Ev(
 // CHECK:      call void @_ZN2B3C1Ev(
 // CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev(
 // CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev(
 // CHECK-NOT:  call
 // CHECK-NOT:  call
 // CHECK:      store i64 [[T0]],
 // CHECK:      store i64 [[T0]],
+// CHECK:      load [[B]]*, [[B]]** [[BVAR]]
 // CHECK-NOT:  call
 // CHECK-NOT:  call
 // CHECK:      call void @llvm.memcpy
 // CHECK:      call void @llvm.memcpy
 // CHECK-NOT:  call
 // CHECK-NOT:  call