This called a build failure:<div><br></div><div><a href="http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/5542/steps/build_clang/logs/stdio">http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/5542/steps/build_clang/logs/stdio</a></div>
<div><br><div class="gmail_quote">On Sun, Nov 6, 2011 at 1:01 AM, John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com">rjmccall@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Author: rjmccall<br>
Date: Sun Nov  6 03:01:30 2011<br>
New Revision: 143867<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=143867&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=143867&view=rev</a><br>
Log:<br>
Change the AST representation of operations on Objective-C<br>
property references to use a new PseudoObjectExpr<br>
expression which pairs a syntactic form of the expression<br>
with a set of semantic expressions implementing it.<br>
This should significantly reduce the complexity required<br>
elsewhere in the compiler to deal with these kinds of<br>
expressions (e.g. IR generation's special l-value kind,<br>
the static analyzer's Message abstraction), at the lower<br>
cost of specifically dealing with the odd AST structure<br>
of these expressions.  It should also greatly simplify<br>
efforts to implement similar language features in the<br>
future, most notably Managed C++'s properties and indexed<br>
properties.<br>
<br>
Most of the effort here is in dealing with the various<br>
clients of the AST.  I've gone ahead and simplified the<br>
ObjC rewriter's use of properties;  other clients, like<br>
IR-gen and the static analyzer, have all the old<br>
complexity *and* all the new complexity, at least<br>
temporarily.  Many thanks to Ted for writing and advising<br>
on the necessary changes to the static analyzer.<br>
<br>
I've xfailed a small diagnostics regression in the static<br>
analyzer at Ted's request.<br>
<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/DeclBase.h<br>
    cfe/trunk/include/clang/AST/Expr.h<br>
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/AST/Stmt.h<br>
    cfe/trunk/include/clang/Basic/StmtNodes.td<br>
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
    cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp<br>
    cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp<br>
    cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp<br>
    cfe/trunk/lib/AST/DeclBase.cpp<br>
    cfe/trunk/lib/AST/Expr.cpp<br>
    cfe/trunk/lib/AST/ExprClassification.cpp<br>
    cfe/trunk/lib/AST/ExprConstant.cpp<br>
    cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
    cfe/trunk/lib/AST/StmtDumper.cpp<br>
    cfe/trunk/lib/AST/StmtPrinter.cpp<br>
    cfe/trunk/lib/AST/StmtProfile.cpp<br>
    cfe/trunk/lib/Analysis/CFG.cpp<br>
    cfe/trunk/lib/Analysis/LiveVariables.cpp<br>
    cfe/trunk/lib/CodeGen/CGExpr.cpp<br>
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp<br>
    cfe/trunk/lib/CodeGen/CGExprComplex.cpp<br>
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp<br>
    cfe/trunk/lib/CodeGen/CGObjC.cpp<br>
    cfe/trunk/lib/CodeGen/CGValue.h<br>
    cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
    cfe/trunk/lib/Rewrite/RewriteObjC.cpp<br>
    cfe/trunk/lib/Sema/SemaChecking.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>
    cfe/trunk/lib/Sema/SemaPseudoObject.cpp<br>
    cfe/trunk/lib/Sema/SemaStmt.cpp<br>
    cfe/trunk/lib/Sema/TreeTransform.h<br>
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp<br>
    cfe/trunk/test/Analysis/casts.m<br>
    cfe/trunk/test/Analysis/retain-release-path-notes.m<br>
    cfe/trunk/tools/libclang/CIndex.cpp<br>
    cfe/trunk/tools/libclang/CXCursor.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/DeclBase.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/DeclBase.h (original)<br>
+++ cfe/trunk/include/clang/AST/DeclBase.h Sun Nov  6 03:01:30 2011<br>
@@ -974,6 +974,14 @@<br>
   /// declaration context DC.<br>
   bool Encloses(const DeclContext *DC) const;<br>
<br>
+  /// \brief Find the nearest non-closure ancestor of this context,<br>
+  /// i.e. the innermost semantic parent of this context which is not<br>
+  /// a closure.  A context may be its own non-closure ancestor.<br>
+  DeclContext *getNonClosureAncestor();<br>
+  const DeclContext *getNonClosureAncestor() const {<br>
+    return const_cast<DeclContext*>(this)->getNonClosureAncestor();<br>
+  }<br>
+<br>
   /// getPrimaryContext - There may be many different<br>
   /// declarations of the same entity (including forward declarations<br>
   /// of classes, multiple definitions of namespaces, etc.), each with<br>
<br>
Modified: cfe/trunk/include/clang/AST/Expr.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/Expr.h (original)<br>
+++ cfe/trunk/include/clang/AST/Expr.h Sun Nov  6 03:01:30 2011<br>
@@ -2758,6 +2758,13 @@<br>
   bool isCompoundAssignmentOp() const {<br>
     return isCompoundAssignmentOp(getOpcode());<br>
   }<br>
+  static Opcode getOpForCompoundAssignment(Opcode Opc) {<br>
+    assert(isCompoundAssignmentOp(Opc));<br>
+    if (Opc >= BO_XorAssign)<br>
+      return Opcode(unsigned(Opc) - BO_XorAssign + BO_Xor);<br>
+    else<br>
+      return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul);<br>
+  }<br>
<br>
   static bool isShiftAssignOp(Opcode Opc) {<br>
     return Opc == BO_ShlAssign || Opc == BO_ShrAssign;<br>
@@ -4251,6 +4258,140 @@<br>
   child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }<br>
 };<br>
<br>
+/// PseudoObjectExpr - An expression which accesses a pseudo-object<br>
+/// l-value.  A pseudo-object is an abstract object, accesses to which<br>
+/// are translated to calls.  The pseudo-object expression has a<br>
+/// syntactic form, which shows how the expression was actually<br>
+/// written in the source code, and a semantic form, which is a series<br>
+/// of expressions to be executed in order which detail how the<br>
+/// operation is actually evaluated.  Optionally, one of the semantic<br>
+/// forms may also provide a result value for the expression.<br>
+///<br>
+/// If any of the semantic-form expressions is an OpaqueValueExpr,<br>
+/// that OVE is required to have a source expression, and it is bound<br>
+/// to the result of that source expression.  Such OVEs may appear<br>
+/// only in subsequent semantic-form expressions and as<br>
+/// sub-expressions of the syntactic form.<br>
+///<br>
+/// PseudoObjectExpr should be used only when an operation can be<br>
+/// usefully described in terms of fairly simple rewrite rules on<br>
+/// objects and functions that are meant to be used by end-developers.<br>
+/// For example, under the Itanium ABI, dynamic casts are implemented<br>
+/// as a call to a runtime function called __dynamic_cast; using this<br>
+/// class to describe that would be inappropriate because that call is<br>
+/// not really part of the user-visible semantics, and instead the<br>
+/// cast is properly reflected in the AST and IR-generation has been<br>
+/// taught to generate the call as necessary.  In contrast, an<br>
+/// Objective-C property access is semantically defined to be<br>
+/// equivalent to a particular message send, and this is very much<br>
+/// part of the user model.  The name of this class encourages this<br>
+/// modelling design.<br>
+class PseudoObjectExpr : public Expr {<br>
+  // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions.<br>
+  // Always at least two, because the first sub-expression is the<br>
+  // syntactic form.<br>
+<br>
+  // PseudoObjectExprBits.ResultIndex - The index of the<br>
+  // sub-expression holding the result.  0 means the result is void,<br>
+  // which is unambiguous because it's the index of the syntactic<br>
+  // form.  Note that this is therefore 1 higher than the value passed<br>
+  // in to Create, which is an index within the semantic forms.<br>
+  // Note also that ASTStmtWriter assumes this encoding.<br>
+<br>
+  Expr **getSubExprsBuffer() { return reinterpret_cast<Expr**>(this + 1); }<br>
+  const Expr * const *getSubExprsBuffer() const {<br>
+    return reinterpret_cast<const Expr * const *>(this + 1);<br>
+  }<br>
+<br>
+  friend class ASTStmtReader;<br>
+<br>
+  PseudoObjectExpr(QualType type, ExprValueKind VK,<br>
+                   Expr *syntactic, ArrayRef<Expr*> semantic,<br>
+                   unsigned resultIndex);<br>
+<br>
+  PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs);<br>
+<br>
+  unsigned getNumSubExprs() const {<br>
+    return PseudoObjectExprBits.NumSubExprs;<br>
+  }<br>
+<br>
+public:<br>
+  /// NoResult - A value for the result index indicating that there is<br>
+  /// no semantic result.<br>
+  enum { NoResult = ~0U };<br>
+<br>
+  static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic,<br>
+                                  ArrayRef<Expr*> semantic,<br>
+                                  unsigned resultIndex);<br>
+<br>
+  static PseudoObjectExpr *Create(ASTContext &Context, EmptyShell shell,<br>
+                                  unsigned numSemanticExprs);<br>
+<br>
+  /// Return the syntactic form of this expression, i.e. the<br>
+  /// expression it actually looks like.  Likely to be expressed in<br>
+  /// terms of OpaqueValueExprs bound in the semantic form.<br>
+  Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; }<br>
+  const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; }<br>
+<br>
+  /// Return the index of the result-bearing expression into the semantics<br>
+  /// expressions, or PseudoObjectExpr::NoResult if there is none.<br>
+  unsigned getResultExprIndex() const {<br>
+    if (PseudoObjectExprBits.ResultIndex == 0) return NoResult;<br>
+    return PseudoObjectExprBits.ResultIndex - 1;<br>
+  }<br>
+<br>
+  /// Return the result-bearing expression, or null if there is none.<br>
+  Expr *getResultExpr() {<br>
+    if (PseudoObjectExprBits.ResultIndex == 0)<br>
+      return 0;<br>
+    return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex];<br>
+  }<br>
+  const Expr *getResultExpr() const {<br>
+    return const_cast<PseudoObjectExpr*>(this)->getResultExpr();<br>
+  }<br>
+<br>
+  unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; }<br>
+<br>
+  typedef Expr * const *semantics_iterator;<br>
+  typedef const Expr * const *const_semantics_iterator;<br>
+  semantics_iterator semantics_begin() {<br>
+    return getSubExprsBuffer() + 1;<br>
+  }<br>
+  const_semantics_iterator semantics_begin() const {<br>
+    return getSubExprsBuffer() + 1;<br>
+  }<br>
+  semantics_iterator semantics_end() {<br>
+    return getSubExprsBuffer() + getNumSubExprs();<br>
+  }<br>
+  const_semantics_iterator semantics_end() const {<br>
+    return getSubExprsBuffer() + getNumSubExprs();<br>
+  }<br>
+  Expr *getSemanticExpr(unsigned index) {<br>
+    assert(index + 1 < getNumSubExprs());<br>
+    return getSubExprsBuffer()[index + 1];<br>
+  }<br>
+  const Expr *getSemanticExpr(unsigned index) const {<br>
+    return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index);<br>
+  }<br>
+<br>
+  SourceLocation getExprLoc() const {<br>
+    return getSyntacticForm()->getExprLoc();<br>
+  }<br>
+  SourceRange getSourceRange() const {<br>
+    return getSyntacticForm()->getSourceRange();<br>
+  }<br>
+<br>
+  child_range children() {<br>
+    Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer());<br>
+    return child_range(cs, cs + getNumSubExprs());<br>
+  }<br>
+<br>
+  static bool classof(const Stmt *T) {<br>
+    return T->getStmtClass() == PseudoObjectExprClass;<br>
+  }<br>
+  static bool classof(const PseudoObjectExpr *) { return true; }<br>
+};<br>
+<br>
 /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,<br>
 /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the<br>
 /// similarly-named C++0x instructions.  All of these instructions take one<br>
<br>
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Sun Nov  6 03:01:30 2011<br>
@@ -1874,6 +1874,23 @@<br>
   return true;<br>
 }<br>
<br>
+// PseudoObjectExpr is a special case because of the wierdness with<br>
+// syntactic expressions and opaque values.<br>
+template<typename Derived><br>
+bool RecursiveASTVisitor<Derived>::<br>
+TraversePseudoObjectExpr(PseudoObjectExpr *S) {<br>
+  TRY_TO(WalkUpFromPseudoObjectExpr(S));<br>
+  TRY_TO(TraverseStmt(S->getSyntacticForm()));<br>
+  for (PseudoObjectExpr::semantics_iterator<br>
+         i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) {<br>
+    Expr *sub = *i;<br>
+    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))<br>
+      sub = OVE->getSourceExpr();<br>
+    TRY_TO(TraverseStmt(sub));<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
 DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {<br>
     // This is called for code like 'return T()' where T is a built-in<br>
     // (i.e. non-class) type.<br>
<br>
Modified: cfe/trunk/include/clang/AST/Stmt.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/Stmt.h (original)<br>
+++ cfe/trunk/include/clang/AST/Stmt.h Sun Nov  6 03:01:30 2011<br>
@@ -146,6 +146,7 @@<br>
     friend class CXXUnresolvedConstructExpr; // ctor<br>
     friend class CXXDependentScopeMemberExpr; // ctor<br>
     friend class OverloadExpr; // ctor<br>
+    friend class PseudoObjectExpr; // ctor<br>
     friend class AtomicExpr; // ctor<br>
     unsigned : NumStmtBits;<br>
<br>
@@ -184,6 +185,18 @@<br>
     unsigned NumPreArgs : 1;<br>
   };<br>
<br>
+  class PseudoObjectExprBitfields {<br>
+    friend class PseudoObjectExpr;<br>
+    friend class ASTStmtReader; // deserialization<br>
+<br>
+    unsigned : NumExprBits;<br>
+<br>
+    // These don't need to be particularly wide, because they're<br>
+    // strictly limited by the forms of expressions we permit.<br>
+    unsigned NumSubExprs : 8;<br>
+    unsigned ResultIndex : 32 - 8 - NumExprBits;<br>
+  };<br>
+<br>
   class ObjCIndirectCopyRestoreExprBitfields {<br>
     friend class ObjCIndirectCopyRestoreExpr;<br>
     unsigned : NumExprBits;<br>
@@ -201,6 +214,7 @@<br>
     DeclRefExprBitfields DeclRefExprBits;<br>
     CastExprBitfields CastExprBits;<br>
     CallExprBitfields CallExprBits;<br>
+    PseudoObjectExprBitfields PseudoObjectExprBits;<br>
     ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;<br>
   };<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Basic/StmtNodes.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)<br>
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Sun Nov  6 03:01:30 2011<br>
@@ -77,6 +77,7 @@<br>
 def ParenListExpr : DStmt<Expr>;<br>
 def VAArgExpr : DStmt<Expr>;<br>
 def GenericSelectionExpr : DStmt<Expr>;<br>
+def PseudoObjectExpr : DStmt<Expr>;<br>
<br>
 // Atomic expressions<br>
 def AtomicExpr : DStmt<Expr>;<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Sun Nov  6 03:01:30 2011<br>
@@ -1000,6 +1000,8 @@<br>
       EXPR_BLOCK_DECL_REF,<br>
       /// \brief A GenericSelectionExpr record.<br>
       EXPR_GENERIC_SELECTION,<br>
+      /// \brief A PseudoObjectExpr record.<br>
+      EXPR_PSEUDO_OBJECT,<br>
       /// \brief An AtomicExpr record.<br>
       EXPR_ATOMIC,<br>
<br>
<br>
Modified: cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp (original)<br>
+++ cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp Sun Nov  6 03:01:30 2011<br>
@@ -160,12 +160,14 @@<br>
     if (!E) return false;<br>
<br>
     E = E->IgnoreParenCasts();<br>
+<br>
+    // Also look through property-getter sugar.<br>
+    if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E))<br>
+      E = pseudoOp->getResultExpr()->IgnoreImplicit();<br>
+<br>
     if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))<br>
       return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);<br>
<br>
-    if (ObjCPropertyRefExpr *propE = dyn_cast<ObjCPropertyRefExpr>(E))<br>
-      return propE->getGetterSelector() == DelegateSel;<br>
-<br>
     return false;<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp (original)<br>
+++ cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp Sun Nov  6 03:01:30 2011<br>
@@ -236,7 +236,15 @@<br>
       }<br>
     }<br>
<br>
-    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getSubExpr())){<br>
+    Expr *subExpr = E->getSubExpr();<br>
+<br>
+    // Look through pseudo-object expressions.<br>
+    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {<br>
+      subExpr = pseudo->getResultExpr();<br>
+      assert(subExpr && "no result for pseudo-object of non-void type?");<br>
+    }<br>
+<br>
+    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {<br>
       if (implCE->getCastKind() == CK_ARCConsumeObject)<br>
         return rewriteToBridgedCast(E, OBC_BridgeRetained);<br>
       if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)<br>
<br>
Modified: cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp (original)<br>
+++ cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp Sun Nov  6 03:01:30 2011<br>
@@ -78,6 +78,15 @@<br>
     return true;<br>
   }<br>
