[cfe-commits] r142931 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Rewrite/ lib/Sema/ lib/Serialization/ test/SemaObjC/ test/SemaObjCXX/

Eli Friedman eli.friedman at gmail.com
Wed Oct 26 18:14:32 PDT 2011


On Tue, Oct 25, 2011 at 10:37 AM, John McCall <rjmccall at apple.com> wrote:
> Author: rjmccall
> Date: Tue Oct 25 12:37:35 2011
> New Revision: 142931
>
> URL: http://llvm.org/viewvc/llvm-project?rev=142931&view=rev
> Log:
> Restore r142914 and r142915, now with missing file and apparent
> GCC compiler workaround.

This commit appears to be causing a crash on
g++.old-deja/g++.jason/net.C in the gcc testsuite.

-Eli

>
> Added:
>    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
> Modified:
>    cfe/trunk/include/clang/AST/ASTContext.h
>    cfe/trunk/include/clang/AST/BuiltinTypes.def
>    cfe/trunk/include/clang/AST/Expr.h
>    cfe/trunk/include/clang/AST/ExprObjC.h
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>    cfe/trunk/include/clang/Sema/Sema.h
>    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>    cfe/trunk/lib/AST/ASTContext.cpp
>    cfe/trunk/lib/AST/Type.cpp
>    cfe/trunk/lib/AST/TypeLoc.cpp
>    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
>    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
>    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>    cfe/trunk/lib/Rewrite/RewriteObjC.cpp
>    cfe/trunk/lib/Sema/CMakeLists.txt
>    cfe/trunk/lib/Sema/SemaChecking.cpp
>    cfe/trunk/lib/Sema/SemaExpr.cpp
>    cfe/trunk/lib/Sema/SemaExprCXX.cpp
>    cfe/trunk/lib/Sema/SemaExprMember.cpp
>    cfe/trunk/lib/Sema/SemaExprObjC.cpp
>    cfe/trunk/lib/Sema/SemaInit.cpp
>    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
>    cfe/trunk/lib/Sema/SemaOverload.cpp
>    cfe/trunk/lib/Sema/SemaStmt.cpp
>    cfe/trunk/lib/Sema/TreeTransform.h
>    cfe/trunk/lib/Serialization/ASTCommon.cpp
>    cfe/trunk/lib/Serialization/ASTReader.cpp
>    cfe/trunk/test/SemaObjC/property-category-1.m
>    cfe/trunk/test/SemaObjC/property-error-readonly-assign.m
>    cfe/trunk/test/SemaObjC/property-in-class-extension.m
>    cfe/trunk/test/SemaObjC/property-user-setter.m
>    cfe/trunk/test/SemaObjCXX/propert-dot-error.mm
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Tue Oct 25 12:37:35 2011
> @@ -496,7 +496,7 @@
>   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
>   CanQualType VoidPtrTy, NullPtrTy;
>   CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
> -  CanQualType ARCUnbridgedCastTy;
> +  CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
>   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
>
>   // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
>
> Modified: cfe/trunk/include/clang/AST/BuiltinTypes.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/BuiltinTypes.def?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/BuiltinTypes.def (original)
> +++ cfe/trunk/include/clang/AST/BuiltinTypes.def Tue Oct 25 12:37:35 2011
> @@ -179,6 +179,24 @@
>  //   x->foo       # if only contains non-static members
>  PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)
>
> +// The type of an expression which refers to a pseudo-object,
> +// such as those introduced by Objective C's @property or
> +// VS.NET's __property declarations.  A placeholder type.  The
> +// pseudo-object is actually accessed by emitting a call to
> +// some sort of function or method;  typically there is a pair
> +// of a setter and a getter, with the setter used if the
> +// pseudo-object reference is used syntactically as the
> +// left-hand-side of an assignment operator.
> +//
> +// A pseudo-object reference naming an Objective-C @property is
> +// always a dot access with a base of object-pointer type,
> +// e.g. 'x.foo'.
> +//
> +// In VS.NET, a __property declaration creates an implicit
> +// member with an associated name, which can then be named
> +// in any of the normal ways an ordinary member could be.
> +PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
> +
>  // __builtin_any_type.  A placeholder type.  Useful for clients
>  // like debuggers that don't know what type to give something.
>  // Only a small number of operations are valid on expressions of
>
> Modified: cfe/trunk/include/clang/AST/Expr.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Tue Oct 25 12:37:35 2011
> @@ -1456,12 +1456,26 @@
>
>   bool isPrefix() const { return isPrefix(getOpcode()); }
>   bool isPostfix() const { return isPostfix(getOpcode()); }
> +
> +  static bool isIncrementOp(Opcode Op) {
> +    return Op == UO_PreInc || Op == UO_PostInc;
> +  }
>   bool isIncrementOp() const {
> -    return Opc == UO_PreInc || Opc == UO_PostInc;
> +    return isIncrementOp(getOpcode());
> +  }
> +
> +  static bool isDecrementOp(Opcode Op) {
> +    return Op == UO_PreDec || Op == UO_PostDec;
>   }
> +  bool isDecrementOp() const {
> +    return isDecrementOp(getOpcode());
> +  }
> +
> +  static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
>   bool isIncrementDecrementOp() const {
> -    return Opc <= UO_PreDec;
> +    return isIncrementDecrementOp(getOpcode());
>   }
> +
>   static bool isArithmeticOp(Opcode Op) {
>     return Op >= UO_Plus && Op <= UO_LNot;
>   }
>
> Modified: cfe/trunk/include/clang/AST/ExprObjC.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ExprObjC.h (original)
> +++ cfe/trunk/include/clang/AST/ExprObjC.h Tue Oct 25 12:37:35 2011
> @@ -227,7 +227,6 @@
>
>  /// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
>  /// property.
> -///
>  class ObjCPropertyRefExpr : public Expr {
>  private:
>   /// If the bool is true, this is an implicit property reference; the
> @@ -237,6 +236,11 @@
>   llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
>   ObjCMethodDecl *Setter;
>
> +  // FIXME: Maybe we should store the property identifier here,
> +  // because it's not rederivable from the other data when there's an
> +  // implicit property with no getter (because the 'foo' -> 'setFoo:'
> +  // transformation is lossy on the first character).
> +
>   SourceLocation IdLoc;
>
>   /// \brief When the receiver in property access is 'super', this is
> @@ -255,6 +259,7 @@
>            base->containsUnexpandedParameterPack()),
>       PropertyOrGetter(PD, false), Setter(0),
>       IdLoc(l), ReceiverLoc(), Receiver(base) {
> +    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
>   }
>
>   ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
> @@ -265,6 +270,7 @@
>            st->containsUnexpandedParameterPack()),
>       PropertyOrGetter(PD, false), Setter(0),
>       IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
> +    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
>   }
>
>   ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
> @@ -275,6 +281,7 @@
>            Base->containsUnexpandedParameterPack()),
>       PropertyOrGetter(Getter, true), Setter(Setter),
>       IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
> +    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
>   }
>
>   ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
> @@ -284,6 +291,7 @@
>     : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
>       PropertyOrGetter(Getter, true), Setter(Setter),
>       IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
> +    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
>   }
>
>   ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
> @@ -293,6 +301,7 @@
>     : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
>       PropertyOrGetter(Getter, true), Setter(Setter),
>       IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
> +    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
>   }
>
>   explicit ObjCPropertyRefExpr(EmptyShell Empty)
> @@ -348,14 +357,15 @@
>       if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
>         ResultType = Getter->getResultType();
>       else
> -        ResultType = getType();
> +        ResultType = PDecl->getType();
>     } else {
>       const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
> -      ResultType = Getter->getResultType(); // with reference!
> +      if (Getter)
> +        ResultType = Getter->getResultType(); // with reference!
>     }
>     return ResultType;
>   }
> -
> +
>   QualType getSetterArgType() const {
>     QualType ArgType;
>     if (isImplicitProperty()) {
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct 25 12:37:35 2011
> @@ -3612,16 +3612,22 @@
>   "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function "
>   "type%select{|s}2 %1%select{| and %3}2 is a GNU extension">,
>   InGroup<PointerArith>;
> -def error_readonly_property_assignment : Error<
> -  "assigning to property with 'readonly' attribute not allowed">;
>  def error_readonly_message_assignment : Error<
>   "assigning to 'readonly' return result of an objective-c message not allowed">;
>  def ext_integer_increment_complex : Extension<
>   "ISO C does not support '++'/'--' on complex integer type %0">;
>  def ext_integer_complement_complex : Extension<
>   "ISO C does not support '~' for complex conjugation of %0">;
> -def error_nosetter_property_assignment : Error<
> -  "setter method is needed to assign to object using property" " assignment syntax">;
> +def err_nosetter_property_assignment : Error<
> +  "%select{assignment to readonly property|"
> +  "no setter method %1 for assignment to property}0">;
> +def err_nosetter_property_incdec : Error<
> +  "%select{%select{increment|decrement}1 of readonly property|"
> +  "no setter method %2 for %select{increment|decrement}1 of property}0">;
> +def err_nogetter_property_compound_assignment : Error<
> +  "a getter method is needed to perform a compound assignment on a property">;
> +def err_nogetter_property_incdec : Error<
> +  "no getter method %1 for %select{increment|decrement} of property">;
>  def error_no_subobject_property_setting : Error<
>   "expression is not assignable">;
>  def err_qualified_objc_access : Error<
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 25 12:37:35 2011
> @@ -5319,6 +5319,8 @@
>   ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
>                                               const ObjCObjectPointerType *OPT,
>                                               bool IsInstance);
> +  ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
> +                                           bool IsInstance);
>
>   bool inferObjCARCLifetime(ValueDecl *decl);
>
> @@ -5777,10 +5779,13 @@
>   // For compound assignment, pass both expressions and the converted type.
>   QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
>     Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType);
> -
> -  void ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS,
> -                                QualType& LHSTy);
> -  ExprResult ConvertPropertyForRValue(Expr *E);
> +
> +  ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc,
> +                                     UnaryOperatorKind Opcode, Expr *Op);
> +  ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc,
> +                                         BinaryOperatorKind Opcode,
> +                                         Expr *LHS, Expr *RHS);
> +  ExprResult checkPseudoObjectRValue(Expr *E);
>
>   QualType CheckConditionalOperands( // C99 6.5.15
>     ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Oct 25 12:37:35 2011
> @@ -556,7 +556,9 @@
>       /// \brief The OpenCL 'half' / ARM NEON __fp16 type.
>       PREDEF_TYPE_HALF_ID       = 33,
>       /// \brief ARC's unbridged-cast placeholder type.
> -      PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34
> +      PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
> +      /// \brief The pseudo-object placeholder type.
> +      PREDEF_TYPE_PSEUDO_OBJECT = 35
>     };
>
>     /// \brief The number of predefined type IDs that are reserved for
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Tue Oct 25 12:37:35 2011
> @@ -461,6 +461,9 @@
>   // Placeholder type for bound members.
>   InitBuiltinType(BoundMemberTy,       BuiltinType::BoundMember);
>
> +  // Placeholder type for pseudo-objects.
> +  InitBuiltinType(PseudoObjectTy,      BuiltinType::PseudoObject);
> +
>   // "any" type; useful for debugger-like clients.
>   InitBuiltinType(UnknownAnyTy,        BuiltinType::UnknownAny);
>
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Tue Oct 25 12:37:35 2011
> @@ -1493,6 +1493,7 @@
>   case NullPtr:           return "nullptr_t";
>   case Overload:          return "<overloaded function type>";
>   case BoundMember:       return "<bound member function type>";
> +  case PseudoObject:      return "<pseudo-object type>";
>   case Dependent:         return "<dependent type>";
>   case UnknownAny:        return "<unknown type>";
>   case ARCUnbridgedCast:  return "<ARC unbridged cast type>";
>
> Modified: cfe/trunk/lib/AST/TypeLoc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/TypeLoc.cpp (original)
> +++ cfe/trunk/lib/AST/TypeLoc.cpp Tue Oct 25 12:37:35 2011
> @@ -238,6 +238,7 @@
>     case BuiltinType::BoundMember:
>     case BuiltinType::UnknownAny:
>     case BuiltinType::ARCUnbridgedCast:
> +    case BuiltinType::PseudoObject:
>     case BuiltinType::ObjCId:
>     case BuiltinType::ObjCClass:
>     case BuiltinType::ObjCSel:
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Tue Oct 25 12:37:35 2011
> @@ -326,7 +326,8 @@
>   }
>
>   case CK_GetObjCProperty: {
> -    LValue LV = CGF.EmitLValue(E->getSubExpr());
> +    LValue LV =
> +      CGF.EmitObjCPropertyRefLValue(E->getSubExpr()->getObjCProperty());
>     assert(LV.isPropertyRef());
>     RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV, getReturnValueSlot());
>     EmitMoveFromReturnSlot(E, RV);
>
> Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Tue Oct 25 12:37:35 2011
> @@ -363,7 +363,7 @@
>   case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
>
>   case CK_GetObjCProperty: {
> -    LValue LV = CGF.EmitLValue(Op);
> +    LValue LV = CGF.EmitObjCPropertyRefLValue(Op->getObjCProperty());
>     assert(LV.isPropertyRef() && "Unknown LValue type!");
>     return CGF.EmitLoadOfPropertyRefLValue(LV).getComplexVal();
>   }
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Oct 25 12:37:35 2011
> @@ -1167,10 +1167,10 @@
>     break;
>
>   case CK_GetObjCProperty: {
> -    assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
>     assert(E->isGLValue() && E->getObjectKind() == OK_ObjCProperty &&
>            "CK_GetObjCProperty for non-lvalue or non-ObjCProperty");
> -    RValue RV = CGF.EmitLoadOfLValue(CGF.EmitLValue(E));
> +    LValue LV = CGF.EmitObjCPropertyRefLValue(E->getObjCProperty());
> +    RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV);
>     return RV.getScalarVal();
>   }
>
>
> Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
> +++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Tue Oct 25 12:37:35 2011
> @@ -1304,7 +1304,7 @@
>     } else {
>       OMD = PropRefExpr->getImplicitPropertySetter();
>       Sel = OMD->getSelector();
> -      Ty = PropRefExpr->getType();
> +      Ty = (*OMD->param_begin())->getType();
>     }
>     Super = PropRefExpr->isSuperReceiver();
>     if (!Super) {
> @@ -1380,7 +1380,7 @@
>     } else {
>       OMD = PropRefExpr->getImplicitPropertyGetter();
>       Sel = OMD->getSelector();
> -      Ty = PropRefExpr->getType();
> +      Ty = OMD->getResultType();
>     }
>     Super = PropRefExpr->isSuperReceiver();
>     if (!Super)
>
> Modified: cfe/trunk/lib/Sema/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/CMakeLists.txt (original)
> +++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Oct 25 12:37:35 2011
> @@ -31,6 +31,7 @@
>   SemaLookup.cpp
>   SemaObjCProperty.cpp
>   SemaOverload.cpp
> +  SemaPseudoObject.cpp
>   SemaStmt.cpp
>   SemaTemplate.cpp
>   SemaTemplateDeduction.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Oct 25 12:37:35 2011
> @@ -4256,7 +4256,8 @@
>   if (LT != Qualifiers::OCL_None)
>     return;
>
> -  if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(LHS)) {
> +  if (ObjCPropertyRefExpr *PRE
> +        = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens())) {
>     if (PRE->isImplicitProperty())
>       return;
>     const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Oct 25 12:37:35 2011
> @@ -363,19 +363,9 @@
>   assert(!T.isNull() && "r-value conversion on typeless expression?");
>
>   // We can't do lvalue-to-rvalue on atomics yet.
> -  if (T->getAs<AtomicType>())
> +  if (T->isAtomicType())
>     return Owned(E);
>
> -  // Create a load out of an ObjCProperty l-value, if necessary.
> -  if (E->getObjectKind() == OK_ObjCProperty) {
> -    ExprResult Res = ConvertPropertyForRValue(E);
> -    if (Res.isInvalid())
> -      return Owned(E);
> -    E = Res.take();
> -    if (!E->isGLValue())
> -      return Owned(E);
> -  }
> -
>   // We don't want to throw lvalue-to-rvalue casts on top of
>   // expressions of certain types in C++.
>   if (getLangOptions().CPlusPlus &&
> @@ -3969,6 +3959,23 @@
>   unsigned NumInit = InitArgList.size();
>   Expr **InitList = InitArgList.release();
>
> +  // Immediately handle non-overload placeholders.  Overloads can be
> +  // resolved contextually, but everything else here can't.
> +  for (unsigned I = 0; I != NumInit; ++I) {
> +    if (const BuiltinType *pty
> +          = InitList[I]->getType()->getAsPlaceholderType()) {
> +      if (pty->getKind() == BuiltinType::Overload) continue;
> +
> +      ExprResult result = CheckPlaceholderExpr(InitList[I]);
> +
> +      // Ignore failures; dropping the entire initializer list because
> +      // of one failure would be terrible for indexing/etc.
> +      if (result.isInvalid()) continue;
> +
> +      InitList[I] = result.take();
> +    }
> +  }
> +
>   // Semantic analysis for initializers is done by ActOnDeclarator() and
>   // CheckInitializer() - it requires knowledge of the object being intialized.
>
> @@ -6953,51 +6960,41 @@
>  /// depends on various declarations and thus must be treated specially.
>  ///
>  static bool IsReadonlyProperty(Expr *E, Sema &S) {
> -  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
> -    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
> -    if (PropExpr->isImplicitProperty()) return false;
> +  const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
> +  if (!PropExpr) return false;
> +  if (PropExpr->isImplicitProperty()) return false;
>
> -    ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
> -    QualType BaseType = PropExpr->isSuperReceiver() ?
> +  ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
> +  QualType BaseType = PropExpr->isSuperReceiver() ?
>                             PropExpr->getSuperReceiverType() :
>                             PropExpr->getBase()->getType();
>
> -    if (const ObjCObjectPointerType *OPT =
> -          BaseType->getAsObjCInterfacePointerType())
> -      if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
> -        if (S.isPropertyReadonly(PDecl, IFace))
> -          return true;
> -  }
> +  if (const ObjCObjectPointerType *OPT =
> +      BaseType->getAsObjCInterfacePointerType())
> +    if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
> +      if (S.isPropertyReadonly(PDecl, IFace))
> +        return true;
>   return false;
>  }
>
>  static bool IsConstProperty(Expr *E, Sema &S) {
> -  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
> -    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
> -    if (PropExpr->isImplicitProperty()) return false;
> +  const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
> +  if (!PropExpr) return false;
> +  if (PropExpr->isImplicitProperty()) return false;
>
> -    ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
> -    QualType T = PDecl->getType();
> -    if (T->isReferenceType())
> -      T = T->getAs<ReferenceType>()->getPointeeType();
> -    CanQualType CT = S.Context.getCanonicalType(T);
> -    return CT.isConstQualified();
> -  }
> -  return false;
> +  ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
> +  QualType T = PDecl->getType().getNonReferenceType();
> +  return T.isConstQualified();
>  }
>
>  static bool IsReadonlyMessage(Expr *E, Sema &S) {
> -  if (E->getStmtClass() != Expr::MemberExprClass)
> -    return false;
> -  const MemberExpr *ME = cast<MemberExpr>(E);
> -  NamedDecl *Member = ME->getMemberDecl();
> -  if (isa<FieldDecl>(Member)) {
> -    Expr *Base = ME->getBase()->IgnoreParenImpCasts();
> -    if (Base->getStmtClass() != Expr::ObjCMessageExprClass)
> -      return false;
> -    return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0;
> -  }
> -  return false;
> +  const MemberExpr *ME = dyn_cast<MemberExpr>(E);
> +  if (!ME) return false;
> +  if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
> +  ObjCMessageExpr *Base =
> +    dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
> +  if (!Base) return false;
> +  return Base->getMethodDecl() != 0;
>  }
>
>  /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not,
> @@ -7085,10 +7082,8 @@
>     Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
>     break;
>   case Expr::MLV_ReadonlyProperty:
> -    Diag = diag::error_readonly_property_assignment;
> -    break;
>   case Expr::MLV_NoSetterProperty:
> -    Diag = diag::error_nosetter_property_assignment;
> +    llvm_unreachable("readonly properties should be processed differently");
>     break;
>   case Expr::MLV_InvalidMessageExpression:
>     Diag = diag::error_readonly_message_assignment;
> @@ -7114,6 +7109,8 @@
>  QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
>                                        SourceLocation Loc,
>                                        QualType CompoundType) {
> +  assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
> +
>   // Verify that LHS is a modifiable lvalue, and emit error if not.
>   if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
>     return QualType();
> @@ -7124,14 +7121,6 @@
>   AssignConvertType ConvTy;
>   if (CompoundType.isNull()) {
>     QualType LHSTy(LHSType);
> -    // Simple assignment "x = y".
> -    if (LHSExpr->getObjectKind() == OK_ObjCProperty) {
> -      ExprResult LHSResult = Owned(LHSExpr);
> -      ConvertPropertyForLValue(LHSResult, RHS, LHSTy);
> -      if (LHSResult.isInvalid())
> -        return QualType();
> -      LHSExpr = LHSResult.take();
> -    }
>     ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
>     if (RHS.isInvalid())
>       return QualType();
> @@ -7292,104 +7281,6 @@
>     return ResType.getUnqualifiedType();
>   }
>  }
> -
> -ExprResult Sema::ConvertPropertyForRValue(Expr *E) {
> -  assert(E->getValueKind() == VK_LValue &&
> -         E->getObjectKind() == OK_ObjCProperty);
> -  const ObjCPropertyRefExpr *PRE = E->getObjCProperty();
> -
> -  QualType T = E->getType();
> -  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;
> -  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();
> -    }
> -  }
> -  else {
> -    // lvalue-ness of an explicit property is determined by
> -    // getter type.
> -    QualType ResT = PRE->getGetterResultType();
> -    VK = Expr::getValueKindForType(ResT);
> -  }
> -
> -  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty,
> -                               E, 0, VK);
> -
> -  ExprResult Result = MaybeBindToTemporary(E);
> -  if (!Result.isInvalid())
> -    E = Result.take();
> -
> -  return Owned(E);
> -}
> -
> -void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS,
> -                                    QualType &LHSTy) {
> -  assert(LHS.get()->getValueKind() == VK_LValue &&
> -         LHS.get()->getObjectKind() == OK_ObjCProperty);
> -  const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty();
> -
> -  bool Consumed = false;
> -
> -  if (PropRef->isImplicitProperty()) {
> -    // If using property-dot syntax notation for assignment, and there is a
> -    // setter, RHS expression is being passed to the setter argument. So,
> -    // type conversion (and comparison) is RHS to setter's argument type.
> -    if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) {
> -      ObjCMethodDecl::param_const_iterator P = SetterMD->param_begin();
> -      LHSTy = (*P)->getType();
> -      Consumed = (getLangOptions().ObjCAutoRefCount &&
> -                  (*P)->hasAttr<NSConsumedAttr>());
> -
> -    // Otherwise, if the getter returns an l-value, just call that.
> -    } else {
> -      QualType Result = PropRef->getImplicitPropertyGetter()->getResultType();
> -      ExprValueKind VK = Expr::getValueKindForType(Result);
> -      if (VK == VK_LValue) {
> -        LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(),
> -                                        CK_GetObjCProperty, LHS.take(), 0, VK);
> -        return;
> -      }
> -    }
> -  } else {
> -    const ObjCMethodDecl *setter
> -      = PropRef->getExplicitProperty()->getSetterMethodDecl();
> -    if (setter) {
> -      ObjCMethodDecl::param_const_iterator P = setter->param_begin();
> -      LHSTy = (*P)->getType();
> -      if (getLangOptions().ObjCAutoRefCount)
> -        Consumed = (*P)->hasAttr<NSConsumedAttr>();
> -    }
> -  }
> -
> -  if ((getLangOptions().CPlusPlus && LHSTy->isRecordType()) ||
> -      getLangOptions().ObjCAutoRefCount) {
> -    InitializedEntity Entity =
> -      InitializedEntity::InitializeParameter(Context, LHSTy, Consumed);
> -    ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS);
> -    if (!ArgE.isInvalid()) {
> -      RHS = ArgE;
> -      if (getLangOptions().ObjCAutoRefCount && !PropRef->isSuperReceiver())
> -        checkRetainCycles(const_cast<Expr*>(PropRef->getBase()), RHS.get());
> -    }
> -  }
> -  LHSTy = LHSTy.getNonReferenceType();
> -}
>
>
>  /// getPrimaryDecl - Helper function for CheckAddressOfOperand().
> @@ -7473,31 +7364,39 @@
>  /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
>  /// In C++, the operand might be an overloaded function name, in which case
>  /// we allow the '&' but retain the overloaded-function type.
> -static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
> +static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
>                                       SourceLocation OpLoc) {
> -  if (OrigOp->isTypeDependent())
> -    return S.Context.DependentTy;
> -  if (OrigOp->getType() == S.Context.OverloadTy) {
> -    if (!isa<OverloadExpr>(OrigOp->IgnoreParens())) {
> -      S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
> -        << OrigOp->getSourceRange();
> +  if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
> +    if (PTy->getKind() == BuiltinType::Overload) {
> +      if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
> +        S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
> +          << OrigOp.get()->getSourceRange();
> +        return QualType();
> +      }
> +
> +      return S.Context.OverloadTy;
> +    }
> +
> +    if (PTy->getKind() == BuiltinType::UnknownAny)
> +      return S.Context.UnknownAnyTy;
> +
> +    if (PTy->getKind() == BuiltinType::BoundMember) {
> +      S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
> +        << OrigOp.get()->getSourceRange();
>       return QualType();
>     }
> -
> -    return S.Context.OverloadTy;
> -  }
> -  if (OrigOp->getType() == S.Context.UnknownAnyTy)
> -    return S.Context.UnknownAnyTy;
> -  if (OrigOp->getType() == S.Context.BoundMemberTy) {
> -    S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
> -      << OrigOp->getSourceRange();
> -    return QualType();
> +
> +    OrigOp = S.CheckPlaceholderExpr(OrigOp.take());
> +    if (OrigOp.isInvalid()) return QualType();
>   }
>
> -  assert(!OrigOp->getType()->isPlaceholderType());
> +  if (OrigOp.get()->isTypeDependent())
> +    return S.Context.DependentTy;
> +
> +  assert(!OrigOp.get()->getType()->isPlaceholderType());
>
>   // Make sure to ignore parentheses in subsequent checks
> -  Expr *op = OrigOp->IgnoreParens();
> +  Expr *op = OrigOp.get()->IgnoreParens();
>
>   if (S.getLangOptions().C99) {
>     // Implement C99-only parts of addressof rules.
> @@ -7530,16 +7429,16 @@
>     // If the underlying expression isn't a decl ref, give up.
>     if (!isa<DeclRefExpr>(op)) {
>       S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
> -        << OrigOp->getSourceRange();
> +        << OrigOp.get()->getSourceRange();
>       return QualType();
>     }
>     DeclRefExpr *DRE = cast<DeclRefExpr>(op);
>     CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
>
>     // The id-expression was parenthesized.
> -    if (OrigOp != DRE) {
> +    if (OrigOp.get() != DRE) {
>       S.Diag(OpLoc, diag::err_parens_pointer_member_function)
> -        << OrigOp->getSourceRange();
> +        << OrigOp.get()->getSourceRange();
>
>     // The method was named without a qualifier.
>     } else if (!DRE->getQualifier()) {
> @@ -7553,10 +7452,15 @@
>     // C99 6.5.3.2p1
>     // The operand must be either an l-value or a function designator
>     if (!op->getType()->isFunctionType()) {
> -      // FIXME: emit more specific diag...
> -      S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
> -        << op->getSourceRange();
> -      return QualType();
> +      // Use a special diagnostic for loads from property references.
> +      if (isa<ObjCPropertyRefExpr>(op->IgnoreImplicit()->IgnoreParens())) {
> +        AddressOfError = AO_Property_Expansion;
> +      } else {
> +        // FIXME: emit more specific diag...
> +        S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
> +          << op->getSourceRange();
> +        return QualType();
> +      }
>     }
>   } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1
>     // The operand cannot be a bit-field
> @@ -7781,23 +7685,6 @@
>   ExprValueKind VK = VK_RValue;
>   ExprObjectKind OK = OK_Ordinary;
>
> -  // Check if a 'foo<int>' involved in a binary op, identifies a single
> -  // function unambiguously (i.e. an lvalue ala 13.4)
> -  // But since an assignment can trigger target based overload, exclude it in
> -  // our blind search. i.e:
> -  // template<class T> void f(); template<class T, class U> void f(U);
> -  // f<int> == 0;  // resolve f<int> blindly
> -  // void (*p)(int); p = f<int>;  // resolve f<int> using target
> -  if (Opc != BO_Assign) {
> -    ExprResult resolvedLHS = CheckPlaceholderExpr(LHS.get());
> -    if (!resolvedLHS.isUsable()) return ExprError();
> -    LHS = move(resolvedLHS);
> -
> -    ExprResult resolvedRHS = CheckPlaceholderExpr(RHS.get());
> -    if (!resolvedRHS.isUsable()) return ExprError();
> -    RHS = move(resolvedRHS);
> -  }
> -
>   switch (Opc) {
>   case BO_Assign:
>     ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
> @@ -8093,38 +7980,83 @@
>   return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
>  }
>
> +/// Build an overloaded binary operator expression in the given scope.
> +static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
> +                                       BinaryOperatorKind Opc,
> +                                       Expr *LHS, Expr *RHS) {
> +  // Find all of the overloaded operators visible from this
> +  // point. We perform both an operator-name lookup from the local
> +  // scope and an argument-dependent lookup based on the types of
> +  // the arguments.
> +  UnresolvedSet<16> Functions;
> +  OverloadedOperatorKind OverOp
> +    = BinaryOperator::getOverloadedOperator(Opc);
> +  if (Sc && OverOp != OO_None)
> +    S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
> +                                   RHS->getType(), Functions);
> +
> +  // Build the (potentially-overloaded, potentially-dependent)
> +  // binary operation.
> +  return S.CreateOverloadedBinOp(OpLoc, Opc, Functions, LHS, RHS);
> +}
> +
>  ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
>                             BinaryOperatorKind Opc,
>                             Expr *LHSExpr, Expr *RHSExpr) {
> +  // Handle pseudo-objects in the LHS.
> +  if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
> +    // Assignments with a pseudo-object l-value need special analysis.
> +    if (pty->getKind() == BuiltinType::PseudoObject &&
> +        BinaryOperator::isAssignmentOp(Opc))
> +      return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr);
> +
> +    // Don't resolve overloads if the other type is overloadable.
> +    if (pty->getKind() == BuiltinType::Overload) {
> +      // We can't actually test that if we still have a placeholder,
> +      // though.  Fortunately, none of the exceptions we see in that
> +      // code below are valid when the LHS is an overload set.
> +      ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
> +      if (resolvedRHS.isInvalid()) return ExprError();
> +      RHSExpr = resolvedRHS.take();
> +
> +      if (RHSExpr->getType()->isOverloadableType())
> +        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
> +    }
> +
> +    ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
> +    if (LHS.isInvalid()) return ExprError();
> +    LHSExpr = LHS.take();
> +  }
> +
> +  // Handle pseudo-objects in the RHS.
> +  if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) {
> +    // An overload in the RHS can potentially be resolved by the type
> +    // being assigned to.
> +    if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload)
> +      return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
> +
> +    // Don't resolve overloads if the other type is overloadable.
> +    if (pty->getKind() == BuiltinType::Overload &&
> +        LHSExpr->getType()->isOverloadableType())
> +      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
> +
> +    ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
> +    if (!resolvedRHS.isUsable()) return ExprError();
> +    RHSExpr = resolvedRHS.take();
> +  }
> +
>   if (getLangOptions().CPlusPlus) {
>     bool UseBuiltinOperator;
>
>     if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) {
>       UseBuiltinOperator = false;
> -    } else if (Opc == BO_Assign &&
> -               LHSExpr->getObjectKind() == OK_ObjCProperty) {
> -      UseBuiltinOperator = true;
>     } else {
>       UseBuiltinOperator = !LHSExpr->getType()->isOverloadableType() &&
>                            !RHSExpr->getType()->isOverloadableType();
>     }
>
> -    if (!UseBuiltinOperator) {
> -      // Find all of the overloaded operators visible from this
> -      // point. We perform both an operator-name lookup from the local
> -      // scope and an argument-dependent lookup based on the types of
> -      // the arguments.
> -      UnresolvedSet<16> Functions;
> -      OverloadedOperatorKind OverOp
> -        = BinaryOperator::getOverloadedOperator(Opc);
> -      if (S && OverOp != OO_None)
> -        LookupOverloadedOperatorName(OverOp, S, LHSExpr->getType(),
> -                                     RHSExpr->getType(), Functions);
> -
> -      // Build the (potentially-overloaded, potentially-dependent)
> -      // binary operation.
> -      return CreateOverloadedBinOp(OpLoc, Opc, Functions, LHSExpr, RHSExpr);
> -    }
> +    if (!UseBuiltinOperator)
> +      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
>   }
>
>   // Build a built-in binary operation.
> @@ -8150,12 +8082,9 @@
>                                                 Opc == UO_PreDec);
>     break;
>   case UO_AddrOf:
> -    resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc);
> +    resultType = CheckAddressOfOperand(*this, Input, OpLoc);
>     break;
>   case UO_Deref: {
> -    ExprResult resolved = CheckPlaceholderExpr(Input.get());
> -    if (!resolved.isUsable()) return ExprError();
> -    Input = move(resolved);
>     Input = DefaultFunctionArrayLvalueConversion(Input.take());
>     resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
>     break;
> @@ -8177,11 +8106,6 @@
>              Opc == UO_Plus &&
>              resultType->isPointerType())
>       break;
> -    else if (resultType->isPlaceholderType()) {
> -      Input = CheckPlaceholderExpr(Input.take());
> -      if (Input.isInvalid()) return ExprError();
> -      return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
> -    }
>
>     return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
>       << resultType << Input.get()->getSourceRange());
> @@ -8199,11 +8123,7 @@
>         << resultType << Input.get()->getSourceRange();
>     else if (resultType->hasIntegerRepresentation())
>       break;
> -    else if (resultType->isPlaceholderType()) {
> -      Input = CheckPlaceholderExpr(Input.take());
> -      if (Input.isInvalid()) return ExprError();
> -      return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
> -    } else {
> +    else {
>       return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
>         << resultType << Input.get()->getSourceRange());
>     }
> @@ -8231,10 +8151,6 @@
>         Input = ImpCastExprToType(Input.take(), Context.BoolTy,
>                                   ScalarTypeToBooleanCastKind(resultType));
>       }
> -    } else if (resultType->isPlaceholderType()) {
> -      Input = CheckPlaceholderExpr(Input.take());
> -      if (Input.isInvalid()) return ExprError();
> -      return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
>     } else {
>       return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
>         << resultType << Input.get()->getSourceRange());
> @@ -8275,6 +8191,32 @@
>
>  ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
>                               UnaryOperatorKind Opc, Expr *Input) {
> +  // First things first: handle placeholders so that the
> +  // overloaded-operator check considers the right type.
> +  if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) {
> +    // Increment and decrement of pseudo-object references.
> +    if (pty->getKind() == BuiltinType::PseudoObject &&
> +        UnaryOperator::isIncrementDecrementOp(Opc))
> +      return checkPseudoObjectIncDec(S, OpLoc, Opc, Input);
> +
> +    // extension is always a builtin operator.
> +    if (Opc == UO_Extension)
> +      return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
> +
> +    // & gets special logic for several kinds of placeholder.
> +    // The builtin code knows what to do.
> +    if (Opc == UO_AddrOf &&
> +        (pty->getKind() == BuiltinType::Overload ||
> +         pty->getKind() == BuiltinType::UnknownAny ||
> +         pty->getKind() == BuiltinType::BoundMember))
> +      return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
> +
> +    // Anything else needs to be handled now.
> +    ExprResult Result = CheckPlaceholderExpr(Input);
> +    if (Result.isInvalid()) return ExprError();
> +    Input = Result.take();
> +  }
> +
>   if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
>       UnaryOperator::getOverloadedOperator(Opc) != OO_None) {
>     // Find all of the overloaded operators visible from this
> @@ -10151,6 +10093,10 @@
>   case BuiltinType::UnknownAny:
>     return diagnoseUnknownAnyExpr(*this, E);
>
> +  // Pseudo-objects.
> +  case BuiltinType::PseudoObject:
> +    return checkPseudoObjectRValue(E);
> +
>   // Everything else should be impossible.
>  #define BUILTIN_TYPE(Id, SingletonId) \
>   case BuiltinType::Id:
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Oct 25 12:37:35 2011
> @@ -2260,15 +2260,7 @@
>     break;
>
>   case ICK_Lvalue_To_Rvalue:
> -    // Should this get its own ICK?
> -    if (From->getObjectKind() == OK_ObjCProperty) {
> -      ExprResult FromRes = ConvertPropertyForRValue(From);
> -      if (FromRes.isInvalid())
> -        return ExprError();
> -      From = FromRes.take();
> -      if (!From->isGLValue()) break;
> -    }
> -
> +    assert(From->getObjectKind() != OK_ObjCProperty);
>     FromType = FromType.getUnqualifiedType();
>     From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue,
>                                     From, 0, VK_RValue);
> @@ -4194,6 +4186,10 @@
>   if (Result.isInvalid()) return ExprError();
>   Base = Result.get();
>
> +  Result = CheckPlaceholderExpr(Base);
> +  if (Result.isInvalid()) return ExprError();
> +  Base = Result.take();
> +
>   QualType BaseType = Base->getType();
>   MayBePseudoDestructor = false;
>   if (BaseType->isDependentType()) {
> @@ -4592,6 +4588,12 @@
>  /// Perform the conversions required for an expression used in a
>  /// context that ignores the result.
>  ExprResult Sema::IgnoredValueConversions(Expr *E) {
> +  if (E->hasPlaceholderType()) {
> +    ExprResult result = CheckPlaceholderExpr(E);
> +    if (result.isInvalid()) return Owned(E);
> +    E = result.take();
> +  }
> +
>   // C99 6.3.2.1:
>   //   [Except in specific positions,] an lvalue that does not have
>   //   array type is converted to the value stored in the
> @@ -4607,14 +4609,6 @@
>     return Owned(E);
>   }
>
> -  // We always want to do this on ObjC property references.
> -  if (E->getObjectKind() == OK_ObjCProperty) {
> -    ExprResult Res = ConvertPropertyForRValue(E);
> -    if (Res.isInvalid()) return Owned(E);
> -    E = Res.take();
> -    if (E->isRValue()) return Owned(E);
> -  }
> -
>   // Otherwise, this rule does not apply in C++, at least not for the moment.
>   if (getLangOptions().CPlusPlus) return Owned(E);
>
>
> Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Oct 25 12:37:35 2011
> @@ -777,7 +777,7 @@
>   QualType BaseType = BaseExprType;
>   if (IsArrow) {
>     assert(BaseType->isPointerType());
> -    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
> +    BaseType = BaseType->castAs<PointerType>()->getPointeeType();
>   }
>   R.setBaseObjectType(BaseType);
>
> @@ -814,15 +814,6 @@
>       CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
>     return ExprError();
>
> -  // Perform a property load on the base regardless of whether we
> -  // actually need it for the declaration.
> -  if (BaseExpr && BaseExpr->getObjectKind() == OK_ObjCProperty) {
> -    ExprResult Result = ConvertPropertyForRValue(BaseExpr);
> -    if (Result.isInvalid())
> -      return ExprError();
> -    BaseExpr = Result.take();
> -  }
> -
>   // Construct an unresolved result if we in fact got an unresolved
>   // result.
>   if (R.isOverloadedResult() || R.isUnresolvableResult()) {
> @@ -1209,11 +1200,8 @@
>           if (DiagnoseUseOfDecl(PD, MemberLoc))
>             return ExprError();
>
> -          QualType T = PD->getType();
> -          if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
> -            T = getMessageSendResultType(BaseType, Getter, false, false);
> -
> -          return Owned(new (Context) ObjCPropertyRefExpr(PD, T,
> +          return Owned(new (Context) ObjCPropertyRefExpr(PD,
> +                                                         Context.PseudoObjectTy,
>                                                          VK_LValue,
>                                                          OK_ObjCProperty,
>                                                          MemberLoc,
> @@ -1231,16 +1219,10 @@
>           if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,
>                                                      SetterSel, Context))
>             SMD = dyn_cast<ObjCMethodDecl>(SDecl);
> -          QualType PType = getMessageSendResultType(BaseType, OMD, false,
> -                                                    false);
>
> -          ExprValueKind VK = VK_LValue;
> -          if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType())
> -            VK = VK_RValue;
> -          ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
> -
> -          return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType,
> -                                                         VK, OK,
> +          return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD,
> +                                                         Context.PseudoObjectTy,
> +                                                         VK_LValue, OK_ObjCProperty,
>                                                          MemberLoc, BaseExpr.take()));
>         }
>       }
> @@ -1295,23 +1277,9 @@
>         return ExprError();
>
>       if (Getter || Setter) {
> -        QualType PType;
> -
> -        ExprValueKind VK = VK_LValue;
> -        if (Getter) {
> -          PType = getMessageSendResultType(QualType(OT, 0), Getter, true,
> -                                           false);
> -          if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType())
> -            VK = VK_RValue;
> -        } else {
> -          // Get the expression type from Setter's incoming parameter.
> -          PType = (*(Setter->param_end() -1))->getType();
> -        }
> -        ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
> -
> -        // FIXME: we must check that the setter has property type.
>         return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
> -                                                       PType, VK, OK,
> +                                                       Context.PseudoObjectTy,
> +                                                       VK_LValue, OK_ObjCProperty,
>                                                        MemberLoc, BaseExpr.take()));
>       }
>
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Oct 25 12:37:35 2011
> @@ -527,6 +527,35 @@
>   return Method;
>  }
>
> +/// LookupMethodInType - Look up a method in an ObjCObjectType.
> +ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
> +                                               bool isInstance) {
> +  const ObjCObjectType *objType = type->castAs<ObjCObjectType>();
> +  if (ObjCInterfaceDecl *iface = objType->getInterface()) {
> +    // Look it up in the main interface (and categories, etc.)
> +    if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))
> +      return method;
> +
> +    // Okay, look for "private" methods declared in any
> +    // @implementations we've seen.
> +    if (isInstance) {
> +      if (ObjCMethodDecl *method = LookupPrivateInstanceMethod(sel, iface))
> +        return method;
> +    } else {
> +      if (ObjCMethodDecl *method = LookupPrivateClassMethod(sel, iface))
> +        return method;
> +    }
> +  }
> +
> +  // Check qualifiers.
> +  for (ObjCObjectType::qual_iterator
> +         i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i)
> +    if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance))
> +      return method;
> +
> +  return 0;
> +}
> +
>  /// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
>  /// list of a qualified objective pointer type.
>  ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
> @@ -575,23 +604,14 @@
>     // Check whether we can reference this property.
>     if (DiagnoseUseOfDecl(PD, MemberLoc))
>       return ExprError();
> -    QualType ResTy = PD->getType();
> -    ResTy = ResTy.getNonLValueExprType(Context);
> -    Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
> -    ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
> -    if (Getter &&
> -        (Getter->hasRelatedResultType()
> -         || DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)))
> -        ResTy = getMessageSendResultType(QualType(OPT, 0), Getter, false,
> -                                         Super);
>
>     if (Super)
> -      return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
> +      return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
>                                                      VK_LValue, OK_ObjCProperty,
>                                                      MemberLoc,
>                                                      SuperLoc, SuperType));
>     else
> -      return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
> +      return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
>                                                      VK_LValue, OK_ObjCProperty,
>                                                      MemberLoc, BaseExpr));
>   }
> @@ -603,17 +623,16 @@
>       if (DiagnoseUseOfDecl(PD, MemberLoc))
>         return ExprError();
>
> -      QualType T = PD->getType();
> -      if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
> -        T = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super);
>       if (Super)
> -        return Owned(new (Context) ObjCPropertyRefExpr(PD, T,
> +        return Owned(new (Context) ObjCPropertyRefExpr(PD,
> +                                                       Context.PseudoObjectTy,
>                                                        VK_LValue,
>                                                        OK_ObjCProperty,
>                                                        MemberLoc,
>                                                        SuperLoc, SuperType));
>       else
> -        return Owned(new (Context) ObjCPropertyRefExpr(PD, T,
> +        return Owned(new (Context) ObjCPropertyRefExpr(PD,
> +                                                       Context.PseudoObjectTy,
>                                                        VK_LValue,
>                                                        OK_ObjCProperty,
>                                                        MemberLoc,
> @@ -668,28 +687,16 @@
>     return ExprError();
>
>   if (Getter || Setter) {
> -    QualType PType;
> -    if (Getter)
> -      PType = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super);
> -    else {
> -      ParmVarDecl *ArgDecl = *Setter->param_begin();
> -      PType = ArgDecl->getType().getUnqualifiedType(); // can't be an array
> -    }
> -
> -    ExprValueKind VK = VK_LValue;
> -    ExprObjectKind OK = OK_ObjCProperty;
> -    if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() &&
> -        PType->isVoidType())
> -      VK = VK_RValue, OK = OK_Ordinary;
> -
>     if (Super)
>       return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
> -                                                     PType, VK, OK,
> +                                                     Context.PseudoObjectTy,
> +                                                     VK_LValue, OK_ObjCProperty,
>                                                      MemberLoc,
>                                                      SuperLoc, SuperType));
>     else
>       return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
> -                                                     PType, VK, OK,
> +                                                     Context.PseudoObjectTy,
> +                                                     VK_LValue, OK_ObjCProperty,
>                                                      MemberLoc, BaseExpr));
>
>   }
> @@ -825,34 +832,17 @@
>     return ExprError();
>
>   if (Getter || Setter) {
> -    QualType PType;
> -
> -    ExprValueKind VK = VK_LValue;
> -    if (Getter) {
> -      PType = getMessageSendResultType(Context.getObjCInterfaceType(IFace),
> -                                       Getter, true,
> -                                       receiverNamePtr->isStr("super"));
> -      if (!getLangOptions().CPlusPlus &&
> -          !PType.hasQualifiers() && PType->isVoidType())
> -        VK = VK_RValue;
> -    } else {
> -      for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
> -           E = Setter->param_end(); PI != E; ++PI)
> -        PType = (*PI)->getType();
> -      VK = VK_LValue;
> -    }
> -
> -    ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
> -
>     if (IsSuper)
>     return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
> -                                                   PType, VK, OK,
> +                                                   Context.PseudoObjectTy,
> +                                                   VK_LValue, OK_ObjCProperty,
>                                                    propertyNameLoc,
>                                                    receiverNameLoc,
>                                           Context.getObjCInterfaceType(IFace)));
>
>     return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
> -                                                   PType, VK, OK,
> +                                                   Context.PseudoObjectTy,
> +                                                   VK_LValue, OK_ObjCProperty,
>                                                    propertyNameLoc,
>                                                    receiverNameLoc, IFace));
>   }
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Oct 25 12:37:35 2011
> @@ -3795,15 +3795,8 @@
>   setSequenceKind(NormalSequence);
>
>   for (unsigned I = 0; I != NumArgs; ++I)
> -    if (Args[I]->getObjectKind() == OK_ObjCProperty) {
> -      ExprResult Result = S.ConvertPropertyForRValue(Args[I]);
> -      if (Result.isInvalid()) {
> -        SetFailed(FK_ConversionFromPropertyFailed);
> -        return;
> -      }
> -      Args[I] = Result.take();
> -    } else if (const BuiltinType *PlaceholderTy
> -                 = Args[I]->getType()->getAsPlaceholderType()) {
> +    if (const BuiltinType *PlaceholderTy
> +          = Args[I]->getType()->getAsPlaceholderType()) {
>       // FIXME: should we be doing this here?
>       if (PlaceholderTy->getKind() != BuiltinType::Overload) {
>         ExprResult result = S.CheckPlaceholderExpr(Args[I]);
> @@ -4493,13 +4486,6 @@
>     assert(Args.size() == 1);
>     CurInit = Args.get()[0];
>     if (!CurInit.get()) return ExprError();
> -
> -    // Read from a property when initializing something with it.
> -    if (CurInit.get()->getObjectKind() == OK_ObjCProperty) {
> -      CurInit = S.ConvertPropertyForRValue(CurInit.take());
> -      if (CurInit.isInvalid())
> -        return ExprError();
> -    }
>     break;
>   }
>
>
> Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue Oct 25 12:37:35 2011
> @@ -800,9 +800,7 @@
>                                       SelfExpr, true, true);
>       ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
>       ParmVarDecl *Param = (*P);
> -      QualType T = Param->getType();
> -      if (T->isReferenceType())
> -        T = T->getAs<ReferenceType>()->getPointeeType();
> +      QualType T = Param->getType().getNonReferenceType();
>       Expr *rhs = new (Context) DeclRefExpr(Param, T,
>                                             VK_LValue, SourceLocation());
>       ExprResult Res = BuildBinOp(S, lhs->getLocEnd(),
> @@ -954,8 +952,8 @@
>                                             ObjCMethodDecl *GetterMethod,
>                                             SourceLocation Loc) {
>   if (GetterMethod &&
> -      GetterMethod->getResultType().getNonReferenceType()
> -      != property->getType().getNonReferenceType()) {
> +      !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(),
> +                           property->getType().getNonReferenceType())) {
>     AssignConvertType result = Incompatible;
>     if (property->getType()->isObjCObjectPointerType())
>       result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Oct 25 12:37:35 2011
> @@ -575,17 +575,6 @@
>  /// Return true on unrecoverable error.
>  static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
>                                         UnbridgedCastsSet *unbridgedCasts = 0) {
> -  // ObjCProperty l-values are placeholder-like.
> -  if (E->getObjectKind() == OK_ObjCProperty) {
> -    ExprResult result = S.ConvertPropertyForRValue(E);
> -    if (result.isInvalid())
> -      return true;
> -
> -    E = result.take();
> -    return false;
> -  }
> -
> -  // Handle true placeholders.
>   if (const BuiltinType *placeholder =  E->getType()->getAsPlaceholderType()) {
>     // We can't handle overloaded expressions here because overload
>     // resolution might reasonably tweak them.
> @@ -1003,6 +992,9 @@
>  Sema::PerformImplicitConversion(Expr *From, QualType ToType,
>                                 AssignmentAction Action, bool AllowExplicit,
>                                 ImplicitConversionSequence& ICS) {
> +  if (checkPlaceholderForOverload(*this, From))
> +    return ExprError();
> +
>   // Objective-C ARC: Determine whether we will allow the writeback conversion.
>   bool AllowObjCWritebackConversion
>     = getLangOptions().ObjCAutoRefCount &&
> @@ -4086,6 +4078,9 @@
>  /// PerformContextuallyConvertToBool - Perform a contextual conversion
>  /// of the expression From to bool (C++0x [conv]p3).
>  ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
> +  if (checkPlaceholderForOverload(*this, From))
> +    return ExprError();
> +
>   ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
>   if (!ICS.isBad())
>     return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
> @@ -4145,6 +4140,9 @@
>  /// PerformContextuallyConvertToObjCPointer - Perform a contextual
>  /// conversion of the expression From to an Objective-C pointer type.
>  ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
> +  if (checkPlaceholderForOverload(*this, From))
> +    return ExprError();
> +
>   QualType Ty = Context.getObjCIdType();
>   ImplicitConversionSequence ICS =
>     TryContextuallyConvertToObjCPointer(*this, From);
> @@ -9009,39 +9007,9 @@
>   if (checkPlaceholderForOverload(*this, Args[1]))
>     return ExprError();
>
> -  // The LHS is more complicated.
> -  if (Args[0]->getObjectKind() == OK_ObjCProperty) {
> -
> -    // There's a tension for assignment operators between primitive
> -    // property assignment and the overloaded operators.
> -    if (BinaryOperator::isAssignmentOp(Opc)) {
> -      const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
> -
> -      // Is the property "logically" settable?
> -      bool Settable = (PRE->isExplicitProperty() ||
> -                       PRE->getImplicitPropertySetter());
> -
> -      // To avoid gratuitously inventing semantics, use the primitive
> -      // unless it isn't.  Thoughts in case we ever really care:
> -      // - If the property isn't logically settable, we have to
> -      //   load and hope.
> -      // - If the property is settable and this is simple assignment,
> -      //   we really should use the primitive.
> -      // - If the property is settable, then we could try overloading
> -      //   on a generic lvalue of the appropriate type;  if it works
> -      //   out to a builtin candidate, we would do that same operation
> -      //   on the property, and otherwise just error.
> -      if (Settable)
> -        return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
> -    }
> -
> -    ExprResult Result = ConvertPropertyForRValue(Args[0]);
> -    if (Result.isInvalid())
> -      return ExprError();
> -    Args[0] = Result.take();
> -  }
> -
> -  // Handle all the other placeholders.
> +  // Do placeholder-like conversion on the LHS; note that we should
> +  // not get here with a PseudoObject LHS.
> +  assert(Args[0]->getObjectKind() != OK_ObjCProperty);
>   if (checkPlaceholderForOverload(*this, Args[0]))
>     return ExprError();
>
>
> Added: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=142931&view=auto
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (added)
> +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Oct 25 12:37:35 2011
> @@ -0,0 +1,342 @@
> +//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +//  This file implements semantic analysis for expressions involving
> +//  pseudo-object references.  Pseudo-objects are conceptual objects
> +//  whose storage is entirely abstract and all accesses to which are
> +//  translated through some sort of abstraction barrier.
> +//
> +//  For example, Objective-C objects can have "properties", either
> +//  declared or undeclared.  A property may be accessed by writing
> +//    expr.prop
> +//  where 'expr' is an r-value of Objective-C pointer type and 'prop'
> +//  is the name of the property.  If this expression is used in a context
> +//  needing an r-value, it is treated as if it were a message-send
> +//  of the associated 'getter' selector, typically:
> +//    [expr prop]
> +//  If it is used as the LHS of a simple assignment, it is treated
> +//  as a message-send of the associated 'setter' selector, typically:
> +//    [expr setProp: RHS]
> +//  If it is used as the LHS of a compound assignment, or the operand
> +//  of a unary increment or decrement, both are required;  for example,
> +//  'expr.prop *= 100' would be translated to:
> +//    [expr setProp: [expr prop] * 100]
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "clang/Sema/SemaInternal.h"
> +#include "clang/Sema/Initialization.h"
> +#include "clang/AST/ExprObjC.h"
> +#include "clang/Lex/Preprocessor.h"
> +
> +using namespace clang;
> +using namespace sema;
> +
> +static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
> +                                            const ObjCPropertyRefExpr *PRE) {
> +  bool instanceProperty;
> +  QualType searchType;
> +  if (PRE->isObjectReceiver()) {
> +    searchType = PRE->getBase()->getType()
> +      ->castAs<ObjCObjectPointerType>()->getPointeeType();
> +    instanceProperty = true;
> +  } else if (PRE->isSuperReceiver()) {
> +    searchType = PRE->getSuperReceiverType();
> +    instanceProperty = false;
> +    if (const ObjCObjectPointerType *PT
> +        = searchType->getAs<ObjCObjectPointerType>()) {
> +      searchType = PT->getPointeeType();
> +      instanceProperty = true;
> +    }
> +  } else if (PRE->isClassReceiver()) {
> +    searchType = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
> +    instanceProperty = false;
> +  }
> +
> +  return S.LookupMethodInObjectType(sel, searchType, instanceProperty);
> +}
> +
> +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();
> +
> +    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();
> +    } else {
> +      T = prop->getType();
> +      VK = Expr::getValueKindForType(T);
> +      T = T.getNonLValueExprType(Context);
> +    }
> +  }
> +
> +  E->setType(T);
> +  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK);
> +
> +  ExprResult Result = MaybeBindToTemporary(E);
> +  if (!Result.isInvalid())
> +    E = Result.take();
> +
> +  return Owned(E);
> +}
> +
> +namespace {
> +  struct PseudoObjectInfo {
> +    const ObjCPropertyRefExpr *RefExpr;
> +    bool HasSetter;
> +    Selector SetterSelector;
> +    ParmVarDecl *SetterParam;
> +    QualType SetterParamType;
> +
> +    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;
> +      }
> +
> +      // 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;
> +      }
> +
> +      // If that failed, trust the type on the @property declaration.
> +      if (!prop->isReadOnly()) {
> +        HasSetter = true;
> +        SetterParamType = prop->getType().getUnqualifiedType();
> +      }
> +    }
> +  };
> +}
> +
> +/// 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);
> +
> +  // 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);
> +    }
> +
> +    // Otherwise, it's an error.
> +    Diag(opcLoc, diag::err_nosetter_property_incdec)
> +      << unsigned(info.RefExpr->isImplicitProperty())
> +      << unsigned(UnaryOperator::isDecrementOp(opcode))
> +      << info.SetterSelector
> +      << op->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();
> +    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);
> +  if (result.isInvalid()) return ExprError();
> +
> +  // Change the object kind back.
> +  op->setObjectKind(OK_ObjCProperty);
> +  return result;
> +}
> +
> +ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
> +                                             BinaryOperatorKind opcode,
> +                                             Expr *LHS, Expr *RHS) {
> +  assert(BinaryOperator::isAssignmentOp(opcode));
> +  PseudoObjectInfo info(*this, LHS);
> +
> +  // 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);
> +    }
> +
> +    // Otherwise, it's an error.
> +    Diag(opcLoc, diag::err_nosetter_property_assignment)
> +      << unsigned(info.RefExpr->isImplicitProperty())
> +      << info.SetterSelector
> +      << LHS->getSourceRange() << RHS->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));
> +
> +    // 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);
> +
> +      LHS->setObjectKind(OK_Ordinary);
> +      QualType resultType = CheckAssignmentOperands(LHS, RHSResult, opcLoc,
> +                                                    /*compound*/ QualType());
> +      LHS->setObjectKind(OK_ObjCProperty);
> +
> +      if (!RHSResult.isInvalid()) RHS = RHSResult.take();
> +      if (resultType.isNull()) return ExprError();
> +    }
> +
> +    // 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);
> +
> +    return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(),
> +                                        RHS->getValueKind(),
> +                                        RHS->getObjectKind(),
> +                                        opcLoc);
> +  }
> +
> +  // 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();
> +  }
> +
> +  // 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;
> +}
>
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Oct 25 12:37:35 2011
> @@ -492,6 +492,10 @@
>   if (!Cond)
>     return StmtError();
>
> +  CondResult = CheckPlaceholderExpr(Cond);
> +  if (CondResult.isInvalid())
> +    return StmtError();
> +
>   CondResult
>     = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond,
>                           PDiag(diag::err_typecheck_statement_requires_integer),
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 25 12:37:35 2011
> @@ -2249,8 +2249,8 @@
>   /// By default, performs semantic analysis to build the new expression.
>   /// Subclasses may override this routine to provide different behavior.
>   ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg,
> -                                              ObjCPropertyDecl *Property,
> -                                              SourceLocation PropertyLoc) {
> +                                        ObjCPropertyDecl *Property,
> +                                        SourceLocation PropertyLoc) {
>     CXXScopeSpec SS;
>     ExprResult Base = getSema().Owned(BaseArg);
>     LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
> @@ -8049,7 +8049,7 @@
>                                                    E->getLocation());
>
>   return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
> -                                                 E->getType(),
> +                                                 SemaRef.Context.PseudoObjectTy,
>                                                  E->getImplicitPropertyGetter(),
>                                                  E->getImplicitPropertySetter(),
>                                                  E->getLocation());
>
> Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Tue Oct 25 12:37:35 2011
> @@ -52,6 +52,7 @@
>   case BuiltinType::Char32:     ID = PREDEF_TYPE_CHAR32_ID;     break;
>   case BuiltinType::Overload:   ID = PREDEF_TYPE_OVERLOAD_ID;   break;
>   case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER;  break;
> +  case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;
>   case BuiltinType::Dependent:  ID = PREDEF_TYPE_DEPENDENT_ID;  break;
>   case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY;   break;
>   case BuiltinType::ARCUnbridgedCast:
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Oct 25 12:37:35 2011
> @@ -3857,6 +3857,7 @@
>     case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy;       break;
>     case PREDEF_TYPE_OVERLOAD_ID:   T = Context.OverloadTy;         break;
>     case PREDEF_TYPE_BOUND_MEMBER:  T = Context.BoundMemberTy;      break;
> +    case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy;     break;
>     case PREDEF_TYPE_DEPENDENT_ID:  T = Context.DependentTy;        break;
>     case PREDEF_TYPE_UNKNOWN_ANY:   T = Context.UnknownAnyTy;       break;
>     case PREDEF_TYPE_NULLPTR_ID:    T = Context.NullPtrTy;          break;
>
> Modified: cfe/trunk/test/SemaObjC/property-category-1.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-category-1.m?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-category-1.m (original)
> +++ cfe/trunk/test/SemaObjC/property-category-1.m Tue Oct 25 12:37:35 2011
> @@ -48,6 +48,6 @@
>
>  @implementation I0     // expected-warning {{property 'p0' requires method 'p0' to be define}}
>  - (void) foo {
> -  self.p0 = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
> +  self.p0 = 0; // expected-error {{assignment to readonly property}}
>  }
>  @end
>
> Modified: cfe/trunk/test/SemaObjC/property-error-readonly-assign.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-error-readonly-assign.m?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-error-readonly-assign.m (original)
> +++ cfe/trunk/test/SemaObjC/property-error-readonly-assign.m Tue Oct 25 12:37:35 2011
> @@ -13,9 +13,9 @@
>  @end
>
>  void f0(A *a, B* b) {
> -  a.x = 10;  // expected-error {{assigning to property with 'readonly' attribute not allowed}}
> +  a.x = 10;  // expected-error {{assignment to readonly property}}
>   a.ok = 20;
> -  b.x = 10;  // expected-error {{setter method is needed to assign to object using property assignment syntax}}
> +  b.x = 10;  // expected-error {{no setter method 'setX:' for assignment to property}}
>   b.ok = 20;
>  }
>
> @@ -39,6 +39,6 @@
>  @implementation NSWindow (Category)
>  -(void)methodToMakeClangCrash
>  {
> - self.frame =  NSMakeRect(); // expected-error {{setter method is needed to assign to object using property assignment syntax}}
> + self.frame =  NSMakeRect(); // expected-error {{no setter method 'setFrame:' for assignment to property}}
>  }
>  @end
>
> Modified: cfe/trunk/test/SemaObjC/property-in-class-extension.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension.m?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-in-class-extension.m (original)
> +++ cfe/trunk/test/SemaObjC/property-in-class-extension.m Tue Oct 25 12:37:35 2011
> @@ -9,7 +9,7 @@
>
>  void FUNC () {
>     Foo *foo;
> -    foo.bar = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
> +    foo.bar = 0; // expected-error {{assignment to readonly property}}
>  }
>
>  // rdar://8747333
>
> Modified: cfe/trunk/test/SemaObjC/property-user-setter.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-user-setter.m?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-user-setter.m (original)
> +++ cfe/trunk/test/SemaObjC/property-user-setter.m Tue Oct 25 12:37:35 2011
> @@ -20,7 +20,7 @@
>  -(void) im0 {
>   self.x = 0;
>   self.y = 2;
> -  self.z = 2; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
> +  self.z = 2; // expected-error {{assignment to readonly property}}
>  }
>  @end
>
> @@ -85,7 +85,7 @@
>  - (void)setFoo:(int)value;
>  @end
>
> -void g(int);
> +void g(int); // expected-note {{passing argument to parameter here}}
>
>  void f(C *c) {
>     c.Foo = 17; // OK
>
> Modified: cfe/trunk/test/SemaObjCXX/propert-dot-error.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/propert-dot-error.mm?rev=142931&r1=142930&r2=142931&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/propert-dot-error.mm (original)
> +++ cfe/trunk/test/SemaObjCXX/propert-dot-error.mm Tue Oct 25 12:37:35 2011
> @@ -20,7 +20,7 @@
>  @end
>
>  void f(A* a) {
> -  a.x = X(); // expected-error {{setter method is needed to assign to object using property assignment syntax}}
> +  a.x = X(); // expected-error {{no setter method 'setX:' for assignment to property}}
>  }
>
>  struct Y : X { };
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>




More information about the cfe-commits mailing list