[cfe-commits] r143867 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Serialization/ lib/ARCMigrate/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Rewrite/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/Analysis/ tool

Chandler Carruth chandlerc at google.com
Sun Nov 6 01:13:55 PST 2011


This called a build failure:

http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/5542/steps/build_clang/logs/stdio

On Sun, Nov 6, 2011 at 1:01 AM, John McCall <rjmccall at apple.com> wrote:

> Author: rjmccall
> Date: Sun Nov  6 03:01:30 2011
> New Revision: 143867
>
> URL: http://llvm.org/viewvc/llvm-project?rev=143867&view=rev
> Log:
> Change the AST representation of operations on Objective-C
> property references to use a new PseudoObjectExpr
> expression which pairs a syntactic form of the expression
> with a set of semantic expressions implementing it.
> This should significantly reduce the complexity required
> elsewhere in the compiler to deal with these kinds of
> expressions (e.g. IR generation's special l-value kind,
> the static analyzer's Message abstraction), at the lower
> cost of specifically dealing with the odd AST structure
> of these expressions.  It should also greatly simplify
> efforts to implement similar language features in the
> future, most notably Managed C++'s properties and indexed
> properties.
>
> Most of the effort here is in dealing with the various
> clients of the AST.  I've gone ahead and simplified the
> ObjC rewriter's use of properties;  other clients, like
> IR-gen and the static analyzer, have all the old
> complexity *and* all the new complexity, at least
> temporarily.  Many thanks to Ted for writing and advising
> on the necessary changes to the static analyzer.
>
> I've xfailed a small diagnostics regression in the static
> analyzer at Ted's request.
>
>
> Modified:
>    cfe/trunk/include/clang/AST/DeclBase.h
>    cfe/trunk/include/clang/AST/Expr.h
>    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>    cfe/trunk/include/clang/AST/Stmt.h
>    cfe/trunk/include/clang/Basic/StmtNodes.td
>    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>    cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
>    cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp
>    cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
>    cfe/trunk/lib/AST/DeclBase.cpp
>    cfe/trunk/lib/AST/Expr.cpp
>    cfe/trunk/lib/AST/ExprClassification.cpp
>    cfe/trunk/lib/AST/ExprConstant.cpp
>    cfe/trunk/lib/AST/ItaniumMangle.cpp
>    cfe/trunk/lib/AST/StmtDumper.cpp
>    cfe/trunk/lib/AST/StmtPrinter.cpp
>    cfe/trunk/lib/AST/StmtProfile.cpp
>    cfe/trunk/lib/Analysis/CFG.cpp
>    cfe/trunk/lib/Analysis/LiveVariables.cpp
>    cfe/trunk/lib/CodeGen/CGExpr.cpp
>    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
>    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
>    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>    cfe/trunk/lib/CodeGen/CGObjC.cpp
>    cfe/trunk/lib/CodeGen/CGValue.h
>    cfe/trunk/lib/CodeGen/CodeGenFunction.h
>    cfe/trunk/lib/Rewrite/RewriteObjC.cpp
>    cfe/trunk/lib/Sema/SemaChecking.cpp
>    cfe/trunk/lib/Sema/SemaExpr.cpp
>    cfe/trunk/lib/Sema/SemaExprObjC.cpp
>    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
>    cfe/trunk/lib/Sema/SemaStmt.cpp
>    cfe/trunk/lib/Sema/TreeTransform.h
>    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
>    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
>    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
>    cfe/trunk/test/Analysis/casts.m
>    cfe/trunk/test/Analysis/retain-release-path-notes.m
>    cfe/trunk/tools/libclang/CIndex.cpp
>    cfe/trunk/tools/libclang/CXCursor.cpp
>
> Modified: cfe/trunk/include/clang/AST/DeclBase.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclBase.h (original)
> +++ cfe/trunk/include/clang/AST/DeclBase.h Sun Nov  6 03:01:30 2011
> @@ -974,6 +974,14 @@
>   /// declaration context DC.
>   bool Encloses(const DeclContext *DC) const;
>
> +  /// \brief Find the nearest non-closure ancestor of this context,
> +  /// i.e. the innermost semantic parent of this context which is not
> +  /// a closure.  A context may be its own non-closure ancestor.
> +  DeclContext *getNonClosureAncestor();
> +  const DeclContext *getNonClosureAncestor() const {
> +    return const_cast<DeclContext*>(this)->getNonClosureAncestor();
> +  }
> +
>   /// getPrimaryContext - There may be many different
>   /// declarations of the same entity (including forward declarations
>   /// of classes, multiple definitions of namespaces, etc.), each with
>
> Modified: cfe/trunk/include/clang/AST/Expr.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Sun Nov  6 03:01:30 2011
> @@ -2758,6 +2758,13 @@
>   bool isCompoundAssignmentOp() const {
>     return isCompoundAssignmentOp(getOpcode());
>   }
> +  static Opcode getOpForCompoundAssignment(Opcode Opc) {
> +    assert(isCompoundAssignmentOp(Opc));
> +    if (Opc >= BO_XorAssign)
> +      return Opcode(unsigned(Opc) - BO_XorAssign + BO_Xor);
> +    else
> +      return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul);
> +  }
>
>   static bool isShiftAssignOp(Opcode Opc) {
>     return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
> @@ -4251,6 +4258,140 @@
>   child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
>  };
>
> +/// PseudoObjectExpr - An expression which accesses a pseudo-object
> +/// l-value.  A pseudo-object is an abstract object, accesses to which
> +/// are translated to calls.  The pseudo-object expression has a
> +/// syntactic form, which shows how the expression was actually
> +/// written in the source code, and a semantic form, which is a series
> +/// of expressions to be executed in order which detail how the
> +/// operation is actually evaluated.  Optionally, one of the semantic
> +/// forms may also provide a result value for the expression.
> +///
> +/// If any of the semantic-form expressions is an OpaqueValueExpr,
> +/// that OVE is required to have a source expression, and it is bound
> +/// to the result of that source expression.  Such OVEs may appear
> +/// only in subsequent semantic-form expressions and as
> +/// sub-expressions of the syntactic form.
> +///
> +/// PseudoObjectExpr should be used only when an operation can be
> +/// usefully described in terms of fairly simple rewrite rules on
> +/// objects and functions that are meant to be used by end-developers.
> +/// For example, under the Itanium ABI, dynamic casts are implemented
> +/// as a call to a runtime function called __dynamic_cast; using this
> +/// class to describe that would be inappropriate because that call is
> +/// not really part of the user-visible semantics, and instead the
> +/// cast is properly reflected in the AST and IR-generation has been
> +/// taught to generate the call as necessary.  In contrast, an
> +/// Objective-C property access is semantically defined to be
> +/// equivalent to a particular message send, and this is very much
> +/// part of the user model.  The name of this class encourages this
> +/// modelling design.
> +class PseudoObjectExpr : public Expr {
> +  // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions.
> +  // Always at least two, because the first sub-expression is the
> +  // syntactic form.
> +
> +  // PseudoObjectExprBits.ResultIndex - The index of the
> +  // sub-expression holding the result.  0 means the result is void,
> +  // which is unambiguous because it's the index of the syntactic
> +  // form.  Note that this is therefore 1 higher than the value passed
> +  // in to Create, which is an index within the semantic forms.
> +  // Note also that ASTStmtWriter assumes this encoding.
> +
> +  Expr **getSubExprsBuffer() { return reinterpret_cast<Expr**>(this + 1);
> }
> +  const Expr * const *getSubExprsBuffer() const {
> +    return reinterpret_cast<const Expr * const *>(this + 1);
> +  }
> +
> +  friend class ASTStmtReader;
> +
> +  PseudoObjectExpr(QualType type, ExprValueKind VK,
> +                   Expr *syntactic, ArrayRef<Expr*> semantic,
> +                   unsigned resultIndex);
> +
> +  PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs);
> +
> +  unsigned getNumSubExprs() const {
> +    return PseudoObjectExprBits.NumSubExprs;
> +  }
> +
> +public:
> +  /// NoResult - A value for the result index indicating that there is
> +  /// no semantic result.
> +  enum { NoResult = ~0U };
> +
> +  static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic,
> +                                  ArrayRef<Expr*> semantic,
> +                                  unsigned resultIndex);
> +
> +  static PseudoObjectExpr *Create(ASTContext &Context, EmptyShell shell,
> +                                  unsigned numSemanticExprs);
> +
> +  /// Return the syntactic form of this expression, i.e. the
> +  /// expression it actually looks like.  Likely to be expressed in
> +  /// terms of OpaqueValueExprs bound in the semantic form.
> +  Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; }
> +  const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; }
> +
> +  /// Return the index of the result-bearing expression into the semantics
> +  /// expressions, or PseudoObjectExpr::NoResult if there is none.
> +  unsigned getResultExprIndex() const {
> +    if (PseudoObjectExprBits.ResultIndex == 0) return NoResult;
> +    return PseudoObjectExprBits.ResultIndex - 1;
> +  }
> +
> +  /// Return the result-bearing expression, or null if there is none.
> +  Expr *getResultExpr() {
> +    if (PseudoObjectExprBits.ResultIndex == 0)
> +      return 0;
> +    return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex];
> +  }
> +  const Expr *getResultExpr() const {
> +    return const_cast<PseudoObjectExpr*>(this)->getResultExpr();
> +  }
> +
> +  unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; }
> +
> +  typedef Expr * const *semantics_iterator;
> +  typedef const Expr * const *const_semantics_iterator;
> +  semantics_iterator semantics_begin() {
> +    return getSubExprsBuffer() + 1;
> +  }
> +  const_semantics_iterator semantics_begin() const {
> +    return getSubExprsBuffer() + 1;
> +  }
> +  semantics_iterator semantics_end() {
> +    return getSubExprsBuffer() + getNumSubExprs();
> +  }
> +  const_semantics_iterator semantics_end() const {
> +    return getSubExprsBuffer() + getNumSubExprs();
> +  }
> +  Expr *getSemanticExpr(unsigned index) {
> +    assert(index + 1 < getNumSubExprs());
> +    return getSubExprsBuffer()[index + 1];
> +  }
> +  const Expr *getSemanticExpr(unsigned index) const {
> +    return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index);
> +  }
> +
> +  SourceLocation getExprLoc() const {
> +    return getSyntacticForm()->getExprLoc();
> +  }
> +  SourceRange getSourceRange() const {
> +    return getSyntacticForm()->getSourceRange();
> +  }
> +
> +  child_range children() {
> +    Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer());
> +    return child_range(cs, cs + getNumSubExprs());
> +  }
> +
> +  static bool classof(const Stmt *T) {
> +    return T->getStmtClass() == PseudoObjectExprClass;
> +  }
> +  static bool classof(const PseudoObjectExpr *) { return true; }
> +};
> +
>  /// AtomicExpr - Variadic atomic builtins: __atomic_exchange,
> __atomic_fetch_*,
>  /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for
> the
>  /// similarly-named C++0x instructions.  All of these instructions take
> one
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Sun Nov  6 03:01:30
> 2011
> @@ -1874,6 +1874,23 @@
>   return true;
>  }
>
> +// PseudoObjectExpr is a special case because of the wierdness with
> +// syntactic expressions and opaque values.
> +template<typename Derived>
> +bool RecursiveASTVisitor<Derived>::
> +TraversePseudoObjectExpr(PseudoObjectExpr *S) {
> +  TRY_TO(WalkUpFromPseudoObjectExpr(S));
> +  TRY_TO(TraverseStmt(S->getSyntacticForm()));
> +  for (PseudoObjectExpr::semantics_iterator
> +         i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) {
> +    Expr *sub = *i;
> +    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
> +      sub = OVE->getSourceExpr();
> +    TRY_TO(TraverseStmt(sub));
> +  }
> +  return true;
> +}
> +
>  DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
>     // This is called for code like 'return T()' where T is a built-in
>     // (i.e. non-class) type.
>
> Modified: cfe/trunk/include/clang/AST/Stmt.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Stmt.h (original)
> +++ cfe/trunk/include/clang/AST/Stmt.h Sun Nov  6 03:01:30 2011
> @@ -146,6 +146,7 @@
>     friend class CXXUnresolvedConstructExpr; // ctor
>     friend class CXXDependentScopeMemberExpr; // ctor
>     friend class OverloadExpr; // ctor
> +    friend class PseudoObjectExpr; // ctor
>     friend class AtomicExpr; // ctor
>     unsigned : NumStmtBits;
>
> @@ -184,6 +185,18 @@
>     unsigned NumPreArgs : 1;
>   };
>
> +  class PseudoObjectExprBitfields {
> +    friend class PseudoObjectExpr;
> +    friend class ASTStmtReader; // deserialization
> +
> +    unsigned : NumExprBits;
> +
> +    // These don't need to be particularly wide, because they're
> +    // strictly limited by the forms of expressions we permit.
> +    unsigned NumSubExprs : 8;
> +    unsigned ResultIndex : 32 - 8 - NumExprBits;
> +  };
> +
>   class ObjCIndirectCopyRestoreExprBitfields {
>     friend class ObjCIndirectCopyRestoreExpr;
>     unsigned : NumExprBits;
> @@ -201,6 +214,7 @@
>     DeclRefExprBitfields DeclRefExprBits;
>     CastExprBitfields CastExprBits;
>     CallExprBitfields CallExprBits;
> +    PseudoObjectExprBitfields PseudoObjectExprBits;
>     ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
>   };
>
>
> Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/StmtNodes.td Sun Nov  6 03:01:30 2011
> @@ -77,6 +77,7 @@
>  def ParenListExpr : DStmt<Expr>;
>  def VAArgExpr : DStmt<Expr>;
>  def GenericSelectionExpr : DStmt<Expr>;
> +def PseudoObjectExpr : DStmt<Expr>;
>
>  // Atomic expressions
>  def AtomicExpr : DStmt<Expr>;
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Sun Nov  6
> 03:01:30 2011
> @@ -1000,6 +1000,8 @@
>       EXPR_BLOCK_DECL_REF,
>       /// \brief A GenericSelectionExpr record.
>       EXPR_GENERIC_SELECTION,
> +      /// \brief A PseudoObjectExpr record.
> +      EXPR_PSEUDO_OBJECT,
>       /// \brief An AtomicExpr record.
>       EXPR_ATOMIC,
>
>
> Modified: cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp Sun Nov  6
> 03:01:30 2011
> @@ -160,12 +160,14 @@
>     if (!E) return false;
>
>     E = E->IgnoreParenCasts();
> +
> +    // Also look through property-getter sugar.
> +    if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E))
> +      E = pseudoOp->getResultExpr()->IgnoreImplicit();
> +
>     if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
>       return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);
>
> -    if (ObjCPropertyRefExpr *propE = dyn_cast<ObjCPropertyRefExpr>(E))
> -      return propE->getGetterSelector() == DelegateSel;
> -
>     return false;
>   }
>
>
> Modified: cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp Sun Nov  6 03:01:30
> 2011
> @@ -236,7 +236,15 @@
>       }
>     }
>
> -    if (ImplicitCastExpr *implCE =
> dyn_cast<ImplicitCastExpr>(E->getSubExpr())){
> +    Expr *subExpr = E->getSubExpr();
> +
> +    // Look through pseudo-object expressions.
> +    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
> +      subExpr = pseudo->getResultExpr();
> +      assert(subExpr && "no result for pseudo-object of non-void type?");
> +    }
> +
> +    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
>       if (implCE->getCastKind() == CK_ARCConsumeObject)
>         return rewriteToBridgedCast(E, OBC_BridgeRetained);
>       if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
>
> Modified: cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp Sun Nov  6
> 03:01:30 2011
> @@ -78,6 +78,15 @@
>     return true;
>   }
>
> +  bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
> +    if (isZeroingPropIvar(POE) && isRemovable(POE)) {
> +      Transaction Trans(Pass.TA);
> +      Pass.TA.removeStmt(POE);
> +    }
> +
> +    return true;
> +  }
> +
>   bool VisitBinaryOperator(BinaryOperator *BOE) {
>     if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
>       Transaction Trans(Pass.TA);
> @@ -142,17 +151,21 @@
>   }
>
>   bool isZeroingPropIvar(Expr *E) {
> -    BinaryOperator *BOE = dyn_cast_or_null<BinaryOperator>(E);
> -    if (!BOE) return false;
> +    E = E->IgnoreParens();
> +    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
> +      return isZeroingPropIvar(BO);
> +    if (PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(E))
> +      return isZeroingPropIvar(PO);
> +    return false;
> +  }
>
> +  bool isZeroingPropIvar(BinaryOperator *BOE) {
>     if (BOE->getOpcode() == BO_Comma)
>       return isZeroingPropIvar(BOE->getLHS()) &&
>              isZeroingPropIvar(BOE->getRHS());
>
>     if (BOE->getOpcode() != BO_Assign)
> -        return false;
> -
> -    ASTContext &Ctx = Pass.Ctx;
> +      return false;
>
>     Expr *LHS = BOE->getLHS();
>     if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {
> @@ -172,25 +185,38 @@
>       if (!IvarBacksPropertySynthesis)
>         return false;
>     }
> -    else if (ObjCPropertyRefExpr *PropRefExp =
> dyn_cast<ObjCPropertyRefExpr>(LHS)) {
> -      // TODO: Using implicit property decl.
> -      if (PropRefExp->isImplicitProperty())
> -        return false;
> -      if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
> -        if (!SynthesizedProperties.count(PDecl))
> -          return false;
> -      }
> -    }
>     else
>         return false;
>
> -    Expr *RHS = BOE->getRHS();
> -    bool RHSIsNull = RHS->isNullPointerConstant(Ctx,
> -
>  Expr::NPC_ValueDependentIsNull);
> -    if (RHSIsNull)
> +    return isZero(BOE->getRHS());
> +  }
> +
> +  bool isZeroingPropIvar(PseudoObjectExpr *PO) {
> +    BinaryOperator *BO = dyn_cast<BinaryOperator>(PO->getSyntacticForm());
> +    if (!BO) return false;
> +    if (BO->getOpcode() != BO_Assign) return false;
> +
> +    ObjCPropertyRefExpr *PropRefExp =
> +      dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParens());
> +    if (!PropRefExp) return false;
> +
> +    // TODO: Using implicit property decl.
> +    if (PropRefExp->isImplicitProperty())
> +      return false;
> +
> +    if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
> +      if (!SynthesizedProperties.count(PDecl))
> +        return false;
> +    }
> +
> +    return isZero(cast<OpaqueValueExpr>(BO->getRHS())->getSourceExpr());
> +  }
> +
> +  bool isZero(Expr *E) {
> +    if (E->isNullPointerConstant(Pass.Ctx,
> Expr::NPC_ValueDependentIsNull))
>       return true;
>
> -    return isZeroingPropIvar(RHS);
> +    return isZeroingPropIvar(E);
>   }
>  };
>
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Sun Nov  6 03:01:30 2011
> @@ -640,7 +640,11 @@
>  }
>
>  DeclContext *Decl::getNonClosureContext() {
> -  DeclContext *DC = getDeclContext();
> +  return getDeclContext()->getNonClosureAncestor();
> +}
> +
> +DeclContext *DeclContext::getNonClosureAncestor() {
> +  DeclContext *DC = this;
>
>   // This is basically "while (DC->isClosure()) DC = DC->getParent();"
>   // except that it's significantly more efficient to cast to a known
>
> Modified: cfe/trunk/lib/AST/Expr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Expr.cpp (original)
> +++ cfe/trunk/lib/AST/Expr.cpp Sun Nov  6 03:01:30 2011
> @@ -1694,6 +1694,19 @@
>     R1 = getSourceRange();
>     return true;
>
> +  case PseudoObjectExprClass: {
> +    const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this);
> +
> +    // Only complain about things that have the form of a getter.
> +    if (isa<UnaryOperator>(PO->getSyntacticForm()) ||
> +        isa<BinaryOperator>(PO->getSyntacticForm()))
> +      return false;
> +
> +    Loc = getExprLoc();
> +    R1 = getSourceRange();
> +    return true;
> +  }
> +
>   case StmtExprClass: {
>     // Statement exprs don't logically have side effects themselves, but
> are
>     // sometimes used in macros in ways that give them a type that is
> unused.
> @@ -2598,6 +2611,9 @@
>   } else if (const MaterializeTemporaryExpr *M
>                                    =
> dyn_cast<MaterializeTemporaryExpr>(this)) {
>     return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
> +  } else if (const OpaqueValueExpr *OVE =
> dyn_cast<OpaqueValueExpr>(this)) {
> +    if (const Expr *Source = OVE->getSourceExpr())
> +      return Source->isNullPointerConstant(Ctx, NPC);
>   }
>
>   // C++0x nullptr_t is always a null pointer constant.
> @@ -3306,6 +3322,72 @@
>   return cast<OpaqueValueExpr>(e);
>  }
>
> +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context,
> EmptyShell sh,
> +                                           unsigned numSemanticExprs) {
> +  void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) +
> +                                    (1 + numSemanticExprs) *
> sizeof(Expr*),
> +                                  llvm::alignOf<PseudoObjectExpr>());
> +  return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);
> +}
> +
> +PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned
> numSemanticExprs)
> +  : Expr(PseudoObjectExprClass, shell) {
> +  PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1;
> +}
> +
> +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax,
> +                                           ArrayRef<Expr*> semantics,
> +                                           unsigned resultIndex) {
> +  assert(syntax && "no syntactic expression!");
> +  assert(semantics.size() && "no semantic expressions!");
> +
> +  QualType type;
> +  ExprValueKind VK;
> +  if (resultIndex == NoResult) {
> +    type = C.VoidTy;
> +    VK = VK_RValue;
> +  } else {
> +    assert(resultIndex < semantics.size());
> +    type = semantics[resultIndex]->getType();
> +    VK = semantics[resultIndex]->getValueKind();
> +    assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary);
> +  }
> +
> +  void *buffer = C.Allocate(sizeof(PseudoObjectExpr) +
> +                              (1 + semantics.size()) * sizeof(Expr*),
> +                            llvm::alignOf<PseudoObjectExpr>());
> +  return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,
> +                                      resultIndex);
> +}
> +
> +PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,
> +                                   Expr *syntax, ArrayRef<Expr*>
> semantics,
> +                                   unsigned resultIndex)
> +  : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary,
> +         /*filled in at end of ctor*/ false, false, false, false) {
> +  PseudoObjectExprBits.NumSubExprs = semantics.size() + 1;
> +  PseudoObjectExprBits.ResultIndex = resultIndex + 1;
> +
> +  for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) {
> +    Expr *E = (i == 0 ? syntax : semantics[i-1]);
> +    getSubExprsBuffer()[i] = E;
> +
> +    if (E->isTypeDependent())
> +      ExprBits.TypeDependent = true;
> +    if (E->isValueDependent())
> +      ExprBits.ValueDependent = true;
> +    if (E->isInstantiationDependent())
> +      ExprBits.InstantiationDependent = true;
> +    if (E->containsUnexpandedParameterPack())
> +      ExprBits.ContainsUnexpandedParameterPack = true;
> +
> +    if (isa<OpaqueValueExpr>(E))
> +      assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 &&
> +             "opaque-value semantic expressions for pseudo-object "
> +             "operations must have sources");
> +  }
> +}
> +
>
>  //===----------------------------------------------------------------------===//
>  //  ExprIterator.
>
>  //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/lib/AST/ExprClassification.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprClassification.cpp (original)
> +++ cfe/trunk/lib/AST/ExprClassification.cpp Sun Nov  6 03:01:30 2011
> @@ -232,6 +232,11 @@
>     return ClassifyExprValueKind(Lang, E,
>                                  cast<OpaqueValueExpr>(E)->getValueKind());
>
> +    // Pseudo-object expressions can produce l-values with reference
> magic.
> +  case Expr::PseudoObjectExprClass:
> +    return ClassifyExprValueKind(Lang, E,
> +
> cast<PseudoObjectExpr>(E)->getValueKind());
> +
>     // Implicit casts are lvalues if they're lvalue casts. Other than
> that, we
>     // only specifically record class temporaries.
>   case Expr::ImplicitCastExprClass:
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Nov  6 03:01:30 2011
> @@ -3450,6 +3450,7 @@
>   case Expr::AsTypeExprClass:
>   case Expr::ObjCIndirectCopyRestoreExprClass:
>   case Expr::MaterializeTemporaryExprClass:
> +  case Expr::PseudoObjectExprClass:
>   case Expr::AtomicExprClass:
>     return ICEDiag(2, E->getLocStart());
>
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Sun Nov  6 03:01:30 2011
> @@ -2257,6 +2257,7 @@
>   case Expr::CXXNoexceptExprClass:
>   case Expr::CUDAKernelCallExprClass:
>   case Expr::AsTypeExprClass:
> +  case Expr::PseudoObjectExprClass:
>   case Expr::AtomicExprClass:
>   {
>     // As bad as this diagnostic is, it's better than crashing.
>
> Modified: cfe/trunk/lib/AST/StmtDumper.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtDumper.cpp (original)
> +++ cfe/trunk/lib/AST/StmtDumper.cpp Sun Nov  6 03:01:30 2011
> @@ -148,6 +148,7 @@
>     void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
>     void VisitAddrLabelExpr(AddrLabelExpr *Node);
>     void VisitBlockExpr(BlockExpr *Node);
> +    void VisitOpaqueValueExpr(OpaqueValueExpr *Node);
>
>     // C++
>     void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
> @@ -524,6 +525,15 @@
>   DumpSubTree(block->getBody());
>  }
>
> +void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
> +  DumpExpr(Node);
> +
> +  if (Expr *Source = Node->getSourceExpr()) {
> +    OS << '\n';
> +    DumpSubTree(Source);
> +  }
> +}
> +
>  // GNU extensions.
>
>  void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Sun Nov  6 03:01:30 2011
> @@ -1027,6 +1027,10 @@
>   OS << ")";
>  }
>
> +void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) {
> +  PrintExpr(Node->getSyntacticForm());
> +}
> +
>  void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
>   const char *Name = 0;
>   switch (Node->getOp()) {
>
> Modified: cfe/trunk/lib/AST/StmtProfile.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtProfile.cpp (original)
> +++ cfe/trunk/lib/AST/StmtProfile.cpp Sun Nov  6 03:01:30 2011
> @@ -475,6 +475,15 @@
>   }
>  }
>
> +void StmtProfiler::VisitPseudoObjectExpr(const PseudoObjectExpr *S) {
> +  VisitExpr(S);
> +  for (PseudoObjectExpr::const_semantics_iterator
> +         i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i)
> +    // Normally, we would not profile the source expressions of OVEs.
> +    if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i))
> +      Visit(OVE->getSourceExpr());
> +}
> +
>  void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) {
>   VisitExpr(S);
>   ID.AddInteger(S->getOp());
>
> Modified: cfe/trunk/lib/Analysis/CFG.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Analysis/CFG.cpp (original)
> +++ cfe/trunk/lib/Analysis/CFG.cpp Sun Nov  6 03:01:30 2011
> @@ -344,6 +344,7 @@
>   CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
>   CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
>   CFGBlock *VisitReturnStmt(ReturnStmt *R);
> +  CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
>   CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
>                                           AddStmtChoice asc);
>   CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
> @@ -981,6 +982,9 @@
>     case Stmt::OpaqueValueExprClass:
>       return Block;
>
> +    case Stmt::PseudoObjectExprClass:
> +      return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
> +
>     case Stmt::ReturnStmtClass:
>       return VisitReturnStmt(cast<ReturnStmt>(S));
>
> @@ -1907,6 +1911,31 @@
>   return NYS();
>  }
>
> +CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +  autoCreateBlock();
> +
> +  // Add the PseudoObject as the last thing.
> +  appendStmt(Block, E);
> +
> +  CFGBlock *lastBlock = Block;
> +
> +  // Before that, evaluate all of the semantics in order.  In
> +  // CFG-land, that means appending them in reverse order.
> +  for (unsigned i = E->getNumSemanticExprs(); i != 0; ) {
> +    Expr *Semantic = E->getSemanticExpr(--i);
> +
> +    // If the semantic is an opaque value, we're being asked to bind
> +    // it to its source expression.
> +    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
> +      Semantic = OVE->getSourceExpr();
> +
> +    if (CFGBlock *B = Visit(Semantic))
> +      lastBlock = B;
> +  }
> +
> +  return lastBlock;
> +}
> +
>  CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
>   CFGBlock *LoopSuccessor = NULL;
>
>
> Modified: cfe/trunk/lib/Analysis/LiveVariables.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/LiveVariables.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Analysis/LiveVariables.cpp (original)
> +++ cfe/trunk/lib/Analysis/LiveVariables.cpp Sun Nov  6 03:01:30 2011
> @@ -288,6 +288,18 @@
>       }
>       break;
>     }
> +    case Stmt::PseudoObjectExprClass: {
> +      // A pseudo-object operation only directly consumes its result
> +      // expression.
> +      Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();
> +      if (!child) return;
> +      if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
> +        child = OV->getSourceExpr();
> +      child = child->IgnoreParens();
> +      val.liveStmts = LV.SSetFact.add(val.liveStmts, child);
> +      return;
> +    }
> +
>     // FIXME: These cases eventually shouldn't be needed.
>     case Stmt::ExprWithCleanupsClass: {
>       S = cast<ExprWithCleanups>(S)->getSubExpr();
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Nov  6 03:01:30 2011
> @@ -672,6 +672,8 @@
>     return EmitStringLiteralLValue(cast<StringLiteral>(E));
>   case Expr::ObjCEncodeExprClass:
>     return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E));
> +  case Expr::PseudoObjectExprClass:
> +    return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E));
>
>   case Expr::BlockDeclRefExprClass:
>     return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E));
> @@ -2768,3 +2770,86 @@
>
> cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy,
>                                             Node);
>  }
> +
> +namespace {
> +  struct LValueOrRValue {
> +    LValue LV;
> +    RValue RV;
> +  };
> +}
> +
> +static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
> +                                           const PseudoObjectExpr *E,
> +                                           bool forLValue,
> +                                           AggValueSlot slot) {
> +  llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques;
> +
> +  // Find the result expression, if any.
> +  const Expr *resultExpr = E->getResultExpr();
> +  LValueOrRValue result;
> +
> +  for (PseudoObjectExpr::const_semantics_iterator
> +         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {
> +    const Expr *semantic = *i;
> +
> +    // If this semantic expression is an opaque value, bind it
> +    // to the result of its source expression.
> +    if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
> +
> +      // If this is the result expression, we may need to evaluate
> +      // directly into the slot.
> +      typedef CodeGenFunction::OpaqueValueMappingData OVMA;
> +      OVMA opaqueData;
> +      if (ov == resultExpr && ov->isRValue() && !forLValue &&
> +          CodeGenFunction::hasAggregateLLVMType(ov->getType()) &&
> +          !ov->getType()->isAnyComplexType()) {
> +        CGF.EmitAggExpr(ov->getSourceExpr(), slot);
> +
> +        LValue LV = CGF.MakeAddrLValue(slot.getAddr(), ov->getType());
> +        opaqueData = OVMA::bind(CGF, ov, LV);
> +        result.RV = slot.asRValue();
> +
> +      // Otherwise, emit as normal.
> +      } else {
> +        opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr());
> +
> +        // If this is the result, also evaluate the result now.
> +        if (ov == resultExpr) {
> +          if (forLValue)
> +            result.LV = CGF.EmitLValue(ov);
> +          else
> +            result.RV = CGF.EmitAnyExpr(ov, slot);
> +        }
> +      }
> +
> +      opaques.push_back(opaqueData);
> +
> +    // Otherwise, if the expression is the result, evaluate it
> +    // and remember the result.
> +    } else if (semantic == resultExpr) {
> +      if (forLValue)
> +        result.LV = CGF.EmitLValue(semantic);
> +      else
> +        result.RV = CGF.EmitAnyExpr(semantic, slot);
> +
> +    // Otherwise, evaluate the expression in an ignored context.
> +    } else {
> +      CGF.EmitIgnoredExpr(semantic);
> +    }
> +  }
> +
> +  // Unbind all the opaques now.
> +  for (unsigned i = 0, e = opaques.size(); i != e; ++i)
> +    opaques[i].unbind(CGF);
> +
> +  return result;
> +}
> +
> +RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E,
> +                                               AggValueSlot slot) {
> +  return emitPseudoObjectExpr(*this, E, false, slot).RV;
> +}
> +
> +LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E)
> {
> +  return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV;
> +}
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sun Nov  6 03:01:30 2011
> @@ -148,6 +148,15 @@
>   void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
>   void VisitOpaqueValueExpr(OpaqueValueExpr *E);
>
> +  void VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +    if (E->isGLValue()) {
> +      LValue LV = CGF.EmitPseudoObjectLValue(E);
> +      return EmitFinalDestCopy(E, LV);
> +    }
> +
> +    CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType()));
> +  }
> +
>   void VisitVAArgExpr(VAArgExpr *E);
>
>   void EmitInitializationToLValue(Expr *E, LValue Address);
>
> Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Sun Nov  6 03:01:30 2011
> @@ -137,6 +137,10 @@
>     return CGF.getOpaqueRValueMapping(E).getComplexVal();
>   }
>
> +  ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +    return CGF.EmitPseudoObjectRValue(E).getComplexVal();
> +  }
> +
>   // FIXME: CompoundLiteralExpr
>
>   ComplexPairTy EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy);
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Nov  6 03:01:30 2011
> @@ -197,6 +197,10 @@
>     return
> llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength());
>   }
>
> +  Value *VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +    return CGF.EmitPseudoObjectRValue(E).getScalarVal();
> +  }
> +
>   Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
>     if (E->isGLValue())
>       return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Nov  6 03:01:30 2011
> @@ -2231,6 +2231,59 @@
>   return true;
>  }
>
> +/// Try to emit a PseudoObjectExpr at +1.
> +///
> +/// This massively duplicates emitPseudoObjectRValue.
> +static TryEmitResult tryEmitARCRetainPseudoObject(CodeGenFunction &CGF,
> +                                                  const PseudoObjectExpr
> *E) {
> +  llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques;
> +
> +  // Find the result expression.
> +  const Expr *resultExpr = E->getResultExpr();
> +  assert(resultExpr);
> +  TryEmitResult result;
> +
> +  for (PseudoObjectExpr::const_semantics_iterator
> +         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {
> +    const Expr *semantic = *i;
> +
> +    // If this semantic expression is an opaque value, bind it
> +    // to the result of its source expression.
> +    if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
> +      typedef CodeGenFunction::OpaqueValueMappingData OVMA;
> +      OVMA opaqueData;
> +
> +      // If this semantic is the result of the pseudo-object
> +      // expression, try to evaluate the source as +1.
> +      if (ov == resultExpr) {
> +        assert(!OVMA::shouldBindAsLValue(ov));
> +        result = tryEmitARCRetainScalarExpr(CGF, ov->getSourceExpr());
> +        opaqueData = OVMA::bind(CGF, ov,
> RValue::get(result.getPointer()));
> +
> +      // Otherwise, just bind it.
> +      } else {
> +        opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr());
> +      }
> +      opaques.push_back(opaqueData);
> +
> +    // Otherwise, if the expression is the result, evaluate it
> +    // and remember the result.
> +    } else if (semantic == resultExpr) {
> +      result = tryEmitARCRetainScalarExpr(CGF, semantic);
> +
> +    // Otherwise, evaluate the expression in an ignored context.
> +    } else {
> +      CGF.EmitIgnoredExpr(semantic);
> +    }
> +  }
> +
> +  // Unbind all the opaques now.
> +  for (unsigned i = 0, e = opaques.size(); i != e; ++i)
> +    opaques[i].unbind(CGF);
> +
> +  return result;
> +}
> +
>  static TryEmitResult
>  tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) {
>   // Look through cleanups.
> @@ -2356,6 +2409,17 @@
>       llvm::Value *result = emitARCRetainCall(CGF, e);
>       if (resultType) result = CGF.Builder.CreateBitCast(result,
> resultType);
>       return TryEmitResult(result, true);
> +
> +    // Look through pseudo-object expressions.
> +    } else if (const PseudoObjectExpr *pseudo =
> dyn_cast<PseudoObjectExpr>(e)) {
> +      TryEmitResult result
> +        = tryEmitARCRetainPseudoObject(CGF, pseudo);
> +      if (resultType) {
> +        llvm::Value *value = result.getPointer();
> +        value = CGF.Builder.CreateBitCast(value, resultType);
> +        result.setPointer(value);
> +      }
> +      return result;
>     }
>
>     // Conservatively halt the search at any other expression kind.
>
> Modified: cfe/trunk/lib/CodeGen/CGValue.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGValue.h (original)
> +++ cfe/trunk/lib/CodeGen/CGValue.h Sun Nov  6 03:01:30 2011
> @@ -27,6 +27,7 @@
>   class ObjCPropertyRefExpr;
>
>  namespace CodeGen {
> +  class AggValueSlot;
>   class CGBitFieldInfo;
>
>  /// RValue - This trivial value class is used to represent the result of
> an
> @@ -452,7 +453,7 @@
>   RValue asRValue() const {
>     return RValue::getAggregate(getAddr(), isVolatile());
>   }
> -
> +
>   void setZeroed(bool V = true) { ZeroedFlag = V; }
>   IsZeroed_t isZeroed() const {
>     return IsZeroed_t(ZeroedFlag);
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sun Nov  6 03:01:30 2011
> @@ -950,20 +950,86 @@
>
>   public:
>     PeepholeProtection() : Inst(0) {}
> -  };
> +  };
>
> -  /// An RAII object to set (and then clear) a mapping for an
> OpaqueValueExpr.
> -  class OpaqueValueMapping {
> -    CodeGenFunction &CGF;
> +  /// A non-RAII class containing all the information about a bound
> +  /// opaque value.  OpaqueValueMapping, below, is a RAII wrapper for
> +  /// this which makes individual mappings very simple; using this
> +  /// class directly is useful when you have a variable number of
> +  /// opaque values or don't want the RAII functionality for some
> +  /// reason.
> +  class OpaqueValueMappingData {
>     const OpaqueValueExpr *OpaqueValue;
>     bool BoundLValue;
>     CodeGenFunction::PeepholeProtection Protection;
>
> +    OpaqueValueMappingData(const OpaqueValueExpr *ov,
> +                           bool boundLValue)
> +      : OpaqueValue(ov), BoundLValue(boundLValue) {}
>   public:
> +    OpaqueValueMappingData() : OpaqueValue(0) {}
> +
>     static bool shouldBindAsLValue(const Expr *expr) {
>       return expr->isGLValue() || expr->getType()->isRecordType();
>     }
>
> +    static OpaqueValueMappingData bind(CodeGenFunction &CGF,
> +                                       const OpaqueValueExpr *ov,
> +                                       const Expr *e) {
> +      if (shouldBindAsLValue(ov))
> +        return bind(CGF, ov, CGF.EmitLValue(e));
> +      return bind(CGF, ov, CGF.EmitAnyExpr(e));
> +    }
> +
> +    static OpaqueValueMappingData bind(CodeGenFunction &CGF,
> +                                       const OpaqueValueExpr *ov,
> +                                       const LValue &lv) {
> +      assert(shouldBindAsLValue(ov));
> +      CGF.OpaqueLValues.insert(std::make_pair(ov, lv));
> +      return OpaqueValueMappingData(ov, true);
> +    }
> +
> +    static OpaqueValueMappingData bind(CodeGenFunction &CGF,
> +                                       const OpaqueValueExpr *ov,
> +                                       const RValue &rv) {
> +      assert(!shouldBindAsLValue(ov));
> +      CGF.OpaqueRValues.insert(std::make_pair(ov, rv));
> +
> +      OpaqueValueMappingData data(ov, false);
> +
> +      // Work around an extremely aggressive peephole optimization in
> +      // EmitScalarConversion which assumes that all other uses of a
> +      // value are extant.
> +      data.Protection = CGF.protectFromPeepholes(rv);
> +
> +      return data;
> +    }
> +
> +    bool isValid() const { return OpaqueValue != 0; }
> +    void clear() { OpaqueValue = 0; }
> +
> +    void unbind(CodeGenFunction &CGF) {
> +      assert(OpaqueValue && "no data to unbind!");
> +
> +      if (BoundLValue) {
> +        CGF.OpaqueLValues.erase(OpaqueValue);
> +      } else {
> +        CGF.OpaqueRValues.erase(OpaqueValue);
> +        CGF.unprotectFromPeepholes(Protection);
> +      }
> +    }
> +  };
> +
> +  /// An RAII object to set (and then clear) a mapping for an
> OpaqueValueExpr.
> +  class OpaqueValueMapping {
> +    CodeGenFunction &CGF;
> +    OpaqueValueMappingData Data;
> +
> +  public:
> +    static bool shouldBindAsLValue(const Expr *expr) {
> +      return OpaqueValueMappingData::shouldBindAsLValue(expr);
> +    }
> +
>     /// Build the opaque value mapping for the given conditional
>     /// operator if it's the GNU ?: extension.  This is a common
>     /// enough pattern that the convenience operator is really
> @@ -971,75 +1037,34 @@
>     ///
>     OpaqueValueMapping(CodeGenFunction &CGF,
>                        const AbstractConditionalOperator *op) : CGF(CGF) {
> -      if (isa<ConditionalOperator>(op)) {
> -        OpaqueValue = 0;
> -        BoundLValue = false;
> +      if (isa<ConditionalOperator>(op))
> +        // Leave Data empty.
>         return;
> -      }
>
>       const BinaryConditionalOperator *e =
> cast<BinaryConditionalOperator>(op);
> -      init(e->getOpaqueValue(), e->getCommon());
> +      Data = OpaqueValueMappingData::bind(CGF, e->getOpaqueValue(),
> +                                          e->getCommon());
>     }
>
>     OpaqueValueMapping(CodeGenFunction &CGF,
>                        const OpaqueValueExpr *opaqueValue,
>                        LValue lvalue)
> -      : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(true) {
> -      assert(opaqueValue && "no opaque value expression!");
> -      assert(shouldBindAsLValue(opaqueValue));
> -      initLValue(lvalue);
> +      : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue,
> lvalue)) {
>     }
>
>     OpaqueValueMapping(CodeGenFunction &CGF,
>                        const OpaqueValueExpr *opaqueValue,
>                        RValue rvalue)
> -      : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(false) {
> -      assert(opaqueValue && "no opaque value expression!");
> -      assert(!shouldBindAsLValue(opaqueValue));
> -      initRValue(rvalue);
> +      : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue,
> rvalue)) {
>     }
>
>     void pop() {
> -      assert(OpaqueValue && "mapping already popped!");
> -      popImpl();
> -      OpaqueValue = 0;
> +      Data.unbind(CGF);
> +      Data.clear();
>     }
>
>     ~OpaqueValueMapping() {
> -      if (OpaqueValue) popImpl();
> -    }
> -
> -  private:
> -    void popImpl() {
> -      if (BoundLValue)
> -        CGF.OpaqueLValues.erase(OpaqueValue);
> -      else {
> -        CGF.OpaqueRValues.erase(OpaqueValue);
> -        CGF.unprotectFromPeepholes(Protection);
> -      }
> -    }
> -
> -    void init(const OpaqueValueExpr *ov, const Expr *e) {
> -      OpaqueValue = ov;
> -      BoundLValue = shouldBindAsLValue(ov);
> -      assert(BoundLValue == shouldBindAsLValue(e)
> -             && "inconsistent expression value kinds!");
> -      if (BoundLValue)
> -        initLValue(CGF.EmitLValue(e));
> -      else
> -        initRValue(CGF.EmitAnyExpr(e));
> -    }
> -
> -    void initLValue(const LValue &lv) {
> -      CGF.OpaqueLValues.insert(std::make_pair(OpaqueValue, lv));
> -    }
> -
> -    void initRValue(const RValue &rv) {
> -      // Work around an extremely aggressive peephole optimization in
> -      // EmitScalarConversion which assumes that all other uses of a
> -      // value are extant.
> -      Protection = CGF.protectFromPeepholes(rv);
> -      CGF.OpaqueRValues.insert(std::make_pair(OpaqueValue, rv));
> +      if (Data.isValid()) Data.unbind(CGF);
>     }
>   };
>
> @@ -2015,6 +2040,10 @@
>   LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
>   LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
>
> +  RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
> +                                AggValueSlot slot =
> AggValueSlot::ignored());
> +  LValue EmitPseudoObjectLValue(const PseudoObjectExpr *e);
> +
>   llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
>                               const ObjCIvarDecl *Ivar);
>   LValue EmitLValueForAnonRecordField(llvm::Value* Base,
>
> Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
> +++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Sun Nov  6 03:01:30 2011
> @@ -138,12 +138,6 @@
>
>     llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
>
> -    // This maps a property to it's assignment statement.
> -    llvm::DenseMap<Expr *, BinaryOperator *> PropSetters;
> -    // This maps a property to it's synthesied message expression.
> -    // This allows us to rewrite chained getters (e.g. o.a.b.c).
> -    llvm::DenseMap<Expr *, Stmt *> PropGetters;
> -
>     // This maps an original source AST to it's rewritten form. This allows
>     // us to avoid rewriting the same node twice (which is very uncommon).
>     // This is needed to support some of the exotic property rewriting.
> @@ -154,6 +148,19 @@
>     VarDecl *GlobalVarDecl;
>
>     bool DisableReplaceStmt;
> +    class DisableReplaceStmtScope {
> +      RewriteObjC &R;
> +      bool SavedValue;
> +
> +    public:
> +      DisableReplaceStmtScope(RewriteObjC &R)
> +        : R(R), SavedValue(R.DisableReplaceStmt) {
> +        R.DisableReplaceStmt = true;
> +      }
> +      ~DisableReplaceStmtScope() {
> +        R.DisableReplaceStmt = SavedValue;
> +      }
> +    };
>
>     static const int OBJC_ABI_VERSION = 7;
>   public:
> @@ -186,7 +193,7 @@
>         return; // We can't rewrite the same node twice.
>
>       if (DisableReplaceStmt)
> -        return; // Used when rewriting the assignment of a property
> setter.
> +        return;
>
>       // If replacement succeeded or warning disabled return with no
> warning.
>       if (!Rewrite.ReplaceStmt(Old, New)) {
> @@ -200,6 +207,9 @@
>     }
>
>     void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
> +      if (DisableReplaceStmt)
> +        return;
> +
>       // Measure the old text.
>       int Size = Rewrite.getRangeSize(SrcRange);
>       if (Size == -1) {
> @@ -282,18 +292,14 @@
>
>     // Expression Rewriting.
>     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
> -    void CollectPropertySetters(Stmt *S);
>
>     Stmt *CurrentBody;
>     ParentMap *PropParentMap; // created lazily.
>
>     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
> -    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation
> OrigStart,
> -                                 bool &replaced);
> -    Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
> -    Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr);
> -    Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr
> *newStmt,
> -                                SourceRange SrcRange);
> +    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
> +    Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
> +    Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
>     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
>     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
>     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
> @@ -1281,184 +1287,173 @@
>               "/* @end */");
>  }
>
> -Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp,
> Expr *newStmt,
> -                                         SourceRange SrcRange) {
> -  ObjCMethodDecl *OMD = 0;
> -  QualType Ty;
> -  Selector Sel;
> -  Stmt *Receiver = 0;
> -  bool Super = false;
> -  QualType SuperTy;
> -  SourceLocation SuperLocation;
> -  SourceLocation SelectorLoc;
> -  // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or
> ObjCImplicitSetterGetterRefExpr.
> -  // This allows us to reuse all the fun and games in SynthMessageExpr().
> -  if (ObjCPropertyRefExpr *PropRefExpr =
> -        dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) {
> -    SelectorLoc = PropRefExpr->getLocation();
> -    if (PropRefExpr->isExplicitProperty()) {
> -      ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty();
> -      OMD = PDecl->getSetterMethodDecl();
> -      Ty = PDecl->getType();
> -      Sel = PDecl->getSetterName();
> -    } else {
> -      OMD = PropRefExpr->getImplicitPropertySetter();
> -      Sel = OMD->getSelector();
> -      Ty = (*OMD->param_begin())->getType();
> -    }
> -    Super = PropRefExpr->isSuperReceiver();
> -    if (!Super) {
> -      Receiver = PropRefExpr->getBase();
> -    } else {
> -      SuperTy = PropRefExpr->getSuperReceiverType();
> -      SuperLocation = PropRefExpr->getReceiverLocation();
> -    }
> -  }
> -
> -  assert(OMD && "RewritePropertyOrImplicitSetter - null OMD");
> +Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr
> *PseudoOp) {
> +  SourceRange OldRange = PseudoOp->getSourceRange();
>
> -  ObjCMessageExpr *MsgExpr;
> -  if (Super)
> -    MsgExpr = ObjCMessageExpr::Create(*Context,
> -                                      Ty.getNonReferenceType(),
> -                                      Expr::getValueKindForType(Ty),
> -                                      /*FIXME?*/SourceLocation(),
> -                                      SuperLocation,
> -                                      /*IsInstanceSuper=*/true,
> -                                      SuperTy,
> -                                      Sel, SelectorLoc, OMD,
> -                                      newStmt,
> -                                      /*FIXME:*/SourceLocation());
> -  else {
> -    // FIXME. Refactor this into common code with that in
> -    // RewritePropertyOrImplicitGetter
> -    assert(Receiver && "RewritePropertyOrImplicitSetter - null Receiver");
> -    if (Expr *Exp = dyn_cast<Expr>(Receiver))
> -      if (PropGetters[Exp])
> -        // This allows us to handle chain/nested property/implicit
> getters.
> -        Receiver = PropGetters[Exp];
> -
> -    MsgExpr = ObjCMessageExpr::Create(*Context,
> -                                      Ty.getNonReferenceType(),
> -                                      Expr::getValueKindForType(Ty),
> -                                      /*FIXME: */SourceLocation(),
> -                                      cast<Expr>(Receiver),
> -                                      Sel, SelectorLoc, OMD,
> -                                      newStmt,
> -                                      /*FIXME:*/SourceLocation());
> +  // We just magically know some things about the structure of this
> +  // expression.
> +  ObjCMessageExpr *OldMsg =
> +    cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
> +                            PseudoOp->getNumSemanticExprs() - 1));
> +
> +  // Because the rewriter doesn't allow us to rewrite rewritten code,
> +  // we need to suppress rewriting the sub-statements.
> +  Expr *Base, *RHS;
> +  {
> +    DisableReplaceStmtScope S(*this);
> +
> +    // Rebuild the base expression if we have one.
> +    Base = 0;
> +    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
> +      Base = OldMsg->getInstanceReceiver();
> +      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
> +      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
> +    }
> +
> +    // Rebuild the RHS.
> +    RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();
> +    RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
> +    RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
> +  }
> +
> +  // TODO: avoid this copy.
> +  SmallVector<SourceLocation, 1> SelLocs;
> +  OldMsg->getSelectorLocs(SelLocs);
> +
> +  ObjCMessageExpr *NewMsg;
> +  switch (OldMsg->getReceiverKind()) {
> +  case ObjCMessageExpr::Class:
> +    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
> +                                     OldMsg->getValueKind(),
> +                                     OldMsg->getLeftLoc(),
> +                                     OldMsg->getClassReceiverTypeInfo(),
> +                                     OldMsg->getSelector(),
> +                                     SelLocs,
> +                                     OldMsg->getMethodDecl(),
> +                                     RHS,
> +                                     OldMsg->getRightLoc());
> +    break;
> +
> +  case ObjCMessageExpr::Instance:
> +    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
> +                                     OldMsg->getValueKind(),
> +                                     OldMsg->getLeftLoc(),
> +                                     Base,
> +                                     OldMsg->getSelector(),
> +                                     SelLocs,
> +                                     OldMsg->getMethodDecl(),
> +                                     RHS,
> +                                     OldMsg->getRightLoc());
> +    break;
> +
> +  case ObjCMessageExpr::SuperClass:
> +  case ObjCMessageExpr::SuperInstance:
> +    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
> +                                     OldMsg->getValueKind(),
> +                                     OldMsg->getLeftLoc(),
> +                                     OldMsg->getSuperLoc(),
> +                 OldMsg->getReceiverKind() ==
> ObjCMessageExpr::SuperInstance,
> +                                     OldMsg->getSuperType(),
> +                                     OldMsg->getSelector(),
> +                                     SelLocs,
> +                                     OldMsg->getMethodDecl(),
> +                                     RHS,
> +                                     OldMsg->getRightLoc());
> +    break;
>   }
> -  Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
>
> -  // Now do the actual rewrite.
> -  ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
> -  //delete BinOp;
> -  // NOTE: We don't want to call MsgExpr->Destroy(), as it holds
> references
> -  // to things that stay around.
> -  Context->Deallocate(MsgExpr);
> -  return ReplacingStmt;
> +  Stmt *Replacement = SynthMessageExpr(NewMsg);
> +  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
> +  return Replacement;
>  }
>
> -Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr
> *PropOrGetterRefExpr) {
> -  // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or
> ImplicitGetter.
> -  // This allows us to reuse all the fun and games in SynthMessageExpr().
> -  Stmt *Receiver = 0;
> -  ObjCMethodDecl *OMD = 0;
> -  QualType Ty;
> -  Selector Sel;
> -  bool Super = false;
> -  QualType SuperTy;
> -  SourceLocation SuperLocation;
> -  SourceLocation SelectorLoc;
> -  if (ObjCPropertyRefExpr *PropRefExpr =
> -        dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) {
> -    SelectorLoc = PropRefExpr->getLocation();
> -    if (PropRefExpr->isExplicitProperty()) {
> -      ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty();
> -      OMD = PDecl->getGetterMethodDecl();
> -      Ty = PDecl->getType();
> -      Sel = PDecl->getGetterName();
> -    } else {
> -      OMD = PropRefExpr->getImplicitPropertyGetter();
> -      Sel = OMD->getSelector();
> -      Ty = OMD->getResultType();
> -    }
> -    Super = PropRefExpr->isSuperReceiver();
> -    if (!Super)
> -      Receiver = PropRefExpr->getBase();
> -    else {
> -      SuperTy = PropRefExpr->getSuperReceiverType();
> -      SuperLocation = PropRefExpr->getReceiverLocation();
> +Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr
> *PseudoOp) {
> +  SourceRange OldRange = PseudoOp->getSourceRange();
> +
> +  // We just magically know some things about the structure of this
> +  // expression.
> +  ObjCMessageExpr *OldMsg =
> +    cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
> +
> +  // Because the rewriter doesn't allow us to rewrite rewritten code,
> +  // we need to suppress rewriting the sub-statements.
> +  Expr *Base = 0;
> +  {
> +    DisableReplaceStmtScope S(*this);
> +
> +    // Rebuild the base expression if we have one.
> +    if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
> +      Base = OldMsg->getInstanceReceiver();
> +      Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
> +      Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
>     }
>   }
> -
> -  assert (OMD && "RewritePropertyOrImplicitGetter - OMD is null");
> -
> -  ObjCMessageExpr *MsgExpr;
> -  if (Super)
> -    MsgExpr = ObjCMessageExpr::Create(*Context,
> -                                      Ty.getNonReferenceType(),
> -                                      Expr::getValueKindForType(Ty),
> -                                      PropOrGetterRefExpr->getLocStart(),
> -                                      SuperLocation,
> -                                      /*IsInstanceSuper=*/true,
> -                                      SuperTy,
> -                                      Sel, SelectorLoc, OMD,
> -                                      ArrayRef<Expr*>(),
> -                                      PropOrGetterRefExpr->getLocEnd());
> -  else {
> -    assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is
> null");
> -    if (Expr *Exp = dyn_cast<Expr>(Receiver))
> -      if (PropGetters[Exp])
> -        // This allows us to handle chain/nested property/implicit
> getters.
> -        Receiver = PropGetters[Exp];
> -    MsgExpr = ObjCMessageExpr::Create(*Context,
> -                                      Ty.getNonReferenceType(),
> -                                      Expr::getValueKindForType(Ty),
> -                                      PropOrGetterRefExpr->getLocStart(),
> -                                      cast<Expr>(Receiver),
> -                                      Sel, SelectorLoc, OMD,
> -                                      ArrayRef<Expr*>(),
> -                                      PropOrGetterRefExpr->getLocEnd());
> -  }
> -
> -  Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(),
> -                                         MsgExpr->getLocEnd());
> -
> -  if (!PropParentMap)
> -    PropParentMap = new ParentMap(CurrentBody);
> -  bool NestedPropertyRef = false;
> -  Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr);
> -  ImplicitCastExpr*ICE=0;
> -  if (Parent)
> -    if ((ICE = dyn_cast<ImplicitCastExpr>(Parent))) {
> -      assert((ICE->getCastKind() == CK_GetObjCProperty)
> -             && "RewritePropertyOrImplicitGetter");
> -      Parent = PropParentMap->getParent(Parent);
> -      NestedPropertyRef = (Parent && isa<ObjCPropertyRefExpr>(Parent));
> -    }
> -  if (NestedPropertyRef) {
> -    // We stash away the ReplacingStmt since actually doing the
> -    // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
> -    PropGetters[ICE] = ReplacingStmt;
> -    // NOTE: We don't want to call MsgExpr->Destroy(), as it holds
> references
> -    // to things that stay around.
> -    Context->Deallocate(MsgExpr);
> -    return PropOrGetterRefExpr; // return the original...
> -  } else {
> -    ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt);
> -    // delete PropRefExpr; elsewhere...
> -    // NOTE: We don't want to call MsgExpr->Destroy(), as it holds
> references
> -    // to things that stay around.
> -    Context->Deallocate(MsgExpr);
> -    return ReplacingStmt;
> +
> +  // Intentionally empty.
> +  SmallVector<SourceLocation, 1> SelLocs;
> +  SmallVector<Expr*, 1> Args;
> +
> +  ObjCMessageExpr *NewMsg;
> +  switch (OldMsg->getReceiverKind()) {
> +  case ObjCMessageExpr::Class:
> +    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
> +                                     OldMsg->getValueKind(),
> +                                     OldMsg->getLeftLoc(),
> +                                     OldMsg->getClassReceiverTypeInfo(),
> +                                     OldMsg->getSelector(),
> +                                     SelLocs,
> +                                     OldMsg->getMethodDecl(),
> +                                     Args,
> +                                     OldMsg->getRightLoc());
> +    break;
> +
> +  case ObjCMessageExpr::Instance:
> +    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
> +                                     OldMsg->getValueKind(),
> +                                     OldMsg->getLeftLoc(),
> +                                     Base,
> +                                     OldMsg->getSelector(),
> +                                     SelLocs,
> +                                     OldMsg->getMethodDecl(),
> +                                     Args,
> +                                     OldMsg->getRightLoc());
> +    break;
> +
> +  case ObjCMessageExpr::SuperClass:
> +  case ObjCMessageExpr::SuperInstance:
> +    NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
> +                                     OldMsg->getValueKind(),
> +                                     OldMsg->getLeftLoc(),
> +                                     OldMsg->getSuperLoc(),
> +                 OldMsg->getReceiverKind() ==
> ObjCMessageExpr::SuperInstance,
> +                                     OldMsg->getSuperType(),
> +                                     OldMsg->getSelector(),
> +                                     SelLocs,
> +                                     OldMsg->getMethodDecl(),
> +                                     Args,
> +                                     OldMsg->getRightLoc());
> +    break;
>   }
> +
> +  Stmt *Replacement = SynthMessageExpr(NewMsg);
> +  ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
> +  return Replacement;
>  }
>
> -Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
> -                                          SourceLocation OrigStart,
> -                                          bool &replaced) {
> +Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
> +  SourceRange OldRange = IV->getSourceRange();
> +  Expr *BaseExpr = IV->getBase();
> +
> +  // Rewrite the base, but without actually doing replaces.
> +  {
> +    DisableReplaceStmtScope S(*this);
> +    BaseExpr =
> cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
> +    IV->setBase(BaseExpr);
> +  }
> +
>   ObjCIvarDecl *D = IV->getDecl();
> -  const Expr *BaseExpr = IV->getBase();
> +
> +  Expr *Replacement = IV;
>   if (CurMethodDef) {
>     if (BaseExpr->getType()->isObjCObjectPointerType()) {
>       const ObjCInterfaceType *iFaceDecl =
> @@ -1483,25 +1478,19 @@
>                                                     CK_BitCast,
>                                                     IV->getBase());
>       // Don't forget the parens to enforce the proper binding.
> -      ParenExpr *PE = new (Context)
> ParenExpr(IV->getBase()->getLocStart(),
> -                                              IV->getBase()->getLocEnd(),
> +      ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
> +                                              OldRange.getEnd(),
>                                               castExpr);
> -      replaced = true;
>       if (IV->isFreeIvar() &&
>           CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
>         MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
>                                                   IV->getLocation(),
>                                                   D->getType(),
>                                                   VK_LValue, OK_Ordinary);
> -        // delete IV; leak for now, see RewritePropertyOrImplicitSetter()
> usage for more info.
> -        return ME;
> +        Replacement = ME;
> +      } else {
> +        IV->setBase(PE);
>       }
> -      // Get the new text
> -      // Cannot delete IV->getBase(), since PE points to it.
> -      // Replace the old base with the cast. This is important when doing
> -      // embedded rewrites. For example, [newInv->_container addObject:0].
> -      IV->setBase(PE);
> -      return IV;
>     }
>   } else { // we are outside a method.
>     assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside
> a method");
> @@ -1532,36 +1521,15 @@
>       // Don't forget the parens to enforce the proper binding.
>       ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
>                                     IV->getBase()->getLocEnd(), castExpr);
> -      replaced = true;
>       // Cannot delete IV->getBase(), since PE points to it.
>       // Replace the old base with the cast. This is important when doing
>       // embedded rewrites. For example, [newInv->_container addObject:0].
>       IV->setBase(PE);
> -      return IV;
>     }
>   }
> -  return IV;
> -}
>
> -Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {
> -  for (Stmt::child_range CI = S->children(); CI; ++CI) {
> -    if (*CI) {
> -      Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);
> -      if (newStmt)
> -        *CI = newStmt;
> -    }
> -  }
> -  if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
> -    SourceRange OrigStmtRange = S->getSourceRange();
> -    Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr,
> OrigStmtRange.getBegin(),
> -                                           replaced);
> -    return newStmt;
> -  }
> -  if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) {
> -    Stmt *newStmt = SynthMessageExpr(MsgRefExpr);
> -    return newStmt;
> -  }
> -  return S;
> +  ReplaceStmtWithRange(IV, Replacement, OldRange);
> +  return Replacement;
>  }
>
>  /// SynthCountByEnumWithState - To print:
> @@ -4753,6 +4721,9 @@
>     return CondExpr;
>   } else if (const ObjCIvarRefExpr *IRE =
> dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
>     CPT = IRE->getType()->getAs<BlockPointerType>();
> +  } else if (const PseudoObjectExpr *POE
> +               = dyn_cast<PseudoObjectExpr>(BlockExp)) {
> +    CPT = POE->getType()->castAs<BlockPointerType>();
>   } else {
>     assert(1 && "RewriteBlockClass: Bad type");
>   }
> @@ -5580,26 +5551,6 @@
>  // Function Body / Expression rewriting
>
>  //===----------------------------------------------------------------------===//
>
> -// This is run as a first "pass" prior to
> RewriteFunctionBodyOrGlobalInitializer().
> -// The allows the main rewrite loop to associate all ObjCPropertyRefExprs
> with
> -// their respective BinaryOperator. Without this knowledge, we'd need to
> rewrite
> -// the ObjCPropertyRefExpr twice (once as a getter, and later as a
> setter).
> -// Since the rewriter isn't capable of rewriting rewritten code, it's
> important
> -// we get this right.
> -void RewriteObjC::CollectPropertySetters(Stmt *S) {
> -  // Perform a bottom up traversal of all children.
> -  for (Stmt::child_range CI = S->children(); CI; ++CI)
> -    if (*CI)
> -      CollectPropertySetters(*CI);
> -
> -  if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
> -    if (BinOp->isAssignmentOp()) {
> -      if (isa<ObjCPropertyRefExpr>(BinOp->getLHS()))
> -        PropSetters[BinOp->getLHS()] = BinOp;
> -    }
> -  }
> -}
> -
>  Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
>   if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
>       isa<DoStmt>(S) || isa<ForStmt>(S))
> @@ -5609,46 +5560,28 @@
>     ObjCBcLabelNo.push_back(++BcLabelCount);
>   }
>
> +  // Pseudo-object operations and ivar references need special
> +  // treatment because we're going to recursively rewrite them.
> +  if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
> +    if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
> +      return RewritePropertyOrImplicitSetter(PseudoOp);
> +    } else {
> +      return RewritePropertyOrImplicitGetter(PseudoOp);
> +    }
> +  } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S))
> {
> +    return RewriteObjCIvarRefExpr(IvarRefExpr);
> +  }
> +
>   SourceRange OrigStmtRange = S->getSourceRange();
>
>   // Perform a bottom up rewrite of all children.
>   for (Stmt::child_range CI = S->children(); CI; ++CI)
>     if (*CI) {
> -      Stmt *newStmt;
> -      Stmt *ChildStmt = (*CI);
> -      if (ObjCIvarRefExpr *IvarRefExpr =
> dyn_cast<ObjCIvarRefExpr>(ChildStmt)) {
> -        Expr *OldBase = IvarRefExpr->getBase();
> -        bool replaced = false;
> -        newStmt = RewriteObjCNestedIvarRefExpr(ChildStmt, replaced);
> -        if (replaced) {
> -          if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt))
> -            ReplaceStmt(OldBase, IRE->getBase());
> -          else
> -            ReplaceStmt(ChildStmt, newStmt);
> -        }
> -      }
> -      else
> -        newStmt = RewriteFunctionBodyOrGlobalInitializer(ChildStmt);
> +      Stmt *childStmt = (*CI);
> +      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
>       if (newStmt) {
> -          if (Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(ChildStmt))
> -            if (PropSetters[PropOrImplicitRefExpr] == S) {
> -              S = newStmt;
> -              newStmt = 0;
> -            }
> -        if (newStmt)
> -          *CI = newStmt;
> -      }
> -      // If dealing with an assignment with LHS being a property reference
> -      // expression, the entire assignment tree is rewritten into a
> property
> -      // setter messaging. This involvs the RHS too. Do not attempt to
> rewrite
> -      // RHS again.
> -      if (Expr *Exp = dyn_cast<Expr>(ChildStmt))
> -        if (isa<ObjCPropertyRefExpr>(Exp)) {
> -          if (PropSetters[Exp]) {
> -            ++CI;
> -            continue;
> -          }
> -        }
> +        *CI = newStmt;
> +      }
>     }
>
>   if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
> @@ -5661,7 +5594,6 @@
>     // Rewrite the block body in place.
>     Stmt *SaveCurrentBody = CurrentBody;
>     CurrentBody = BE->getBody();
> -    CollectPropertySetters(CurrentBody);
>     PropParentMap = 0;
>     // block literal on rhs of a property-dot-sytax assignment
>     // must be replaced by its synthesize ast so getRewrittenText
> @@ -5689,67 +5621,6 @@
>   if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
>     return RewriteAtEncode(AtEncode);
>
> -  if (isa<ObjCPropertyRefExpr>(S)) {
> -    Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S);
> -    assert(PropOrImplicitRefExpr && "Property or implicit setter/getter
> is null");
> -
> -    BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr];
> -    if (BinOp) {
> -      // Because the rewriter doesn't allow us to rewrite rewritten code,
> -      // we need to rewrite the right hand side prior to rewriting the
> setter.
> -      DisableReplaceStmt = true;
> -      // Save the source range. Even if we disable the replacement, the
> -      // rewritten node will have been inserted into the tree. If the
> synthesized
> -      // node is at the 'end', the rewriter will fail. Consider this:
> -      //    self.errorHandler = handler ? handler :
> -      //              ^(NSURL *errorURL, NSError *error) { return
> (BOOL)1; };
> -      SourceRange SrcRange = BinOp->getSourceRange();
> -      Stmt *newStmt =
> RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());
> -      // Need to rewrite the ivar access expression if need be.
> -      if (isa<ObjCIvarRefExpr>(newStmt)) {
> -        bool replaced = false;
> -        newStmt = RewriteObjCNestedIvarRefExpr(newStmt, replaced);
> -      }
> -
> -      DisableReplaceStmt = false;
> -      //
> -      // Unlike the main iterator, we explicily avoid changing 'BinOp'. If
> -      // we changed the RHS of BinOp, the rewriter would fail (since it
> needs
> -      // to see the original expression). Consider this example:
> -      //
> -      // Foo *obj1, *obj2;
> -      //
> -      // obj1.i = [obj2 rrrr];
> -      //
> -      // 'BinOp' for the previous expression looks like:
> -      //
> -      // (BinaryOperator 0x231ccf0 'int' '='
> -      //   (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef
> Property="i"
> -      //     (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0))
> -      //   (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr
> -      //     (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0)))
> -      //
> -      // 'newStmt' represents the rewritten message expression. For
> example:
> -      //
> -      // (CallExpr 0x231d300 'id':'struct objc_object *'
> -      //   (ParenExpr 0x231d2e0 'int (*)(id, SEL)'
> -      //     (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)'
> -      //       (CStyleCastExpr 0x231d220 'void *'
> -      //         (DeclRefExpr 0x231d200 'id (id, SEL, ...)'
> FunctionDecl='objc_msgSend' 0x231cdc0))))
> -      //
> -      // Note that 'newStmt' is passed to RewritePropertyOrImplicitSetter
> so that it
> -      // can be used as the setter argument. ReplaceStmt() will still
> 'see'
> -      // the original RHS (since we haven't altered BinOp).
> -      //
> -      // This implies the Rewrite* routines can no longer delete the
> original
> -      // node. As a result, we now leak the original AST nodes.
> -      //
> -      return RewritePropertyOrImplicitSetter(BinOp,
> dyn_cast<Expr>(newStmt), SrcRange);
> -    } else {
> -      return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr);
> -    }
> -  }
> -
>   if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
>     return RewriteAtSelector(AtSelector);
>
> @@ -5930,7 +5801,6 @@
>     if (CompoundStmt *Body =
> dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
>       CurFunctionDef = FD;
>       CurFunctionDeclToDeclareForBlock = FD;
> -      CollectPropertySetters(Body);
>       CurrentBody = Body;
>       Body =
>
>  cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
> @@ -5951,7 +5821,6 @@
>   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
>     if (CompoundStmt *Body = MD->getCompoundBody()) {
>       CurMethodDef = MD;
> -      CollectPropertySetters(Body);
>       CurrentBody = Body;
>       Body =
>
>  cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
> @@ -5989,7 +5858,6 @@
>     }
>     if (VD->getInit()) {
>       GlobalVarDecl = VD;
> -      CollectPropertySetters(VD->getInit());
>       CurrentBody = VD->getInit();
>       RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
>       CurrentBody = 0;
>
> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Sun Nov  6 03:01:30 2011
> @@ -4213,6 +4213,26 @@
>       continue;
>     }
>
> +    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {
> +      // Only pay attention to pseudo-objects on property references.
> +      ObjCPropertyRefExpr *pre
> +        = dyn_cast<ObjCPropertyRefExpr>(pseudo->getSyntacticForm()
> +                                              ->IgnoreParens());
> +      if (!pre) return false;
> +      if (pre->isImplicitProperty()) return false;
> +      ObjCPropertyDecl *property = pre->getExplicitProperty();
> +      if (!property->isRetaining() &&
> +          !(property->getPropertyIvarDecl() &&
> +            property->getPropertyIvarDecl()->getType()
> +              .getObjCLifetime() == Qualifiers::OCL_Strong))
> +          return false;
> +
> +      owner.Indirect = true;
> +      e = const_cast<Expr*>(cast<OpaqueValueExpr>(pre->getBase())
> +                              ->getSourceExpr());
> +      continue;
> +    }
> +
>     // Array ivars?
>
>     return false;
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Nov  6 03:01:30 2011
> @@ -7468,7 +7468,7 @@
>     // The operand must be either an l-value or a function designator
>     if (!op->getType()->isFunctionType()) {
>       // Use a special diagnostic for loads from property references.
> -      if (isa<ObjCPropertyRefExpr>(op->IgnoreImplicit()->IgnoreParens()))
> {
> +      if (isa<PseudoObjectExpr>(op)) {
>         AddressOfError = AO_Property_Expansion;
>       } else {
>         // FIXME: emit more specific diag...
> @@ -7483,9 +7483,6 @@
>   } else if (op->getObjectKind() == OK_VectorComponent) {
>     // The operand cannot be an element of a vector
>     AddressOfError = AO_Vector_Element;
> -  } else if (op->getObjectKind() == OK_ObjCProperty) {
> -    // cannot take address of a property expression.
> -    AddressOfError = AO_Property_Expansion;
>   } else if (dcl) { // C99 6.5.3.2p1
>     // We have an lvalue with a decl. Make sure the decl is not declared
>     // with the register storage-class specifier.
> @@ -8951,8 +8948,15 @@
>       return;
>   }
>
> -  // Strip off any parens and casts.
> -  StringLiteral *SL =
> dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts());
> +  // Ignore any parens, implicit casts (should only be
> +  // array-to-pointer decays), and not-so-opaque values.  The last is
> +  // important for making this trigger for property assignments.
> +  SrcExpr = SrcExpr->IgnoreParenImpCasts();
> +  if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))
> +    if (OV->getSourceExpr())
> +      SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
> +
> +  StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
>   if (!SL || !SL->isAscii())
>     return;
>
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sun Nov  6 03:01:30 2011
> @@ -467,14 +467,13 @@
>
>  bool Sema::isSelfExpr(Expr *receiver) {
>   // 'self' is objc 'self' in an objc method only.
> -  DeclContext *DC = CurContext;
> -  while (isa<BlockDecl>(DC))
> -    DC = DC->getParent();
> -  if (DC && !isa<ObjCMethodDecl>(DC))
> -    return false;
> +  ObjCMethodDecl *method =
> +    dyn_cast<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
> +  if (!method) return false;
> +
>   receiver = receiver->IgnoreParenLValueCasts();
>   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))
> -    if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))
> +    if (DRE->getDecl() == method->getSelfDecl())
>       return true;
>   return false;
>  }
> @@ -1725,6 +1724,12 @@
>       return merge(left, Visit(e->getFalseExpr()));
>     }
>
> +    /// Look through pseudo-objects.
> +    ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {
> +      // If we're getting here, we should always have a result.
> +      return Visit(e->getResultExpr());
> +    }
> +
>     /// Statement expressions are okay if their result expression is okay.
>     ACCResult VisitStmtExpr(StmtExpr *e) {
>       return Visit(e->getSubStmt()->body_back());
>
> Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Sun Nov  6 03:01:30 2011
> @@ -38,11 +38,364 @@
>  using namespace clang;
>  using namespace sema;
>
> +namespace {
> +  // Basically just a very focused copy of TreeTransform.
> +  template <class T> struct Rebuilder {
> +    Sema &S;
> +    Rebuilder(Sema &S) : S(S) {}
> +
> +    T &getDerived() { return static_cast<T&>(*this); }
> +
> +    Expr *rebuild(Expr *e) {
> +      // Fast path: nothing to look through.
> +      if (typename T::specific_type *specific
> +            = dyn_cast<typename T::specific_type>(e))
> +        return getDerived().rebuildSpecific(specific);
> +
> +      // Otherwise, we should look through and rebuild anything that
> +      // IgnoreParens would.
> +
> +      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
> +        e = rebuild(parens->getSubExpr());
> +        return new (S.Context) ParenExpr(parens->getLParen(),
> +                                         parens->getRParen(),
> +                                         e);
> +      }
> +
> +      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
> +        assert(uop->getOpcode() == UO_Extension);
> +        e = rebuild(uop->getSubExpr());
> +        return new (S.Context) UnaryOperator(e, uop->getOpcode(),
> +                                             uop->getType(),
> +                                             uop->getValueKind(),
> +                                             uop->getObjectKind(),
> +                                             uop->getOperatorLoc());
> +      }
> +
> +      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
> +        assert(!gse->isResultDependent());
> +        unsigned resultIndex = gse->getResultIndex();
> +        unsigned numAssocs = gse->getNumAssocs();
> +
> +        SmallVector<Expr*, 8> assocs(numAssocs);
> +        SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
> +
> +        for (unsigned i = 0; i != numAssocs; ++i) {
> +          Expr *assoc = gse->getAssocExpr(i);
> +          if (i == resultIndex) assoc = rebuild(assoc);
> +          assocs[i] = assoc;
> +          assocTypes[i] = gse->getAssocTypeSourceInfo(i);
> +        }
> +
> +        return new (S.Context) GenericSelectionExpr(S.Context,
> +                                                    gse->getGenericLoc(),
> +
>  gse->getControllingExpr(),
> +                                                    assocTypes.data(),
> +                                                    assocs.data(),
> +                                                    numAssocs,
> +                                                    gse->getDefaultLoc(),
> +                                                    gse->getRParenLoc(),
> +
>  gse->containsUnexpandedParameterPack(),
> +                                                    resultIndex);
> +      }
> +
> +      llvm_unreachable("bad expression to rebuild!");
> +    }
> +  };
> +
> +  struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
> +    Expr *NewBase;
> +    ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
> +      : Rebuilder(S), NewBase(newBase) {}
> +
> +    typedef ObjCPropertyRefExpr specific_type;
> +    Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
> +      // Fortunately, the constraint that we're rebuilding something
> +      // with a base limits the number of cases here.
> +      assert(refExpr->getBase());
> +
> +      if (refExpr->isExplicitProperty()) {
> +        return new (S.Context)
> +          ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
> +                              refExpr->getType(), refExpr->getValueKind(),
> +                              refExpr->getObjectKind(),
> refExpr->getLocation(),
> +                              NewBase);
> +      }
> +      return new (S.Context)
> +        ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
> +                            refExpr->getImplicitPropertySetter(),
> +                            refExpr->getType(), refExpr->getValueKind(),
> +
>  refExpr->getObjectKind(),refExpr->getLocation(),
> +                            NewBase);
> +    }
> +  };
> +
> +  class PseudoOpBuilder {
> +  public:
> +    Sema &S;
> +    unsigned ResultIndex;
> +    SourceLocation GenericLoc;
> +    SmallVector<Expr *, 4> Semantics;
> +
> +    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
> +      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
> +        GenericLoc(genericLoc) {}
> +
> +    /// Add a normal semantic expression.
> +    void addSemanticExpr(Expr *semantic) {
> +      Semantics.push_back(semantic);
> +    }
> +
> +    /// Add the 'result' semantic expression.
> +    void addResultSemanticExpr(Expr *resultExpr) {
> +      assert(ResultIndex == PseudoObjectExpr::NoResult);
> +      ResultIndex = Semantics.size();
> +      Semantics.push_back(resultExpr);
> +    }
> +
> +    ExprResult buildRValueOperation(Expr *op);
> +    ExprResult buildAssignmentOperation(Scope *Sc,
> +                                        SourceLocation opLoc,
> +                                        BinaryOperatorKind opcode,
> +                                        Expr *LHS, Expr *RHS);
> +    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
> +                                    UnaryOperatorKind opcode,
> +                                    Expr *op);
> +
> +    ExprResult complete(Expr *syntacticForm);
> +
> +    OpaqueValueExpr *capture(Expr *op);
> +    OpaqueValueExpr *captureValueAsResult(Expr *op);
> +
> +    void setResultToLastSemantic() {
> +      assert(ResultIndex == PseudoObjectExpr::NoResult);
> +      ResultIndex = Semantics.size() - 1;
> +    }
> +
> +    /// Return true if assignments have a non-void result.
> +    virtual bool assignmentsHaveResult() { return true; }
> +
> +    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
> +    virtual ExprResult buildGet() = 0;
> +    virtual ExprResult buildSet(Expr *, SourceLocation,
> +                                bool captureSetValueAsResult) = 0;
> +  };
> +
> +  /// A PseudoOpBuilder for Objective-C @properties.
> +  class ObjCPropertyOpBuilder : public PseudoOpBuilder {
> +    ObjCPropertyRefExpr *RefExpr;
> +    OpaqueValueExpr *InstanceReceiver;
> +    ObjCMethodDecl *Getter;
> +
> +    ObjCMethodDecl *Setter;
> +    Selector SetterSelector;
> +
> +  public:
> +    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
> +      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
> +      InstanceReceiver(0), Getter(0), Setter(0) {
> +    }
> +
> +    ExprResult buildRValueOperation(Expr *op);
> +    ExprResult buildAssignmentOperation(Scope *Sc,
> +                                        SourceLocation opLoc,
> +                                        BinaryOperatorKind opcode,
> +                                        Expr *LHS, Expr *RHS);
> +    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
> +                                    UnaryOperatorKind opcode,
> +                                    Expr *op);
> +
> +    bool tryBuildGetOfReference(Expr *op, ExprResult &result);
> +    bool findSetter();
> +    bool findGetter();
> +
> +    Expr *rebuildAndCaptureObject(Expr *syntacticBase);
> +    ExprResult buildGet();
> +    ExprResult buildSet(Expr *op, SourceLocation, bool);
> +  };
> +}
> +
> +/// Capture the given expression in an OpaqueValueExpr.
> +OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
> +  // Make a new OVE whose source is the given expression.
> +  OpaqueValueExpr *captured =
> +    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
> +                                    e->getValueKind());
> +  captured->setSourceExpr(e);
> +
> +  // Make sure we bind that in the semantics.
> +  addSemanticExpr(captured);
> +  return captured;
> +}
> +
> +/// Capture the given expression as the result of this pseudo-object
> +/// operation.  This routine is safe against expressions which may
> +/// already be captured.
> +///
> +/// \param Returns the captured expression, which will be the
> +///   same as the input if the input was already captured
> +OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
> +  assert(ResultIndex == PseudoObjectExpr::NoResult);
> +
> +  // If the expression hasn't already been captured, just capture it
> +  // and set the new semantic
> +  if (!isa<OpaqueValueExpr>(e)) {
> +    OpaqueValueExpr *cap = capture(e);
> +    setResultToLastSemantic();
> +    return cap;
> +  }
> +
> +  // Otherwise, it must already be one of our semantic expressions;
> +  // set ResultIndex to its index.
> +  unsigned index = 0;
> +  for (;; ++index) {
> +    assert(index < Semantics.size() &&
> +           "captured expression not found in semantics!");
> +    if (e == Semantics[index]) break;
> +  }
> +  ResultIndex = index;
> +  return cast<OpaqueValueExpr>(e);
> +}
> +
> +/// The routine which creates the final PseudoObjectExpr.
> +ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
> +  return PseudoObjectExpr::Create(S.Context, syntactic,
> +                                  Semantics, ResultIndex);
> +}
> +
> +/// The main skeleton for building an r-value operation.
> +ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
> +  Expr *syntacticBase = rebuildAndCaptureObject(op);
> +
> +  ExprResult getExpr = buildGet();
> +  if (getExpr.isInvalid()) return ExprError();
> +  addResultSemanticExpr(getExpr.take());
> +
> +  return complete(syntacticBase);
> +}
> +
> +/// The basic skeleton for building a simple or compound
> +/// assignment operation.
> +ExprResult
> +PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation
> opcLoc,
> +                                          BinaryOperatorKind opcode,
> +                                          Expr *LHS, Expr *RHS) {
> +  assert(BinaryOperator::isAssignmentOp(opcode));
> +
> +  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
> +  OpaqueValueExpr *capturedRHS = capture(RHS);
> +
> +  Expr *syntactic;
> +
> +  ExprResult result;
> +  if (opcode == BO_Assign) {
> +    result = capturedRHS;
> +    syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
> +                                               opcode,
> capturedRHS->getType(),
> +
> capturedRHS->getValueKind(),
> +                                               OK_Ordinary, opcLoc);
> +  } else {
> +    ExprResult opLHS = buildGet();
> +    if (opLHS.isInvalid()) return ExprError();
> +
> +    // Build an ordinary, non-compound operation.
> +    BinaryOperatorKind nonCompound =
> +      BinaryOperator::getOpForCompoundAssignment(opcode);
> +    result = S.BuildBinOp(Sc, opcLoc, nonCompound,
> +                          opLHS.take(), capturedRHS);
> +    if (result.isInvalid()) return ExprError();
> +
> +    syntactic =
> +      new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS,
> opcode,
> +                                             result.get()->getType(),
> +                                             result.get()->getValueKind(),
> +                                             OK_Ordinary,
> +                                             opLHS.get()->getType(),
> +                                             result.get()->getType(),
> +                                             opcLoc);
> +  }
> +
> +  // The result of the assignment, if not void, is the value set into
> +  // the l-value.
> +  result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
> +  if (result.isInvalid()) return ExprError();
> +  addSemanticExpr(result.take());
> +
> +  return complete(syntactic);
> +}
> +
> +/// The basic skeleton for building an increment or decrement
> +/// operation.
> +ExprResult
> +PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
> +                                      UnaryOperatorKind opcode,
> +                                      Expr *op) {
> +  assert(UnaryOperator::isIncrementDecrementOp(opcode));
> +
> +  Expr *syntacticOp = rebuildAndCaptureObject(op);
> +
> +  // Load the value.
> +  ExprResult result = buildGet();
> +  if (result.isInvalid()) return ExprError();
> +
> +  QualType resultType = result.get()->getType();
> +
> +  // That's the postfix result.
> +  if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
> +    result = capture(result.take());
> +    setResultToLastSemantic();
> +  }
> +
> +  // Add or subtract a literal 1.
> +  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
> +  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
> +                                     GenericLoc);
> +
> +  if (UnaryOperator::isIncrementOp(opcode)) {
> +    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
> +  } else {
> +    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
> +  }
> +  if (result.isInvalid()) return ExprError();
> +
> +  // Store that back into the result.  The value stored is the result
> +  // of a prefix operation.
> +  result = buildSet(result.take(), opcLoc,
> +             UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
> +  if (result.isInvalid()) return ExprError();
> +  addSemanticExpr(result.take());
> +
> +  UnaryOperator *syntactic =
> +    new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
> +                                  VK_LValue, OK_Ordinary, opcLoc);
> +  return complete(syntactic);
> +}
> +
> +
>
> +//===----------------------------------------------------------------------===//
> +//  Objective-C @property and implicit property references
>
> +//===----------------------------------------------------------------------===//
> +
> +/// Look up a method in the receiver type of an Objective-C property
> +/// reference.
>  static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
>                                             const ObjCPropertyRefExpr
> *PRE) {
>   if (PRE->isObjectReceiver()) {
>     const ObjCObjectPointerType *PT =
>       PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
> +
> +    // Special case for 'self' in class method implementations.
> +    if (PT->isObjCClassType() &&
> +        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
> +      // This cast is safe because isSelfExpr is only true within
> +      // methods.
> +      ObjCMethodDecl *method =
> +        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
> +      return S.LookupMethodInObjectType(sel,
> +
> S.Context.getObjCInterfaceType(method->getClassInterface()),
> +                                        /*instance*/ false);
> +    }
> +
>     return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
>   }
>
> @@ -59,281 +412,374 @@
>   return S.LookupMethodInObjectType(sel, IT, false);
>  }
>
> -ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
> -  assert(E->getValueKind() == VK_LValue &&
> -         E->getObjectKind() == OK_ObjCProperty);
> -  const ObjCPropertyRefExpr *PRE = E->getObjCProperty();
> -
> -  QualType ReceiverType;
> -  if (PRE->isObjectReceiver())
> -    ReceiverType = PRE->getBase()->getType();
> -  else if (PRE->isSuperReceiver())
> -    ReceiverType = PRE->getSuperReceiverType();
> -  else
> -    ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver());
> -
> -  ExprValueKind VK = VK_RValue;
> -  QualType T;
> -  if (PRE->isImplicitProperty()) {
> -    if (ObjCMethodDecl *GetterMethod =
> -          PRE->getImplicitPropertyGetter()) {
> -      T = getMessageSendResultType(ReceiverType, GetterMethod,
> -                                   PRE->isClassReceiver(),
> -                                   PRE->isSuperReceiver());
> -      VK = Expr::getValueKindForType(GetterMethod->getResultType());
> -    } else {
> -      Diag(PRE->getLocation(), diag::err_getter_not_found)
> -            << PRE->getBase()->getType();
> -      return ExprError();
> -    }
> -  } else {
> -    ObjCPropertyDecl *prop = PRE->getExplicitProperty();
> +bool ObjCPropertyOpBuilder::findGetter() {
> +  if (Getter) return true;
> +
> +  Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(),
> RefExpr);
> +  return (Getter != 0);
> +}
>
> -    ObjCMethodDecl *getter =
> -      LookupMethodInReceiverType(*this, prop->getGetterName(), PRE);
> -    if (getter && !getter->hasRelatedResultType())
> -      DiagnosePropertyAccessorMismatch(prop, getter, PRE->getLocation());
> -    if (!getter) getter = prop->getGetterMethodDecl();
> -
> -    // Figure out the type of the expression.  Mostly this is the
> -    // result type of the getter, if possible.
> -    if (getter) {
> -      T = getMessageSendResultType(ReceiverType, getter,
> -                                   PRE->isClassReceiver(),
> -                                   PRE->isSuperReceiver());
> -      VK = Expr::getValueKindForType(getter->getResultType());
> -
> -      // As a special case, if the method returns 'id', try to get a
> -      // better type from the property.
> -      if (VK == VK_RValue && T->isObjCIdType() &&
> -          prop->getType()->isObjCRetainableType())
> -        T = prop->getType();
> +/// Try to find the most accurate setter declaration for the property
> +/// reference.
> +///
> +/// \return true if a setter was found, in which case Setter
> +bool ObjCPropertyOpBuilder::findSetter() {
> +  // For implicit properties, just trust the lookup we already did.
> +  if (RefExpr->isImplicitProperty()) {
> +    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
> +      Setter = setter;
> +      SetterSelector = setter->getSelector();
> +      return true;
>     } else {
> -      T = prop->getType();
> -      VK = Expr::getValueKindForType(T);
> -      T = T.getNonLValueExprType(Context);
> +      IdentifierInfo *getterName =
> +        RefExpr->getImplicitPropertyGetter()->getSelector()
> +          .getIdentifierInfoForSlot(0);
> +      SetterSelector =
> +        SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
> +                                           S.PP.getSelectorTable(),
> +                                           getterName);
> +      return false;
>     }
>   }
>
> -  E->setType(T);
> -  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK);
> +  // For explicit properties, this is more involved.
> +  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
> +  SetterSelector = prop->getSetterName();
> +
> +  // Do a normal method lookup first.
> +  if (ObjCMethodDecl *setter =
> +        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
> +    Setter = setter;
> +    return true;
> +  }
> +
> +  // That can fail in the somewhat crazy situation that we're
> +  // type-checking a message send within the @interface declaration
> +  // that declared the @property.  But it's not clear that that's
> +  // valuable to support.
> +
> +  return false;
> +}
> +
> +/// Capture the base object of an Objective-C property expression.
> +Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase)
> {
> +  assert(InstanceReceiver == 0);
> +
> +  // If we have a base, capture it in an OVE and rebuild the syntactic
> +  // form to use the OVE as its base.
> +  if (RefExpr->isObjectReceiver()) {
> +    InstanceReceiver = capture(RefExpr->getBase());
> +
> +    syntacticBase =
> +      ObjCPropertyRefRebuilder(S,
> InstanceReceiver).rebuild(syntacticBase);
> +  }
> +
> +  return syntacticBase;
> +}
> +
> +/// Load from an Objective-C property reference.
> +ExprResult ObjCPropertyOpBuilder::buildGet() {
> +  findGetter();
> +  assert(Getter);
>
> -  ExprResult Result = MaybeBindToTemporary(E);
> -  if (!Result.isInvalid())
> -    E = Result.take();
> +  QualType receiverType;
> +  SourceLocation superLoc;
> +  if (RefExpr->isClassReceiver()) {
> +    receiverType =
> S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
> +  } else if (RefExpr->isSuperReceiver()) {
> +    superLoc = RefExpr->getReceiverLocation();
> +    receiverType = RefExpr->getSuperReceiverType();
> +  } else {
> +    assert(InstanceReceiver);
> +    receiverType = InstanceReceiver->getType();
> +  }
>
> -  return Owned(E);
> +  // Build a message-send.
> +  ExprResult msg;
> +  if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
> +    assert(InstanceReceiver || RefExpr->isSuperReceiver());
> +    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
> +                                 Getter->getSelector(), Getter,
> +                                 GenericLoc, GenericLoc, GenericLoc,
> +                                 MultiExprArg());
> +  } else {
> +    TypeSourceInfo *receiverTypeInfo = 0;
> +    if (!RefExpr->isSuperReceiver())
> +      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
> +
> +    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
> +                              Getter->getSelector(), Getter,
> +                              GenericLoc, GenericLoc, GenericLoc,
> +                              MultiExprArg());
> +  }
> +  return msg;
>  }
>
> -namespace {
> -  struct PseudoObjectInfo {
> -    const ObjCPropertyRefExpr *RefExpr;
> -    bool HasSetter;
> -    Selector SetterSelector;
> -    ParmVarDecl *SetterParam;
> -    QualType SetterParamType;
> +/// Store to an Objective-C property reference.
> +///
> +/// \param bindSetValueAsResult - If true, capture the actual
> +///   value being set as the value of the property operation.
> +ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation
> opcLoc,
> +                                           bool captureSetValueAsResult) {
> +  bool hasSetter = findSetter();
> +  assert(hasSetter); (void) hasSetter;
> +
> +  QualType receiverType;
> +  SourceLocation superLoc;
> +  if (RefExpr->isClassReceiver()) {
> +    receiverType =
> S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
> +  } else if (RefExpr->isSuperReceiver()) {
> +    superLoc = RefExpr->getReceiverLocation();
> +    receiverType = RefExpr->getSuperReceiverType();
> +  } else {
> +    assert(InstanceReceiver);
> +    receiverType = InstanceReceiver->getType();
> +  }
>
> -    void setSetter(ObjCMethodDecl *setter) {
> -      HasSetter = true;
> -      SetterParam = *setter->param_begin();
> -      SetterParamType = SetterParam->getType().getUnqualifiedType();
> -    }
> -
> -    PseudoObjectInfo(Sema &S, Expr *E)
> -      : RefExpr(E->getObjCProperty()), HasSetter(false), SetterParam(0) {
> -
> -      assert(E->getValueKind() == VK_LValue &&
> -             E->getObjectKind() == OK_ObjCProperty);
> -
> -      // Try to find a setter.
> -
> -      // For implicit properties, just trust the lookup we already did.
> -      if (RefExpr->isImplicitProperty()) {
> -        if (ObjCMethodDecl *setter =
> RefExpr->getImplicitPropertySetter()) {
> -          setSetter(setter);
> -          SetterSelector = setter->getSelector();
> -        } else {
> -          IdentifierInfo *getterName =
> -            RefExpr->getImplicitPropertyGetter()->getSelector()
> -              .getIdentifierInfoForSlot(0);
> -          SetterSelector =
> -            SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
> -                                               S.PP.getSelectorTable(),
> -                                               getterName);
> -        }
> -        return;
> -      }
> +  // Use assignment constraints when possible; they give us better
> +  // diagnostics.  "When possible" basically means anything except a
> +  // C++ class type.
> +  if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {
> +    QualType paramType = (*Setter->param_begin())->getType();
> +    if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {
> +      ExprResult opResult = op;
> +      Sema::AssignConvertType assignResult
> +        = S.CheckSingleAssignmentConstraints(paramType, opResult);
> +      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
> +                                     op->getType(), opResult.get(),
> +                                     Sema::AA_Assigning))
> +        return ExprError();
>
> -      // For explicit properties, this is more involved.
> -      ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
> -      SetterSelector = prop->getSetterName();
> -
> -      // Do a normal method lookup first.
> -      if (ObjCMethodDecl *setter =
> -            LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
> -        setSetter(setter);
> -        return;
> -      }
> +      op = opResult.take();
> +      assert(op && "successful assignment left argument invalid?");
> +    }
> +  }
>
> -      // If that failed, trust the type on the @property declaration.
> -      if (!prop->isReadOnly()) {
> -        HasSetter = true;
> -        SetterParamType = prop->getType().getUnqualifiedType();
> -      }
> +  // Arguments.
> +  Expr *args[] = { op };
> +
> +  // Build a message-send.
> +  ExprResult msg;
> +  if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
> +    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
> +                                 SetterSelector, Setter,
> +                                 GenericLoc, GenericLoc, GenericLoc,
> +                                 MultiExprArg(args, 1));
> +  } else {
> +    TypeSourceInfo *receiverTypeInfo = 0;
> +    if (!RefExpr->isSuperReceiver())
> +      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
> +
> +    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
> +                              SetterSelector, Setter,
> +                              GenericLoc, GenericLoc, GenericLoc,
> +                              MultiExprArg(args, 1));
> +  }
> +
> +  if (!msg.isInvalid() && captureSetValueAsResult) {
> +    ObjCMessageExpr *msgExpr =
> +      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
> +    Expr *arg = msgExpr->getArg(0);
> +    msgExpr->setArg(0, captureValueAsResult(arg));
> +  }
> +
> +  return msg;
> +}
> +
> +/// @property-specific behavior for doing lvalue-to-rvalue conversion.
> +ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
> +  // Explicit properties always have getters, but implicit ones don't.
> +  // Check that before proceeding.
> +  if (RefExpr->isImplicitProperty() &&
> +      !RefExpr->getImplicitPropertyGetter()) {
> +    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
> +      << RefExpr->getBase()->getType();
> +    return ExprError();
> +  }
> +
> +  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
> +  if (result.isInvalid()) return ExprError();
> +
> +  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
> +    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
> +                                       Getter, RefExpr->getLocation());
> +
> +  // As a special case, if the method returns 'id', try to get
> +  // a better type from the property.
> +  if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
> +      result.get()->getType()->isObjCIdType()) {
> +    QualType propType = RefExpr->getExplicitProperty()->getType();
> +    if (const ObjCObjectPointerType *ptr
> +          = propType->getAs<ObjCObjectPointerType>()) {
> +      if (!ptr->isObjCIdType())
> +        result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
>     }
> -  };
> +  }
> +
> +  return result;
>  }
>
> -/// Check an increment or decrement of a pseudo-object expression.
> -ExprResult Sema::checkPseudoObjectIncDec(Scope *S, SourceLocation opcLoc,
> -                                         UnaryOperatorKind opcode, Expr
> *op) {
> -  assert(UnaryOperator::isIncrementDecrementOp(opcode));
> -  PseudoObjectInfo info(*this, op);
> +/// Try to build this as a call to a getter that returns a reference.
> +///
> +/// \return true if it was possible, whether or not it actually
> +///   succeeded
> +bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
> +                                                   ExprResult &result) {
> +  if (!S.getLangOptions().CPlusPlus) return false;
> +
> +  findGetter();
> +  assert(Getter && "property has no setter and no getter!");
> +
> +  // Only do this if the getter returns an l-value reference type.
> +  QualType resultType = Getter->getResultType();
> +  if (!resultType->isLValueReferenceType()) return false;
> +
> +  result = buildRValueOperation(op);
> +  return true;
> +}
> +
> +/// @property-specific behavior for doing assignments.
> +ExprResult
> +ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
> +                                                SourceLocation opcLoc,
> +                                                BinaryOperatorKind opcode,
> +                                                Expr *LHS, Expr *RHS) {
> +  assert(BinaryOperator::isAssignmentOp(opcode));
>
>   // If there's no setter, we have no choice but to try to assign to
>   // the result of the getter.
> -  if (!info.HasSetter) {
> -    QualType resultType = info.RefExpr->getGetterResultType();
> -    assert(!resultType.isNull() && "property has no setter and no
> getter!");
> -
> -    // Only do this if the getter returns an l-value reference type.
> -    if (const LValueReferenceType *refType
> -          = resultType->getAs<LValueReferenceType>()) {
> -      op = ImplicitCastExpr::Create(Context, refType->getPointeeType(),
> -                                    CK_GetObjCProperty, op, 0, VK_LValue);
> -      return BuildUnaryOp(S, opcLoc, opcode, op);
> +  if (!findSetter()) {
> +    ExprResult result;
> +    if (tryBuildGetOfReference(LHS, result)) {
> +      if (result.isInvalid()) return ExprError();
> +      return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
>     }
>
>     // Otherwise, it's an error.
> -    Diag(opcLoc, diag::err_nosetter_property_incdec)
> -      << unsigned(info.RefExpr->isImplicitProperty())
> -      << unsigned(UnaryOperator::isDecrementOp(opcode))
> -      << info.SetterSelector
> -      << op->getSourceRange();
> +    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
> +      << unsigned(RefExpr->isImplicitProperty())
> +      << SetterSelector
> +      << LHS->getSourceRange() << RHS->getSourceRange();
>     return ExprError();
>   }
>
> -  // ++/-- behave like compound assignments, i.e. they need a getter.
> -  QualType getterResultType = info.RefExpr->getGetterResultType();
> -  if (getterResultType.isNull()) {
> -    assert(info.RefExpr->isImplicitProperty());
> -    Diag(opcLoc, diag::err_nogetter_property_incdec)
> -      << unsigned(UnaryOperator::isDecrementOp(opcode))
> -      << info.RefExpr->getImplicitPropertyGetter()->getSelector()
> -      << op->getSourceRange();
> +  // If there is a setter, we definitely want to use it.
> +
> +  // Verify that we can do a compound assignment.
> +  if (opcode != BO_Assign && !findGetter()) {
> +    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
> +      << LHS->getSourceRange() << RHS->getSourceRange();
>     return ExprError();
>   }
>
> -  // HACK: change the type of the operand to prevent further placeholder
> -  // transformation.
> -  op->setType(getterResultType.getNonLValueExprType(Context));
> -  op->setObjectKind(OK_Ordinary);
> -
> -  ExprResult result = CreateBuiltinUnaryOp(opcLoc, opcode, op);
> +  ExprResult result =
> +    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS,
> RHS);
>   if (result.isInvalid()) return ExprError();
>
> -  // Change the object kind back.
> -  op->setObjectKind(OK_ObjCProperty);
> +  // Various warnings about property assignments in ARC.
> +  if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
> +    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
> +    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
> +  }
> +
>   return result;
>  }
>
> -ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation
> opcLoc,
> -                                             BinaryOperatorKind opcode,
> -                                             Expr *LHS, Expr *RHS) {
> -  assert(BinaryOperator::isAssignmentOp(opcode));
> -  PseudoObjectInfo info(*this, LHS);
> -
> +/// @property-specific behavior for doing increments and decrements.
> +ExprResult
> +ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation
> opcLoc,
> +                                            UnaryOperatorKind opcode,
> +                                            Expr *op) {
>   // If there's no setter, we have no choice but to try to assign to
>   // the result of the getter.
> -  if (!info.HasSetter) {
> -    QualType resultType = info.RefExpr->getGetterResultType();
> -    assert(!resultType.isNull() && "property has no setter and no
> getter!");
> -
> -    // Only do this if the getter returns an l-value reference type.
> -    if (const LValueReferenceType *refType
> -          = resultType->getAs<LValueReferenceType>()) {
> -      LHS = ImplicitCastExpr::Create(Context, refType->getPointeeType(),
> -                                     CK_GetObjCProperty, LHS, 0,
> VK_LValue);
> -      return BuildBinOp(S, opcLoc, opcode, LHS, RHS);
> +  if (!findSetter()) {
> +    ExprResult result;
> +    if (tryBuildGetOfReference(op, result)) {
> +      if (result.isInvalid()) return ExprError();
> +      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
>     }
>
>     // Otherwise, it's an error.
> -    Diag(opcLoc, diag::err_nosetter_property_assignment)
> -      << unsigned(info.RefExpr->isImplicitProperty())
> -      << info.SetterSelector
> -      << LHS->getSourceRange() << RHS->getSourceRange();
> +    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
> +      << unsigned(RefExpr->isImplicitProperty())
> +      << unsigned(UnaryOperator::isDecrementOp(opcode))
> +      << SetterSelector
> +      << op->getSourceRange();
>     return ExprError();
>   }
>
>   // If there is a setter, we definitely want to use it.
>
> -  // If this is a simple assignment, just initialize the parameter
> -  // with the RHS.
> -  if (opcode == BO_Assign) {
> -    LHS->setType(info.SetterParamType.getNonLValueExprType(Context));
> +  // We also need a getter.
> +  if (!findGetter()) {
> +    assert(RefExpr->isImplicitProperty());
> +    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
> +      << unsigned(UnaryOperator::isDecrementOp(opcode))
> +      << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
> +      << op->getSourceRange();
> +    return ExprError();
> +  }
>
> -    // Under certain circumstances, we need to type-check the RHS as a
> -    // straight-up parameter initialization.  This gives somewhat
> -    // inferior diagnostics, so we try to avoid it.
> -
> -    if (RHS->isTypeDependent()) {
> -      // Just build the expression.
> -
> -    } else if ((getLangOptions().CPlusPlus &&
> LHS->getType()->isRecordType()) ||
> -               (getLangOptions().ObjCAutoRefCount &&
> -                info.SetterParam &&
> -                info.SetterParam->hasAttr<NSConsumedAttr>())) {
> -      InitializedEntity param = (info.SetterParam
> -        ? InitializedEntity::InitializeParameter(Context,
> info.SetterParam)
> -        : InitializedEntity::InitializeParameter(Context,
> info.SetterParamType,
> -                                                 /*consumed*/ false));
> -      ExprResult arg = PerformCopyInitialization(param, opcLoc, RHS);
> -      if (arg.isInvalid()) return ExprError();
> -      RHS = arg.take();
> -
> -      // Warn about assignments of +1 objects to unsafe pointers in ARC.
> -      // CheckAssignmentOperands does this on the other path.
> -      if (getLangOptions().ObjCAutoRefCount)
> -        checkUnsafeExprAssigns(opcLoc, LHS, RHS);
> -    } else {
> -      ExprResult RHSResult = Owned(RHS);
> +  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
> +}
>
> -      LHS->setObjectKind(OK_Ordinary);
> -      QualType resultType = CheckAssignmentOperands(LHS, RHSResult,
> opcLoc,
> -                                                    /*compound*/
> QualType());
> -      LHS->setObjectKind(OK_ObjCProperty);
>
> +//===----------------------------------------------------------------------===//
> +//  General Sema routines.
>
> +//===----------------------------------------------------------------------===//
>
> -      if (!RHSResult.isInvalid()) RHS = RHSResult.take();
> -      if (resultType.isNull()) return ExprError();
> -    }
> +ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
> +  Expr *opaqueRef = E->IgnoreParens();
> +  if (ObjCPropertyRefExpr *refExpr
> +        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> +    ObjCPropertyOpBuilder builder(*this, refExpr);
> +    return builder.buildRValueOperation(E);
> +  } else {
> +    llvm_unreachable("unknown pseudo-object kind!");
> +  }
> +}
>
> -    // Warn about property sets in ARC that might cause retain cycles.
> -    if (getLangOptions().ObjCAutoRefCount &&
> !info.RefExpr->isSuperReceiver())
> -      checkRetainCycles(const_cast<Expr*>(info.RefExpr->getBase()), RHS);
> +/// Check an increment or decrement of a pseudo-object expression.
> +ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
> +                                         UnaryOperatorKind opcode, Expr
> *op) {
> +  // Do nothing if the operand is dependent.
> +  if (op->isTypeDependent())
> +    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
> +                                       VK_RValue, OK_Ordinary, opcLoc);
>
> -    return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(),
> -                                        RHS->getValueKind(),
> -                                        RHS->getObjectKind(),
> -                                        opcLoc);
> +  assert(UnaryOperator::isIncrementDecrementOp(opcode));
> +  Expr *opaqueRef = op->IgnoreParens();
> +  if (ObjCPropertyRefExpr *refExpr
> +        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> +    ObjCPropertyOpBuilder builder(*this, refExpr);
> +    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
> +  } else {
> +    llvm_unreachable("unknown pseudo-object kind!");
>   }
> +}
>
> -  // If this is a compound assignment, we need to use the getter, too.
> -  QualType getterResultType = info.RefExpr->getGetterResultType();
> -  if (getterResultType.isNull()) {
> -    Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
> -      << LHS->getSourceRange() << RHS->getSourceRange();
> -    return ExprError();
> +ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation
> opcLoc,
> +                                             BinaryOperatorKind opcode,
> +                                             Expr *LHS, Expr *RHS) {
> +  // Do nothing if either argument is dependent.
> +  if (LHS->isTypeDependent() || RHS->isTypeDependent())
> +    return new (Context) BinaryOperator(LHS, RHS, opcode,
> Context.DependentTy,
> +                                        VK_RValue, OK_Ordinary, opcLoc);
> +
> +  // Filter out non-overload placeholder types in the RHS.
> +  if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
> +    if (PTy->getKind() != BuiltinType::Overload) {
> +      ExprResult result = CheckPlaceholderExpr(RHS);
> +      if (result.isInvalid()) return ExprError();
> +      RHS = result.take();
> +    }
>   }
>
> -  // HACK: change the type of the LHS to prevent further placeholder
> -  // transformation.
> -  LHS->setType(getterResultType.getNonLValueExprType(Context));
> -  LHS->setObjectKind(OK_Ordinary);
> -
> -  ExprResult result = CreateBuiltinBinOp(opcLoc, opcode, LHS, RHS);
> -  if (result.isInvalid()) return ExprError();
> -
> -  // Change the object kind back.
> -  LHS->setObjectKind(OK_ObjCProperty);
> -  return result;
> +  Expr *opaqueRef = LHS->IgnoreParens();
> +  if (ObjCPropertyRefExpr *refExpr
> +        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
> +    ObjCPropertyOpBuilder builder(*this, refExpr);
> +    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
> +  } else {
> +    llvm_unreachable("unknown pseudo-object kind!");
> +  }
>  }
>
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Sun Nov  6 03:01:30 2011
> @@ -198,7 +198,7 @@
>       Diag(Loc, diag::warn_unused_result) << R1 << R2;
>       return;
>     }
> -  } else if (isa<ObjCPropertyRefExpr>(E)) {
> +  } else if (isa<PseudoObjectExpr>(E)) {
>     DiagID = diag::warn_unused_property_expr;
>   } else if (const CXXFunctionalCastExpr *FC
>                                        =
> dyn_cast<CXXFunctionalCastExpr>(E)) {
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Sun Nov  6 03:01:30 2011
> @@ -6103,6 +6103,22 @@
>
>  template<typename Derived>
>  ExprResult
> +TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) {
> +  // Rebuild the syntactic form.
> +  ExprResult result = getDerived().TransformExpr(E->getSyntacticForm());
> +  if (result.isInvalid()) return ExprError();
> +
> +  // If that gives us a pseudo-object result back, the pseudo-object
> +  // expression must have been an lvalue-to-rvalue conversion which we
> +  // should reapply.
> +  if (result.get()->hasPlaceholderType(BuiltinType::PseudoObject))
> +    result = SemaRef.checkPseudoObjectRValue(result.take());
> +
> +  return result;
> +}
> +
> +template<typename Derived>
> +ExprResult
>  TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
>                                                 UnaryExprOrTypeTraitExpr
> *E) {
>   if (E->isArgumentType()) {
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Sun Nov  6 03:01:30 2011
> @@ -775,6 +775,24 @@
>   E->RParenLoc = ReadSourceLocation(Record, Idx);
>  }
>
> +void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +  VisitExpr(E);
> +  unsigned numSemanticExprs = Record[Idx++];
> +  assert(numSemanticExprs + 1 == E->PseudoObjectExprBits.NumSubExprs);
> +  E->PseudoObjectExprBits.ResultIndex = Record[Idx++];
> +
> +  // Read the syntactic expression.
> +  E->getSubExprsBuffer()[0] = Reader.ReadSubExpr();
> +
> +  // Read all the semantic expressions.
> +  for (unsigned i = 0; i != numSemanticExprs; ++i) {
> +    Expr *subExpr = Reader.ReadSubExpr();
> +    if (isa<OpaqueValueExpr>(subExpr))
> +      cast<OpaqueValueExpr>(subExpr)->setSourceExpr(Reader.ReadSubExpr());
> +    E->getSubExprsBuffer()[i+1] = subExpr;
> +  }
> +}
> +
>  void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) {
>   VisitExpr(E);
>   E->setOp(AtomicExpr::AtomicOp(Record[Idx++]));
> @@ -2059,6 +2077,12 @@
>       S = new (Context) AsTypeExpr(Empty);
>       break;
>
> +    case EXPR_PSEUDO_OBJECT: {
> +      unsigned numSemanticExprs = Record[ASTStmtReader::NumExprFields];
> +      S = PseudoObjectExpr::Create(Context, Empty, numSemanticExprs);
> +      break;
> +    }
> +
>     case EXPR_ATOMIC:
>       S = new (Context) AtomicExpr(Empty);
>       break;
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Sun Nov  6 03:01:30 2011
> @@ -736,6 +736,25 @@
>   Code = serialization::EXPR_GENERIC_SELECTION;
>  }
>
> +void ASTStmtWriter::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +  VisitExpr(E);
> +  Record.push_back(E->getNumSemanticExprs());
> +
> +  // Push the result index.  Currently, this needs to exactly match
> +  // the encoding used internally for ResultIndex.
> +  unsigned result = E->getResultExprIndex();
> +  result = (result == PseudoObjectExpr::NoResult ? 0 : result + 1);
> +  Record.push_back(result);
> +
> +  Writer.AddStmt(E->getSyntacticForm());
> +  for (PseudoObjectExpr::semantics_iterator
> +         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {
> +    Writer.AddStmt(*i);
> +    if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i))
> +      Writer.AddStmt(OVE->getSourceExpr());
> +  }
> +}
> +
>  void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) {
>   VisitExpr(E);
>   Record.push_back(E->getOp());
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Sun Nov  6 03:01:30
> 2011
> @@ -857,6 +857,21 @@
>       Bldr.addNodes(Dst);
>       break;
>     }
> +
> +    case Stmt::PseudoObjectExprClass: {
> +      Bldr.takeNodes(Pred);
> +      const ProgramState *state = Pred->getState();
> +      const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
> +      if (const Expr *Result = PE->getResultExpr()) {
> +        SVal V = state->getSVal(Result);
> +        Bldr.generateNode(S, Pred, state->BindExpr(S, V));
> +      }
> +      else
> +        Bldr.generateNode(S, Pred, state->BindExpr(S, UnknownVal()));
> +
> +      Bldr.addNodes(Dst);
> +      break;
> +    }
>   }
>  }
>
>
> Modified: cfe/trunk/test/Analysis/casts.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/casts.m?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Analysis/casts.m (original)
> +++ cfe/trunk/test/Analysis/casts.m Sun Nov  6 03:01:30 2011
> @@ -33,9 +33,10 @@
>   RDR10087620Enum   elem;
>  }
>  @property (readwrite, nonatomic) RDR10087620Enum elem;
> + at end
> +
>  static void
>  adium_media_ready_cb(RDR10087620 *InObj)
>  {
>   InObj.elem |= EEOne;
>  }
> - at end
> \ No newline at end of file
>
> Modified: cfe/trunk/test/Analysis/retain-release-path-notes.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-path-notes.m?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Analysis/retain-release-path-notes.m (original)
> +++ cfe/trunk/test/Analysis/retain-release-path-notes.m Sun Nov  6
> 03:01:30 2011
> @@ -1,5 +1,10 @@
>  // 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
>
> +// This actually still works after the pseudo-object refactor, it just
> +// uses messages that say 'method' instead of 'property'.  Ted wanted
> +// this xfailed and filed as a bug.  rdar://problem/10402993
> +// XFAIL: *
> +
>  /***
>  This file is for testing the path-sensitive notes for retain/release
> errors.
>  Its goal is to have simple branch coverage of any path-based diagnostics,
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Sun Nov  6 03:01:30 2011
> @@ -1714,6 +1714,8 @@
>   void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
>   void VisitVAArgExpr(VAArgExpr *E);
>   void VisitSizeOfPackExpr(SizeOfPackExpr *E);
> +  void VisitPseudoObjectExpr(PseudoObjectExpr *E);
> +  void VisitOpaqueValueExpr(OpaqueValueExpr *E);
>
>  private:
>   void AddDeclarationNameInfo(Stmt *S);
> @@ -2022,6 +2024,17 @@
>  void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
>   WL.push_back(SizeOfPackExprParts(E, Parent));
>  }
> +void EnqueueVisitor::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
> +  // If the opaque value has a source expression, just transparently
> +  // visit that.  This is useful for (e.g.) pseudo-object expressions.
> +  if (Expr *SourceExpr = E->getSourceExpr())
> +    return Visit(SourceExpr);
> +  AddStmt(E);
> +}
> +void EnqueueVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
> +  // Treat the expression like its syntactic form.
> +  Visit(E->getSyntacticForm());
> +}
>
>  void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {
>   EnqueueVisitor(WL, MakeCXCursor(S, StmtParent,
> TU,RegionOfInterest)).Visit(S);
> @@ -2702,6 +2715,11 @@
>     return RE->getDecl();
>   if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E))
>     return PRE->isExplicitProperty() ? PRE->getExplicitProperty() : 0;
> +  if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
> +    return getDeclFromExpr(POE->getSyntacticForm());
> +  if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
> +    if (Expr *Src = OVE->getSourceExpr())
> +      return getDeclFromExpr(Src);
>
>   if (CallExpr *CE = dyn_cast<CallExpr>(E))
>     return getDeclFromExpr(CE->getCallee());
>
> Modified: cfe/trunk/tools/libclang/CXCursor.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=143867&r1=143866&r2=143867&view=diff
>
> ==============================================================================
> --- cfe/trunk/tools/libclang/CXCursor.cpp (original)
> +++ cfe/trunk/tools/libclang/CXCursor.cpp Sun Nov  6 03:01:30 2011
> @@ -219,7 +219,6 @@
>   case Stmt::MaterializeTemporaryExprClass:
>   case Stmt::ObjCIndirectCopyRestoreExprClass:
>   case Stmt::OffsetOfExprClass:
> -  case Stmt::OpaqueValueExprClass:
>   case Stmt::ParenListExprClass:
>   case Stmt::PredefinedExprClass:
>   case Stmt::ShuffleVectorExprClass:
> @@ -229,6 +228,16 @@
>     K = CXCursor_UnexposedExpr;
>     break;
>
> +  case Stmt::OpaqueValueExprClass:
> +    if (Expr *Src = cast<OpaqueValueExpr>(S)->getSourceExpr())
> +      return MakeCXCursor(Src, Parent, TU, RegionOfInterest);
> +    K = CXCursor_UnexposedExpr;
> +    break;
> +
> +  case Stmt::PseudoObjectExprClass:
> +    return MakeCXCursor(cast<PseudoObjectExpr>(S)->getSyntacticForm(),
> +                        Parent, TU, RegionOfInterest);
> +
>   case Stmt::CompoundStmtClass:
>     K = CXCursor_CompoundStmt;
>     break;
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111106/c5261896/attachment.html>


More information about the cfe-commits mailing list