<br>
+  bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) {<br>
+    if (isZeroingPropIvar(POE) && isRemovable(POE)) {<br>
+      Transaction Trans(Pass.TA);<br>
+      Pass.TA.removeStmt(POE);<br>
+    }<br>
+<br>
+    return true;<br>
+  }<br>
+<br>
   bool VisitBinaryOperator(BinaryOperator *BOE) {<br>
     if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {<br>
       Transaction Trans(Pass.TA);<br>
@@ -142,17 +151,21 @@<br>
   }<br>
<br>
   bool isZeroingPropIvar(Expr *E) {<br>
-    BinaryOperator *BOE = dyn_cast_or_null<BinaryOperator>(E);<br>
-    if (!BOE) return false;<br>
+    E = E->IgnoreParens();<br>
+    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E))<br>
+      return isZeroingPropIvar(BO);<br>
+    if (PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(E))<br>
+      return isZeroingPropIvar(PO);<br>
+    return false;<br>
+  }<br>
<br>
+  bool isZeroingPropIvar(BinaryOperator *BOE) {<br>
     if (BOE->getOpcode() == BO_Comma)<br>
       return isZeroingPropIvar(BOE->getLHS()) &&<br>
              isZeroingPropIvar(BOE->getRHS());<br>
<br>
     if (BOE->getOpcode() != BO_Assign)<br>
-        return false;<br>
-<br>
-    ASTContext &Ctx = Pass.Ctx;<br>
+      return false;<br>
<br>
     Expr *LHS = BOE->getLHS();<br>
     if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {<br>
@@ -172,25 +185,38 @@<br>
       if (!IvarBacksPropertySynthesis)<br>
         return false;<br>
     }<br>
-    else if (ObjCPropertyRefExpr *PropRefExp = dyn_cast<ObjCPropertyRefExpr>(LHS)) {<br>
-      // TODO: Using implicit property decl.<br>
-      if (PropRefExp->isImplicitProperty())<br>
-        return false;<br>
-      if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {<br>
-        if (!SynthesizedProperties.count(PDecl))<br>
-          return false;<br>
-      }<br>
-    }<br>
     else<br>
         return false;<br>
<br>
-    Expr *RHS = BOE->getRHS();<br>
-    bool RHSIsNull = RHS->isNullPointerConstant(Ctx,<br>
-                                                Expr::NPC_ValueDependentIsNull);<br>
-    if (RHSIsNull)<br>
+    return isZero(BOE->getRHS());<br>
+  }<br>
+<br>
+  bool isZeroingPropIvar(PseudoObjectExpr *PO) {<br>
+    BinaryOperator *BO = dyn_cast<BinaryOperator>(PO->getSyntacticForm());<br>
+    if (!BO) return false;<br>
+    if (BO->getOpcode() != BO_Assign) return false;<br>
+<br>
+    ObjCPropertyRefExpr *PropRefExp =<br>
+      dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParens());<br>
+    if (!PropRefExp) return false;<br>
+<br>
+    // TODO: Using implicit property decl.<br>
+    if (PropRefExp->isImplicitProperty())<br>
+      return false;<br>
+<br>
+    if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {<br>
+      if (!SynthesizedProperties.count(PDecl))<br>
+        return false;<br>
+    }<br>
+<br>
+    return isZero(cast<OpaqueValueExpr>(BO->getRHS())->getSourceExpr());<br>
+  }<br>
+<br>
+  bool isZero(Expr *E) {<br>
+    if (E->isNullPointerConstant(Pass.Ctx, Expr::NPC_ValueDependentIsNull))<br>
       return true;<br>
<br>
-    return isZeroingPropIvar(RHS);<br>
+    return isZeroingPropIvar(E);<br>
   }<br>
 };<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/DeclBase.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/DeclBase.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclBase.cpp Sun Nov  6 03:01:30 2011<br>
@@ -640,7 +640,11 @@<br>
 }<br>
<br>
 DeclContext *Decl::getNonClosureContext() {<br>
-  DeclContext *DC = getDeclContext();<br>
+  return getDeclContext()->getNonClosureAncestor();<br>
+}<br>
+<br>
+DeclContext *DeclContext::getNonClosureAncestor() {<br>
+  DeclContext *DC = this;<br>
<br>
   // This is basically "while (DC->isClosure()) DC = DC->getParent();"<br>
   // except that it's significantly more efficient to cast to a known<br>
<br>
Modified: cfe/trunk/lib/AST/Expr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/Expr.cpp (original)<br>
+++ cfe/trunk/lib/AST/Expr.cpp Sun Nov  6 03:01:30 2011<br>
@@ -1694,6 +1694,19 @@<br>
     R1 = getSourceRange();<br>
     return true;<br>
<br>
+  case PseudoObjectExprClass: {<br>
+    const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this);<br>
+<br>
+    // Only complain about things that have the form of a getter.<br>
+    if (isa<UnaryOperator>(PO->getSyntacticForm()) ||<br>
+        isa<BinaryOperator>(PO->getSyntacticForm()))<br>
+      return false;<br>
+<br>
+    Loc = getExprLoc();<br>
+    R1 = getSourceRange();<br>
+    return true;<br>
+  }<br>
+<br>
   case StmtExprClass: {<br>
     // Statement exprs don't logically have side effects themselves, but are<br>
     // sometimes used in macros in ways that give them a type that is unused.<br>
@@ -2598,6 +2611,9 @@<br>
   } else if (const MaterializeTemporaryExpr *M<br>
                                    = dyn_cast<MaterializeTemporaryExpr>(this)) {<br>
     return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);<br>
+  } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) {<br>
+    if (const Expr *Source = OVE->getSourceExpr())<br>
+      return Source->isNullPointerConstant(Ctx, NPC);<br>
   }<br>
<br>
   // C++0x nullptr_t is always a null pointer constant.<br>
@@ -3306,6 +3322,72 @@<br>
   return cast<OpaqueValueExpr>(e);<br>
 }<br>
<br>
+PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context, EmptyShell sh,<br>
+                                           unsigned numSemanticExprs) {<br>
+  void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) +<br>
+                                    (1 + numSemanticExprs) * sizeof(Expr*),<br>
+                                  llvm::alignOf<PseudoObjectExpr>());<br>
+  return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);<br>
+}<br>
+<br>
+PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs)<br>
+  : Expr(PseudoObjectExprClass, shell) {<br>
+  PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1;<br>
+}<br>
+<br>
+PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax,<br>
+                                           ArrayRef<Expr*> semantics,<br>
+                                           unsigned resultIndex) {<br>
+  assert(syntax && "no syntactic expression!");<br>
+  assert(semantics.size() && "no semantic expressions!");<br>
+<br>
+  QualType type;<br>
+  ExprValueKind VK;<br>
+  if (resultIndex == NoResult) {<br>
+    type = C.VoidTy;<br>
+    VK = VK_RValue;<br>
+  } else {<br>
+    assert(resultIndex < semantics.size());<br>
+    type = semantics[resultIndex]->getType();<br>
+    VK = semantics[resultIndex]->getValueKind();<br>
+    assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary);<br>
+  }<br>
+<br>
+  void *buffer = C.Allocate(sizeof(PseudoObjectExpr) +<br>
+                              (1 + semantics.size()) * sizeof(Expr*),<br>
+                            llvm::alignOf<PseudoObjectExpr>());<br>
+  return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,<br>
+                                      resultIndex);<br>
+}<br>
+<br>
+PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,<br>
+                                   Expr *syntax, ArrayRef<Expr*> semantics,<br>
+                                   unsigned resultIndex)<br>
+  : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary,<br>
+         /*filled in at end of ctor*/ false, false, false, false) {<br>
+  PseudoObjectExprBits.NumSubExprs = semantics.size() + 1;<br>
+  PseudoObjectExprBits.ResultIndex = resultIndex + 1;<br>
+<br>
+  for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) {<br>
+    Expr *E = (i == 0 ? syntax : semantics[i-1]);<br>
+    getSubExprsBuffer()[i] = E;<br>
+<br>
+    if (E->isTypeDependent())<br>
+      ExprBits.TypeDependent = true;<br>
+    if (E->isValueDependent())<br>
+      ExprBits.ValueDependent = true;<br>
+    if (E->isInstantiationDependent())<br>
+      ExprBits.InstantiationDependent = true;<br>
+    if (E->containsUnexpandedParameterPack())<br>
+      ExprBits.ContainsUnexpandedParameterPack = true;<br>
+<br>
+    if (isa<OpaqueValueExpr>(E))<br>
+      assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 &&<br>
+             "opaque-value semantic expressions for pseudo-object "<br>
+             "operations must have sources");<br>
+  }<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 //  ExprIterator.<br>
 //===----------------------------------------------------------------------===//<br>
<br>
Modified: cfe/trunk/lib/AST/ExprClassification.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprClassification.cpp Sun Nov  6 03:01:30 2011<br>
@@ -232,6 +232,11 @@<br>
     return ClassifyExprValueKind(Lang, E,<br>
                                  cast<OpaqueValueExpr>(E)->getValueKind());<br>
<br>
+    // Pseudo-object expressions can produce l-values with reference magic.<br>
+  case Expr::PseudoObjectExprClass:<br>
+    return ClassifyExprValueKind(Lang, E,<br>
+                                 cast<PseudoObjectExpr>(E)->getValueKind());<br>
+<br>
     // Implicit casts are lvalues if they're lvalue casts. Other than that, we<br>
     // only specifically record class temporaries.<br>
   case Expr::ImplicitCastExprClass:<br>
<br>
Modified: cfe/trunk/lib/AST/ExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Nov  6 03:01:30 2011<br>
@@ -3450,6 +3450,7 @@<br>
   case Expr::AsTypeExprClass:<br>
   case Expr::ObjCIndirectCopyRestoreExprClass:<br>
   case Expr::MaterializeTemporaryExprClass:<br>
+  case Expr::PseudoObjectExprClass:<br>
   case Expr::AtomicExprClass:<br>
     return ICEDiag(2, E->getLocStart());<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)<br>
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Sun Nov  6 03:01:30 2011<br>
@@ -2257,6 +2257,7 @@<br>
   case Expr::CXXNoexceptExprClass:<br>
   case Expr::CUDAKernelCallExprClass:<br>
   case Expr::AsTypeExprClass:<br>
+  case Expr::PseudoObjectExprClass:<br>
   case Expr::AtomicExprClass:<br>
   {<br>
     // As bad as this diagnostic is, it's better than crashing.<br>
<br>
Modified: cfe/trunk/lib/AST/StmtDumper.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtDumper.cpp Sun Nov  6 03:01:30 2011<br>
@@ -148,6 +148,7 @@<br>
     void VisitCompoundAssignOperator(CompoundAssignOperator *Node);<br>
     void VisitAddrLabelExpr(AddrLabelExpr *Node);<br>
     void VisitBlockExpr(BlockExpr *Node);<br>
+    void VisitOpaqueValueExpr(OpaqueValueExpr *Node);<br>
<br>
     // C++<br>
     void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);<br>
@@ -524,6 +525,15 @@<br>
   DumpSubTree(block->getBody());<br>
 }<br>
<br>
+void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {<br>
+  DumpExpr(Node);<br>
+<br>
+  if (Expr *Source = Node->getSourceExpr()) {<br>
+    OS << '\n';<br>
+    DumpSubTree(Source);<br>
+  }<br>
+}<br>
+<br>
 // GNU extensions.<br>
<br>
 void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {<br>
<br>
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Sun Nov  6 03:01:30 2011<br>
@@ -1027,6 +1027,10 @@<br>
   OS << ")";<br>
 }<br>
<br>
+void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) {<br>
+  PrintExpr(Node->getSyntacticForm());<br>
+}<br>
+<br>
 void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {<br>
   const char *Name = 0;<br>
   switch (Node->getOp()) {<br>
<br>
Modified: cfe/trunk/lib/AST/StmtProfile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtProfile.cpp Sun Nov  6 03:01:30 2011<br>
@@ -475,6 +475,15 @@<br>
   }<br>
 }<br>
<br>
+void StmtProfiler::VisitPseudoObjectExpr(const PseudoObjectExpr *S) {<br>
+  VisitExpr(S);<br>
+  for (PseudoObjectExpr::const_semantics_iterator<br>
+         i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i)<br>
+    // Normally, we would not profile the source expressions of OVEs.<br>
+    if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i))<br>
+      Visit(OVE->getSourceExpr());<br>
+}<br>
+<br>
 void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) {<br>
   VisitExpr(S);<br>
   ID.AddInteger(S->getOp());<br>
<br>
Modified: cfe/trunk/lib/Analysis/CFG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Analysis/CFG.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/CFG.cpp Sun Nov  6 03:01:30 2011<br>
@@ -344,6 +344,7 @@<br>
   CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);<br>
   CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);<br>
   CFGBlock *VisitReturnStmt(ReturnStmt *R);<br>
+  CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);<br>
   CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,<br>
                                           AddStmtChoice asc);<br>
   CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);<br>
@@ -981,6 +982,9 @@<br>
     case Stmt::OpaqueValueExprClass:<br>
       return Block;<br>
<br>
+    case Stmt::PseudoObjectExprClass:<br>
+      return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));<br>
+<br>
     case Stmt::ReturnStmtClass:<br>
       return VisitReturnStmt(cast<ReturnStmt>(S));<br>
<br>
@@ -1907,6 +1911,31 @@<br>
   return NYS();<br>
 }<br>
<br>
+CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+  autoCreateBlock();<br>
+<br>
+  // Add the PseudoObject as the last thing.<br>
+  appendStmt(Block, E);<br>
+<br>
+  CFGBlock *lastBlock = Block;<br>
+<br>
+  // Before that, evaluate all of the semantics in order.  In<br>
+  // CFG-land, that means appending them in reverse order.<br>
+  for (unsigned i = E->getNumSemanticExprs(); i != 0; ) {<br>
+    Expr *Semantic = E->getSemanticExpr(--i);<br>
+<br>
+    // If the semantic is an opaque value, we're being asked to bind<br>
+    // it to its source expression.<br>
+    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))<br>
+      Semantic = OVE->getSourceExpr();<br>
+<br>
+    if (CFGBlock *B = Visit(Semantic))<br>
+      lastBlock = B;<br>
+  }<br>
+<br>
+  return lastBlock;<br>
+}<br>
+<br>
 CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {<br>
   CFGBlock *LoopSuccessor = NULL;<br>
<br>
<br>
Modified: cfe/trunk/lib/Analysis/LiveVariables.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/LiveVariables.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/LiveVariables.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Analysis/LiveVariables.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/LiveVariables.cpp Sun Nov  6 03:01:30 2011<br>
@@ -288,6 +288,18 @@<br>
       }<br>
       break;<br>
     }<br>
+    case Stmt::PseudoObjectExprClass: {<br>
+      // A pseudo-object operation only directly consumes its result<br>
+      // expression.<br>
+      Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();<br>
+      if (!child) return;<br>
+      if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))<br>
+        child = OV->getSourceExpr();<br>
+      child = child->IgnoreParens();<br>
+      val.liveStmts = LV.SSetFact.add(val.liveStmts, child);<br>
+      return;<br>
+    }<br>
+<br>
     // FIXME: These cases eventually shouldn't be needed.<br>
     case Stmt::ExprWithCleanupsClass: {<br>
       S = cast<ExprWithCleanups>(S)->getSubExpr();<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Nov  6 03:01:30 2011<br>
@@ -672,6 +672,8 @@<br>
     return EmitStringLiteralLValue(cast<StringLiteral>(E));<br>
   case Expr::ObjCEncodeExprClass:<br>
     return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E));<br>
+  case Expr::PseudoObjectExprClass:<br>
+    return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E));<br>
<br>
   case Expr::BlockDeclRefExprClass:<br>
     return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E));<br>
@@ -2768,3 +2770,86 @@<br>
   cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy,<br>
                                             Node);<br>
 }<br>
