SemaPseudoObject.cpp revision 4b9c2d235fb9449e249d74f48ecfec601650de93
13c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// 23c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 33c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// The LLVM Compiler Infrastructure 43c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 53c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// This file is distributed under the University of Illinois Open Source 63c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// License. See LICENSE.TXT for details. 73c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 83c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===----------------------------------------------------------------------===// 93c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// This file implements semantic analysis for expressions involving 113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// pseudo-object references. Pseudo-objects are conceptual objects 123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// whose storage is entirely abstract and all accesses to which are 133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// translated through some sort of abstraction barrier. 143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// For example, Objective-C objects can have "properties", either 163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// declared or undeclared. A property may be accessed by writing 173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// expr.prop 183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// where 'expr' is an r-value of Objective-C pointer type and 'prop' 193c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// is the name of the property. If this expression is used in a context 203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// needing an r-value, it is treated as if it were a message-send 213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// of the associated 'getter' selector, typically: 223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// [expr prop] 233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// If it is used as the LHS of a simple assignment, it is treated 243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// as a message-send of the associated 'setter' selector, typically: 253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// [expr setProp: RHS] 263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// If it is used as the LHS of a compound assignment, or the operand 273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// of a unary increment or decrement, both are required; for example, 283c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 'expr.prop *= 100' would be translated to: 293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// [expr setProp: [expr prop] * 100] 303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===----------------------------------------------------------------------===// 323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/SemaInternal.h" 343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/Initialization.h" 353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/AST/ExprObjC.h" 363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Lex/Preprocessor.h" 373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 383c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace clang; 393c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace sema; 403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 414b9c2d235fb9449e249d74f48ecfec601650de93John McCallnamespace { 424b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Basically just a very focused copy of TreeTransform. 434b9c2d235fb9449e249d74f48ecfec601650de93John McCall template <class T> struct Rebuilder { 444b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema &S; 454b9c2d235fb9449e249d74f48ecfec601650de93John McCall Rebuilder(Sema &S) : S(S) {} 464b9c2d235fb9449e249d74f48ecfec601650de93John McCall 474b9c2d235fb9449e249d74f48ecfec601650de93John McCall T &getDerived() { return static_cast<T&>(*this); } 484b9c2d235fb9449e249d74f48ecfec601650de93John McCall 494b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *rebuild(Expr *e) { 504b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Fast path: nothing to look through. 514b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (typename T::specific_type *specific 524b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<typename T::specific_type>(e)) 534b9c2d235fb9449e249d74f48ecfec601650de93John McCall return getDerived().rebuildSpecific(specific); 544b9c2d235fb9449e249d74f48ecfec601650de93John McCall 554b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Otherwise, we should look through and rebuild anything that 564b9c2d235fb9449e249d74f48ecfec601650de93John McCall // IgnoreParens would. 574b9c2d235fb9449e249d74f48ecfec601650de93John McCall 584b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { 594b9c2d235fb9449e249d74f48ecfec601650de93John McCall e = rebuild(parens->getSubExpr()); 604b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) ParenExpr(parens->getLParen(), 614b9c2d235fb9449e249d74f48ecfec601650de93John McCall parens->getRParen(), 624b9c2d235fb9449e249d74f48ecfec601650de93John McCall e); 634b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 644b9c2d235fb9449e249d74f48ecfec601650de93John McCall 654b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { 664b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(uop->getOpcode() == UO_Extension); 674b9c2d235fb9449e249d74f48ecfec601650de93John McCall e = rebuild(uop->getSubExpr()); 684b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) UnaryOperator(e, uop->getOpcode(), 694b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getType(), 704b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getValueKind(), 714b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getObjectKind(), 724b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getOperatorLoc()); 734b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 744b9c2d235fb9449e249d74f48ecfec601650de93John McCall 754b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 764b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(!gse->isResultDependent()); 774b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned resultIndex = gse->getResultIndex(); 784b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned numAssocs = gse->getNumAssocs(); 794b9c2d235fb9449e249d74f48ecfec601650de93John McCall 804b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<Expr*, 8> assocs(numAssocs); 814b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs); 824b9c2d235fb9449e249d74f48ecfec601650de93John McCall 834b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = 0; i != numAssocs; ++i) { 844b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *assoc = gse->getAssocExpr(i); 854b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (i == resultIndex) assoc = rebuild(assoc); 864b9c2d235fb9449e249d74f48ecfec601650de93John McCall assocs[i] = assoc; 874b9c2d235fb9449e249d74f48ecfec601650de93John McCall assocTypes[i] = gse->getAssocTypeSourceInfo(i); 884b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 904b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) GenericSelectionExpr(S.Context, 914b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getGenericLoc(), 924b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getControllingExpr(), 934b9c2d235fb9449e249d74f48ecfec601650de93John McCall assocTypes.data(), 944b9c2d235fb9449e249d74f48ecfec601650de93John McCall assocs.data(), 954b9c2d235fb9449e249d74f48ecfec601650de93John McCall numAssocs, 964b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getDefaultLoc(), 974b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getRParenLoc(), 984b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->containsUnexpandedParameterPack(), 994b9c2d235fb9449e249d74f48ecfec601650de93John McCall resultIndex); 1004b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1014b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1024b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("bad expression to rebuild!"); 1034b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1044b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 1054b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1064b9c2d235fb9449e249d74f48ecfec601650de93John McCall struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { 1074b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *NewBase; 1084b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) 1094b9c2d235fb9449e249d74f48ecfec601650de93John McCall : Rebuilder(S), NewBase(newBase) {} 1104b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1114b9c2d235fb9449e249d74f48ecfec601650de93John McCall typedef ObjCPropertyRefExpr specific_type; 1124b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { 1134b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Fortunately, the constraint that we're rebuilding something 1144b9c2d235fb9449e249d74f48ecfec601650de93John McCall // with a base limits the number of cases here. 1154b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(refExpr->getBase()); 1164b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1174b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (refExpr->isExplicitProperty()) { 1184b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) 1194b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefExpr(refExpr->getExplicitProperty(), 1204b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getType(), refExpr->getValueKind(), 1214b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getObjectKind(), refExpr->getLocation(), 1224b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewBase); 1234b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1244b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) 1254b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), 1264b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getImplicitPropertySetter(), 1274b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getType(), refExpr->getValueKind(), 1284b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getObjectKind(),refExpr->getLocation(), 1294b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewBase); 1304b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1314b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 1324b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1334b9c2d235fb9449e249d74f48ecfec601650de93John McCall class PseudoOpBuilder { 1344b9c2d235fb9449e249d74f48ecfec601650de93John McCall public: 1354b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema &S; 1364b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned ResultIndex; 1374b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation GenericLoc; 1384b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<Expr *, 4> Semantics; 1394b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1404b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOpBuilder(Sema &S, SourceLocation genericLoc) 1414b9c2d235fb9449e249d74f48ecfec601650de93John McCall : S(S), ResultIndex(PseudoObjectExpr::NoResult), 1424b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc(genericLoc) {} 1434b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1444b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// Add a normal semantic expression. 1454b9c2d235fb9449e249d74f48ecfec601650de93John McCall void addSemanticExpr(Expr *semantic) { 1464b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantics.push_back(semantic); 1474b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1484b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1494b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// Add the 'result' semantic expression. 1504b9c2d235fb9449e249d74f48ecfec601650de93John McCall void addResultSemanticExpr(Expr *resultExpr) { 1514b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(ResultIndex == PseudoObjectExpr::NoResult); 1524b9c2d235fb9449e249d74f48ecfec601650de93John McCall ResultIndex = Semantics.size(); 1534b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantics.push_back(resultExpr); 1544b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1554b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1564b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildRValueOperation(Expr *op); 1574b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildAssignmentOperation(Scope *Sc, 1584b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation opLoc, 1594b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 1604b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS); 1614b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 1624b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 1634b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op); 1644b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1654b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult complete(Expr *syntacticForm); 1664b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1674b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *capture(Expr *op); 1684b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *captureValueAsResult(Expr *op); 1694b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1704b9c2d235fb9449e249d74f48ecfec601650de93John McCall void setResultToLastSemantic() { 1714b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(ResultIndex == PseudoObjectExpr::NoResult); 1724b9c2d235fb9449e249d74f48ecfec601650de93John McCall ResultIndex = Semantics.size() - 1; 1734b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1744b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1754b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// Return true if assignments have a non-void result. 1764b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual bool assignmentsHaveResult() { return true; } 1774b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1784b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual Expr *rebuildAndCaptureObject(Expr *) = 0; 1794b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual ExprResult buildGet() = 0; 1804b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual ExprResult buildSet(Expr *, SourceLocation, 1814b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool captureSetValueAsResult) = 0; 1824b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 1834b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1844b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// A PseudoOpBuilder for Objective-C @properties. 1854b9c2d235fb9449e249d74f48ecfec601650de93John McCall class ObjCPropertyOpBuilder : public PseudoOpBuilder { 1864b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefExpr *RefExpr; 1874b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *InstanceReceiver; 1884b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMethodDecl *Getter; 1894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1904b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMethodDecl *Setter; 1914b9c2d235fb9449e249d74f48ecfec601650de93John McCall Selector SetterSelector; 1924b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1934b9c2d235fb9449e249d74f48ecfec601650de93John McCall public: 1944b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : 1954b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), 1964b9c2d235fb9449e249d74f48ecfec601650de93John McCall InstanceReceiver(0), Getter(0), Setter(0) { 1974b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1984b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1994b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildRValueOperation(Expr *op); 2004b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildAssignmentOperation(Scope *Sc, 2014b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation opLoc, 2024b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 2034b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS); 2044b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 2054b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 2064b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op); 2074b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2084b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool tryBuildGetOfReference(Expr *op, ExprResult &result); 2094b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool findSetter(); 2104b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool findGetter(); 2114b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2124b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *rebuildAndCaptureObject(Expr *syntacticBase); 2134b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildGet(); 2144b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildSet(Expr *op, SourceLocation, bool); 2154b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 2164b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 2174b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2184b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression in an OpaqueValueExpr. 2194b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { 2204b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Make a new OVE whose source is the given expression. 2214b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *captured = 2224b9c2d235fb9449e249d74f48ecfec601650de93John McCall new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), 2234b9c2d235fb9449e249d74f48ecfec601650de93John McCall e->getValueKind()); 2244b9c2d235fb9449e249d74f48ecfec601650de93John McCall captured->setSourceExpr(e); 2254b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2264b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Make sure we bind that in the semantics. 2274b9c2d235fb9449e249d74f48ecfec601650de93John McCall addSemanticExpr(captured); 2284b9c2d235fb9449e249d74f48ecfec601650de93John McCall return captured; 2294b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 2304b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2314b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression as the result of this pseudo-object 2324b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation. This routine is safe against expressions which may 2334b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// already be captured. 2344b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 2354b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \param Returns the captured expression, which will be the 2364b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// same as the input if the input was already captured 2374b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { 2384b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(ResultIndex == PseudoObjectExpr::NoResult); 2394b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2404b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the expression hasn't already been captured, just capture it 2414b9c2d235fb9449e249d74f48ecfec601650de93John McCall // and set the new semantic 2424b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!isa<OpaqueValueExpr>(e)) { 2434b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *cap = capture(e); 2444b9c2d235fb9449e249d74f48ecfec601650de93John McCall setResultToLastSemantic(); 2454b9c2d235fb9449e249d74f48ecfec601650de93John McCall return cap; 2464b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 2474b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2484b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Otherwise, it must already be one of our semantic expressions; 2494b9c2d235fb9449e249d74f48ecfec601650de93John McCall // set ResultIndex to its index. 2504b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned index = 0; 2514b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (;; ++index) { 2524b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(index < Semantics.size() && 2534b9c2d235fb9449e249d74f48ecfec601650de93John McCall "captured expression not found in semantics!"); 2544b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (e == Semantics[index]) break; 2554b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 2564b9c2d235fb9449e249d74f48ecfec601650de93John McCall ResultIndex = index; 2574b9c2d235fb9449e249d74f48ecfec601650de93John McCall return cast<OpaqueValueExpr>(e); 2584b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 2594b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2604b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The routine which creates the final PseudoObjectExpr. 2614b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::complete(Expr *syntactic) { 2624b9c2d235fb9449e249d74f48ecfec601650de93John McCall return PseudoObjectExpr::Create(S.Context, syntactic, 2634b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantics, ResultIndex); 2644b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 2654b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2664b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The main skeleton for building an r-value operation. 2674b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { 2684b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntacticBase = rebuildAndCaptureObject(op); 2694b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2704b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult getExpr = buildGet(); 2714b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (getExpr.isInvalid()) return ExprError(); 2724b9c2d235fb9449e249d74f48ecfec601650de93John McCall addResultSemanticExpr(getExpr.take()); 2734b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2744b9c2d235fb9449e249d74f48ecfec601650de93John McCall return complete(syntacticBase); 2754b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 2764b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2774b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building a simple or compound 2784b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// assignment operation. 2794b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 2804b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 2814b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 2824b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS) { 2834b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(BinaryOperator::isAssignmentOp(opcode)); 2844b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2854b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntacticLHS = rebuildAndCaptureObject(LHS); 2864b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *capturedRHS = capture(RHS); 2874b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2884b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntactic; 2894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2904b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result; 2914b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (opcode == BO_Assign) { 2924b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = capturedRHS; 2934b9c2d235fb9449e249d74f48ecfec601650de93John McCall syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, 2944b9c2d235fb9449e249d74f48ecfec601650de93John McCall opcode, capturedRHS->getType(), 2954b9c2d235fb9449e249d74f48ecfec601650de93John McCall capturedRHS->getValueKind(), 2964b9c2d235fb9449e249d74f48ecfec601650de93John McCall OK_Ordinary, opcLoc); 2974b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 2984b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult opLHS = buildGet(); 2994b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (opLHS.isInvalid()) return ExprError(); 3004b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3014b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Build an ordinary, non-compound operation. 3024b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind nonCompound = 3034b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperator::getOpForCompoundAssignment(opcode); 3044b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.BuildBinOp(Sc, opcLoc, nonCompound, 3054b9c2d235fb9449e249d74f48ecfec601650de93John McCall opLHS.take(), capturedRHS); 3064b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3074b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3084b9c2d235fb9449e249d74f48ecfec601650de93John McCall syntactic = 3094b9c2d235fb9449e249d74f48ecfec601650de93John McCall new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, 3104b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getType(), 3114b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getValueKind(), 3124b9c2d235fb9449e249d74f48ecfec601650de93John McCall OK_Ordinary, 3134b9c2d235fb9449e249d74f48ecfec601650de93John McCall opLHS.get()->getType(), 3144b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getType(), 3154b9c2d235fb9449e249d74f48ecfec601650de93John McCall opcLoc); 3164b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3174b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3184b9c2d235fb9449e249d74f48ecfec601650de93John McCall // The result of the assignment, if not void, is the value set into 3194b9c2d235fb9449e249d74f48ecfec601650de93John McCall // the l-value. 3204b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = buildSet(result.take(), opcLoc, assignmentsHaveResult()); 3214b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3224b9c2d235fb9449e249d74f48ecfec601650de93John McCall addSemanticExpr(result.take()); 3234b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3244b9c2d235fb9449e249d74f48ecfec601650de93John McCall return complete(syntactic); 3254b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3264b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3274b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building an increment or decrement 3284b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation. 3294b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 3304b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 3314b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 3324b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op) { 3334b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(UnaryOperator::isIncrementDecrementOp(opcode)); 3344b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3354b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntacticOp = rebuildAndCaptureObject(op); 3364b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3374b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Load the value. 3384b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = buildGet(); 3394b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3404b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3414b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType resultType = result.get()->getType(); 3424b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3434b9c2d235fb9449e249d74f48ecfec601650de93John McCall // That's the postfix result. 3444b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) { 3454b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = capture(result.take()); 3464b9c2d235fb9449e249d74f48ecfec601650de93John McCall setResultToLastSemantic(); 3474b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3484b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3494b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add or subtract a literal 1. 3504b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); 3514b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, 3524b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc); 3534b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3544b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (UnaryOperator::isIncrementOp(opcode)) { 3554b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one); 3564b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 3574b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one); 3584b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3594b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3604b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3614b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Store that back into the result. The value stored is the result 3624b9c2d235fb9449e249d74f48ecfec601650de93John McCall // of a prefix operation. 3634b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = buildSet(result.take(), opcLoc, 3644b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperator::isPrefix(opcode) && assignmentsHaveResult()); 3654b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3664b9c2d235fb9449e249d74f48ecfec601650de93John McCall addSemanticExpr(result.take()); 3674b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3684b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperator *syntactic = 3694b9c2d235fb9449e249d74f48ecfec601650de93John McCall new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, 3704b9c2d235fb9449e249d74f48ecfec601650de93John McCall VK_LValue, OK_Ordinary, opcLoc); 3714b9c2d235fb9449e249d74f48ecfec601650de93John McCall return complete(syntactic); 3724b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3734b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3744b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3754b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 3764b9c2d235fb9449e249d74f48ecfec601650de93John McCall// Objective-C @property and implicit property references 3774b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 3784b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3794b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Look up a method in the receiver type of an Objective-C property 3804b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference. 3813c3b7f90a863af43fa63043d396553ecf205351cJohn McCallstatic ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 3823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall const ObjCPropertyRefExpr *PRE) { 3833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (PRE->isObjectReceiver()) { 384aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer const ObjCObjectPointerType *PT = 385aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 3864b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3874b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Special case for 'self' in class method implementations. 3884b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (PT->isObjCClassType() && 3894b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) { 3904b9c2d235fb9449e249d74f48ecfec601650de93John McCall // This cast is safe because isSelfExpr is only true within 3914b9c2d235fb9449e249d74f48ecfec601650de93John McCall // methods. 3924b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMethodDecl *method = 3934b9c2d235fb9449e249d74f48ecfec601650de93John McCall cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); 3944b9c2d235fb9449e249d74f48ecfec601650de93John McCall return S.LookupMethodInObjectType(sel, 3954b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Context.getObjCInterfaceType(method->getClassInterface()), 3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall /*instance*/ false); 3974b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3984b9c2d235fb9449e249d74f48ecfec601650de93John McCall 399aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 4003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 4013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 402aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer if (PRE->isSuperReceiver()) { 403aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer if (const ObjCObjectPointerType *PT = 404aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 405aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 406aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer 407aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); 408aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer } 409aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer 410aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer assert(PRE->isClassReceiver() && "Invalid expression"); 411aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 412aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, IT, false); 4133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 4143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 4154b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findGetter() { 4164b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (Getter) return true; 4174b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4184b9c2d235fb9449e249d74f48ecfec601650de93John McCall Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr); 4194b9c2d235fb9449e249d74f48ecfec601650de93John McCall return (Getter != 0); 4204b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 4214b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4224b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to find the most accurate setter declaration for the property 4234b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference. 4244b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 4254b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if a setter was found, in which case Setter 4264b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findSetter() { 4274b9c2d235fb9449e249d74f48ecfec601650de93John McCall // For implicit properties, just trust the lookup we already did. 4284b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isImplicitProperty()) { 4294b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 4304b9c2d235fb9449e249d74f48ecfec601650de93John McCall Setter = setter; 4314b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector = setter->getSelector(); 4324b9c2d235fb9449e249d74f48ecfec601650de93John McCall return true; 4333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 4344b9c2d235fb9449e249d74f48ecfec601650de93John McCall IdentifierInfo *getterName = 4354b9c2d235fb9449e249d74f48ecfec601650de93John McCall RefExpr->getImplicitPropertyGetter()->getSelector() 4364b9c2d235fb9449e249d74f48ecfec601650de93John McCall .getIdentifierInfoForSlot(0); 4374b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector = 4384b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelectorTable::constructSetterName(S.PP.getIdentifierTable(), 4394b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.PP.getSelectorTable(), 4404b9c2d235fb9449e249d74f48ecfec601650de93John McCall getterName); 4414b9c2d235fb9449e249d74f48ecfec601650de93John McCall return false; 4423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 4433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 4443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 4454b9c2d235fb9449e249d74f48ecfec601650de93John McCall // For explicit properties, this is more involved. 4464b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 4474b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector = prop->getSetterName(); 4484b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4494b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Do a normal method lookup first. 4504b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCMethodDecl *setter = 4514b9c2d235fb9449e249d74f48ecfec601650de93John McCall LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 4524b9c2d235fb9449e249d74f48ecfec601650de93John McCall Setter = setter; 4534b9c2d235fb9449e249d74f48ecfec601650de93John McCall return true; 4544b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 4554b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4564b9c2d235fb9449e249d74f48ecfec601650de93John McCall // That can fail in the somewhat crazy situation that we're 4574b9c2d235fb9449e249d74f48ecfec601650de93John McCall // type-checking a message send within the @interface declaration 4584b9c2d235fb9449e249d74f48ecfec601650de93John McCall // that declared the @property. But it's not clear that that's 4594b9c2d235fb9449e249d74f48ecfec601650de93John McCall // valuable to support. 4604b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4614b9c2d235fb9449e249d74f48ecfec601650de93John McCall return false; 4624b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 4634b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4644b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the base object of an Objective-C property expression. 4654b9c2d235fb9449e249d74f48ecfec601650de93John McCallExpr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 4664b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver == 0); 4674b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4684b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If we have a base, capture it in an OVE and rebuild the syntactic 4694b9c2d235fb9449e249d74f48ecfec601650de93John McCall // form to use the OVE as its base. 4704b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isObjectReceiver()) { 4714b9c2d235fb9449e249d74f48ecfec601650de93John McCall InstanceReceiver = capture(RefExpr->getBase()); 4724b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4734b9c2d235fb9449e249d74f48ecfec601650de93John McCall syntacticBase = 4744b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); 4754b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 4764b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4774b9c2d235fb9449e249d74f48ecfec601650de93John McCall return syntacticBase; 4784b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 4794b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4804b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Load from an Objective-C property reference. 4814b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildGet() { 4824b9c2d235fb9449e249d74f48ecfec601650de93John McCall findGetter(); 4834b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(Getter); 4843c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 4854b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType receiverType; 4864b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation superLoc; 4874b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isClassReceiver()) { 4884b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 4894b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else if (RefExpr->isSuperReceiver()) { 4904b9c2d235fb9449e249d74f48ecfec601650de93John McCall superLoc = RefExpr->getReceiverLocation(); 4914b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = RefExpr->getSuperReceiverType(); 4924b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 4934b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver); 4944b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = InstanceReceiver->getType(); 4954b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 4963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 4974b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Build a message-send. 4984b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult msg; 4994b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 5004b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver || RefExpr->isSuperReceiver()); 5014b9c2d235fb9449e249d74f48ecfec601650de93John McCall msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc, 5024b9c2d235fb9449e249d74f48ecfec601650de93John McCall Getter->getSelector(), Getter, 5034b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc, GenericLoc, GenericLoc, 5044b9c2d235fb9449e249d74f48ecfec601650de93John McCall MultiExprArg()); 5054b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 5064b9c2d235fb9449e249d74f48ecfec601650de93John McCall TypeSourceInfo *receiverTypeInfo = 0; 5074b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!RefExpr->isSuperReceiver()) 5084b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType); 5094b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5104b9c2d235fb9449e249d74f48ecfec601650de93John McCall msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc, 5114b9c2d235fb9449e249d74f48ecfec601650de93John McCall Getter->getSelector(), Getter, 5124b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc, GenericLoc, GenericLoc, 5134b9c2d235fb9449e249d74f48ecfec601650de93John McCall MultiExprArg()); 5144b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5154b9c2d235fb9449e249d74f48ecfec601650de93John McCall return msg; 5163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 5173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5184b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Store to an Objective-C property reference. 5194b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 5204b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \param bindSetValueAsResult - If true, capture the actual 5214b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// value being set as the value of the property operation. 5224b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 5234b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool captureSetValueAsResult) { 5244b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool hasSetter = findSetter(); 5254b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(hasSetter); (void) hasSetter; 5264b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5274b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType receiverType; 5284b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation superLoc; 5294b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isClassReceiver()) { 5304b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 5314b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else if (RefExpr->isSuperReceiver()) { 5324b9c2d235fb9449e249d74f48ecfec601650de93John McCall superLoc = RefExpr->getReceiverLocation(); 5334b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = RefExpr->getSuperReceiverType(); 5344b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 5354b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver); 5364b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = InstanceReceiver->getType(); 5374b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5394b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Use assignment constraints when possible; they give us better 5404b9c2d235fb9449e249d74f48ecfec601650de93John McCall // diagnostics. "When possible" basically means anything except a 5414b9c2d235fb9449e249d74f48ecfec601650de93John McCall // C++ class type. 5424b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) { 5434b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType paramType = (*Setter->param_begin())->getType(); 5444b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) { 5454b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult opResult = op; 5464b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema::AssignConvertType assignResult 5474b9c2d235fb9449e249d74f48ecfec601650de93John McCall = S.CheckSingleAssignmentConstraints(paramType, opResult); 5484b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 5494b9c2d235fb9449e249d74f48ecfec601650de93John McCall op->getType(), opResult.get(), 5504b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema::AA_Assigning)) 5514b9c2d235fb9449e249d74f48ecfec601650de93John McCall return ExprError(); 5524b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5534b9c2d235fb9449e249d74f48ecfec601650de93John McCall op = opResult.take(); 5544b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(op && "successful assignment left argument invalid?"); 5553c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 5564b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5584b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Arguments. 5594b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *args[] = { op }; 5603c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5614b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Build a message-send. 5624b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult msg; 5634b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 5644b9c2d235fb9449e249d74f48ecfec601650de93John McCall msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc, 5654b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector, Setter, 5664b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc, GenericLoc, GenericLoc, 5674b9c2d235fb9449e249d74f48ecfec601650de93John McCall MultiExprArg(args, 1)); 5684b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 5694b9c2d235fb9449e249d74f48ecfec601650de93John McCall TypeSourceInfo *receiverTypeInfo = 0; 5704b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!RefExpr->isSuperReceiver()) 5714b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType); 5724b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5734b9c2d235fb9449e249d74f48ecfec601650de93John McCall msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc, 5744b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector, Setter, 5754b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc, GenericLoc, GenericLoc, 5764b9c2d235fb9449e249d74f48ecfec601650de93John McCall MultiExprArg(args, 1)); 5774b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5794b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!msg.isInvalid() && captureSetValueAsResult) { 5804b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMessageExpr *msgExpr = 5814b9c2d235fb9449e249d74f48ecfec601650de93John McCall cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 5824b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *arg = msgExpr->getArg(0); 5834b9c2d235fb9449e249d74f48ecfec601650de93John McCall msgExpr->setArg(0, captureValueAsResult(arg)); 5844b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5864b9c2d235fb9449e249d74f48ecfec601650de93John McCall return msg; 5874b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 5884b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5894b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing lvalue-to-rvalue conversion. 5904b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 5914b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Explicit properties always have getters, but implicit ones don't. 5924b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Check that before proceeding. 5934b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isImplicitProperty() && 5944b9c2d235fb9449e249d74f48ecfec601650de93John McCall !RefExpr->getImplicitPropertyGetter()) { 5954b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 5964b9c2d235fb9449e249d74f48ecfec601650de93John McCall << RefExpr->getBase()->getType(); 5974b9c2d235fb9449e249d74f48ecfec601650de93John McCall return ExprError(); 5984b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5994b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6004b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 6014b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 6024b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6034b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 6044b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 6054b9c2d235fb9449e249d74f48ecfec601650de93John McCall Getter, RefExpr->getLocation()); 6064b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6074b9c2d235fb9449e249d74f48ecfec601650de93John McCall // As a special case, if the method returns 'id', try to get 6084b9c2d235fb9449e249d74f48ecfec601650de93John McCall // a better type from the property. 6094b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isExplicitProperty() && result.get()->isRValue() && 6104b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getType()->isObjCIdType()) { 6114b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType propType = RefExpr->getExplicitProperty()->getType(); 6124b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (const ObjCObjectPointerType *ptr 6134b9c2d235fb9449e249d74f48ecfec601650de93John McCall = propType->getAs<ObjCObjectPointerType>()) { 6144b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!ptr->isObjCIdType()) 6154b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 6163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 6174b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6184b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6194b9c2d235fb9449e249d74f48ecfec601650de93John McCall return result; 6203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 6213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6224b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to build this as a call to a getter that returns a reference. 6234b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 6244b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if it was possible, whether or not it actually 6254b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// succeeded 6264b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 6274b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult &result) { 6284b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!S.getLangOptions().CPlusPlus) return false; 6294b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6304b9c2d235fb9449e249d74f48ecfec601650de93John McCall findGetter(); 6314b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(Getter && "property has no setter and no getter!"); 6324b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6334b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Only do this if the getter returns an l-value reference type. 6344b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType resultType = Getter->getResultType(); 6354b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!resultType->isLValueReferenceType()) return false; 6364b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6374b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = buildRValueOperation(op); 6384b9c2d235fb9449e249d74f48ecfec601650de93John McCall return true; 6394b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 6404b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing assignments. 6424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 6434b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 6444b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation opcLoc, 6454b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 6464b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS) { 6474b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(BinaryOperator::isAssignmentOp(opcode)); 6483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6493c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there's no setter, we have no choice but to try to assign to 6503c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // the result of the getter. 6514b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!findSetter()) { 6524b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result; 6534b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (tryBuildGetOfReference(LHS, result)) { 6544b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 6554b9c2d235fb9449e249d74f48ecfec601650de93John McCall return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); 6563c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 6573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6583c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Otherwise, it's an error. 6594b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nosetter_property_assignment) 6604b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(RefExpr->isImplicitProperty()) 6614b9c2d235fb9449e249d74f48ecfec601650de93John McCall << SetterSelector 6624b9c2d235fb9449e249d74f48ecfec601650de93John McCall << LHS->getSourceRange() << RHS->getSourceRange(); 6633c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 6643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 6653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6664b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If there is a setter, we definitely want to use it. 6674b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6684b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Verify that we can do a compound assignment. 6694b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (opcode != BO_Assign && !findGetter()) { 6704b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 6714b9c2d235fb9449e249d74f48ecfec601650de93John McCall << LHS->getSourceRange() << RHS->getSourceRange(); 6723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 6733c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 6743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6754b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = 6764b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 6773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (result.isInvalid()) return ExprError(); 6783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6794b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Various warnings about property assignments in ARC. 6804b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) { 6814b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 6824b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 6834b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6844b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return result; 6863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 6873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6884b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing increments and decrements. 6894b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 6904b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 6914b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 6924b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op) { 6933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there's no setter, we have no choice but to try to assign to 6943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // the result of the getter. 6954b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!findSetter()) { 6964b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result; 6974b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (tryBuildGetOfReference(op, result)) { 6984b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 6994b9c2d235fb9449e249d74f48ecfec601650de93John McCall return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); 7003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Otherwise, it's an error. 7034b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nosetter_property_incdec) 7044b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(RefExpr->isImplicitProperty()) 7054b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(UnaryOperator::isDecrementOp(opcode)) 7064b9c2d235fb9449e249d74f48ecfec601650de93John McCall << SetterSelector 7074b9c2d235fb9449e249d74f48ecfec601650de93John McCall << op->getSourceRange(); 7083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 7093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there is a setter, we definitely want to use it. 7123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7134b9c2d235fb9449e249d74f48ecfec601650de93John McCall // We also need a getter. 7144b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!findGetter()) { 7154b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(RefExpr->isImplicitProperty()); 7164b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nogetter_property_incdec) 7174b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(UnaryOperator::isDecrementOp(opcode)) 7184b9c2d235fb9449e249d74f48ecfec601650de93John McCall << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME! 7194b9c2d235fb9449e249d74f48ecfec601650de93John McCall << op->getSourceRange(); 7204b9c2d235fb9449e249d74f48ecfec601650de93John McCall return ExprError(); 7214b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7234b9c2d235fb9449e249d74f48ecfec601650de93John McCall return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 7244b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 7253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7264b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 7274b9c2d235fb9449e249d74f48ecfec601650de93John McCall// General Sema routines. 7284b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 7293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7304b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectRValue(Expr *E) { 7314b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *opaqueRef = E->IgnoreParens(); 7324b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCPropertyRefExpr *refExpr 7334b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 7344b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder builder(*this, refExpr); 7354b9c2d235fb9449e249d74f48ecfec601650de93John McCall return builder.buildRValueOperation(E); 7364b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 7374b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("unknown pseudo-object kind!"); 7383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7394b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 7403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Check an increment or decrement of a pseudo-object expression. 7424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, 7434b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, Expr *op) { 7444b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Do nothing if the operand is dependent. 7454b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (op->isTypeDependent()) 7464b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (Context) UnaryOperator(op, opcode, Context.DependentTy, 7474b9c2d235fb9449e249d74f48ecfec601650de93John McCall VK_RValue, OK_Ordinary, opcLoc); 7484b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7494b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(UnaryOperator::isIncrementDecrementOp(opcode)); 7504b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *opaqueRef = op->IgnoreParens(); 7514b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCPropertyRefExpr *refExpr 7524b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 7534b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder builder(*this, refExpr); 7544b9c2d235fb9449e249d74f48ecfec601650de93John McCall return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 7554b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 7564b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("unknown pseudo-object kind!"); 7573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7584b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 7593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7604b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 7614b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 7624b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS) { 7634b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Do nothing if either argument is dependent. 7644b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (LHS->isTypeDependent() || RHS->isTypeDependent()) 7654b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, 7664b9c2d235fb9449e249d74f48ecfec601650de93John McCall VK_RValue, OK_Ordinary, opcLoc); 7674b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7684b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Filter out non-overload placeholder types in the RHS. 7694b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) { 7704b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (PTy->getKind() != BuiltinType::Overload) { 7714b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = CheckPlaceholderExpr(RHS); 7724b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 7734b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS = result.take(); 7744b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7754b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7774b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *opaqueRef = LHS->IgnoreParens(); 7784b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCPropertyRefExpr *refExpr 7794b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 7804b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder builder(*this, refExpr); 7814b9c2d235fb9449e249d74f48ecfec601650de93John McCall return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 7824b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 7834b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("unknown pseudo-object kind!"); 7844b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 786