SemaPseudoObject.cpp revision 55fc873017f10f6f566b182b70f6fc22aefa3464
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/AST/ExprObjC.h" 353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Lex/Preprocessor.h" 3655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/Initialization.h" 3755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/ScopeInfo.h" 38b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian#include "llvm/ADT/SmallString.h" 393c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 403c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace clang; 413c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace sema; 423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 434b9c2d235fb9449e249d74f48ecfec601650de93John McCallnamespace { 444b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Basically just a very focused copy of TreeTransform. 454b9c2d235fb9449e249d74f48ecfec601650de93John McCall template <class T> struct Rebuilder { 464b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema &S; 474b9c2d235fb9449e249d74f48ecfec601650de93John McCall Rebuilder(Sema &S) : S(S) {} 484b9c2d235fb9449e249d74f48ecfec601650de93John McCall 494b9c2d235fb9449e249d74f48ecfec601650de93John McCall T &getDerived() { return static_cast<T&>(*this); } 504b9c2d235fb9449e249d74f48ecfec601650de93John McCall 514b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *rebuild(Expr *e) { 524b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Fast path: nothing to look through. 534b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (typename T::specific_type *specific 544b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<typename T::specific_type>(e)) 554b9c2d235fb9449e249d74f48ecfec601650de93John McCall return getDerived().rebuildSpecific(specific); 564b9c2d235fb9449e249d74f48ecfec601650de93John McCall 574b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Otherwise, we should look through and rebuild anything that 584b9c2d235fb9449e249d74f48ecfec601650de93John McCall // IgnoreParens would. 594b9c2d235fb9449e249d74f48ecfec601650de93John McCall 604b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { 614b9c2d235fb9449e249d74f48ecfec601650de93John McCall e = rebuild(parens->getSubExpr()); 624b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) ParenExpr(parens->getLParen(), 634b9c2d235fb9449e249d74f48ecfec601650de93John McCall parens->getRParen(), 644b9c2d235fb9449e249d74f48ecfec601650de93John McCall e); 654b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 664b9c2d235fb9449e249d74f48ecfec601650de93John McCall 674b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { 684b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(uop->getOpcode() == UO_Extension); 694b9c2d235fb9449e249d74f48ecfec601650de93John McCall e = rebuild(uop->getSubExpr()); 704b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) UnaryOperator(e, uop->getOpcode(), 714b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getType(), 724b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getValueKind(), 734b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getObjectKind(), 744b9c2d235fb9449e249d74f48ecfec601650de93John McCall uop->getOperatorLoc()); 754b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 764b9c2d235fb9449e249d74f48ecfec601650de93John McCall 774b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 784b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(!gse->isResultDependent()); 794b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned resultIndex = gse->getResultIndex(); 804b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned numAssocs = gse->getNumAssocs(); 814b9c2d235fb9449e249d74f48ecfec601650de93John McCall 824b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<Expr*, 8> assocs(numAssocs); 834b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs); 844b9c2d235fb9449e249d74f48ecfec601650de93John McCall 854b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = 0; i != numAssocs; ++i) { 864b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *assoc = gse->getAssocExpr(i); 874b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (i == resultIndex) assoc = rebuild(assoc); 884b9c2d235fb9449e249d74f48ecfec601650de93John McCall assocs[i] = assoc; 894b9c2d235fb9449e249d74f48ecfec601650de93John McCall assocTypes[i] = gse->getAssocTypeSourceInfo(i); 904b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 914b9c2d235fb9449e249d74f48ecfec601650de93John McCall 924b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) GenericSelectionExpr(S.Context, 934b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getGenericLoc(), 944b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getControllingExpr(), 953b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer assocTypes, 963b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer assocs, 974b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getDefaultLoc(), 984b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->getRParenLoc(), 994b9c2d235fb9449e249d74f48ecfec601650de93John McCall gse->containsUnexpandedParameterPack(), 1004b9c2d235fb9449e249d74f48ecfec601650de93John McCall resultIndex); 1014b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1024b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1034b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("bad expression to rebuild!"); 1044b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1054b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 1064b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1074b9c2d235fb9449e249d74f48ecfec601650de93John McCall struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { 1084b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *NewBase; 1094b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) 110acf9e82fd34c0a125bf2aa8be1ab868082a7f06aBenjamin Kramer : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} 1114b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1124b9c2d235fb9449e249d74f48ecfec601650de93John McCall typedef ObjCPropertyRefExpr specific_type; 1134b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { 1144b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Fortunately, the constraint that we're rebuilding something 1154b9c2d235fb9449e249d74f48ecfec601650de93John McCall // with a base limits the number of cases here. 116a70779f6b9a8135c3459bdeb1f0197b82ea0cb2aEli Friedman assert(refExpr->isObjectReceiver()); 1174b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1184b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (refExpr->isExplicitProperty()) { 1194b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) 1204b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefExpr(refExpr->getExplicitProperty(), 1214b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getType(), refExpr->getValueKind(), 1224b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getObjectKind(), refExpr->getLocation(), 1234b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewBase); 1244b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1254b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (S.Context) 1264b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), 1274b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getImplicitPropertySetter(), 1284b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getType(), refExpr->getValueKind(), 1294b9c2d235fb9449e249d74f48ecfec601650de93John McCall refExpr->getObjectKind(),refExpr->getLocation(), 1304b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewBase); 1314b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1324b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 1334b9c2d235fb9449e249d74f48ecfec601650de93John McCall 134ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> { 135ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *NewBase; 136ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *NewKeyExpr; 137ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) 138ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek : Rebuilder<ObjCSubscriptRefRebuilder>(S), 139ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek NewBase(newBase), NewKeyExpr(newKeyExpr) {} 140ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 141ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek typedef ObjCSubscriptRefExpr specific_type; 142ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { 143ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek assert(refExpr->getBaseExpr()); 144ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek assert(refExpr->getKeyExpr()); 145ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 146ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return new (S.Context) 147ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptRefExpr(NewBase, 148ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek NewKeyExpr, 149ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek refExpr->getType(), refExpr->getValueKind(), 150ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), 151ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek refExpr->setAtIndexMethodDecl(), 152ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek refExpr->getRBracket()); 153ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 154ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek }; 155ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1564b9c2d235fb9449e249d74f48ecfec601650de93John McCall class PseudoOpBuilder { 1574b9c2d235fb9449e249d74f48ecfec601650de93John McCall public: 1584b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema &S; 1594b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned ResultIndex; 1604b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation GenericLoc; 1614b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<Expr *, 4> Semantics; 1624b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1634b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOpBuilder(Sema &S, SourceLocation genericLoc) 1644b9c2d235fb9449e249d74f48ecfec601650de93John McCall : S(S), ResultIndex(PseudoObjectExpr::NoResult), 1654b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc(genericLoc) {} 1664b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1671aa1721f14f2162811f5393dbd84e01eadc2c963Matt Beaumont-Gay virtual ~PseudoOpBuilder() {} 1681aa1721f14f2162811f5393dbd84e01eadc2c963Matt Beaumont-Gay 1694b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// Add a normal semantic expression. 1704b9c2d235fb9449e249d74f48ecfec601650de93John McCall void addSemanticExpr(Expr *semantic) { 1714b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantics.push_back(semantic); 1724b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1734b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1744b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// Add the 'result' semantic expression. 1754b9c2d235fb9449e249d74f48ecfec601650de93John McCall void addResultSemanticExpr(Expr *resultExpr) { 1764b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(ResultIndex == PseudoObjectExpr::NoResult); 1774b9c2d235fb9449e249d74f48ecfec601650de93John McCall ResultIndex = Semantics.size(); 1784b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantics.push_back(resultExpr); 1794b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1804b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1814b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildRValueOperation(Expr *op); 1824b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildAssignmentOperation(Scope *Sc, 1834b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation opLoc, 1844b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 1854b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS); 1864b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 1874b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 1884b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op); 1894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose virtual ExprResult complete(Expr *syntacticForm); 1914b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1924b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *capture(Expr *op); 1934b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *captureValueAsResult(Expr *op); 1944b9c2d235fb9449e249d74f48ecfec601650de93John McCall 1954b9c2d235fb9449e249d74f48ecfec601650de93John McCall void setResultToLastSemantic() { 1964b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(ResultIndex == PseudoObjectExpr::NoResult); 1974b9c2d235fb9449e249d74f48ecfec601650de93John McCall ResultIndex = Semantics.size() - 1; 1984b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1994b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2004b9c2d235fb9449e249d74f48ecfec601650de93John McCall /// Return true if assignments have a non-void result. 20125f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman bool CanCaptureValueOfType(QualType ty) { 20225f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman assert(!ty->isIncompleteType()); 20325f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman assert(!ty->isDependentType()); 20425f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman 20525f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl()) 20625f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman return ClassDecl->isTriviallyCopyable(); 20725f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman return true; 20825f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman } 2094b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2104b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual Expr *rebuildAndCaptureObject(Expr *) = 0; 2114b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual ExprResult buildGet() = 0; 2124b9c2d235fb9449e249d74f48ecfec601650de93John McCall virtual ExprResult buildSet(Expr *, SourceLocation, 2134b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool captureSetValueAsResult) = 0; 2144b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 2154b9c2d235fb9449e249d74f48ecfec601650de93John McCall 216e23fb90712233bdfa04387e48b54a7168e23cb3eDmitri Gribenko /// A PseudoOpBuilder for Objective-C \@properties. 2174b9c2d235fb9449e249d74f48ecfec601650de93John McCall class ObjCPropertyOpBuilder : public PseudoOpBuilder { 2184b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefExpr *RefExpr; 219b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis ObjCPropertyRefExpr *SyntacticRefExpr; 2204b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *InstanceReceiver; 2214b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMethodDecl *Getter; 2224b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2234b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMethodDecl *Setter; 2244b9c2d235fb9449e249d74f48ecfec601650de93John McCall Selector SetterSelector; 225a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian Selector GetterSelector; 2264b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2274b9c2d235fb9449e249d74f48ecfec601650de93John McCall public: 2284b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : 2294b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), 230b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) { 2314b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 2324b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2334b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildRValueOperation(Expr *op); 2344b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildAssignmentOperation(Scope *Sc, 2354b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation opLoc, 2364b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 2374b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS); 2384b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 2394b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 2404b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op); 2414b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2424b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool tryBuildGetOfReference(Expr *op, ExprResult &result); 243b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian bool findSetter(bool warn=true); 2444b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool findGetter(); 2454b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2464b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *rebuildAndCaptureObject(Expr *syntacticBase); 2474b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildGet(); 2484b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult buildSet(Expr *op, SourceLocation, bool); 24958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose ExprResult complete(Expr *SyntacticForm); 25058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 25158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose bool isWeakProperty() const; 2524b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 253ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 254ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /// A PseudoOpBuilder for Objective-C array/dictionary indexing. 255ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek class ObjCSubscriptOpBuilder : public PseudoOpBuilder { 256ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptRefExpr *RefExpr; 257ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek OpaqueValueExpr *InstanceBase; 258ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek OpaqueValueExpr *InstanceKey; 259ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCMethodDecl *AtIndexGetter; 260ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Selector AtIndexGetterSelector; 261ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 262ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCMethodDecl *AtIndexSetter; 263ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Selector AtIndexSetterSelector; 264ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 265ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek public: 266ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) : 267ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), 268ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek RefExpr(refExpr), 269ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek InstanceBase(0), InstanceKey(0), 270ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetter(0), AtIndexSetter(0) { } 271ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 272ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult buildRValueOperation(Expr *op); 273ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult buildAssignmentOperation(Scope *Sc, 274ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation opLoc, 275ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek BinaryOperatorKind opcode, 276ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *LHS, Expr *RHS); 277ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *rebuildAndCaptureObject(Expr *syntacticBase); 278ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 279ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool findAtIndexGetter(); 280ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool findAtIndexSetter(); 281ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 282ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult buildGet(); 283ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult buildSet(Expr *op, SourceLocation, bool); 284ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek }; 285ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 2864b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 2874b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2884b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression in an OpaqueValueExpr. 2894b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { 2904b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Make a new OVE whose source is the given expression. 2914b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *captured = 2924b9c2d235fb9449e249d74f48ecfec601650de93John McCall new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), 29397df54e0c075bc8d6a869597e771dad0c11a2180Douglas Gregor e->getValueKind(), e->getObjectKind(), 29497df54e0c075bc8d6a869597e771dad0c11a2180Douglas Gregor e); 2954b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2964b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Make sure we bind that in the semantics. 2974b9c2d235fb9449e249d74f48ecfec601650de93John McCall addSemanticExpr(captured); 2984b9c2d235fb9449e249d74f48ecfec601650de93John McCall return captured; 2994b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3004b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3014b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression as the result of this pseudo-object 3024b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation. This routine is safe against expressions which may 3034b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// already be captured. 3044b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 30570517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \returns the captured expression, which will be the 3064b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// same as the input if the input was already captured 3074b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { 3084b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(ResultIndex == PseudoObjectExpr::NoResult); 3094b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3104b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the expression hasn't already been captured, just capture it 3114b9c2d235fb9449e249d74f48ecfec601650de93John McCall // and set the new semantic 3124b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!isa<OpaqueValueExpr>(e)) { 3134b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *cap = capture(e); 3144b9c2d235fb9449e249d74f48ecfec601650de93John McCall setResultToLastSemantic(); 3154b9c2d235fb9449e249d74f48ecfec601650de93John McCall return cap; 3164b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3174b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3184b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Otherwise, it must already be one of our semantic expressions; 3194b9c2d235fb9449e249d74f48ecfec601650de93John McCall // set ResultIndex to its index. 3204b9c2d235fb9449e249d74f48ecfec601650de93John McCall unsigned index = 0; 3214b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (;; ++index) { 3224b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(index < Semantics.size() && 3234b9c2d235fb9449e249d74f48ecfec601650de93John McCall "captured expression not found in semantics!"); 3244b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (e == Semantics[index]) break; 3254b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3264b9c2d235fb9449e249d74f48ecfec601650de93John McCall ResultIndex = index; 3274b9c2d235fb9449e249d74f48ecfec601650de93John McCall return cast<OpaqueValueExpr>(e); 3284b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3294b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3304b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The routine which creates the final PseudoObjectExpr. 3314b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::complete(Expr *syntactic) { 3324b9c2d235fb9449e249d74f48ecfec601650de93John McCall return PseudoObjectExpr::Create(S.Context, syntactic, 3334b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantics, ResultIndex); 3344b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3354b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3364b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The main skeleton for building an r-value operation. 3374b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { 3384b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntacticBase = rebuildAndCaptureObject(op); 3394b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3404b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult getExpr = buildGet(); 3414b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (getExpr.isInvalid()) return ExprError(); 3424b9c2d235fb9449e249d74f48ecfec601650de93John McCall addResultSemanticExpr(getExpr.take()); 3434b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3444b9c2d235fb9449e249d74f48ecfec601650de93John McCall return complete(syntacticBase); 3454b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3464b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3474b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building a simple or compound 3484b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// assignment operation. 3494b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 3504b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 3514b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 3524b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS) { 3534b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(BinaryOperator::isAssignmentOp(opcode)); 3544b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3554b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntacticLHS = rebuildAndCaptureObject(LHS); 3564b9c2d235fb9449e249d74f48ecfec601650de93John McCall OpaqueValueExpr *capturedRHS = capture(RHS); 3574b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3584b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntactic; 3594b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3604b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result; 3614b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (opcode == BO_Assign) { 3624b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = capturedRHS; 3634b9c2d235fb9449e249d74f48ecfec601650de93John McCall syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, 3644b9c2d235fb9449e249d74f48ecfec601650de93John McCall opcode, capturedRHS->getType(), 3654b9c2d235fb9449e249d74f48ecfec601650de93John McCall capturedRHS->getValueKind(), 366be9af1288881110e406b87914162eaa59f1e5918Lang Hames OK_Ordinary, opcLoc, false); 3674b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 3684b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult opLHS = buildGet(); 3694b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (opLHS.isInvalid()) return ExprError(); 3704b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3714b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Build an ordinary, non-compound operation. 3724b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind nonCompound = 3734b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperator::getOpForCompoundAssignment(opcode); 3744b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.BuildBinOp(Sc, opcLoc, nonCompound, 3754b9c2d235fb9449e249d74f48ecfec601650de93John McCall opLHS.take(), capturedRHS); 3764b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3774b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3784b9c2d235fb9449e249d74f48ecfec601650de93John McCall syntactic = 3794b9c2d235fb9449e249d74f48ecfec601650de93John McCall new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, 3804b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getType(), 3814b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getValueKind(), 3824b9c2d235fb9449e249d74f48ecfec601650de93John McCall OK_Ordinary, 3834b9c2d235fb9449e249d74f48ecfec601650de93John McCall opLHS.get()->getType(), 3844b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getType(), 385be9af1288881110e406b87914162eaa59f1e5918Lang Hames opcLoc, false); 3864b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3874b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3884b9c2d235fb9449e249d74f48ecfec601650de93John McCall // The result of the assignment, if not void, is the value set into 3894b9c2d235fb9449e249d74f48ecfec601650de93John McCall // the l-value. 39025f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman result = buildSet(result.take(), opcLoc, /*captureSetValueAsResult*/ true); 3914b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 3924b9c2d235fb9449e249d74f48ecfec601650de93John McCall addSemanticExpr(result.take()); 3934b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3944b9c2d235fb9449e249d74f48ecfec601650de93John McCall return complete(syntactic); 3954b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3974b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building an increment or decrement 3984b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation. 3994b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 4004b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 4014b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 4024b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op) { 4034b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(UnaryOperator::isIncrementDecrementOp(opcode)); 4044b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4054b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *syntacticOp = rebuildAndCaptureObject(op); 4064b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4074b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Load the value. 4084b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = buildGet(); 4094b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 4104b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4114b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType resultType = result.get()->getType(); 4124b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4134b9c2d235fb9449e249d74f48ecfec601650de93John McCall // That's the postfix result. 41425f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman if (UnaryOperator::isPostfix(opcode) && CanCaptureValueOfType(resultType)) { 4154b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = capture(result.take()); 4164b9c2d235fb9449e249d74f48ecfec601650de93John McCall setResultToLastSemantic(); 4174b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 4184b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4194b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add or subtract a literal 1. 4204b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); 4214b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, 4224b9c2d235fb9449e249d74f48ecfec601650de93John McCall GenericLoc); 4234b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4244b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (UnaryOperator::isIncrementOp(opcode)) { 4254b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one); 4264b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 4274b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one); 4284b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 4294b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 4304b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4314b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Store that back into the result. The value stored is the result 4324b9c2d235fb9449e249d74f48ecfec601650de93John McCall // of a prefix operation. 43325f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman result = buildSet(result.take(), opcLoc, UnaryOperator::isPrefix(opcode)); 4344b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 4354b9c2d235fb9449e249d74f48ecfec601650de93John McCall addSemanticExpr(result.take()); 4364b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4374b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperator *syntactic = 4384b9c2d235fb9449e249d74f48ecfec601650de93John McCall new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, 4394b9c2d235fb9449e249d74f48ecfec601650de93John McCall VK_LValue, OK_Ordinary, opcLoc); 4404b9c2d235fb9449e249d74f48ecfec601650de93John McCall return complete(syntactic); 4414b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 4424b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4434b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4444b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 4454b9c2d235fb9449e249d74f48ecfec601650de93John McCall// Objective-C @property and implicit property references 4464b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 4474b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4484b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Look up a method in the receiver type of an Objective-C property 4494b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference. 4503c3b7f90a863af43fa63043d396553ecf205351cJohn McCallstatic ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 4513c3b7f90a863af43fa63043d396553ecf205351cJohn McCall const ObjCPropertyRefExpr *PRE) { 4523c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (PRE->isObjectReceiver()) { 453aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer const ObjCObjectPointerType *PT = 454aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 4554b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4564b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Special case for 'self' in class method implementations. 4574b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (PT->isObjCClassType() && 4584b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) { 4594b9c2d235fb9449e249d74f48ecfec601650de93John McCall // This cast is safe because isSelfExpr is only true within 4604b9c2d235fb9449e249d74f48ecfec601650de93John McCall // methods. 4614b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMethodDecl *method = 4624b9c2d235fb9449e249d74f48ecfec601650de93John McCall cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); 4634b9c2d235fb9449e249d74f48ecfec601650de93John McCall return S.LookupMethodInObjectType(sel, 4644b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Context.getObjCInterfaceType(method->getClassInterface()), 4654b9c2d235fb9449e249d74f48ecfec601650de93John McCall /*instance*/ false); 4664b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 4674b9c2d235fb9449e249d74f48ecfec601650de93John McCall 468aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 4693c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 4703c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 471aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer if (PRE->isSuperReceiver()) { 472aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer if (const ObjCObjectPointerType *PT = 473aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 474aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 475aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer 476aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); 477aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer } 478aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer 479aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer assert(PRE->isClassReceiver() && "Invalid expression"); 480aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 481aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, IT, false); 4823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 4833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 48458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosebool ObjCPropertyOpBuilder::isWeakProperty() const { 48558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose QualType T; 48658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (RefExpr->isExplicitProperty()) { 48758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty(); 48858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) 48958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return true; 49058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 49158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose T = Prop->getType(); 49258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } else if (Getter) { 49358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose T = Getter->getResultType(); 49458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } else { 49558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return false; 49658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 49758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 49858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return T.getObjCLifetime() == Qualifiers::OCL_Weak; 49958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose} 50058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 5014b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findGetter() { 5024b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (Getter) return true; 5034b9c2d235fb9449e249d74f48ecfec601650de93John McCall 504dc4df51d32dea56fbec79037570832dffbcc14e6John McCall // For implicit properties, just trust the lookup we already did. 505dc4df51d32dea56fbec79037570832dffbcc14e6John McCall if (RefExpr->isImplicitProperty()) { 506a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian if ((Getter = RefExpr->getImplicitPropertyGetter())) { 507a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian GetterSelector = Getter->getSelector(); 508a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian return true; 509a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian } 510a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian else { 511a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian // Must build the getter selector the hard way. 512a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter(); 513a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian assert(setter && "both setter and getter are null - cannot happen"); 514a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian IdentifierInfo *setterName = 515a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian setter->getSelector().getIdentifierInfoForSlot(0); 516a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian const char *compStr = setterName->getNameStart(); 517a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian compStr += 3; 518a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian IdentifierInfo *getterName = &S.Context.Idents.get(compStr); 519a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian GetterSelector = 520a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian S.PP.getSelectorTable().getNullarySelector(getterName); 521a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian return false; 522a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian 523a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian } 524dc4df51d32dea56fbec79037570832dffbcc14e6John McCall } 525dc4df51d32dea56fbec79037570832dffbcc14e6John McCall 526dc4df51d32dea56fbec79037570832dffbcc14e6John McCall ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 527dc4df51d32dea56fbec79037570832dffbcc14e6John McCall Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); 5284b9c2d235fb9449e249d74f48ecfec601650de93John McCall return (Getter != 0); 5294b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 5304b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5314b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to find the most accurate setter declaration for the property 5324b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference. 5334b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 5344b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if a setter was found, in which case Setter 535b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanianbool ObjCPropertyOpBuilder::findSetter(bool warn) { 5364b9c2d235fb9449e249d74f48ecfec601650de93John McCall // For implicit properties, just trust the lookup we already did. 5374b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isImplicitProperty()) { 5384b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 5394b9c2d235fb9449e249d74f48ecfec601650de93John McCall Setter = setter; 5404b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector = setter->getSelector(); 5414b9c2d235fb9449e249d74f48ecfec601650de93John McCall return true; 5423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 5434b9c2d235fb9449e249d74f48ecfec601650de93John McCall IdentifierInfo *getterName = 5444b9c2d235fb9449e249d74f48ecfec601650de93John McCall RefExpr->getImplicitPropertyGetter()->getSelector() 5454b9c2d235fb9449e249d74f48ecfec601650de93John McCall .getIdentifierInfoForSlot(0); 5464b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector = 5474b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelectorTable::constructSetterName(S.PP.getIdentifierTable(), 5484b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.PP.getSelectorTable(), 5494b9c2d235fb9449e249d74f48ecfec601650de93John McCall getterName); 5504b9c2d235fb9449e249d74f48ecfec601650de93John McCall return false; 5513c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 5523c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 5533c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 5544b9c2d235fb9449e249d74f48ecfec601650de93John McCall // For explicit properties, this is more involved. 5554b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 5564b9c2d235fb9449e249d74f48ecfec601650de93John McCall SetterSelector = prop->getSetterName(); 5574b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5584b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Do a normal method lookup first. 5594b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCMethodDecl *setter = 5604b9c2d235fb9449e249d74f48ecfec601650de93John McCall LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 5611e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose if (setter->isPropertyAccessor() && warn) 562b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian if (const ObjCInterfaceDecl *IFace = 563b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { 564b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian const StringRef thisPropertyName(prop->getName()); 565b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian char front = thisPropertyName.front(); 566b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian front = islower(front) ? toupper(front) : tolower(front); 567b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian SmallString<100> PropertyName = thisPropertyName; 568b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian PropertyName[0] = front; 569b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); 570b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember)) 571b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) { 572cba0ebce65667f76e291346d377f402579743ceaFariborz Jahanian S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use) 573b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian << prop->getName() << prop1->getName() << setter->getSelector(); 574b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian S.Diag(prop->getLocation(), diag::note_property_declare); 575b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian S.Diag(prop1->getLocation(), diag::note_property_declare); 576b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian } 577b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian } 5784b9c2d235fb9449e249d74f48ecfec601650de93John McCall Setter = setter; 5794b9c2d235fb9449e249d74f48ecfec601650de93John McCall return true; 5804b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5814b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5824b9c2d235fb9449e249d74f48ecfec601650de93John McCall // That can fail in the somewhat crazy situation that we're 5834b9c2d235fb9449e249d74f48ecfec601650de93John McCall // type-checking a message send within the @interface declaration 5844b9c2d235fb9449e249d74f48ecfec601650de93John McCall // that declared the @property. But it's not clear that that's 5854b9c2d235fb9449e249d74f48ecfec601650de93John McCall // valuable to support. 5864b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5874b9c2d235fb9449e249d74f48ecfec601650de93John McCall return false; 5884b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 5894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5904b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the base object of an Objective-C property expression. 5914b9c2d235fb9449e249d74f48ecfec601650de93John McCallExpr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 5924b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver == 0); 5934b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5944b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If we have a base, capture it in an OVE and rebuild the syntactic 5954b9c2d235fb9449e249d74f48ecfec601650de93John McCall // form to use the OVE as its base. 5964b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isObjectReceiver()) { 5974b9c2d235fb9449e249d74f48ecfec601650de93John McCall InstanceReceiver = capture(RefExpr->getBase()); 5984b9c2d235fb9449e249d74f48ecfec601650de93John McCall 5994b9c2d235fb9449e249d74f48ecfec601650de93John McCall syntacticBase = 6004b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); 6014b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6024b9c2d235fb9449e249d74f48ecfec601650de93John McCall 603b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis if (ObjCPropertyRefExpr * 604b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens())) 605b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis SyntacticRefExpr = refE; 606b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis 6074b9c2d235fb9449e249d74f48ecfec601650de93John McCall return syntacticBase; 6084b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 6094b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6104b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Load from an Objective-C property reference. 6114b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildGet() { 6124b9c2d235fb9449e249d74f48ecfec601650de93John McCall findGetter(); 6134b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(Getter); 614b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis 615b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis if (SyntacticRefExpr) 616b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis SyntacticRefExpr->setIsMessagingGetter(); 617b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis 6184b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType receiverType; 6194b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isClassReceiver()) { 6204b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 6214b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else if (RefExpr->isSuperReceiver()) { 6224b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = RefExpr->getSuperReceiverType(); 6234b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 6244b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver); 6254b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = InstanceReceiver->getType(); 6264b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6284b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Build a message-send. 6294b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult msg; 6304b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 6314b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver || RefExpr->isSuperReceiver()); 632746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 633746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis GenericLoc, Getter->getSelector(), 634746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis Getter, MultiExprArg()); 6354b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 636746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 637746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis GenericLoc, 638746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis Getter->getSelector(), Getter, 639746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis MultiExprArg()); 6404b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6414b9c2d235fb9449e249d74f48ecfec601650de93John McCall return msg; 6423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 6433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6444b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Store to an Objective-C property reference. 6454b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 64670517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \param captureSetValueAsResult If true, capture the actual 6474b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// value being set as the value of the property operation. 6484b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 6494b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool captureSetValueAsResult) { 650b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian bool hasSetter = findSetter(false); 6514b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(hasSetter); (void) hasSetter; 6524b9c2d235fb9449e249d74f48ecfec601650de93John McCall 653b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis if (SyntacticRefExpr) 654b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis SyntacticRefExpr->setIsMessagingSetter(); 655b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis 6564b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType receiverType; 6574b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isClassReceiver()) { 6584b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 6594b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else if (RefExpr->isSuperReceiver()) { 6604b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = RefExpr->getSuperReceiverType(); 6614b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 6624b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(InstanceReceiver); 6634b9c2d235fb9449e249d74f48ecfec601650de93John McCall receiverType = InstanceReceiver->getType(); 6644b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6664b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Use assignment constraints when possible; they give us better 6674b9c2d235fb9449e249d74f48ecfec601650de93John McCall // diagnostics. "When possible" basically means anything except a 6684b9c2d235fb9449e249d74f48ecfec601650de93John McCall // C++ class type. 6694e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { 6704b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType paramType = (*Setter->param_begin())->getType(); 6714e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { 6724b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult opResult = op; 6734b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema::AssignConvertType assignResult 6744b9c2d235fb9449e249d74f48ecfec601650de93John McCall = S.CheckSingleAssignmentConstraints(paramType, opResult); 6754b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 6764b9c2d235fb9449e249d74f48ecfec601650de93John McCall op->getType(), opResult.get(), 6774b9c2d235fb9449e249d74f48ecfec601650de93John McCall Sema::AA_Assigning)) 6784b9c2d235fb9449e249d74f48ecfec601650de93John McCall return ExprError(); 6794b9c2d235fb9449e249d74f48ecfec601650de93John McCall 6804b9c2d235fb9449e249d74f48ecfec601650de93John McCall op = opResult.take(); 6814b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(op && "successful assignment left argument invalid?"); 6823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 6834b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 6843c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6854b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Arguments. 6864b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *args[] = { op }; 6873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 6884b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Build a message-send. 6894b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult msg; 6904b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 691746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 692746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis GenericLoc, SetterSelector, Setter, 693746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis MultiExprArg(args, 1)); 6944b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 695746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 696746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis GenericLoc, 697746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis SetterSelector, Setter, 698746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis MultiExprArg(args, 1)); 6994b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7014b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!msg.isInvalid() && captureSetValueAsResult) { 7024b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMessageExpr *msgExpr = 7034b9c2d235fb9449e249d74f48ecfec601650de93John McCall cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 7044b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *arg = msgExpr->getArg(0); 70525f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman if (CanCaptureValueOfType(arg->getType())) 70625f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman msgExpr->setArg(0, captureValueAsResult(arg)); 7074b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7094b9c2d235fb9449e249d74f48ecfec601650de93John McCall return msg; 7104b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 7114b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7124b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing lvalue-to-rvalue conversion. 7134b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 7144b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Explicit properties always have getters, but implicit ones don't. 7154b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Check that before proceeding. 716a70779f6b9a8135c3459bdeb1f0197b82ea0cb2aEli Friedman if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) { 7174b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 718a70779f6b9a8135c3459bdeb1f0197b82ea0cb2aEli Friedman << RefExpr->getSourceRange(); 7194b9c2d235fb9449e249d74f48ecfec601650de93John McCall return ExprError(); 7204b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7214b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7224b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 7234b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 7244b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7254b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 7264b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 7274b9c2d235fb9449e249d74f48ecfec601650de93John McCall Getter, RefExpr->getLocation()); 7284b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7294b9c2d235fb9449e249d74f48ecfec601650de93John McCall // As a special case, if the method returns 'id', try to get 7304b9c2d235fb9449e249d74f48ecfec601650de93John McCall // a better type from the property. 7314b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (RefExpr->isExplicitProperty() && result.get()->isRValue() && 7324b9c2d235fb9449e249d74f48ecfec601650de93John McCall result.get()->getType()->isObjCIdType()) { 7334b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType propType = RefExpr->getExplicitProperty()->getType(); 7344b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (const ObjCObjectPointerType *ptr 7354b9c2d235fb9449e249d74f48ecfec601650de93John McCall = propType->getAs<ObjCObjectPointerType>()) { 7364b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!ptr->isObjCIdType()) 7374b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 7383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7394b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 7404b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7414b9c2d235fb9449e249d74f48ecfec601650de93John McCall return result; 7423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 7433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7444b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to build this as a call to a getter that returns a reference. 7454b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// 7464b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if it was possible, whether or not it actually 7474b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// succeeded 7484b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 7494b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult &result) { 7504e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!S.getLangOpts().CPlusPlus) return false; 7514b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7524b9c2d235fb9449e249d74f48ecfec601650de93John McCall findGetter(); 7534b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(Getter && "property has no setter and no getter!"); 7544b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7554b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Only do this if the getter returns an l-value reference type. 7564b9c2d235fb9449e249d74f48ecfec601650de93John McCall QualType resultType = Getter->getResultType(); 7574b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!resultType->isLValueReferenceType()) return false; 7584b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7594b9c2d235fb9449e249d74f48ecfec601650de93John McCall result = buildRValueOperation(op); 7604b9c2d235fb9449e249d74f48ecfec601650de93John McCall return true; 7614b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 7624b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7634b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing assignments. 7644b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 7654b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 7664b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceLocation opcLoc, 7674b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 7684b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS) { 7694b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(BinaryOperator::isAssignmentOp(opcode)); 7703c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7713c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there's no setter, we have no choice but to try to assign to 7723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // the result of the getter. 7734b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!findSetter()) { 7744b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result; 7754b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (tryBuildGetOfReference(LHS, result)) { 7764b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 7774b9c2d235fb9449e249d74f48ecfec601650de93John McCall return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); 7783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7793c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7803c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Otherwise, it's an error. 7814b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nosetter_property_assignment) 7824b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(RefExpr->isImplicitProperty()) 7834b9c2d235fb9449e249d74f48ecfec601650de93John McCall << SetterSelector 7844b9c2d235fb9449e249d74f48ecfec601650de93John McCall << LHS->getSourceRange() << RHS->getSourceRange(); 7853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 7863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7884b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If there is a setter, we definitely want to use it. 7894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 7904b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Verify that we can do a compound assignment. 7914b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (opcode != BO_Assign && !findGetter()) { 7924b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 7934b9c2d235fb9449e249d74f48ecfec601650de93John McCall << LHS->getSourceRange() << RHS->getSourceRange(); 7943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 7953c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 7963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 7974b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result = 7984b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 7993c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (result.isInvalid()) return ExprError(); 8003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 8014b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Various warnings about property assignments in ARC. 8024e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { 8034b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 8044b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 8054b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 8064b9c2d235fb9449e249d74f48ecfec601650de93John McCall 8073c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return result; 8083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 8093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 8104b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing increments and decrements. 8114b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult 8124b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 8134b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, 8144b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *op) { 8153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there's no setter, we have no choice but to try to assign to 8163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // the result of the getter. 8174b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!findSetter()) { 8184b9c2d235fb9449e249d74f48ecfec601650de93John McCall ExprResult result; 8194b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (tryBuildGetOfReference(op, result)) { 8204b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (result.isInvalid()) return ExprError(); 8214b9c2d235fb9449e249d74f48ecfec601650de93John McCall return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); 8223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 8233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 8243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Otherwise, it's an error. 8254b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nosetter_property_incdec) 8264b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(RefExpr->isImplicitProperty()) 8274b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(UnaryOperator::isDecrementOp(opcode)) 8284b9c2d235fb9449e249d74f48ecfec601650de93John McCall << SetterSelector 8294b9c2d235fb9449e249d74f48ecfec601650de93John McCall << op->getSourceRange(); 8303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 8313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 8323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 8333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there is a setter, we definitely want to use it. 8343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 8354b9c2d235fb9449e249d74f48ecfec601650de93John McCall // We also need a getter. 8364b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (!findGetter()) { 8374b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(RefExpr->isImplicitProperty()); 8384b9c2d235fb9449e249d74f48ecfec601650de93John McCall S.Diag(opcLoc, diag::err_nogetter_property_incdec) 8394b9c2d235fb9449e249d74f48ecfec601650de93John McCall << unsigned(UnaryOperator::isDecrementOp(opcode)) 840a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian << GetterSelector 8414b9c2d235fb9449e249d74f48ecfec601650de93John McCall << op->getSourceRange(); 8424b9c2d235fb9449e249d74f48ecfec601650de93John McCall return ExprError(); 8434b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 8443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 8454b9c2d235fb9449e249d74f48ecfec601650de93John McCall return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 8464b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 8473c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 84858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan RoseExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { 84958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) { 85058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagnosticsEngine::Level Level = 85158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, 85258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose SyntacticForm->getLocStart()); 85358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (Level != DiagnosticsEngine::Ignored) 8547a2704800943fbb69207e125d28186278712af36Jordan Rose S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, 8557a2704800943fbb69207e125d28186278712af36Jordan Rose SyntacticRefExpr->isMessagingGetter()); 85658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 85758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 85858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return PseudoOpBuilder::complete(SyntacticForm); 85958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose} 86058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 861ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// ObjCSubscript build stuff. 862ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// 863ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 864ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue 865ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// conversion. 866ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// FIXME. Remove this routine if it is proven that no additional 867ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// specifity is needed. 868ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { 869ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 870ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (result.isInvalid()) return ExprError(); 871ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return result; 872ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 873ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 874ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// objective-c subscripting-specific behavior for doing assignments. 875ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult 876ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, 877ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation opcLoc, 878ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek BinaryOperatorKind opcode, 879ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *LHS, Expr *RHS) { 880ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek assert(BinaryOperator::isAssignmentOp(opcode)); 881ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // There must be a method to do the Index'ed assignment. 882ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!findAtIndexSetter()) 883ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return ExprError(); 884ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 885ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Verify that we can do a compound assignment. 886ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (opcode != BO_Assign && !findAtIndexGetter()) 887ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return ExprError(); 888ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 889ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult result = 890ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 891ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (result.isInvalid()) return ExprError(); 892ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 893ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Various warnings about objc Index'ed assignments in ARC. 8944e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { 895ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS); 896ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 897ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 898ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 899ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return result; 900ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 901ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 902ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// Capture the base object of an Objective-C Index'ed expression. 903ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExpr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 904ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek assert(InstanceBase == 0); 905ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 906ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Capture base expression in an OVE and rebuild the syntactic 907ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // form to use the OVE as its base expression. 908ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek InstanceBase = capture(RefExpr->getBaseExpr()); 909ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek InstanceKey = capture(RefExpr->getKeyExpr()); 910ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 911ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek syntacticBase = 912ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptRefRebuilder(S, InstanceBase, 913ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek InstanceKey).rebuild(syntacticBase); 914ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 915ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return syntacticBase; 916ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 917ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 918ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// CheckSubscriptingKind - This routine decide what type 919ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// of indexing represented by "FromE" is being done. 920ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekSema::ObjCSubscriptKind 921ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Sema::CheckSubscriptingKind(Expr *FromE) { 922ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // If the expression already has integral or enumeration type, we're golden. 923ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType T = FromE->getType(); 924ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (T->isIntegralOrEnumerationType()) 925ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Array; 926ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 927ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // If we don't have a class type in C++, there's no way we can get an 928ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // expression of integral or enumeration type. 929ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek const RecordType *RecordTy = T->getAs<RecordType>(); 930a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian if (!RecordTy && T->isObjCObjectPointerType()) 931ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // All other scalar cases are assumed to be dictionary indexing which 932ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // caller handles, with diagnostics if needed. 933ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Dictionary; 934a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian if (!getLangOpts().CPlusPlus || 935a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian !RecordTy || RecordTy->isIncompleteType()) { 936ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // No indexing can be done. Issue diagnostics and quit. 937a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); 938a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian if (isa<StringLiteral>(IndexExpr)) 939a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) 940a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); 941a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian else 942a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 943a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian << T; 944ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Error; 945ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 946ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 947ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // We must have a complete class type. 948ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (RequireCompleteType(FromE->getExprLoc(), T, 949d10099e5c8238fa0327f03921cf2e3c8975c881eDouglas Gregor diag::err_objc_index_incomplete_class_type, FromE)) 950ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Error; 951ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 952ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Look for a conversion to an integral, enumeration type, or 953ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // objective-C pointer type. 954ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek UnresolvedSet<4> ViableConversions; 955ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek UnresolvedSet<4> ExplicitConversions; 9569d29543284e75648ac89c6e9586fc7cf786cf66fArgyrios Kyrtzidis std::pair<CXXRecordDecl::conversion_iterator, 9579d29543284e75648ac89c6e9586fc7cf786cf66fArgyrios Kyrtzidis CXXRecordDecl::conversion_iterator> Conversions 958ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); 959ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 960ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek int NoIntegrals=0, NoObjCIdPointers=0; 961ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SmallVector<CXXConversionDecl *, 4> ConversionDecls; 962ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 9639d29543284e75648ac89c6e9586fc7cf786cf66fArgyrios Kyrtzidis for (CXXRecordDecl::conversion_iterator 9649d29543284e75648ac89c6e9586fc7cf786cf66fArgyrios Kyrtzidis I = Conversions.first, E = Conversions.second; I != E; ++I) { 965ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (CXXConversionDecl *Conversion 966ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { 967ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType CT = Conversion->getConversionType().getNonReferenceType(); 968ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (CT->isIntegralOrEnumerationType()) { 969ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ++NoIntegrals; 970ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ConversionDecls.push_back(Conversion); 971ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 972ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek else if (CT->isObjCIdType() ||CT->isBlockPointerType()) { 973ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ++NoObjCIdPointers; 974ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ConversionDecls.push_back(Conversion); 975ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 976ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 977ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 978ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (NoIntegrals ==1 && NoObjCIdPointers == 0) 979ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Array; 980ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (NoIntegrals == 0 && NoObjCIdPointers == 1) 981ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Dictionary; 982ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (NoIntegrals == 0 && NoObjCIdPointers == 0) { 983ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // No conversion function was found. Issue diagnostic and return. 984ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 985ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek << FromE->getType(); 986ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Error; 987ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 988ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) 989ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek << FromE->getType(); 990ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek for (unsigned int i = 0; i < ConversionDecls.size(); i++) 991ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at); 992ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 993ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return OS_Error; 994ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 995ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 996dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF 997dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian/// objects used as dictionary subscript key objects. 998dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanianstatic void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, 999dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian Expr *Key) { 1000dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian if (ContainerT.isNull()) 1001dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian return; 1002dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian // dictionary subscripting. 1003dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian // - (id)objectForKeyedSubscript:(id)key; 1004dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian IdentifierInfo *KeyIdents[] = { 1005dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian &S.Context.Idents.get("objectForKeyedSubscript") 1006dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian }; 1007dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1008dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT, 1009dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian true /*instance*/); 1010dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian if (!Getter) 1011dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian return; 1012dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian QualType T = Getter->param_begin()[0]->getType(); 1013dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian S.CheckObjCARCConversion(Key->getSourceRange(), 1014dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian T, Key, Sema::CCK_ImplicitConversion); 1015dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian} 1016dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian 1017ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenekbool ObjCSubscriptOpBuilder::findAtIndexGetter() { 1018ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (AtIndexGetter) 1019ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return true; 1020ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1021ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *BaseExpr = RefExpr->getBaseExpr(); 1022ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType BaseT = BaseExpr->getType(); 1023ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1024ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType ResultType; 1025ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (const ObjCObjectPointerType *PTy = 1026ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek BaseT->getAs<ObjCObjectPointerType>()) { 1027ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultType = PTy->getPointeeType(); 1028ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (const ObjCObjectType *iQFaceTy = 1029ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultType->getAsObjCQualifiedInterfaceType()) 1030ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultType = iQFaceTy->getBaseType(); 1031ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1032ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Sema::ObjCSubscriptKind Res = 1033ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.CheckSubscriptingKind(RefExpr->getKeyExpr()); 1034dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian if (Res == Sema::OS_Error) { 1035dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian if (S.getLangOpts().ObjCAutoRefCount) 1036dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian CheckKeyForObjCARCConversion(S, ResultType, 1037dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian RefExpr->getKeyExpr()); 1038ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1039dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian } 1040ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool arrayRef = (Res == Sema::OS_Array); 1041ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1042ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (ResultType.isNull()) { 1043ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 1044ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek << BaseExpr->getType() << arrayRef; 1045ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1046ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1047ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!arrayRef) { 1048ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // dictionary subscripting. 1049ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // - (id)objectForKeyedSubscript:(id)key; 1050ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek IdentifierInfo *KeyIdents[] = { 1051ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("objectForKeyedSubscript") 1052ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek }; 1053ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1054ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1055ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek else { 1056ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // - (id)objectAtIndexedSubscript:(size_t)index; 1057ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek IdentifierInfo *KeyIdents[] = { 1058ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("objectAtIndexedSubscript") 1059ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek }; 1060ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1061ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1062ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1063ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1064ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, 1065ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek true /*instance*/); 1066ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool receiverIdType = (BaseT->isObjCIdType() || 1067ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek BaseT->isObjCQualifiedIdType()); 1068ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 10694e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { 1070ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), 1071ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation(), AtIndexGetterSelector, 1072ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Context.getObjCIdType() /*ReturnType*/, 1073ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 0 /*TypeSourceInfo */, 1074ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Context.getTranslationUnitDecl(), 1075ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek true /*Instance*/, false/*isVariadic*/, 10761e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose /*isPropertyAccessor=*/false, 1077ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 1078ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCMethodDecl::Required, 1079ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek false); 1080ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, 1081ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation(), SourceLocation(), 1082ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek arrayRef ? &S.Context.Idents.get("index") 1083ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek : &S.Context.Idents.get("key"), 1084ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek arrayRef ? S.Context.UnsignedLongTy 1085ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek : S.Context.getObjCIdType(), 1086ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /*TInfo=*/0, 1087ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SC_None, 1088ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SC_None, 1089ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 0); 1090ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetter->setMethodParams(S.Context, Argument, 1091ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ArrayRef<SourceLocation>()); 1092ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1093ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1094ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!AtIndexGetter) { 1095ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!receiverIdType) { 1096ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found) 1097ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek << BaseExpr->getType() << 0 << arrayRef; 1098ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1099ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1100ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetter = 1101ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, 1102ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek RefExpr->getSourceRange(), 1103ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek true, false); 1104ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1105ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1106ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (AtIndexGetter) { 1107ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType T = AtIndexGetter->param_begin()[0]->getType(); 1108ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if ((arrayRef && !T->isIntegralOrEnumerationType()) || 1109ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek (!arrayRef && !T->isObjCObjectPointerType())) { 1110ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1111ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek arrayRef ? diag::err_objc_subscript_index_type 1112ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek : diag::err_objc_subscript_key_type) << T; 1113ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(AtIndexGetter->param_begin()[0]->getLocation(), 1114ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::note_parameter_type) << T; 1115ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1116ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1117ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType R = AtIndexGetter->getResultType(); 1118ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!R->isObjCObjectPointerType()) { 1119ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1120ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::err_objc_indexing_method_result_type) << R << arrayRef; 1121ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) << 1122ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetter->getDeclName(); 1123ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1124ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1125ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return true; 1126ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 1127ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1128ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenekbool ObjCSubscriptOpBuilder::findAtIndexSetter() { 1129ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (AtIndexSetter) 1130ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return true; 1131ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1132ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *BaseExpr = RefExpr->getBaseExpr(); 1133ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType BaseT = BaseExpr->getType(); 1134ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1135ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType ResultType; 1136ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (const ObjCObjectPointerType *PTy = 1137ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek BaseT->getAs<ObjCObjectPointerType>()) { 1138ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultType = PTy->getPointeeType(); 1139ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (const ObjCObjectType *iQFaceTy = 1140ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultType->getAsObjCQualifiedInterfaceType()) 1141ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultType = iQFaceTy->getBaseType(); 1142ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1143ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1144ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Sema::ObjCSubscriptKind Res = 1145ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.CheckSubscriptingKind(RefExpr->getKeyExpr()); 1146dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian if (Res == Sema::OS_Error) { 1147dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian if (S.getLangOpts().ObjCAutoRefCount) 1148dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian CheckKeyForObjCARCConversion(S, ResultType, 1149dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian RefExpr->getKeyExpr()); 1150ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1151dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian } 1152ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool arrayRef = (Res == Sema::OS_Array); 1153ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1154ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (ResultType.isNull()) { 1155ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 1156ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek << BaseExpr->getType() << arrayRef; 1157ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1158ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1159ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1160ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!arrayRef) { 1161ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // dictionary subscripting. 1162ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // - (void)setObject:(id)object forKeyedSubscript:(id)key; 1163ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek IdentifierInfo *KeyIdents[] = { 1164ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("setObject"), 1165ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("forKeyedSubscript") 1166ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek }; 1167ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 1168ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1169ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek else { 1170ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 1171ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek IdentifierInfo *KeyIdents[] = { 1172ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("setObject"), 1173ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("atIndexedSubscript") 1174ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek }; 1175ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 1176ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1177ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, 1178ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek true /*instance*/); 1179ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1180ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool receiverIdType = (BaseT->isObjCIdType() || 1181ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek BaseT->isObjCQualifiedIdType()); 1182ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 11834e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { 1184ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek TypeSourceInfo *ResultTInfo = 0; 1185ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType ReturnType = S.Context.VoidTy; 1186ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), 1187ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation(), AtIndexSetterSelector, 1188ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ReturnType, 1189ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ResultTInfo, 1190ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Context.getTranslationUnitDecl(), 1191ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek true /*Instance*/, false/*isVariadic*/, 11921e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose /*isPropertyAccessor=*/false, 1193ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 1194ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCMethodDecl::Required, 1195ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek false); 1196ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SmallVector<ParmVarDecl *, 2> Params; 1197ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter, 1198ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation(), SourceLocation(), 1199ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek &S.Context.Idents.get("object"), 1200ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Context.getObjCIdType(), 1201ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /*TInfo=*/0, 1202ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SC_None, 1203ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SC_None, 1204ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 0); 1205ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Params.push_back(object); 1206ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, 1207ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SourceLocation(), SourceLocation(), 1208ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek arrayRef ? &S.Context.Idents.get("index") 1209ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek : &S.Context.Idents.get("key"), 1210ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek arrayRef ? S.Context.UnsignedLongTy 1211ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek : S.Context.getObjCIdType(), 1212ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /*TInfo=*/0, 1213ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SC_None, 1214ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek SC_None, 1215ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 0); 1216ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Params.push_back(key); 1217ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>()); 1218ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1219ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1220ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!AtIndexSetter) { 1221ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!receiverIdType) { 1222ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(BaseExpr->getExprLoc(), 1223ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::err_objc_subscript_method_not_found) 1224ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek << BaseExpr->getType() << 1 << arrayRef; 1225ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return false; 1226ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1227ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetter = 1228ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, 1229ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek RefExpr->getSourceRange(), 1230ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek true, false); 1231ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1232ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1233ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool err = false; 1234ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (AtIndexSetter && arrayRef) { 1235ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType T = AtIndexSetter->param_begin()[1]->getType(); 1236ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!T->isIntegralOrEnumerationType()) { 1237ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1238ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::err_objc_subscript_index_type) << T; 1239ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(AtIndexSetter->param_begin()[1]->getLocation(), 1240ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::note_parameter_type) << T; 1241ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek err = true; 1242ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1243ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek T = AtIndexSetter->param_begin()[0]->getType(); 1244ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!T->isObjCObjectPointerType()) { 1245ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 1246ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::err_objc_subscript_object_type) << T << arrayRef; 1247ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(AtIndexSetter->param_begin()[0]->getLocation(), 1248ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::note_parameter_type) << T; 1249ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek err = true; 1250ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1251ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1252ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek else if (AtIndexSetter && !arrayRef) 1253ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek for (unsigned i=0; i <2; i++) { 1254ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType T = AtIndexSetter->param_begin()[i]->getType(); 1255ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!T->isObjCObjectPointerType()) { 1256ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (i == 1) 1257ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1258ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::err_objc_subscript_key_type) << T; 1259ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek else 1260ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 1261ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::err_objc_subscript_dic_object_type) << T; 1262ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek S.Diag(AtIndexSetter->param_begin()[i]->getLocation(), 1263ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek diag::note_parameter_type) << T; 1264ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek err = true; 1265ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1266ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1267ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1268ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return !err; 1269ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 1270ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1271ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// Get the object at "Index" position in the container. 1272ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// [BaseExpr objectAtIndexedSubscript : IndexExpr]; 1273ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildGet() { 1274ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!findAtIndexGetter()) 1275ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return ExprError(); 1276ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1277ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType receiverType = InstanceBase->getType(); 1278ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1279ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Build a message-send. 1280ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult msg; 1281ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *Index = InstanceKey; 1282ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1283ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Arguments. 1284ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *args[] = { Index }; 1285ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek assert(InstanceBase); 1286ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, 1287ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek GenericLoc, 1288ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexGetterSelector, AtIndexGetter, 1289ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek MultiExprArg(args, 1)); 1290ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return msg; 1291ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 1292ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1293ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// Store into the container the "op" object at "Index"'ed location 1294ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// by building this messaging expression: 1295ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 129670517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \param captureSetValueAsResult If true, capture the actual 1297ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// value being set as the value of the property operation. 1298ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 1299ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek bool captureSetValueAsResult) { 1300ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!findAtIndexSetter()) 1301ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return ExprError(); 1302ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1303ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek QualType receiverType = InstanceBase->getType(); 1304ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *Index = InstanceKey; 1305ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1306ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Arguments. 1307ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *args[] = { op, Index }; 1308ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1309ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek // Build a message-send. 1310ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, 1311ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek GenericLoc, 1312ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetterSelector, 1313ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek AtIndexSetter, 1314ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek MultiExprArg(args, 2)); 1315ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1316ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek if (!msg.isInvalid() && captureSetValueAsResult) { 1317ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCMessageExpr *msgExpr = 1318ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 1319ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Expr *arg = msgExpr->getArg(0); 132025f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman if (CanCaptureValueOfType(arg->getType())) 132125f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman msgExpr->setArg(0, captureValueAsResult(arg)); 1322ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1323ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 1324ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return msg; 1325ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek} 1326ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek 13274b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 13284b9c2d235fb9449e249d74f48ecfec601650de93John McCall// General Sema routines. 13294b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===// 13303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 13314b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectRValue(Expr *E) { 13324b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *opaqueRef = E->IgnoreParens(); 13334b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCPropertyRefExpr *refExpr 13344b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 13354b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder builder(*this, refExpr); 13364b9c2d235fb9449e249d74f48ecfec601650de93John McCall return builder.buildRValueOperation(E); 1337ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } 1338ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek else if (ObjCSubscriptRefExpr *refExpr 1339ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1340ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptOpBuilder builder(*this, refExpr); 1341ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return builder.buildRValueOperation(E); 13424b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 13434b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("unknown pseudo-object kind!"); 13443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 13454b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 13463c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 13474b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Check an increment or decrement of a pseudo-object expression. 13484b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, 13494b9c2d235fb9449e249d74f48ecfec601650de93John McCall UnaryOperatorKind opcode, Expr *op) { 13504b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Do nothing if the operand is dependent. 13514b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (op->isTypeDependent()) 13524b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (Context) UnaryOperator(op, opcode, Context.DependentTy, 13534b9c2d235fb9449e249d74f48ecfec601650de93John McCall VK_RValue, OK_Ordinary, opcLoc); 13544b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13554b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(UnaryOperator::isIncrementDecrementOp(opcode)); 13564b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *opaqueRef = op->IgnoreParens(); 13574b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCPropertyRefExpr *refExpr 13584b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 13594b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder builder(*this, refExpr); 13604b9c2d235fb9449e249d74f48ecfec601650de93John McCall return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 1361ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) { 1362ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek Diag(opcLoc, diag::err_illegal_container_subscripting_op); 1363ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return ExprError(); 13644b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 13654b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("unknown pseudo-object kind!"); 13663c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 13674b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 13683c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 13694b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 13704b9c2d235fb9449e249d74f48ecfec601650de93John McCall BinaryOperatorKind opcode, 13714b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *LHS, Expr *RHS) { 13724b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Do nothing if either argument is dependent. 13734b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (LHS->isTypeDependent() || RHS->isTypeDependent()) 13744b9c2d235fb9449e249d74f48ecfec601650de93John McCall return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, 1375be9af1288881110e406b87914162eaa59f1e5918Lang Hames VK_RValue, OK_Ordinary, opcLoc, false); 13764b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13774b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Filter out non-overload placeholder types in the RHS. 137832509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall if (RHS->getType()->isNonOverloadPlaceholderType()) { 137932509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall ExprResult result = CheckPlaceholderExpr(RHS); 138032509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall if (result.isInvalid()) return ExprError(); 138132509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall RHS = result.take(); 13824b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 13833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 13844b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *opaqueRef = LHS->IgnoreParens(); 13854b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ObjCPropertyRefExpr *refExpr 13864b9c2d235fb9449e249d74f48ecfec601650de93John McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 13874b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCPropertyOpBuilder builder(*this, refExpr); 13884b9c2d235fb9449e249d74f48ecfec601650de93John McCall return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 1389ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } else if (ObjCSubscriptRefExpr *refExpr 1390ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1391ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek ObjCSubscriptOpBuilder builder(*this, refExpr); 1392ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 13934b9c2d235fb9449e249d74f48ecfec601650de93John McCall } else { 13944b9c2d235fb9449e249d74f48ecfec601650de93John McCall llvm_unreachable("unknown pseudo-object kind!"); 13954b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 13963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 139701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall 139801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// Given a pseudo-object reference, rebuild it without the opaque 139901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// values. Basically, undo the behavior of rebuildAndCaptureObject. 140001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// This should never operate in-place. 140101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCallstatic Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { 140201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *opaqueRef = E->IgnoreParens(); 140301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall if (ObjCPropertyRefExpr *refExpr 140401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 140588507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor // Class and super property references don't have opaque values in them. 140688507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) 140788507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor return E; 140888507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor 140988507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor assert(refExpr->isObjectReceiver() && "Unknown receiver kind?"); 141088507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); 141188507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); 1412ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek } else if (ObjCSubscriptRefExpr *refExpr 1413ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1414ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); 1415ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr()); 1416ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), 1417ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek keyOVE->getSourceExpr()).rebuild(E); 141801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall } else { 141901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall llvm_unreachable("unknown pseudo-object kind!"); 142001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall } 142101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall} 142201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall 142301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// Given a pseudo-object expression, recreate what it looks like 142401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// syntactically without the attendant OpaqueValueExprs. 142501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// 142601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// This is a hack which should be removed when TreeTransform is 142701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// capable of rebuilding a tree without stripping implicit 142801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// operations. 142901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCallExpr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { 143001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *syntax = E->getSyntacticForm(); 143101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { 143201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); 143301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), 143401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall uop->getValueKind(), uop->getObjectKind(), 143501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall uop->getOperatorLoc()); 143601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall } else if (CompoundAssignOperator *cop 143701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall = dyn_cast<CompoundAssignOperator>(syntax)) { 143801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); 143901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); 144001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), 144101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall cop->getType(), 144201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall cop->getValueKind(), 144301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall cop->getObjectKind(), 144401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall cop->getComputationLHSType(), 144501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall cop->getComputationResultType(), 1446be9af1288881110e406b87914162eaa59f1e5918Lang Hames cop->getOperatorLoc(), false); 144701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { 144801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); 144901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); 145001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), 145101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall bop->getType(), bop->getValueKind(), 145201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall bop->getObjectKind(), 1453be9af1288881110e406b87914162eaa59f1e5918Lang Hames bop->getOperatorLoc(), false); 145401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall } else { 145501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); 145601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); 145701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall } 145801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall} 1459