+<br>
+namespace {<br>
+  struct LValueOrRValue {<br>
+    LValue LV;<br>
+    RValue RV;<br>
+  };<br>
+}<br>
+<br>
+static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,<br>
+                                           const PseudoObjectExpr *E,<br>
+                                           bool forLValue,<br>
+                                           AggValueSlot slot) {<br>
+  llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques;<br>
+<br>
+  // Find the result expression, if any.<br>
+  const Expr *resultExpr = E->getResultExpr();<br>
+  LValueOrRValue result;<br>
+<br>
+  for (PseudoObjectExpr::const_semantics_iterator<br>
+         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {<br>
+    const Expr *semantic = *i;<br>
+<br>
+    // If this semantic expression is an opaque value, bind it<br>
+    // to the result of its source expression.<br>
+    if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) {<br>
+<br>
+      // If this is the result expression, we may need to evaluate<br>
+      // directly into the slot.<br>
+      typedef CodeGenFunction::OpaqueValueMappingData OVMA;<br>
+      OVMA opaqueData;<br>
+      if (ov == resultExpr && ov->isRValue() && !forLValue &&<br>
+          CodeGenFunction::hasAggregateLLVMType(ov->getType()) &&<br>
+          !ov->getType()->isAnyComplexType()) {<br>
+        CGF.EmitAggExpr(ov->getSourceExpr(), slot);<br>
+<br>
+        LValue LV = CGF.MakeAddrLValue(slot.getAddr(), ov->getType());<br>
+        opaqueData = OVMA::bind(CGF, ov, LV);<br>
+        result.RV = slot.asRValue();<br>
+<br>
+      // Otherwise, emit as normal.<br>
+      } else {<br>
+        opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr());<br>
+<br>
+        // If this is the result, also evaluate the result now.<br>
+        if (ov == resultExpr) {<br>
+          if (forLValue)<br>
+            result.LV = CGF.EmitLValue(ov);<br>
+          else<br>
+            result.RV = CGF.EmitAnyExpr(ov, slot);<br>
+        }<br>
+      }<br>
+<br>
+      opaques.push_back(opaqueData);<br>
+<br>
+    // Otherwise, if the expression is the result, evaluate it<br>
+    // and remember the result.<br>
+    } else if (semantic == resultExpr) {<br>
+      if (forLValue)<br>
+        result.LV = CGF.EmitLValue(semantic);<br>
+      else<br>
+        result.RV = CGF.EmitAnyExpr(semantic, slot);<br>
+<br>
+    // Otherwise, evaluate the expression in an ignored context.<br>
+    } else {<br>
+      CGF.EmitIgnoredExpr(semantic);<br>
+    }<br>
+  }<br>
+<br>
+  // Unbind all the opaques now.<br>
+  for (unsigned i = 0, e = opaques.size(); i != e; ++i)<br>
+    opaques[i].unbind(CGF);<br>
+<br>
+  return result;<br>
+}<br>
+<br>
+RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E,<br>
+                                               AggValueSlot slot) {<br>
+  return emitPseudoObjectExpr(*this, E, false, slot).RV;<br>
+}<br>
+<br>
+LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) {<br>
+  return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV;<br>
+}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sun Nov  6 03:01:30 2011<br>
@@ -148,6 +148,15 @@<br>
   void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);<br>
   void VisitOpaqueValueExpr(OpaqueValueExpr *E);<br>
<br>
+  void VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+    if (E->isGLValue()) {<br>
+      LValue LV = CGF.EmitPseudoObjectLValue(E);<br>
+      return EmitFinalDestCopy(E, LV);<br>
+    }<br>
+<br>
+    CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType()));<br>
+  }<br>
+<br>
   void VisitVAArgExpr(VAArgExpr *E);<br>
<br>
   void EmitInitializationToLValue(Expr *E, LValue Address);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Sun Nov  6 03:01:30 2011<br>
@@ -137,6 +137,10 @@<br>
     return CGF.getOpaqueRValueMapping(E).getComplexVal();<br>
   }<br>
<br>
+  ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+    return CGF.EmitPseudoObjectRValue(E).getComplexVal();<br>
+  }<br>
+<br>
   // FIXME: CompoundLiteralExpr<br>
<br>
   ComplexPairTy EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Nov  6 03:01:30 2011<br>
@@ -197,6 +197,10 @@<br>
     return llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength());<br>
   }<br>
<br>
+  Value *VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+    return CGF.EmitPseudoObjectRValue(E).getScalarVal();<br>
+  }<br>
+<br>
   Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {<br>
     if (E->isGLValue())<br>
       return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Nov  6 03:01:30 2011<br>
@@ -2231,6 +2231,59 @@<br>
   return true;<br>
 }<br>
<br>
+/// Try to emit a PseudoObjectExpr at +1.<br>
+///<br>
+/// This massively duplicates emitPseudoObjectRValue.<br>
+static TryEmitResult tryEmitARCRetainPseudoObject(CodeGenFunction &CGF,<br>
+                                                  const PseudoObjectExpr *E) {<br>
+  llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques;<br>
+<br>
+  // Find the result expression.<br>
+  const Expr *resultExpr = E->getResultExpr();<br>
+  assert(resultExpr);<br>
+  TryEmitResult result;<br>
+<br>
+  for (PseudoObjectExpr::const_semantics_iterator<br>
+         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {<br>
+    const Expr *semantic = *i;<br>
+<br>
+    // If this semantic expression is an opaque value, bind it<br>
+    // to the result of its source expression.<br>
+    if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) {<br>
+      typedef CodeGenFunction::OpaqueValueMappingData OVMA;<br>
+      OVMA opaqueData;<br>
+<br>
+      // If this semantic is the result of the pseudo-object<br>
+      // expression, try to evaluate the source as +1.<br>
+      if (ov == resultExpr) {<br>
+        assert(!OVMA::shouldBindAsLValue(ov));<br>
+        result = tryEmitARCRetainScalarExpr(CGF, ov->getSourceExpr());<br>
+        opaqueData = OVMA::bind(CGF, ov, RValue::get(result.getPointer()));<br>
+<br>
+      // Otherwise, just bind it.<br>
+      } else {<br>
+        opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr());<br>
+      }<br>
+      opaques.push_back(opaqueData);<br>
+<br>
+    // Otherwise, if the expression is the result, evaluate it<br>
+    // and remember the result.<br>
+    } else if (semantic == resultExpr) {<br>
+      result = tryEmitARCRetainScalarExpr(CGF, semantic);<br>
+<br>
+    // Otherwise, evaluate the expression in an ignored context.<br>
+    } else {<br>
+      CGF.EmitIgnoredExpr(semantic);<br>
+    }<br>
+  }<br>
+<br>
+  // Unbind all the opaques now.<br>
+  for (unsigned i = 0, e = opaques.size(); i != e; ++i)<br>
+    opaques[i].unbind(CGF);<br>
+<br>
+  return result;<br>
+}<br>
+<br>
 static TryEmitResult<br>
 tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) {<br>
   // Look through cleanups.<br>
@@ -2356,6 +2409,17 @@<br>
       llvm::Value *result = emitARCRetainCall(CGF, e);<br>
       if (resultType) result = CGF.Builder.CreateBitCast(result, resultType);<br>
       return TryEmitResult(result, true);<br>
+<br>
+    // Look through pseudo-object expressions.<br>
+    } else if (const PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {<br>
+      TryEmitResult result<br>
+        = tryEmitARCRetainPseudoObject(CGF, pseudo);<br>
+      if (resultType) {<br>
+        llvm::Value *value = result.getPointer();<br>
+        value = CGF.Builder.CreateBitCast(value, resultType);<br>
+        result.setPointer(value);<br>
+      }<br>
+      return result;<br>
     }<br>
<br>
     // Conservatively halt the search at any other expression kind.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGValue.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGValue.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGValue.h Sun Nov  6 03:01:30 2011<br>
@@ -27,6 +27,7 @@<br>
   class ObjCPropertyRefExpr;<br>
<br>
 namespace CodeGen {<br>
+  class AggValueSlot;<br>
   class CGBitFieldInfo;<br>
<br>
 /// RValue - This trivial value class is used to represent the result of an<br>
@@ -452,7 +453,7 @@<br>
   RValue asRValue() const {<br>
     return RValue::getAggregate(getAddr(), isVolatile());<br>
   }<br>
-<br>
+<br>
   void setZeroed(bool V = true) { ZeroedFlag = V; }<br>
   IsZeroed_t isZeroed() const {<br>
     return IsZeroed_t(ZeroedFlag);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sun Nov  6 03:01:30 2011<br>
@@ -950,20 +950,86 @@<br>
<br>
   public:<br>
     PeepholeProtection() : Inst(0) {}<br>
-  };<br>
+  };<br>
<br>
-  /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.<br>
-  class OpaqueValueMapping {<br>
-    CodeGenFunction &CGF;<br>
+  /// A non-RAII class containing all the information about a bound<br>
+  /// opaque value.  OpaqueValueMapping, below, is a RAII wrapper for<br>
+  /// this which makes individual mappings very simple; using this<br>
+  /// class directly is useful when you have a variable number of<br>
+  /// opaque values or don't want the RAII functionality for some<br>
+  /// reason.<br>
+  class OpaqueValueMappingData {<br>
     const OpaqueValueExpr *OpaqueValue;<br>
     bool BoundLValue;<br>
     CodeGenFunction::PeepholeProtection Protection;<br>
<br>
+    OpaqueValueMappingData(const OpaqueValueExpr *ov,<br>
+                           bool boundLValue)<br>
+      : OpaqueValue(ov), BoundLValue(boundLValue) {}<br>
   public:<br>
+    OpaqueValueMappingData() : OpaqueValue(0) {}<br>
+<br>
     static bool shouldBindAsLValue(const Expr *expr) {<br>
       return expr->isGLValue() || expr->getType()->isRecordType();<br>
     }<br>
<br>
+    static OpaqueValueMappingData bind(CodeGenFunction &CGF,<br>
+                                       const OpaqueValueExpr *ov,<br>
+                                       const Expr *e) {<br>
+      if (shouldBindAsLValue(ov))<br>
+        return bind(CGF, ov, CGF.EmitLValue(e));<br>
+      return bind(CGF, ov, CGF.EmitAnyExpr(e));<br>
+    }<br>
+<br>
+    static OpaqueValueMappingData bind(CodeGenFunction &CGF,<br>
+                                       const OpaqueValueExpr *ov,<br>
+                                       const LValue &lv) {<br>
+      assert(shouldBindAsLValue(ov));<br>
+      CGF.OpaqueLValues.insert(std::make_pair(ov, lv));<br>
+      return OpaqueValueMappingData(ov, true);<br>
+    }<br>
+<br>
+    static OpaqueValueMappingData bind(CodeGenFunction &CGF,<br>
+                                       const OpaqueValueExpr *ov,<br>
+                                       const RValue &rv) {<br>
+      assert(!shouldBindAsLValue(ov));<br>
+      CGF.OpaqueRValues.insert(std::make_pair(ov, rv));<br>
+<br>
+      OpaqueValueMappingData data(ov, false);<br>
+<br>
+      // Work around an extremely aggressive peephole optimization in<br>
+      // EmitScalarConversion which assumes that all other uses of a<br>
+      // value are extant.<br>
+      data.Protection = CGF.protectFromPeepholes(rv);<br>
+<br>
+      return data;<br>
+    }<br>
+<br>
+    bool isValid() const { return OpaqueValue != 0; }<br>
+    void clear() { OpaqueValue = 0; }<br>
+<br>
+    void unbind(CodeGenFunction &CGF) {<br>
+      assert(OpaqueValue && "no data to unbind!");<br>
+<br>
+      if (BoundLValue) {<br>
+        CGF.OpaqueLValues.erase(OpaqueValue);<br>
+      } else {<br>
+        CGF.OpaqueRValues.erase(OpaqueValue);<br>
+        CGF.unprotectFromPeepholes(Protection);<br>
+      }<br>
+    }<br>
+  };<br>
+<br>
+  /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.<br>
+  class OpaqueValueMapping {<br>
+    CodeGenFunction &CGF;<br>
+    OpaqueValueMappingData Data;<br>
+<br>
+  public:<br>
+    static bool shouldBindAsLValue(const Expr *expr) {<br>
+      return OpaqueValueMappingData::shouldBindAsLValue(expr);<br>
+    }<br>
+<br>
     /// Build the opaque value mapping for the given conditional<br>
     /// operator if it's the GNU ?: extension.  This is a common<br>
     /// enough pattern that the convenience operator is really<br>
@@ -971,75 +1037,34 @@<br>
     ///<br>
     OpaqueValueMapping(CodeGenFunction &CGF,<br>
                        const AbstractConditionalOperator *op) : CGF(CGF) {<br>
-      if (isa<ConditionalOperator>(op)) {<br>
-        OpaqueValue = 0;<br>
-        BoundLValue = false;<br>
+      if (isa<ConditionalOperator>(op))<br>
+        // Leave Data empty.<br>
         return;<br>
-      }<br>
<br>
       const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op);<br>
-      init(e->getOpaqueValue(), e->getCommon());<br>
+      Data = OpaqueValueMappingData::bind(CGF, e->getOpaqueValue(),<br>
+                                          e->getCommon());<br>
     }<br>
<br>
     OpaqueValueMapping(CodeGenFunction &CGF,<br>
                        const OpaqueValueExpr *opaqueValue,<br>
                        LValue lvalue)<br>
-      : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(true) {<br>
-      assert(opaqueValue && "no opaque value expression!");<br>
-      assert(shouldBindAsLValue(opaqueValue));<br>
-      initLValue(lvalue);<br>
+      : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, lvalue)) {<br>
     }<br>
<br>
     OpaqueValueMapping(CodeGenFunction &CGF,<br>
                        const OpaqueValueExpr *opaqueValue,<br>
                        RValue rvalue)<br>
-      : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(false) {<br>
-      assert(opaqueValue && "no opaque value expression!");<br>
-      assert(!shouldBindAsLValue(opaqueValue));<br>
-      initRValue(rvalue);<br>
+      : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, rvalue)) {<br>
     }<br>
<br>
     void pop() {<br>
-      assert(OpaqueValue && "mapping already popped!");<br>
-      popImpl();<br>
-      OpaqueValue = 0;<br>
+      Data.unbind(CGF);<br>
+      Data.clear();<br>
     }<br>
<br>
     ~OpaqueValueMapping() {<br>
-      if (OpaqueValue) popImpl();<br>
-    }<br>
-<br>
-  private:<br>
-    void popImpl() {<br>
-      if (BoundLValue)<br>
-        CGF.OpaqueLValues.erase(OpaqueValue);<br>
-      else {<br>
-        CGF.OpaqueRValues.erase(OpaqueValue);<br>
-        CGF.unprotectFromPeepholes(Protection);<br>
-      }<br>
-    }<br>
-<br>
-    void init(const OpaqueValueExpr *ov, const Expr *e) {<br>
-      OpaqueValue = ov;<br>
-      BoundLValue = shouldBindAsLValue(ov);<br>
-      assert(BoundLValue == shouldBindAsLValue(e)<br>
-             && "inconsistent expression value kinds!");<br>
-      if (BoundLValue)<br>
-        initLValue(CGF.EmitLValue(e));<br>
-      else<br>
-        initRValue(CGF.EmitAnyExpr(e));<br>
-    }<br>
-<br>
-    void initLValue(const LValue &lv) {<br>
-      CGF.OpaqueLValues.insert(std::make_pair(OpaqueValue, lv));<br>
-    }<br>
-<br>
-    void initRValue(const RValue &rv) {<br>
-      // Work around an extremely aggressive peephole optimization in<br>
-      // EmitScalarConversion which assumes that all other uses of a<br>
-      // value are extant.<br>
-      Protection = CGF.protectFromPeepholes(rv);<br>
-      CGF.OpaqueRValues.insert(std::make_pair(OpaqueValue, rv));<br>
+      if (Data.isValid()) Data.unbind(CGF);<br>
     }<br>
   };<br>
<br>
@@ -2015,6 +2040,10 @@<br>
   LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);<br>
   LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);<br>
<br>
+  RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,<br>
+                                AggValueSlot slot = AggValueSlot::ignored());<br>
+  LValue EmitPseudoObjectLValue(const PseudoObjectExpr *e);<br>
+<br>
   llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,<br>
                               const ObjCIvarDecl *Ivar);<br>
   LValue EmitLValueForAnonRecordField(llvm::Value* Base,<br>
<br>
Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)<br>
+++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Sun Nov  6 03:01:30 2011<br>
@@ -138,12 +138,6 @@<br>
<br>
     llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;<br>
<br>
-    // This maps a property to it's assignment statement.<br>
-    llvm::DenseMap<Expr *, BinaryOperator *> PropSetters;<br>
-    // This maps a property to it's synthesied message expression.<br>
-    // This allows us to rewrite chained getters (e.g. o.a.b.c).<br>
-    llvm::DenseMap<Expr *, Stmt *> PropGetters;<br>
-<br>
     // This maps an original source AST to it's rewritten form. This allows<br>
     // us to avoid rewriting the same node twice (which is very uncommon).<br>
     // This is needed to support some of the exotic property rewriting.<br>
@@ -154,6 +148,19 @@<br>
     VarDecl *GlobalVarDecl;<br>
<br>
     bool DisableReplaceStmt;<br>
+    class DisableReplaceStmtScope {<br>
+      RewriteObjC &R;<br>
+      bool SavedValue;<br>
+<br>
+    public:<br>
+      DisableReplaceStmtScope(RewriteObjC &R)<br>
+        : R(R), SavedValue(R.DisableReplaceStmt) {<br>
+        R.DisableReplaceStmt = true;<br>
+      }<br>
+      ~DisableReplaceStmtScope() {<br>
+        R.DisableReplaceStmt = SavedValue;<br>
+      }<br>
+    };<br>
<br>
     static const int OBJC_ABI_VERSION = 7;<br>
   public:<br>
@@ -186,7 +193,7 @@<br>
         return; // We can't rewrite the same node twice.<br>
<br>
       if (DisableReplaceStmt)<br>
-        return; // Used when rewriting the assignment of a property setter.<br>
+        return;<br>
<br>
       // If replacement succeeded or warning disabled return with no warning.<br>
       if (!Rewrite.ReplaceStmt(Old, New)) {<br>
@@ -200,6 +207,9 @@<br>
     }<br>
<br>
     void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {<br>
+      if (DisableReplaceStmt)<br>
+        return;<br>
+<br>
       // Measure the old text.<br>
       int Size = Rewrite.getRangeSize(SrcRange);<br>
       if (Size == -1) {<br>
@@ -282,18 +292,14 @@<br>
<br>
     // Expression Rewriting.<br>
     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);<br>
-    void CollectPropertySetters(Stmt *S);<br>
<br>
     Stmt *CurrentBody;<br>
     ParentMap *PropParentMap; // created lazily.<br>
<br>
     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);<br>
-    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,<br>
-                                 bool &replaced);<br>
-    Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);<br>
-    Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr);<br>
-    Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,<br>
-                                SourceRange SrcRange);<br>
+    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);<br>
+    Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);<br>
+    Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);<br>
     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);<br>
     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);<br>
     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);<br>
@@ -1281,184 +1287,173 @@<br>
               "/* @end */");<br>
 }<br>
<br>
-Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,<br>
-                                         SourceRange SrcRange) {<br>
-  ObjCMethodDecl *OMD = 0;<br>
-  QualType Ty;<br>
-  Selector Sel;<br>
-  Stmt *Receiver = 0;<br>
-  bool Super = false;<br>
-  QualType SuperTy;<br>
-  SourceLocation SuperLocation;<br>
-  SourceLocation SelectorLoc;<br>
-  // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ObjCImplicitSetterGetterRefExpr.<br>
-  // This allows us to reuse all the fun and games in SynthMessageExpr().<br>
-  if (ObjCPropertyRefExpr *PropRefExpr =<br>
-        dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) {<br>
-    SelectorLoc = PropRefExpr->getLocation();<br>
-    if (PropRefExpr->isExplicitProperty()) {<br>
-      ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty();<br>
-      OMD = PDecl->getSetterMethodDecl();<br>
-      Ty = PDecl->getType();<br>
-      Sel = PDecl->getSetterName();<br>
-    } else {<br>
-      OMD = PropRefExpr->getImplicitPropertySetter();<br>
-      Sel = OMD->getSelector();<br>
-      Ty = (*OMD->param_begin())->getType();<br>
-    }<br>
-    Super = PropRefExpr->isSuperReceiver();<br>
-    if (!Super) {<br>
-      Receiver = PropRefExpr->getBase();<br>
-    } else {<br>
-      SuperTy = PropRefExpr->getSuperReceiverType();<br>
-      SuperLocation = PropRefExpr->getReceiverLocation();<br>
-    }<br>
-  }<br>
-<br>
-  assert(OMD && "RewritePropertyOrImplicitSetter - null OMD");<br>
+Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {<br>
+  SourceRange OldRange = PseudoOp->getSourceRange();<br>
<br>
-  ObjCMessageExpr *MsgExpr;<br>
-  if (Super)<br>
-    MsgExpr = ObjCMessageExpr::Create(*Context,<br>
-                                      Ty.getNonReferenceType(),<br>
-                                      Expr::getValueKindForType(Ty),<br>
-                                      /*FIXME?*/SourceLocation(),<br>
-                                      SuperLocation,<br>
-                                      /*IsInstanceSuper=*/true,<br>
-                                      SuperTy,<br>
-                                      Sel, SelectorLoc, OMD,<br>
-                                      newStmt,<br>
-                                      /*FIXME:*/SourceLocation());<br>
-  else {<br>
-    // FIXME. Refactor this into common code with that in<br>
-    // RewritePropertyOrImplicitGetter<br>
-    assert(Receiver && "RewritePropertyOrImplicitSetter - null Receiver");<br>
-    if (Expr *Exp = dyn_cast<Expr>(Receiver))<br>
-      if (PropGetters[Exp])<br>
-        // This allows us to handle chain/nested property/implicit getters.<br>
-        Receiver = PropGetters[Exp];<br>
-<br>
-    MsgExpr = ObjCMessageExpr::Create(*Context,<br>
-                                      Ty.getNonReferenceType(),<br>
-                                      Expr::getValueKindForType(Ty),<br>
-                                      /*FIXME: */SourceLocation(),<br>
-                                      cast<Expr>(Receiver),<br>
-                                      Sel, SelectorLoc, OMD,<br>
-                                      newStmt,<br>
-                                      /*FIXME:*/SourceLocation());<br>
+  // We just magically know some things about the structure of this<br>
+  // expression.<br>
+  ObjCMessageExpr *OldMsg =<br>
+    cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(<br>
+                            PseudoOp->getNumSemanticExprs() - 1));<br>
+<br>
+  // Because the rewriter doesn't allow us to rewrite rewritten code,<br>
+  // we need to suppress rewriting the sub-statements.<br>
+  Expr *Base, *RHS;<br>
+  {<br>
+    DisableReplaceStmtScope S(*this);<br>
+<br>
+    // Rebuild the base expression if we have one.<br>
+    Base = 0;<br>
+    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {<br>
+      Base = OldMsg->getInstanceReceiver();<br>
+      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();<br>
+      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));<br>
+    }<br>
+<br>
+    // Rebuild the RHS.<br>
+    RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();<br>
+    RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();<br>
+    RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));<br>
+  }<br>
+<br>
+  // TODO: avoid this copy.<br>
+  SmallVector<SourceLocation, 1> SelLocs;<br>
+  OldMsg->getSelectorLocs(SelLocs);<br>
+<br>
+  ObjCMessageExpr *NewMsg;<br>
+  switch (OldMsg->getReceiverKind()) {<br>
+  case ObjCMessageExpr::Class:<br>
+    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),<br>
+                                     OldMsg->getValueKind(),<br>
+                                     OldMsg->getLeftLoc(),<br>
+                                     OldMsg->getClassReceiverTypeInfo(),<br>
+                                     OldMsg->getSelector(),<br>
+                                     SelLocs,<br>
+                                     OldMsg->getMethodDecl(),<br>
+                                     RHS,<br>
+                                     OldMsg->getRightLoc());<br>
+    break;<br>
+<br>
+  case ObjCMessageExpr::Instance:<br>
+    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),<br>
+                                     OldMsg->getValueKind(),<br>
+                                     OldMsg->getLeftLoc(),<br>
+                                     Base,<br>
+                                     OldMsg->getSelector(),<br>
+                                     SelLocs,<br>
+                                     OldMsg->getMethodDecl(),<br>
+                                     RHS,<br>
+                                     OldMsg->getRightLoc());<br>
+    break;<br>
+<br>
+  case ObjCMessageExpr::SuperClass:<br>
+  case ObjCMessageExpr::SuperInstance:<br>
+    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),<br>
+                                     OldMsg->getValueKind(),<br>
+                                     OldMsg->getLeftLoc(),<br>
+                                     OldMsg->getSuperLoc(),<br>
+                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,<br>
+                                     OldMsg->getSuperType(),<br>
+                                     OldMsg->getSelector(),<br>
+                                     SelLocs,<br>
+                                     OldMsg->getMethodDecl(),<br>
+                                     RHS,<br>
+                                     OldMsg->getRightLoc());<br>
+    break;<br>
   }<br>
-  Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);<br>
<br>
-  // Now do the actual rewrite.<br>
-  ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);<br>
-  //delete BinOp;<br>
-  // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references<br>
-  // to things that stay around.<br>
-  Context->Deallocate(MsgExpr);<br>
-  return ReplacingStmt;<br>
+  Stmt *Replacement = SynthMessageExpr(NewMsg);<br>
+  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);<br>
+  return Replacement;<br>
 }<br>
<br>
-Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {<br>
-  // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ImplicitGetter.<br>
-  // This allows us to reuse all the fun and games in SynthMessageExpr().<br>
-  Stmt *Receiver = 0;<br>
-  ObjCMethodDecl *OMD = 0;<br>
-  QualType Ty;<br>
-  Selector Sel;<br>
-  bool Super = false;<br>
-  QualType SuperTy;<br>
-  SourceLocation SuperLocation;<br>
-  SourceLocation SelectorLoc;<br>
-  if (ObjCPropertyRefExpr *PropRefExpr =<br>
-        dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) {<br>
-    SelectorLoc = PropRefExpr->getLocation();<br>
-    if (PropRefExpr->isExplicitProperty()) {<br>
-      ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty();<br>
-      OMD = PDecl->getGetterMethodDecl();<br>
-      Ty = PDecl->getType();<br>
-      Sel = PDecl->getGetterName();<br>
-    } else {<br>
-      OMD = PropRefExpr->getImplicitPropertyGetter();<br>
-      Sel = OMD->getSelector();<br>
-      Ty = OMD->getResultType();<br>
-    }<br>
-    Super = PropRefExpr->isSuperReceiver();<br>
-    if (!Super)<br>
-      Receiver = PropRefExpr->getBase();<br>
-    else {<br>
-      SuperTy = PropRefExpr->getSuperReceiverType();<br>
-      SuperLocation = PropRefExpr->getReceiverLocation();<br>
+Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {<br>
+  SourceRange OldRange = PseudoOp->getSourceRange();<br>
+<br>
+  // We just magically know some things about the structure of this<br>
+  // expression.<br>
+  ObjCMessageExpr *OldMsg =<br>
+    cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());<br>
+<br>
+  // Because the rewriter doesn't allow us to rewrite rewritten code,<br>
+  // we need to suppress rewriting the sub-statements.<br>
+  Expr *Base = 0;<br>
+  {<br>
+    DisableReplaceStmtScope S(*this);<br>
+<br>
+    // Rebuild the base expression if we have one.<br>
+    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {<br>
+      Base = OldMsg->getInstanceReceiver();<br>
+      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();<br>
+      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));<br>
     }<br>
   }<br>
-<br>
-  assert (OMD && "RewritePropertyOrImplicitGetter - OMD is null");<br>
-<br>
-  ObjCMessageExpr *MsgExpr;<br>
-  if (Super)<br>
-    MsgExpr = ObjCMessageExpr::Create(*Context,<br>
-                                      Ty.getNonReferenceType(),<br>
-                                      Expr::getValueKindForType(Ty),<br>
-                                      PropOrGetterRefExpr->getLocStart(),<br>
-                                      SuperLocation,<br>
-                                      /*IsInstanceSuper=*/true,<br>
-                                      SuperTy,<br>
-                                      Sel, SelectorLoc, OMD,<br>
-                                      ArrayRef<Expr*>(),<br>
-                                      PropOrGetterRefExpr->getLocEnd());<br>
-  else {<br>
-    assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null");<br>
-    if (Expr *Exp = dyn_cast<Expr>(Receiver))<br>
-      if (PropGetters[Exp])<br>
-        // This allows us to handle chain/nested property/implicit getters.<br>
-        Receiver = PropGetters[Exp];<br>
-    MsgExpr = ObjCMessageExpr::Create(*Context,<br>
-                                      Ty.getNonReferenceType(),<br>
-                                      Expr::getValueKindForType(Ty),<br>
-                                      PropOrGetterRefExpr->getLocStart(),<br>
-                                      cast<Expr>(Receiver),<br>
-                                      Sel, SelectorLoc, OMD,<br>
-                                      ArrayRef<Expr*>(),<br>
-                                      PropOrGetterRefExpr->getLocEnd());<br>
-  }<br>
-<br>
-  Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(),<br>
-                                         MsgExpr->getLocEnd());<br>
-<br>
-  if (!PropParentMap)<br>
-    PropParentMap = new ParentMap(CurrentBody);<br>
-  bool NestedPropertyRef = false;<br>
-  Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr);<br>
-  ImplicitCastExpr*ICE=0;<br>
-  if (Parent)<br>
-    if ((ICE = dyn_cast<ImplicitCastExpr>(Parent))) {<br>
-      assert((ICE->getCastKind() == CK_GetObjCProperty)<br>
-             && "RewritePropertyOrImplicitGetter");<br>
-      Parent = PropParentMap->getParent(Parent);<br>
-      NestedPropertyRef = (Parent && isa<ObjCPropertyRefExpr>(Parent));<br>
-    }<br>
-  if (NestedPropertyRef) {<br>
-    // We stash away the ReplacingStmt since actually doing the<br>
-    // replacement/rewrite won't work for nested getters (e.g. obj.p.i)<br>
-    PropGetters[ICE] = ReplacingStmt;<br>
-    // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references<br>
-    // to things that stay around.<br>
-    Context->Deallocate(MsgExpr);<br>
-    return PropOrGetterRefExpr; // return the original...<br>
-  } else {<br>
-    ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt);<br>
-    // delete PropRefExpr; elsewhere...<br>
-    // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references<br>
-    // to things that stay around.<br>
-    Context->Deallocate(MsgExpr);<br>
-    return ReplacingStmt;<br>
+<br>
+  // Intentionally empty.<br>
+  SmallVector<SourceLocation, 1> SelLocs;<br>
+  SmallVector<Expr*, 1> Args;<br>
+<br>
+  ObjCMessageExpr *NewMsg;<br>
+  switch (OldMsg->getReceiverKind()) {<br>
+  case ObjCMessageExpr::Class:<br>
+    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),<br>
+                                     OldMsg->getValueKind(),<br>
+                                     OldMsg->getLeftLoc(),<br>
+                                     OldMsg->getClassReceiverTypeInfo(),<br>
+                                     OldMsg->getSelector(),<br>
+                                     SelLocs,<br>
+                                     OldMsg->getMethodDecl(),<br>
+                                     Args,<br>
+                                     OldMsg->getRightLoc());<br>
+    break;<br>
+<br>
+  case ObjCMessageExpr::Instance:<br>
+    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),<br>
+                                     OldMsg->getValueKind(),<br>
+                                     OldMsg->getLeftLoc(),<br>
+                                     Base,<br>
+                                     OldMsg->getSelector(),<br>
+                                     SelLocs,<br>
+                                     OldMsg->getMethodDecl(),<br>
+                                     Args,<br>
+                                     OldMsg->getRightLoc());<br>
+    break;<br>
+<br>
+  case ObjCMessageExpr::SuperClass:<br>
+  case ObjCMessageExpr::SuperInstance:<br>
+    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),<br>
+                                     OldMsg->getValueKind(),<br>
+                                     OldMsg->getLeftLoc(),<br>
+                                     OldMsg->getSuperLoc(),<br>
+                 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,<br>
+                                     OldMsg->getSuperType(),<br>
+                                     OldMsg->getSelector(),<br>
+                                     SelLocs,<br>
+                                     OldMsg->getMethodDecl(),<br>
+                                     Args,<br>
+                                     OldMsg->getRightLoc());<br>
+    break;<br>
   }<br>
+<br>
+  Stmt *Replacement = SynthMessageExpr(NewMsg);<br>
+  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);<br>
+  return Replacement;<br>
 }<br>
<br>
-Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,<br>
-                                          SourceLocation OrigStart,<br>
-                                          bool &replaced) {<br>
+Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {<br>
+  SourceRange OldRange = IV->getSourceRange();<br>
+  Expr *BaseExpr = IV->getBase();<br>
+<br>
+  // Rewrite the base, but without actually doing replaces.<br>
+  {<br>
+    DisableReplaceStmtScope S(*this);<br>
+    BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));<br>
+    IV->setBase(BaseExpr);<br>
+  }<br>
+<br>
   ObjCIvarDecl *D = IV->getDecl();<br>
-  const Expr *BaseExpr = IV->getBase();<br>
+<br>
+  Expr *Replacement = IV;<br>
   if (CurMethodDef) {<br>
     if (BaseExpr->getType()->isObjCObjectPointerType()) {<br>
       const ObjCInterfaceType *iFaceDecl =<br>
@@ -1483,25 +1478,19 @@<br>
                                                     CK_BitCast,<br>
                                                     IV->getBase());<br>
       // Don't forget the parens to enforce the proper binding.<br>
-      ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),<br>
-                                              IV->getBase()->getLocEnd(),<br>
+      ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),<br>
+                                              OldRange.getEnd(),<br>
                                               castExpr);<br>
-      replaced = true;<br>
       if (IV->isFreeIvar() &&<br>
           CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {<br>
         MemberExpr *ME = new (Context) MemberExpr(PE, true, D,<br>
                                                   IV->getLocation(),<br>
                                                   D->getType(),<br>
                                                   VK_LValue, OK_Ordinary);<br>
-        // delete IV; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.<br>
-        return ME;<br>
+        Replacement = ME;<br>
+      } else {<br>
+        IV->setBase(PE);<br>
       }<br>
-      // Get the new text<br>
-      // Cannot delete IV->getBase(), since PE points to it.<br>
-      // Replace the old base with the cast. This is important when doing<br>
-      // embedded rewrites. For example, [newInv->_container addObject:0].<br>
-      IV->setBase(PE);<br>
-      return IV;<br>
     }<br>
   } else { // we are outside a method.<br>
     assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");<br>
@@ -1532,36 +1521,15 @@<br>
       // Don't forget the parens to enforce the proper binding.<br>
       ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),<br>
                                     IV->getBase()->getLocEnd(), castExpr);<br>
-      replaced = true;<br>
       // Cannot delete IV->getBase(), since PE points to it.<br>
       // Replace the old base with the cast. This is important when doing<br>
       // embedded rewrites. For example, [newInv->_container addObject:0].<br>
       IV->setBase(PE);<br>
-      return IV;<br>
     }<br>
   }<br>
-  return IV;<br>
-}<br>
<br>
-Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {<br>
-  for (Stmt::child_range CI = S->children(); CI; ++CI) {<br>
-    if (*CI) {<br>
-      Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);<br>
-      if (newStmt)<br>
-        *CI = newStmt;<br>
-    }<br>
-  }<br>
-  if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {<br>
-    SourceRange OrigStmtRange = S->getSourceRange();<br>
-    Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(),<br>
-                                           replaced);<br>
-    return newStmt;<br>
-  }<br>
-  if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) {<br>
-    Stmt *newStmt = SynthMessageExpr(MsgRefExpr);<br>
-    return newStmt;<br>
-  }<br>
-  return S;<br>
+  ReplaceStmtWithRange(IV, Replacement, OldRange);<br>
+  return Replacement;<br>
 }<br>
<br>
 /// SynthCountByEnumWithState - To print:<br>
@@ -4753,6 +4721,9 @@<br>
     return CondExpr;<br>
   } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {<br>
     CPT = IRE->getType()->getAs<BlockPointerType>();<br>
+  } else if (const PseudoObjectExpr *POE<br>
+               = dyn_cast<PseudoObjectExpr>(BlockExp)) {<br>
+    CPT = POE->getType()->castAs<BlockPointerType>();<br>
   } else {<br>
     assert(1 && "RewriteBlockClass: Bad type");<br>
   }<br>
@@ -5580,26 +5551,6 @@<br>
 // Function Body / Expression rewriting<br>
 //===----------------------------------------------------------------------===//<br>
<br>
-// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer().<br>
-// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with<br>
-// their respective BinaryOperator. Without this knowledge, we'd need to rewrite<br>
-// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter).<br>
-// Since the rewriter isn't capable of rewriting rewritten code, it's important<br>
-// we get this right.<br>
-void RewriteObjC::CollectPropertySetters(Stmt *S) {<br>
-  // Perform a bottom up traversal of all children.<br>
-  for (Stmt::child_range CI = S->children(); CI; ++CI)<br>
-    if (*CI)<br>
-      CollectPropertySetters(*CI);<br>
-<br>
-  if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {<br>
-    if (BinOp->isAssignmentOp()) {<br>
-      if (isa<ObjCPropertyRefExpr>(BinOp->getLHS()))<br>
-        PropSetters[BinOp->getLHS()] = BinOp;<br>
-    }<br>
-  }<br>
-}<br>
-<br>
 Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {<br>
   if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||<br>
       isa<DoStmt>(S) || isa<ForStmt>(S))<br>
@@ -5609,46 +5560,28 @@<br>
     ObjCBcLabelNo.push_back(++BcLabelCount);<br>
   }<br>
<br>
+  // Pseudo-object operations and ivar references need special<br>
+  // treatment because we're going to recursively rewrite them.<br>
+  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {<br>
+    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {<br>
+      return RewritePropertyOrImplicitSetter(PseudoOp);<br>
+    } else {<br>
+      return RewritePropertyOrImplicitGetter(PseudoOp);<br>
+    }<br>
+  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {<br>
+    return RewriteObjCIvarRefExpr(IvarRefExpr);<br>
+  }<br>
+<br>
   SourceRange OrigStmtRange = S->getSourceRange();<br>
<br>
   // Perform a bottom up rewrite of all children.<br>
   for (Stmt::child_range CI = S->children(); CI; ++CI)<br>
     if (*CI) {<br>
-      Stmt *newStmt;<br>
-      Stmt *ChildStmt = (*CI);<br>
-      if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(ChildStmt)) {<br>
-        Expr *OldBase = IvarRefExpr->getBase();<br>
-        bool replaced = false;<br>
-        newStmt = RewriteObjCNestedIvarRefExpr(ChildStmt, replaced);<br>
-        if (replaced) {<br>
-          if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt))<br>
-            ReplaceStmt(OldBase, IRE->getBase());<br>
-          else<br>
-            ReplaceStmt(ChildStmt, newStmt);<br>
-        }<br>
-      }<br>
-      else<br>
-        newStmt = RewriteFunctionBodyOrGlobalInitializer(ChildStmt);<br>
+      Stmt *childStmt = (*CI);<br>
+      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);<br>
       if (newStmt) {<br>
-          if (Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(ChildStmt))<br>
-            if (PropSetters[PropOrImplicitRefExpr] == S) {<br>
-              S = newStmt;<br>
-              newStmt = 0;<br>
-            }<br>
-        if (newStmt)<br>
-          *CI = newStmt;<br>
-      }<br>
-      // If dealing with an assignment with LHS being a property reference<br>
-      // expression, the entire assignment tree is rewritten into a property<br>
-      // setter messaging. This involvs the RHS too. Do not attempt to rewrite<br>
-      // RHS again.<br>
-      if (Expr *Exp = dyn_cast<Expr>(ChildStmt))<br>
-        if (isa<ObjCPropertyRefExpr>(Exp)) {<br>
-          if (PropSetters[Exp]) {<br>
-            ++CI;<br>
-            continue;<br>
-          }<br>
-        }<br>
+        *CI = newStmt;<br>
+      }<br>
     }<br>
<br>
   if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {<br>
@@ -5661,7 +5594,6 @@<br>
     // Rewrite the block body in place.<br>
     Stmt *SaveCurrentBody = CurrentBody;<br>
     CurrentBody = BE->getBody();<br>
-    CollectPropertySetters(CurrentBody);<br>
     PropParentMap = 0;<br>
     // block literal on rhs of a property-dot-sytax assignment<br>
     // must be replaced by its synthesize ast so getRewrittenText<br>
@@ -5689,67 +5621,6 @@<br>
   if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))<br>
     return RewriteAtEncode(AtEncode);<br>
<br>
-  if (isa<ObjCPropertyRefExpr>(S)) {<br>
-    Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S);<br>
-    assert(PropOrImplicitRefExpr && "Property or implicit setter/getter is null");<br>
-<br>
-    BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr];<br>
-    if (BinOp) {<br>
-      // Because the rewriter doesn't allow us to rewrite rewritten code,<br>
-      // we need to rewrite the right hand side prior to rewriting the setter.<br>
-      DisableReplaceStmt = true;<br>
-      // Save the source range. Even if we disable the replacement, the<br>
-      // rewritten node will have been inserted into the tree. If the synthesized<br>
-      // node is at the 'end', the rewriter will fail. Consider this:<br>
-      //    self.errorHandler = handler ? handler :<br>
-      //              ^(NSURL *errorURL, NSError *error) { return (BOOL)1; };<br>
-      SourceRange SrcRange = BinOp->getSourceRange();<br>
-      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());<br>
-      // Need to rewrite the ivar access expression if need be.<br>
-      if (isa<ObjCIvarRefExpr>(newStmt)) {<br>
-        bool replaced = false;<br>
-        newStmt = RewriteObjCNestedIvarRefExpr(newStmt, replaced);<br>
-      }<br>
-<br>
-      DisableReplaceStmt = false;<br>
-      //<br>
-      // Unlike the main iterator, we explicily avoid changing 'BinOp'. If<br>
-      // we changed the RHS of BinOp, the rewriter would fail (since it needs<br>
-      // to see the original expression). Consider this example:<br>
-      //<br>
-      // Foo *obj1, *obj2;<br>
-      //<br>
-      // obj1.i = [obj2 rrrr];<br>
-      //<br>
-      // 'BinOp' for the previous expression looks like:<br>
-      //<br>
-      // (BinaryOperator 0x231ccf0 'int' '='<br>
-      //   (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i"<br>
-      //     (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0))<br>
-      //   (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr<br>
-      //     (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0)))<br>
-      //<br>
-      // 'newStmt' represents the rewritten message expression. For example:<br>
-      //<br>
-      // (CallExpr 0x231d300 'id':'struct objc_object *'<br>
-      //   (ParenExpr 0x231d2e0 'int (*)(id, SEL)'<br>
-      //     (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)'<br>
-      //       (CStyleCastExpr 0x231d220 'void *'<br>
-      //         (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0))))<br>
-      //<br>
-      // Note that 'newStmt' is passed to RewritePropertyOrImplicitSetter so that it<br>
-      // can be used as the setter argument. ReplaceStmt() will still 'see'<br>
-      // the original RHS (since we haven't altered BinOp).<br>
-      //<br>
-      // This implies the Rewrite* routines can no longer delete the original<br>
-      // node. As a result, we now leak the original AST nodes.<br>
-      //<br>
-      return RewritePropertyOrImplicitSetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);<br>
-    } else {<br>
-      return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr);<br>
-    }<br>
-  }<br>
-<br>
   if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))<br>
     return RewriteAtSelector(AtSelector);<br>
<br>
@@ -5930,7 +5801,6 @@<br>
     if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {<br>
       CurFunctionDef = FD;<br>
       CurFunctionDeclToDeclareForBlock = FD;<br>
-      CollectPropertySetters(Body);<br>
       CurrentBody = Body;<br>
       Body =<br>
        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));<br>
@@ -5951,7 +5821,6 @@<br>
   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {<br>
     if (CompoundStmt *Body = MD->getCompoundBody()) {<br>
       CurMethodDef = MD;<br>
-      CollectPropertySetters(Body);<br>
       CurrentBody = Body;<br>
       Body =<br>
        cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));<br>
@@ -5989,7 +5858,6 @@<br>
     }<br>
     if (VD->getInit()) {<br>
       GlobalVarDecl = VD;<br>
-      CollectPropertySetters(VD->getInit());<br>
       CurrentBody = VD->getInit();<br>
       RewriteFunctionBodyOrGlobalInitializer(VD->getInit());<br>
       CurrentBody = 0;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Sun Nov  6 03:01:30 2011<br>
@@ -4213,6 +4213,26 @@<br>
       continue;<br>
     }<br>
<br>
+    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {<br>
+      // Only pay attention to pseudo-objects on property references.<br>
+      ObjCPropertyRefExpr *pre<br>
+        = dyn_cast<ObjCPropertyRefExpr>(pseudo->getSyntacticForm()<br>
+                                              ->IgnoreParens());<br>
+      if (!pre) return false;<br>
+      if (pre->isImplicitProperty()) return false;<br>
+      ObjCPropertyDecl *property = pre->getExplicitProperty();<br>
+      if (!property->isRetaining() &&<br>
+          !(property->getPropertyIvarDecl() &&<br>
+            property->getPropertyIvarDecl()->getType()<br>
+              .getObjCLifetime() == Qualifiers::OCL_Strong))<br>
+          return false;<br>
+<br>
+      owner.Indirect = true;<br>
+      e = const_cast<Expr*>(cast<OpaqueValueExpr>(pre->getBase())<br>
+                              ->getSourceExpr());<br>
+      continue;<br>
+    }<br>
+<br>
     // Array ivars?<br>
<br>
     return false;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Nov  6 03:01:30 2011<br>
@@ -7468,7 +7468,7 @@<br>
     // The operand must be either an l-value or a function designator<br>
     if (!op->getType()->isFunctionType()) {<br>
       // Use a special diagnostic for loads from property references.<br>
-      if (isa<ObjCPropertyRefExpr>(op->IgnoreImplicit()->IgnoreParens())) {<br>
+      if (isa<PseudoObjectExpr>(op)) {<br>
         AddressOfError = AO_Property_Expansion;<br>
       } else {<br>
         // FIXME: emit more specific diag...<br>
@@ -7483,9 +7483,6 @@<br>
   } else if (op->getObjectKind() == OK_VectorComponent) {<br>
     // The operand cannot be an element of a vector<br>
     AddressOfError = AO_Vector_Element;<br>
-  } else if (op->getObjectKind() == OK_ObjCProperty) {<br>
-    // cannot take address of a property expression.<br>
-    AddressOfError = AO_Property_Expansion;<br>
   } else if (dcl) { // C99 6.5.3.2p1<br>
     // We have an lvalue with a decl. Make sure the decl is not declared<br>
     // with the register storage-class specifier.<br>
@@ -8951,8 +8948,15 @@<br>
       return;<br>
   }<br>
<br>
-  // Strip off any parens and casts.<br>
-  StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts());<br>
+  // Ignore any parens, implicit casts (should only be<br>
+  // array-to-pointer decays), and not-so-opaque values.  The last is<br>
+  // important for making this trigger for property assignments.<br>
+  SrcExpr = SrcExpr->IgnoreParenImpCasts();<br>
+  if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))<br>
+    if (OV->getSourceExpr())<br>
+      SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();<br>
+<br>
+  StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);<br>
   if (!SL || !SL->isAscii())<br>
     return;<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sun Nov  6 03:01:30 2011<br>
@@ -467,14 +467,13 @@<br>
<br>
 bool Sema::isSelfExpr(Expr *receiver) {<br>
   // 'self' is objc 'self' in an objc method only.<br>
-  DeclContext *DC = CurContext;<br>
-  while (isa<BlockDecl>(DC))<br>
-    DC = DC->getParent();<br>
-  if (DC && !isa<ObjCMethodDecl>(DC))<br>
-    return false;<br>
+  ObjCMethodDecl *method =<br>
+    dyn_cast<ObjCMethodDecl>(CurContext->getNonClosureAncestor());<br>
+  if (!method) return false;<br>
+<br>
   receiver = receiver->IgnoreParenLValueCasts();<br>
   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))<br>
-    if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))<br>
+    if (DRE->getDecl() == method->getSelfDecl())<br>
       return true;<br>
   return false;<br>
 }<br>
@@ -1725,6 +1724,12 @@<br>
       return merge(left, Visit(e->getFalseExpr()));<br>
     }<br>
<br>
+    /// Look through pseudo-objects.<br>
+    ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {<br>
+      // If we're getting here, we should always have a result.<br>
+      return Visit(e->getResultExpr());<br>
+    }<br>
+<br>
     /// Statement expressions are okay if their result expression is okay.<br>
     ACCResult VisitStmtExpr(StmtExpr *e) {<br>
       return Visit(e->getSubStmt()->body_back());<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Sun Nov  6 03:01:30 2011<br>
@@ -38,11 +38,364 @@<br>
 using namespace clang;<br>
 using namespace sema;<br>
<br>
+namespace {<br>
+  // Basically just a very focused copy of TreeTransform.<br>
+  template <class T> struct Rebuilder {<br>
+    Sema &S;<br>
+    Rebuilder(Sema &S) : S(S) {}<br>
+<br>
+    T &getDerived() { return static_cast<T&>(*this); }<br>
+<br>
+    Expr *rebuild(Expr *e) {<br>
+      // Fast path: nothing to look through.<br>
+      if (typename T::specific_type *specific<br>
+            = dyn_cast<typename T::specific_type>(e))<br>
+        return getDerived().rebuildSpecific(specific);<br>
+<br>
+      // Otherwise, we should look through and rebuild anything that<br>
+      // IgnoreParens would.<br>
+<br>
+      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {<br>
+        e = rebuild(parens->getSubExpr());<br>
+        return new (S.Context) ParenExpr(parens->getLParen(),<br>
+                                         parens->getRParen(),<br>
+                                         e);<br>
+      }<br>
+<br>
+      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {<br>
+        assert(uop->getOpcode() == UO_Extension);<br>
+        e = rebuild(uop->getSubExpr());<br>
+        return new (S.Context) UnaryOperator(e, uop->getOpcode(),<br>
+                                             uop->getType(),<br>
+                                             uop->getValueKind(),<br>
+                                             uop->getObjectKind(),<br>
+                                             uop->getOperatorLoc());<br>
+      }<br>
+<br>
+      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {<br>
+        assert(!gse->isResultDependent());<br>
+        unsigned resultIndex = gse->getResultIndex();<br>
+        unsigned numAssocs = gse->getNumAssocs();<br>
+<br>
+        SmallVector<Expr*, 8> assocs(numAssocs);<br>
+        SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);<br>
+<br>
+        for (unsigned i = 0; i != numAssocs; ++i) {<br>
+          Expr *assoc = gse->getAssocExpr(i);<br>
+          if (i == resultIndex) assoc = rebuild(assoc);<br>
+          assocs[i] = assoc;<br>
+          assocTypes[i] = gse->getAssocTypeSourceInfo(i);<br>
+        }<br>
+<br>
+        return new (S.Context) GenericSelectionExpr(S.Context,<br>
+                                                    gse->getGenericLoc(),<br>
+                                                    gse->getControllingExpr(),<br>
+                                                    assocTypes.data(),<br>
+                                                    assocs.data(),<br>
+                                                    numAssocs,<br>
+                                                    gse->getDefaultLoc(),<br>
+                                                    gse->getRParenLoc(),<br>
+                                      gse->containsUnexpandedParameterPack(),<br>
+                                                    resultIndex);<br>
+      }<br>
+<br>
+      llvm_unreachable("bad expression to rebuild!");<br>
+    }<br>
+  };<br>
+<br>
+  struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {<br>
+    Expr *NewBase;<br>
+    ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)<br>
+      : Rebuilder(S), NewBase(newBase) {}<br>
+<br>
+    typedef ObjCPropertyRefExpr specific_type;<br>
+    Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {<br>
+      // Fortunately, the constraint that we're rebuilding something<br>
+      // with a base limits the number of cases here.<br>
+      assert(refExpr->getBase());<br>
+<br>
+      if (refExpr->isExplicitProperty()) {<br>
+        return new (S.Context)<br>
+          ObjCPropertyRefExpr(refExpr->getExplicitProperty(),<br>
+                              refExpr->getType(), refExpr->getValueKind(),<br>
+                              refExpr->getObjectKind(), refExpr->getLocation(),<br>
+                              NewBase);<br>
+      }<br>
+      return new (S.Context)<br>
+        ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),<br>
+                            refExpr->getImplicitPropertySetter(),<br>
+                            refExpr->getType(), refExpr->getValueKind(),<br>
+                            refExpr->getObjectKind(),refExpr->getLocation(),<br>
+                            NewBase);<br>
+    }<br>
+  };<br>
+<br>
+  class PseudoOpBuilder {<br>
+  public:<br>
+    Sema &S;<br>
+    unsigned ResultIndex;<br>
+    SourceLocation GenericLoc;<br>
+    SmallVector<Expr *, 4> Semantics;<br>
+<br>
+    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)<br>
+      : S(S), ResultIndex(PseudoObjectExpr::NoResult),<br>
+        GenericLoc(genericLoc) {}<br>
+<br>
+    /// Add a normal semantic expression.<br>
+    void addSemanticExpr(Expr *semantic) {<br>
+      Semantics.push_back(semantic);<br>
+    }<br>
+<br>
+    /// Add the 'result' semantic expression.<br>
+    void addResultSemanticExpr(Expr *resultExpr) {<br>
+      assert(ResultIndex == PseudoObjectExpr::NoResult);<br>
+      ResultIndex = Semantics.size();<br>
+      Semantics.push_back(resultExpr);<br>
+    }<br>
+<br>
+    ExprResult buildRValueOperation(Expr *op);<br>
+    ExprResult buildAssignmentOperation(Scope *Sc,<br>
+                                        SourceLocation opLoc,<br>
+                                        BinaryOperatorKind opcode,<br>
+                                        Expr *LHS, Expr *RHS);<br>
+    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,<br>
+                                    UnaryOperatorKind opcode,<br>
+                                    Expr *op);<br>
+<br>
+    ExprResult complete(Expr *syntacticForm);<br>
+<br>
+    OpaqueValueExpr *capture(Expr *op);<br>
+    OpaqueValueExpr *captureValueAsResult(Expr *op);<br>
+<br>
+    void setResultToLastSemantic() {<br>
+      assert(ResultIndex == PseudoObjectExpr::NoResult);<br>
+      ResultIndex = Semantics.size() - 1;<br>
+    }<br>
+<br>
+    /// Return true if assignments have a non-void result.<br>
+    virtual bool assignmentsHaveResult() { return true; }<br>
+<br>
+    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;<br>
+    virtual ExprResult buildGet() = 0;<br>
+    virtual ExprResult buildSet(Expr *, SourceLocation,<br>
+                                bool captureSetValueAsResult) = 0;<br>
+  };<br>
+<br>
+  /// A PseudoOpBuilder for Objective-C @properties.<br>
+  class ObjCPropertyOpBuilder : public PseudoOpBuilder {<br>
+    ObjCPropertyRefExpr *RefExpr;<br>
+    OpaqueValueExpr *InstanceReceiver;<br>
+    ObjCMethodDecl *Getter;<br>
+<br>
+    ObjCMethodDecl *Setter;<br>
+    Selector SetterSelector;<br>
+<br>
+  public:<br>
+    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :<br>
+      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),<br>
+      InstanceReceiver(0), Getter(0), Setter(0) {<br>
+    }<br>
+<br>
+    ExprResult buildRValueOperation(Expr *op);<br>
+    ExprResult buildAssignmentOperation(Scope *Sc,<br>
+                                        SourceLocation opLoc,<br>
+                                        BinaryOperatorKind opcode,<br>
+                                        Expr *LHS, Expr *RHS);<br>
+    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,<br>
+                                    UnaryOperatorKind opcode,<br>
+                                    Expr *op);<br>
+<br>
+    bool tryBuildGetOfReference(Expr *op, ExprResult &result);<br>
+    bool findSetter();<br>
+    bool findGetter();<br>
+<br>
+    Expr *rebuildAndCaptureObject(Expr *syntacticBase);<br>
+    ExprResult buildGet();<br>
+    ExprResult buildSet(Expr *op, SourceLocation, bool);<br>
+  };<br>
+}<br>
+<br>
+/// Capture the given expression in an OpaqueValueExpr.<br>
+OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {<br>
+  // Make a new OVE whose source is the given expression.<br>
+  OpaqueValueExpr *captured =<br>
+    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),<br>
+                                    e->getValueKind());<br>
+  captured->setSourceExpr(e);<br>
+<br>
+  // Make sure we bind that in the semantics.<br>
+  addSemanticExpr(captured);<br>
+  return captured;<br>
+}<br>
+<br>
+/// Capture the given expression as the result of this pseudo-object<br>
+/// operation.  This routine is safe against expressions which may<br>
+/// already be captured.<br>
+///<br>
+/// \param Returns the captured expression, which will be the<br>
+///   same as the input if the input was already captured<br>
+OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {<br>
+  assert(ResultIndex == PseudoObjectExpr::NoResult);<br>
+<br>
+  // If the expression hasn't already been captured, just capture it<br>
+  // and set the new semantic<br>
+  if (!isa<OpaqueValueExpr>(e)) {<br>
+    OpaqueValueExpr *cap = capture(e);<br>
+    setResultToLastSemantic();<br>
+    return cap;<br>
+  }<br>
+<br>
+  // Otherwise, it must already be one of our semantic expressions;<br>
+  // set ResultIndex to its index.<br>
+  unsigned index = 0;<br>
+  for (;; ++index) {<br>
+    assert(index < Semantics.size() &&<br>
+           "captured expression not found in semantics!");<br>
+    if (e == Semantics[index]) break;<br>
+  }<br>
+  ResultIndex = index;<br>
+  return cast<OpaqueValueExpr>(e);<br>
+}<br>
+<br>
+/// The routine which creates the final PseudoObjectExpr.<br>
+ExprResult PseudoOpBuilder::complete(Expr *syntactic) {<br>
+  return PseudoObjectExpr::Create(S.Context, syntactic,<br>
+                                  Semantics, ResultIndex);<br>
+}<br>
+<br>
+/// The main skeleton for building an r-value operation.<br>
+ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {<br>
+  Expr *syntacticBase = rebuildAndCaptureObject(op);<br>
+<br>
+  ExprResult getExpr = buildGet();<br>
+  if (getExpr.isInvalid()) return ExprError();<br>
+  addResultSemanticExpr(getExpr.take());<br>
+<br>
+  return complete(syntacticBase);<br>
+}<br>
+<br>
+/// The basic skeleton for building a simple or compound<br>
+/// assignment operation.<br>
+ExprResult<br>
+PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,<br>
+                                          BinaryOperatorKind opcode,<br>
+                                          Expr *LHS, Expr *RHS) {<br>
+  assert(BinaryOperator::isAssignmentOp(opcode));<br>
+<br>
+  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);<br>
+  OpaqueValueExpr *capturedRHS = capture(RHS);<br>
+<br>
+  Expr *syntactic;<br>
+<br>
+  ExprResult result;<br>
+  if (opcode == BO_Assign) {<br>
+    result = capturedRHS;<br>
+    syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,<br>
+                                               opcode, capturedRHS->getType(),<br>
+                                               capturedRHS->getValueKind(),<br>
+                                               OK_Ordinary, opcLoc);<br>
+  } else {<br>
+    ExprResult opLHS = buildGet();<br>
+    if (opLHS.isInvalid()) return ExprError();<br>
+<br>
+    // Build an ordinary, non-compound operation.<br>
+    BinaryOperatorKind nonCompound =<br>
+      BinaryOperator::getOpForCompoundAssignment(opcode);<br>
+    result = S.BuildBinOp(Sc, opcLoc, nonCompound,<br>
+                          opLHS.take(), capturedRHS);<br>
+    if (result.isInvalid()) return ExprError();<br>
+<br>
+    syntactic =<br>
+      new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,<br>
+                                             result.get()->getType(),<br>
+                                             result.get()->getValueKind(),<br>
+                                             OK_Ordinary,<br>
+                                             opLHS.get()->getType(),<br>
+                                             result.get()->getType(),<br>
+                                             opcLoc);<br>
+  }<br>
+<br>
+  // The result of the assignment, if not void, is the value set into<br>
+  // the l-value.<br>
+  result = buildSet(result.take(), opcLoc, assignmentsHaveResult());<br>
+  if (result.isInvalid()) return ExprError();<br>
+  addSemanticExpr(result.take());<br>
+<br>
+  return complete(syntactic);<br>
+}<br>
+<br>
+/// The basic skeleton for building an increment or decrement<br>
+/// operation.<br>
+ExprResult<br>
+PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,<br>
+                                      UnaryOperatorKind opcode,<br>
+                                      Expr *op) {<br>
+  assert(UnaryOperator::isIncrementDecrementOp(opcode));<br>
+<br>
+  Expr *syntacticOp = rebuildAndCaptureObject(op);<br>
+<br>
+  // Load the value.<br>
+  ExprResult result = buildGet();<br>
+  if (result.isInvalid()) return ExprError();<br>
+<br>
+  QualType resultType = result.get()->getType();<br>
+<br>
+  // That's the postfix result.<br>
+  if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {<br>
+    result = capture(result.take());<br>
+    setResultToLastSemantic();<br>
+  }<br>
+<br>
+  // Add or subtract a literal 1.<br>
+  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);<br>
+  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,<br>
+                                     GenericLoc);<br>
+<br>
+  if (UnaryOperator::isIncrementOp(opcode)) {<br>
+    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);<br>
+  } else {<br>
+    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);<br>
+  }<br>
+  if (result.isInvalid()) return ExprError();<br>
+<br>
+  // Store that back into the result.  The value stored is the result<br>
+  // of a prefix operation.<br>
+  result = buildSet(result.take(), opcLoc,<br>
+             UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());<br>
+  if (result.isInvalid()) return ExprError();<br>
+  addSemanticExpr(result.take());<br>
+<br>
+  UnaryOperator *syntactic =<br>
+    new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,<br>
+                                  VK_LValue, OK_Ordinary, opcLoc);<br>
+  return complete(syntactic);<br>
+}<br>
+<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+//  Objective-C @property and implicit property references<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+/// Look up a method in the receiver type of an Objective-C property<br>
+/// reference.<br>
 static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,<br>
                                             const ObjCPropertyRefExpr *PRE) {<br>
   if (PRE->isObjectReceiver()) {<br>
     const ObjCObjectPointerType *PT =<br>
       PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();<br>
+<br>
+    // Special case for 'self' in class method implementations.<br>
+    if (PT->isObjCClassType() &&<br>
+        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {<br>
+      // This cast is safe because isSelfExpr is only true within<br>
+      // methods.<br>
+      ObjCMethodDecl *method =<br>
+        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());<br>
+      return S.LookupMethodInObjectType(sel,<br>
+                 S.Context.getObjCInterfaceType(method->getClassInterface()),<br>
+                                        /*instance*/ false);<br>
+    }<br>
+<br>
     return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);<br>
   }<br>
<br>
@@ -59,281 +412,374 @@<br>
   return S.LookupMethodInObjectType(sel, IT, false);<br>
 }<br>
<br>
-ExprResult Sema::checkPseudoObjectRValue(Expr *E) {<br>
-  assert(E->getValueKind() == VK_LValue &&<br>
-         E->getObjectKind() == OK_ObjCProperty);<br>
-  const ObjCPropertyRefExpr *PRE = E->getObjCProperty();<br>
-<br>
-  QualType ReceiverType;<br>
-  if (PRE->isObjectReceiver())<br>
-    ReceiverType = PRE->getBase()->getType();<br>
-  else if (PRE->isSuperReceiver())<br>
-    ReceiverType = PRE->getSuperReceiverType();<br>
-  else<br>
-    ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver());<br>
-<br>
-  ExprValueKind VK = VK_RValue;<br>
-  QualType T;<br>
-  if (PRE->isImplicitProperty()) {<br>
-    if (ObjCMethodDecl *GetterMethod =<br>
-          PRE->getImplicitPropertyGetter()) {<br>
-      T = getMessageSendResultType(ReceiverType, GetterMethod,<br>
-                                   PRE->isClassReceiver(),<br>
-                                   PRE->isSuperReceiver());<br>
-      VK = Expr::getValueKindForType(GetterMethod->getResultType());<br>
-    } else {<br>
-      Diag(PRE->getLocation(), diag::err_getter_not_found)<br>
-            << PRE->getBase()->getType();<br>
-      return ExprError();<br>
-    }<br>
-  } else {<br>
-    ObjCPropertyDecl *prop = PRE->getExplicitProperty();<br>
+bool ObjCPropertyOpBuilder::findGetter() {<br>
+  if (Getter) return true;<br>
+<br>
+  Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr);<br>
+  return (Getter != 0);<br>
+}<br>
<br>
-    ObjCMethodDecl *getter =<br>
-      LookupMethodInReceiverType(*this, prop->getGetterName(), PRE);<br>
-    if (getter && !getter->hasRelatedResultType())<br>
-      DiagnosePropertyAccessorMismatch(prop, getter, PRE->getLocation());<br>
-    if (!getter) getter = prop->getGetterMethodDecl();<br>
-<br>
-    // Figure out the type of the expression.  Mostly this is the<br>
-    // result type of the getter, if possible.<br>
-    if (getter) {<br>
-      T = getMessageSendResultType(ReceiverType, getter,<br>
-                                   PRE->isClassReceiver(),<br>
-                                   PRE->isSuperReceiver());<br>
-      VK = Expr::getValueKindForType(getter->getResultType());<br>
-<br>
-      // As a special case, if the method returns 'id', try to get a<br>
-      // better type from the property.<br>
-      if (VK == VK_RValue && T->isObjCIdType() &&<br>
-          prop->getType()->isObjCRetainableType())<br>
-        T = prop->getType();<br>
+/// Try to find the most accurate setter declaration for the property<br>
+/// reference.<br>
+///<br>
+/// \return true if a setter was found, in which case Setter<br>
+bool ObjCPropertyOpBuilder::findSetter() {<br>
+  // For implicit properties, just trust the lookup we already did.<br>
+  if (RefExpr->isImplicitProperty()) {<br>
+    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {<br>
+      Setter = setter;<br>
+      SetterSelector = setter->getSelector();<br>
+      return true;<br>
     } else {<br>
-      T = prop->getType();<br>
-      VK = Expr::getValueKindForType(T);<br>
-      T = T.getNonLValueExprType(Context);<br>
+      IdentifierInfo *getterName =<br>
+        RefExpr->getImplicitPropertyGetter()->getSelector()<br>
+          .getIdentifierInfoForSlot(0);<br>
+      SetterSelector =<br>
+        SelectorTable::constructSetterName(S.PP.getIdentifierTable(),<br>
+                                           S.PP.getSelectorTable(),<br>
+                                           getterName);<br>
+      return false;<br>
     }<br>
   }<br>
<br>
-  E->setType(T);<br>
-  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK);<br>
+  // For explicit properties, this is more involved.<br>
+  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();<br>
+  SetterSelector = prop->getSetterName();<br>
+<br>
+  // Do a normal method lookup first.<br>
+  if (ObjCMethodDecl *setter =<br>
+        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {<br>
+    Setter = setter;<br>
+    return true;<br>
+  }<br>
+<br>
+  // That can fail in the somewhat crazy situation that we're<br>
+  // type-checking a message send within the @interface declaration<br>
+  // that declared the @property.  But it's not clear that that's<br>
+  // valuable to support.<br>
+<br>
+  return false;<br>
+}<br>
+<br>
+/// Capture the base object of an Objective-C property expression.<br>
+Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {<br>
+  assert(InstanceReceiver == 0);<br>
+<br>
+  // If we have a base, capture it in an OVE and rebuild the syntactic<br>
+  // form to use the OVE as its base.<br>
+  if (RefExpr->isObjectReceiver()) {<br>
+    InstanceReceiver = capture(RefExpr->getBase());<br>
+<br>
+    syntacticBase =<br>
+      ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);<br>
+  }<br>
+<br>
+  return syntacticBase;<br>
+}<br>
+<br>
+/// Load from an Objective-C property reference.<br>
+ExprResult ObjCPropertyOpBuilder::buildGet() {<br>
+  findGetter();<br>
+  assert(Getter);<br>
<br>
-  ExprResult Result = MaybeBindToTemporary(E);<br>
-  if (!Result.isInvalid())<br>
-    E = Result.take();<br>
+  QualType receiverType;<br>
+  SourceLocation superLoc;<br>
+  if (RefExpr->isClassReceiver()) {<br>
+    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());<br>
+  } else if (RefExpr->isSuperReceiver()) {<br>
+    superLoc = RefExpr->getReceiverLocation();<br>
+    receiverType = RefExpr->getSuperReceiverType();<br>
+  } else {<br>
+    assert(InstanceReceiver);<br>
+    receiverType = InstanceReceiver->getType();<br>
+  }<br>
<br>
-  return Owned(E);<br>
+  // Build a message-send.<br>
+  ExprResult msg;<br>
+  if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {<br>
+    assert(InstanceReceiver || RefExpr->isSuperReceiver());<br>
+    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,<br>
+                                 Getter->getSelector(), Getter,<br>
+                                 GenericLoc, GenericLoc, GenericLoc,<br>
+                                 MultiExprArg());<br>
+  } else {<br>
+    TypeSourceInfo *receiverTypeInfo = 0;<br>
+    if (!RefExpr->isSuperReceiver())<br>
+      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);<br>
+<br>
+    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,<br>
+                              Getter->getSelector(), Getter,<br>
+                              GenericLoc, GenericLoc, GenericLoc,<br>
+                              MultiExprArg());<br>
+  }<br>
+  return msg;<br>
 }<br>
<br>
-namespace {<br>
-  struct PseudoObjectInfo {<br>
-    const ObjCPropertyRefExpr *RefExpr;<br>
-    bool HasSetter;<br>
-    Selector SetterSelector;<br>
-    ParmVarDecl *SetterParam;<br>
-    QualType SetterParamType;<br>
+/// Store to an Objective-C property reference.<br>
+///<br>
+/// \param bindSetValueAsResult - If true, capture the actual<br>
+///   value being set as the value of the property operation.<br>
+ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,<br>
+                                           bool captureSetValueAsResult) {<br>
+  bool hasSetter = findSetter();<br>
+  assert(hasSetter); (void) hasSetter;<br>
+<br>
+  QualType receiverType;<br>
+  SourceLocation superLoc;<br>
+  if (RefExpr->isClassReceiver()) {<br>
+    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());<br>
+  } else if (RefExpr->isSuperReceiver()) {<br>
+    superLoc = RefExpr->getReceiverLocation();<br>
+    receiverType = RefExpr->getSuperReceiverType();<br>
+  } else {<br>
+    assert(InstanceReceiver);<br>
+    receiverType = InstanceReceiver->getType();<br>
+  }<br>
<br>
-    void setSetter(ObjCMethodDecl *setter) {<br>
-      HasSetter = true;<br>
-      SetterParam = *setter->param_begin();<br>
-      SetterParamType = SetterParam->getType().getUnqualifiedType();<br>
-    }<br>
-<br>
-    PseudoObjectInfo(Sema &S, Expr *E)<br>
-      : RefExpr(E->getObjCProperty()), HasSetter(false), SetterParam(0) {<br>
-<br>
-      assert(E->getValueKind() == VK_LValue &&<br>
-             E->getObjectKind() == OK_ObjCProperty);<br>
-<br>
-      // Try to find a setter.<br>
-<br>
-      // For implicit properties, just trust the lookup we already did.<br>
-      if (RefExpr->isImplicitProperty()) {<br>
-        if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {<br>
-          setSetter(setter);<br>
-          SetterSelector = setter->getSelector();<br>
-        } else {<br>
-          IdentifierInfo *getterName =<br>
-            RefExpr->getImplicitPropertyGetter()->getSelector()<br>
-              .getIdentifierInfoForSlot(0);<br>
-          SetterSelector =<br>
-            SelectorTable::constructSetterName(S.PP.getIdentifierTable(),<br>
-                                               S.PP.getSelectorTable(),<br>
-                                               getterName);<br>
-        }<br>
-        return;<br>
-      }<br>
+  // Use assignment constraints when possible; they give us better<br>
+  // diagnostics.  "When possible" basically means anything except a<br>
+  // C++ class type.<br>
+  if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {<br>
+    QualType paramType = (*Setter->param_begin())->getType();<br>
+    if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {<br>
+      ExprResult opResult = op;<br>
+      Sema::AssignConvertType assignResult<br>
+        = S.CheckSingleAssignmentConstraints(paramType, opResult);<br>
+      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,<br>
+                                     op->getType(), opResult.get(),<br>
+                                     Sema::AA_Assigning))<br>
+        return ExprError();<br>
<br>
-      // For explicit properties, this is more involved.<br>
-      ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();<br>
-      SetterSelector = prop->getSetterName();<br>
-<br>
-      // Do a normal method lookup first.<br>
-      if (ObjCMethodDecl *setter =<br>
-            LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {<br>
-        setSetter(setter);<br>
-        return;<br>
-      }<br>
+      op = opResult.take();<br>
+      assert(op && "successful assignment left argument invalid?");<br>
+    }<br>
+  }<br>
<br>
-      // If that failed, trust the type on the @property declaration.<br>
-      if (!prop->isReadOnly()) {<br>
-        HasSetter = true;<br>
-        SetterParamType = prop->getType().getUnqualifiedType();<br>
-      }<br>
+  // Arguments.<br>
+  Expr *args[] = { op };<br>
+<br>
+  // Build a message-send.<br>
+  ExprResult msg;<br>
+  if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {<br>
+    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,<br>
+                                 SetterSelector, Setter,<br>
+                                 GenericLoc, GenericLoc, GenericLoc,<br>
+                                 MultiExprArg(args, 1));<br>
+  } else {<br>
+    TypeSourceInfo *receiverTypeInfo = 0;<br>
+    if (!RefExpr->isSuperReceiver())<br>
+      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);<br>
+<br>
+    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,<br>
+                              SetterSelector, Setter,<br>
+                              GenericLoc, GenericLoc, GenericLoc,<br>
+                              MultiExprArg(args, 1));<br>
+  }<br>
+<br>
+  if (!msg.isInvalid() && captureSetValueAsResult) {<br>
+    ObjCMessageExpr *msgExpr =<br>
+      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());<br>
+    Expr *arg = msgExpr->getArg(0);<br>
+    msgExpr->setArg(0, captureValueAsResult(arg));<br>
+  }<br>
+<br>
+  return msg;<br>
+}<br>
+<br>
+/// @property-specific behavior for doing lvalue-to-rvalue conversion.<br>
+ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {<br>
+  // Explicit properties always have getters, but implicit ones don't.<br>
+  // Check that before proceeding.<br>
+  if (RefExpr->isImplicitProperty() &&<br>
+      !RefExpr->getImplicitPropertyGetter()) {<br>
+    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)<br>
+      << RefExpr->getBase()->getType();<br>
+    return ExprError();<br>
+  }<br>
+<br>
+  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);<br>
+  if (result.isInvalid()) return ExprError();<br>
+<br>
+  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())<br>
+    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),<br>
+                                       Getter, RefExpr->getLocation());<br>
+<br>
+  // As a special case, if the method returns 'id', try to get<br>
+  // a better type from the property.<br>
+  if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&<br>
+      result.get()->getType()->isObjCIdType()) {<br>
+    QualType propType = RefExpr->getExplicitProperty()->getType();<br>
+    if (const ObjCObjectPointerType *ptr<br>
+          = propType->getAs<ObjCObjectPointerType>()) {<br>
+      if (!ptr->isObjCIdType())<br>
+        result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);<br>
     }<br>
-  };<br>
+  }<br>
+<br>
+  return result;<br>
 }<br>
<br>
-/// Check an increment or decrement of a pseudo-object expression.<br>
-ExprResult Sema::checkPseudoObjectIncDec(Scope *S, SourceLocation opcLoc,<br>
-                                         UnaryOperatorKind opcode, Expr *op) {<br>
-  assert(UnaryOperator::isIncrementDecrementOp(opcode));<br>
-  PseudoObjectInfo info(*this, op);<br>
+/// Try to build this as a call to a getter that returns a reference.<br>
+///<br>
+/// \return true if it was possible, whether or not it actually<br>
+///   succeeded<br>
+bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,<br>
+                                                   ExprResult &result) {<br>
+  if (!S.getLangOptions().CPlusPlus) return false;<br>
+<br>
+  findGetter();<br>
+  assert(Getter && "property has no setter and no getter!");<br>
+<br>
+  // Only do this if the getter returns an l-value reference type.<br>
+  QualType resultType = Getter->getResultType();<br>
+  if (!resultType->isLValueReferenceType()) return false;<br>
+<br>
+  result = buildRValueOperation(op);<br>
+  return true;<br>
+}<br>
+<br>
+/// @property-specific behavior for doing assignments.<br>
+ExprResult<br>
+ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,<br>
+                                                SourceLocation opcLoc,<br>
+                                                BinaryOperatorKind opcode,<br>
+                                                Expr *LHS, Expr *RHS) {<br>
+  assert(BinaryOperator::isAssignmentOp(opcode));<br>
<br>
   // If there's no setter, we have no choice but to try to assign to<br>
   // the result of the getter.<br>
-  if (!info.HasSetter) {<br>
-    QualType resultType = info.RefExpr->getGetterResultType();<br>
-    assert(!resultType.isNull() && "property has no setter and no getter!");<br>
-<br>
-    // Only do this if the getter returns an l-value reference type.<br>
-    if (const LValueReferenceType *refType<br>
-          = resultType->getAs<LValueReferenceType>()) {<br>
-      op = ImplicitCastExpr::Create(Context, refType->getPointeeType(),<br>
-                                    CK_GetObjCProperty, op, 0, VK_LValue);<br>
-      return BuildUnaryOp(S, opcLoc, opcode, op);<br>
+  if (!findSetter()) {<br>
+    ExprResult result;<br>
+    if (tryBuildGetOfReference(LHS, result)) {<br>
+      if (result.isInvalid()) return ExprError();<br>
+      return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);<br>
     }<br>
<br>
     // Otherwise, it's an error.<br>
-    Diag(opcLoc, diag::err_nosetter_property_incdec)<br>
-      << unsigned(info.RefExpr->isImplicitProperty())<br>
-      << unsigned(UnaryOperator::isDecrementOp(opcode))<br>
-      << info.SetterSelector<br>
-      << op->getSourceRange();<br>
+    S.Diag(opcLoc, diag::err_nosetter_property_assignment)<br>
+      << unsigned(RefExpr->isImplicitProperty())<br>
+      << SetterSelector<br>
+      << LHS->getSourceRange() << RHS->getSourceRange();<br>
     return ExprError();<br>
   }<br>
<br>
-  // ++/-- behave like compound assignments, i.e. they need a getter.<br>
-  QualType getterResultType = info.RefExpr->getGetterResultType();<br>
-  if (getterResultType.isNull()) {<br>
-    assert(info.RefExpr->isImplicitProperty());<br>
-    Diag(opcLoc, diag::err_nogetter_property_incdec)<br>
-      << unsigned(UnaryOperator::isDecrementOp(opcode))<br>
-      << info.RefExpr->getImplicitPropertyGetter()->getSelector()<br>
-      << op->getSourceRange();<br>
+  // If there is a setter, we definitely want to use it.<br>
+<br>
+  // Verify that we can do a compound assignment.<br>
+  if (opcode != BO_Assign && !findGetter()) {<br>
+    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)<br>
+      << LHS->getSourceRange() << RHS->getSourceRange();<br>
     return ExprError();<br>
   }<br>
<br>
-  // HACK: change the type of the operand to prevent further placeholder<br>
-  // transformation.<br>
-  op->setType(getterResultType.getNonLValueExprType(Context));<br>
-  op->setObjectKind(OK_Ordinary);<br>
-<br>
-  ExprResult result = CreateBuiltinUnaryOp(opcLoc, opcode, op);<br>
+  ExprResult result =<br>
+    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);<br>
   if (result.isInvalid()) return ExprError();<br>
<br>
-  // Change the object kind back.<br>
-  op->setObjectKind(OK_ObjCProperty);<br>
+  // Various warnings about property assignments in ARC.<br>
+  if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {<br>
+    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);<br>
+    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);<br>
+  }<br>
+<br>
   return result;<br>
 }<br>
<br>
-ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,<br>
-                                             BinaryOperatorKind opcode,<br>
-                                             Expr *LHS, Expr *RHS) {<br>
-  assert(BinaryOperator::isAssignmentOp(opcode));<br>
-  PseudoObjectInfo info(*this, LHS);<br>
-<br>
+/// @property-specific behavior for doing increments and decrements.<br>
+ExprResult<br>
+ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,<br>
+                                            UnaryOperatorKind opcode,<br>
+                                            Expr *op) {<br>
   // If there's no setter, we have no choice but to try to assign to<br>
   // the result of the getter.<br>
-  if (!info.HasSetter) {<br>
-    QualType resultType = info.RefExpr->getGetterResultType();<br>
-    assert(!resultType.isNull() && "property has no setter and no getter!");<br>
-<br>
-    // Only do this if the getter returns an l-value reference type.<br>
-    if (const LValueReferenceType *refType<br>
-          = resultType->getAs<LValueReferenceType>()) {<br>
-      LHS = ImplicitCastExpr::Create(Context, refType->getPointeeType(),<br>
-                                     CK_GetObjCProperty, LHS, 0, VK_LValue);<br>
-      return BuildBinOp(S, opcLoc, opcode, LHS, RHS);<br>
+  if (!findSetter()) {<br>
+    ExprResult result;<br>
+    if (tryBuildGetOfReference(op, result)) {<br>
+      if (result.isInvalid()) return ExprError();<br>
+      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());<br>
     }<br>
<br>
     // Otherwise, it's an error.<br>
-    Diag(opcLoc, diag::err_nosetter_property_assignment)<br>
-      << unsigned(info.RefExpr->isImplicitProperty())<br>
-      << info.SetterSelector<br>
-      << LHS->getSourceRange() << RHS->getSourceRange();<br>
+    S.Diag(opcLoc, diag::err_nosetter_property_incdec)<br>
+      << unsigned(RefExpr->isImplicitProperty())<br>
+      << unsigned(UnaryOperator::isDecrementOp(opcode))<br>
+      << SetterSelector<br>
+      << op->getSourceRange();<br>
     return ExprError();<br>
   }<br>
<br>
   // If there is a setter, we definitely want to use it.<br>
<br>
-  // If this is a simple assignment, just initialize the parameter<br>
-  // with the RHS.<br>
-  if (opcode == BO_Assign) {<br>
-    LHS->setType(info.SetterParamType.getNonLValueExprType(Context));<br>
+  // We also need a getter.<br>
+  if (!findGetter()) {<br>
+    assert(RefExpr->isImplicitProperty());<br>
+    S.Diag(opcLoc, diag::err_nogetter_property_incdec)<br>
+      << unsigned(UnaryOperator::isDecrementOp(opcode))<br>
+      << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!<br>
+      << op->getSourceRange();<br>
+    return ExprError();<br>
+  }<br>
<br>
-    // Under certain circumstances, we need to type-check the RHS as a<br>
-    // straight-up parameter initialization.  This gives somewhat<br>
-    // inferior diagnostics, so we try to avoid it.<br>
-<br>
-    if (RHS->isTypeDependent()) {<br>
-      // Just build the expression.<br>
-<br>
-    } else if ((getLangOptions().CPlusPlus && LHS->getType()->isRecordType()) ||<br>
-               (getLangOptions().ObjCAutoRefCount &&<br>
-                info.SetterParam &&<br>
-                info.SetterParam->hasAttr<NSConsumedAttr>())) {<br>
-      InitializedEntity param = (info.SetterParam<br>
-        ? InitializedEntity::InitializeParameter(Context, info.SetterParam)<br>
-        : InitializedEntity::InitializeParameter(Context, info.SetterParamType,<br>
-                                                 /*consumed*/ false));<br>
-      ExprResult arg = PerformCopyInitialization(param, opcLoc, RHS);<br>
-      if (arg.isInvalid()) return ExprError();<br>
-      RHS = arg.take();<br>
-<br>
-      // Warn about assignments of +1 objects to unsafe pointers in ARC.<br>
-      // CheckAssignmentOperands does this on the other path.<br>
-      if (getLangOptions().ObjCAutoRefCount)<br>
-        checkUnsafeExprAssigns(opcLoc, LHS, RHS);<br>
-    } else {<br>
-      ExprResult RHSResult = Owned(RHS);<br>
+  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);<br>
+}<br>
<br>
-      LHS->setObjectKind(OK_Ordinary);<br>
-      QualType resultType = CheckAssignmentOperands(LHS, RHSResult, opcLoc,<br>
-                                                    /*compound*/ QualType());<br>
-      LHS->setObjectKind(OK_ObjCProperty);<br>
+//===----------------------------------------------------------------------===//<br>
+//  General Sema routines.<br>
+//===----------------------------------------------------------------------===//<br>
<br>
-      if (!RHSResult.isInvalid()) RHS = RHSResult.take();<br>
-      if (resultType.isNull()) return ExprError();<br>
-    }<br>
+ExprResult Sema::checkPseudoObjectRValue(Expr *E) {<br>
+  Expr *opaqueRef = E->IgnoreParens();<br>
+  if (ObjCPropertyRefExpr *refExpr<br>
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {<br>
+    ObjCPropertyOpBuilder builder(*this, refExpr);<br>
+    return builder.buildRValueOperation(E);<br>
+  } else {<br>
+    llvm_unreachable("unknown pseudo-object kind!");<br>
+  }<br>
+}<br>
<br>
-    // Warn about property sets in ARC that might cause retain cycles.<br>
-    if (getLangOptions().ObjCAutoRefCount && !info.RefExpr->isSuperReceiver())<br>
-      checkRetainCycles(const_cast<Expr*>(info.RefExpr->getBase()), RHS);<br>
+/// Check an increment or decrement of a pseudo-object expression.<br>
+ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,<br>
+                                         UnaryOperatorKind opcode, Expr *op) {<br>
+  // Do nothing if the operand is dependent.<br>
+  if (op->isTypeDependent())<br>
+    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,<br>
+                                       VK_RValue, OK_Ordinary, opcLoc);<br>
<br>
-    return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(),<br>
-                                        RHS->getValueKind(),<br>
-                                        RHS->getObjectKind(),<br>
-                                        opcLoc);<br>
+  assert(UnaryOperator::isIncrementDecrementOp(opcode));<br>
+  Expr *opaqueRef = op->IgnoreParens();<br>
+  if (ObjCPropertyRefExpr *refExpr<br>
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {<br>
+    ObjCPropertyOpBuilder builder(*this, refExpr);<br>
+    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);<br>
+  } else {<br>
+    llvm_unreachable("unknown pseudo-object kind!");<br>
   }<br>
+}<br>
<br>
-  // If this is a compound assignment, we need to use the getter, too.<br>
-  QualType getterResultType = info.RefExpr->getGetterResultType();<br>
-  if (getterResultType.isNull()) {<br>
-    Diag(opcLoc, diag::err_nogetter_property_compound_assignment)<br>
-      << LHS->getSourceRange() << RHS->getSourceRange();<br>
-    return ExprError();<br>
+ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,<br>
+                                             BinaryOperatorKind opcode,<br>
+                                             Expr *LHS, Expr *RHS) {<br>
+  // Do nothing if either argument is dependent.<br>
+  if (LHS->isTypeDependent() || RHS->isTypeDependent())<br>
+    return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,<br>
+                                        VK_RValue, OK_Ordinary, opcLoc);<br>
+<br>
+  // Filter out non-overload placeholder types in the RHS.<br>
+  if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {<br>
+    if (PTy->getKind() != BuiltinType::Overload) {<br>
+      ExprResult result = CheckPlaceholderExpr(RHS);<br>
+      if (result.isInvalid()) return ExprError();<br>
+      RHS = result.take();<br>
+    }<br>
   }<br>
<br>
-  // HACK: change the type of the LHS to prevent further placeholder<br>
-  // transformation.<br>
-  LHS->setType(getterResultType.getNonLValueExprType(Context));<br>
-  LHS->setObjectKind(OK_Ordinary);<br>
-<br>
-  ExprResult result = CreateBuiltinBinOp(opcLoc, opcode, LHS, RHS);<br>
-  if (result.isInvalid()) return ExprError();<br>
-<br>
-  // Change the object kind back.<br>
-  LHS->setObjectKind(OK_ObjCProperty);<br>
-  return result;<br>
+  Expr *opaqueRef = LHS->IgnoreParens();<br>
+  if (ObjCPropertyRefExpr *refExpr<br>
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {<br>
+    ObjCPropertyOpBuilder builder(*this, refExpr);<br>
+    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);<br>
+  } else {<br>
+    llvm_unreachable("unknown pseudo-object kind!");<br>
+  }<br>
 }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Sun Nov  6 03:01:30 2011<br>
@@ -198,7 +198,7 @@<br>
       Diag(Loc, diag::warn_unused_result) << R1 << R2;<br>
       return;<br>
     }<br>
-  } else if (isa<ObjCPropertyRefExpr>(E)) {<br>
+  } else if (isa<PseudoObjectExpr>(E)) {<br>
     DiagID = diag::warn_unused_property_expr;<br>
   } else if (const CXXFunctionalCastExpr *FC<br>
                                        = dyn_cast<CXXFunctionalCastExpr>(E)) {<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Sun Nov  6 03:01:30 2011<br>
@@ -6103,6 +6103,22 @@<br>
<br>
 template<typename Derived><br>
 ExprResult<br>
+TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+  // Rebuild the syntactic form.<br>
+  ExprResult result = getDerived().TransformExpr(E->getSyntacticForm());<br>
+  if (result.isInvalid()) return ExprError();<br>
+<br>
+  // If that gives us a pseudo-object result back, the pseudo-object<br>
+  // expression must have been an lvalue-to-rvalue conversion which we<br>
+  // should reapply.<br>
+  if (result.get()->hasPlaceholderType(BuiltinType::PseudoObject))<br>
+    result = SemaRef.checkPseudoObjectRValue(result.take());<br>
+<br>
+  return result;<br>
+}<br>
+<br>
+template<typename Derived><br>
+ExprResult<br>
 TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(<br>
                                                 UnaryExprOrTypeTraitExpr *E) {<br>
   if (E->isArgumentType()) {<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Sun Nov  6 03:01:30 2011<br>
@@ -775,6 +775,24 @@<br>
   E->RParenLoc = ReadSourceLocation(Record, Idx);<br>
 }<br>
<br>
+void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+  VisitExpr(E);<br>
+  unsigned numSemanticExprs = Record[Idx++];<br>
+  assert(numSemanticExprs + 1 == E->PseudoObjectExprBits.NumSubExprs);<br>
+  E->PseudoObjectExprBits.ResultIndex = Record[Idx++];<br>
+<br>
+  // Read the syntactic expression.<br>
+  E->getSubExprsBuffer()[0] = Reader.ReadSubExpr();<br>
+<br>
+  // Read all the semantic expressions.<br>
+  for (unsigned i = 0; i != numSemanticExprs; ++i) {<br>
+    Expr *subExpr = Reader.ReadSubExpr();<br>
+    if (isa<OpaqueValueExpr>(subExpr))<br>
+      cast<OpaqueValueExpr>(subExpr)->setSourceExpr(Reader.ReadSubExpr());<br>
+    E->getSubExprsBuffer()[i+1] = subExpr;<br>
+  }<br>
+}<br>
+<br>
 void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) {<br>
   VisitExpr(E);<br>
   E->setOp(AtomicExpr::AtomicOp(Record[Idx++]));<br>
@@ -2059,6 +2077,12 @@<br>
       S = new (Context) AsTypeExpr(Empty);<br>
       break;<br>
<br>
+    case EXPR_PSEUDO_OBJECT: {<br>
+      unsigned numSemanticExprs = Record[ASTStmtReader::NumExprFields];<br>
+      S = PseudoObjectExpr::Create(Context, Empty, numSemanticExprs);<br>
+      break;<br>
+    }<br>
+<br>
     case EXPR_ATOMIC:<br>
       S = new (Context) AtomicExpr(Empty);<br>
       break;<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Sun Nov  6 03:01:30 2011<br>
@@ -736,6 +736,25 @@<br>
   Code = serialization::EXPR_GENERIC_SELECTION;<br>
 }<br>
<br>
+void ASTStmtWriter::VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+  VisitExpr(E);<br>
+  Record.push_back(E->getNumSemanticExprs());<br>
+<br>
+  // Push the result index.  Currently, this needs to exactly match<br>
+  // the encoding used internally for ResultIndex.<br>
+  unsigned result = E->getResultExprIndex();<br>
+  result = (result == PseudoObjectExpr::NoResult ? 0 : result + 1);<br>
+  Record.push_back(result);<br>
+<br>
+  Writer.AddStmt(E->getSyntacticForm());<br>
+  for (PseudoObjectExpr::semantics_iterator<br>
+         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {<br>
+    Writer.AddStmt(*i);<br>
+    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i))<br>
+      Writer.AddStmt(OVE->getSourceExpr());<br>
+  }<br>
+}<br>
+<br>
 void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) {<br>
   VisitExpr(E);<br>
   Record.push_back(E->getOp());<br>
<br>
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Sun Nov  6 03:01:30 2011<br>
@@ -857,6 +857,21 @@<br>
       Bldr.addNodes(Dst);<br>
       break;<br>
     }<br>
+<br>
+    case Stmt::PseudoObjectExprClass: {<br>
+      Bldr.takeNodes(Pred);<br>
+      const ProgramState *state = Pred->getState();<br>
+      const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);<br>
+      if (const Expr *Result = PE->getResultExpr()) {<br>
+        SVal V = state->getSVal(Result);<br>
+        Bldr.generateNode(S, Pred, state->BindExpr(S, V));<br>
+      }<br>
+      else<br>
+        Bldr.generateNode(S, Pred, state->BindExpr(S, UnknownVal()));<br>
+<br>
+      Bldr.addNodes(Dst);<br>
+      break;<br>
+    }<br>
   }<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/test/Analysis/casts.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/casts.m?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/casts.m?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/Analysis/casts.m (original)<br>
+++ cfe/trunk/test/Analysis/casts.m Sun Nov  6 03:01:30 2011<br>
@@ -33,9 +33,10 @@<br>
   RDR10087620Enum   elem;<br>
 }<br>
 @property (readwrite, nonatomic) RDR10087620Enum elem;<br>
+@end<br>
+<br>
 static void<br>
 adium_media_ready_cb(RDR10087620 *InObj)<br>
 {<br>
   InObj.elem |= EEOne;<br>
 }<br>
-@end<br>
\ No newline at end of file<br>
<br>
Modified: cfe/trunk/test/Analysis/retain-release-path-notes.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-path-notes.m?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-path-notes.m?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/Analysis/retain-release-path-notes.m (original)<br>
+++ cfe/trunk/test/Analysis/retain-release-path-notes.m Sun Nov  6 03:01:30 2011<br>
@@ -1,5 +1,10 @@<br>
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s<br>

<br>
+// This actually still works after the pseudo-object refactor, it just<br>
+// uses messages that say 'method' instead of 'property'.  Ted wanted<br>
+// this xfailed and filed as a bug.  rdar://problem/10402993<br>
+// XFAIL: *<br>
+<br>
 /***<br>
 This file is for testing the path-sensitive notes for retain/release errors.<br>
 Its goal is to have simple branch coverage of any path-based diagnostics,<br>
<br>
Modified: cfe/trunk/tools/libclang/CIndex.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/CIndex.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CIndex.cpp Sun Nov  6 03:01:30 2011<br>
@@ -1714,6 +1714,8 @@<br>
   void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);<br>
   void VisitVAArgExpr(VAArgExpr *E);<br>
   void VisitSizeOfPackExpr(SizeOfPackExpr *E);<br>
+  void VisitPseudoObjectExpr(PseudoObjectExpr *E);<br>
+  void VisitOpaqueValueExpr(OpaqueValueExpr *E);<br>
<br>
 private:<br>
   void AddDeclarationNameInfo(Stmt *S);<br>
@@ -2022,6 +2024,17 @@<br>
 void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {<br>
   WL.push_back(SizeOfPackExprParts(E, Parent));<br>
 }<br>
+void EnqueueVisitor::VisitOpaqueValueExpr(OpaqueValueExpr *E) {<br>
+  // If the opaque value has a source expression, just transparently<br>
+  // visit that.  This is useful for (e.g.) pseudo-object expressions.<br>
+  if (Expr *SourceExpr = E->getSourceExpr())<br>
+    return Visit(SourceExpr);<br>
+  AddStmt(E);<br>
+}<br>
+void EnqueueVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *E) {<br>
+  // Treat the expression like its syntactic form.<br>
+  Visit(E->getSyntacticForm());<br>
+}<br>
<br>
 void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {<br>
   EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);<br>
@@ -2702,6 +2715,11 @@<br>
     return RE->getDecl();<br>
   if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E))<br>
     return PRE->isExplicitProperty() ? PRE->getExplicitProperty() : 0;<br>
+  if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))<br>
+    return getDeclFromExpr(POE->getSyntacticForm());<br>
+  if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))<br>
+    if (Expr *Src = OVE->getSourceExpr())<br>
+      return getDeclFromExpr(Src);<br>
<br>
   if (CallExpr *CE = dyn_cast<CallExpr>(E))<br>
     return getDeclFromExpr(CE->getCallee());<br>
<br>
Modified: cfe/trunk/tools/libclang/CXCursor.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=143867&r1=143866&r2=143867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=143867&r1=143866&r2=143867&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CXCursor.cpp Sun Nov  6 03:01:30 2011<br>
@@ -219,7 +219,6 @@<br>
   case Stmt::MaterializeTemporaryExprClass:<br>
   case Stmt::ObjCIndirectCopyRestoreExprClass:<br>
   case Stmt::OffsetOfExprClass:<br>
-  case Stmt::OpaqueValueExprClass:<br>
   case Stmt::ParenListExprClass:<br>
   case Stmt::PredefinedExprClass:<br>
   case Stmt::ShuffleVectorExprClass:<br>
@@ -229,6 +228,16 @@<br>
     K = CXCursor_UnexposedExpr;<br>
     break;<br>
<br>
+  case Stmt::OpaqueValueExprClass:<br>
+    if (Expr *Src = cast<OpaqueValueExpr>(S)->getSourceExpr())<br>
+      return MakeCXCursor(Src, Parent, TU, RegionOfInterest);<br>
+    K = CXCursor_UnexposedExpr;<br>
+    break;<br>
+<br>
+  case Stmt::PseudoObjectExprClass:<br>
+    return MakeCXCursor(cast<PseudoObjectExpr>(S)->getSyntacticForm(),<br>
+                        Parent, TU, RegionOfInterest);<br>
+<br>
   case Stmt::CompoundStmtClass:<br>
     K = CXCursor_CompoundStmt;<br>
     break;<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>