clang API Documentation
00001 //===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements semantic analysis for expressions involving 00011 // pseudo-object references. Pseudo-objects are conceptual objects 00012 // whose storage is entirely abstract and all accesses to which are 00013 // translated through some sort of abstraction barrier. 00014 // 00015 // For example, Objective-C objects can have "properties", either 00016 // declared or undeclared. A property may be accessed by writing 00017 // expr.prop 00018 // where 'expr' is an r-value of Objective-C pointer type and 'prop' 00019 // is the name of the property. If this expression is used in a context 00020 // needing an r-value, it is treated as if it were a message-send 00021 // of the associated 'getter' selector, typically: 00022 // [expr prop] 00023 // If it is used as the LHS of a simple assignment, it is treated 00024 // as a message-send of the associated 'setter' selector, typically: 00025 // [expr setProp: RHS] 00026 // If it is used as the LHS of a compound assignment, or the operand 00027 // of a unary increment or decrement, both are required; for example, 00028 // 'expr.prop *= 100' would be translated to: 00029 // [expr setProp: [expr prop] * 100] 00030 // 00031 //===----------------------------------------------------------------------===// 00032 00033 #include "clang/Sema/SemaInternal.h" 00034 #include "clang/AST/ExprCXX.h" 00035 #include "clang/AST/ExprObjC.h" 00036 #include "clang/Basic/CharInfo.h" 00037 #include "clang/Lex/Preprocessor.h" 00038 #include "clang/Sema/Initialization.h" 00039 #include "clang/Sema/ScopeInfo.h" 00040 #include "llvm/ADT/SmallString.h" 00041 00042 using namespace clang; 00043 using namespace sema; 00044 00045 namespace { 00046 // Basically just a very focused copy of TreeTransform. 00047 template <class T> struct Rebuilder { 00048 Sema &S; 00049 Rebuilder(Sema &S) : S(S) {} 00050 00051 T &getDerived() { return static_cast<T&>(*this); } 00052 00053 Expr *rebuild(Expr *e) { 00054 // Fast path: nothing to look through. 00055 if (typename T::specific_type *specific 00056 = dyn_cast<typename T::specific_type>(e)) 00057 return getDerived().rebuildSpecific(specific); 00058 00059 // Otherwise, we should look through and rebuild anything that 00060 // IgnoreParens would. 00061 00062 if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { 00063 e = rebuild(parens->getSubExpr()); 00064 return new (S.Context) ParenExpr(parens->getLParen(), 00065 parens->getRParen(), 00066 e); 00067 } 00068 00069 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { 00070 assert(uop->getOpcode() == UO_Extension); 00071 e = rebuild(uop->getSubExpr()); 00072 return new (S.Context) UnaryOperator(e, uop->getOpcode(), 00073 uop->getType(), 00074 uop->getValueKind(), 00075 uop->getObjectKind(), 00076 uop->getOperatorLoc()); 00077 } 00078 00079 if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 00080 assert(!gse->isResultDependent()); 00081 unsigned resultIndex = gse->getResultIndex(); 00082 unsigned numAssocs = gse->getNumAssocs(); 00083 00084 SmallVector<Expr*, 8> assocs(numAssocs); 00085 SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs); 00086 00087 for (unsigned i = 0; i != numAssocs; ++i) { 00088 Expr *assoc = gse->getAssocExpr(i); 00089 if (i == resultIndex) assoc = rebuild(assoc); 00090 assocs[i] = assoc; 00091 assocTypes[i] = gse->getAssocTypeSourceInfo(i); 00092 } 00093 00094 return new (S.Context) GenericSelectionExpr(S.Context, 00095 gse->getGenericLoc(), 00096 gse->getControllingExpr(), 00097 assocTypes, 00098 assocs, 00099 gse->getDefaultLoc(), 00100 gse->getRParenLoc(), 00101 gse->containsUnexpandedParameterPack(), 00102 resultIndex); 00103 } 00104 00105 if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) { 00106 assert(!ce->isConditionDependent()); 00107 00108 Expr *LHS = ce->getLHS(), *RHS = ce->getRHS(); 00109 Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS; 00110 rebuiltExpr = rebuild(rebuiltExpr); 00111 00112 return new (S.Context) ChooseExpr(ce->getBuiltinLoc(), 00113 ce->getCond(), 00114 LHS, RHS, 00115 rebuiltExpr->getType(), 00116 rebuiltExpr->getValueKind(), 00117 rebuiltExpr->getObjectKind(), 00118 ce->getRParenLoc(), 00119 ce->isConditionTrue(), 00120 rebuiltExpr->isTypeDependent(), 00121 rebuiltExpr->isValueDependent()); 00122 } 00123 00124 llvm_unreachable("bad expression to rebuild!"); 00125 } 00126 }; 00127 00128 struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { 00129 Expr *NewBase; 00130 ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) 00131 : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} 00132 00133 typedef ObjCPropertyRefExpr specific_type; 00134 Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { 00135 // Fortunately, the constraint that we're rebuilding something 00136 // with a base limits the number of cases here. 00137 assert(refExpr->isObjectReceiver()); 00138 00139 if (refExpr->isExplicitProperty()) { 00140 return new (S.Context) 00141 ObjCPropertyRefExpr(refExpr->getExplicitProperty(), 00142 refExpr->getType(), refExpr->getValueKind(), 00143 refExpr->getObjectKind(), refExpr->getLocation(), 00144 NewBase); 00145 } 00146 return new (S.Context) 00147 ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), 00148 refExpr->getImplicitPropertySetter(), 00149 refExpr->getType(), refExpr->getValueKind(), 00150 refExpr->getObjectKind(),refExpr->getLocation(), 00151 NewBase); 00152 } 00153 }; 00154 00155 struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> { 00156 Expr *NewBase; 00157 Expr *NewKeyExpr; 00158 ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) 00159 : Rebuilder<ObjCSubscriptRefRebuilder>(S), 00160 NewBase(newBase), NewKeyExpr(newKeyExpr) {} 00161 00162 typedef ObjCSubscriptRefExpr specific_type; 00163 Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { 00164 assert(refExpr->getBaseExpr()); 00165 assert(refExpr->getKeyExpr()); 00166 00167 return new (S.Context) 00168 ObjCSubscriptRefExpr(NewBase, 00169 NewKeyExpr, 00170 refExpr->getType(), refExpr->getValueKind(), 00171 refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), 00172 refExpr->setAtIndexMethodDecl(), 00173 refExpr->getRBracket()); 00174 } 00175 }; 00176 00177 struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> { 00178 Expr *NewBase; 00179 MSPropertyRefRebuilder(Sema &S, Expr *newBase) 00180 : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {} 00181 00182 typedef MSPropertyRefExpr specific_type; 00183 Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) { 00184 assert(refExpr->getBaseExpr()); 00185 00186 return new (S.Context) 00187 MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(), 00188 refExpr->isArrow(), refExpr->getType(), 00189 refExpr->getValueKind(), refExpr->getQualifierLoc(), 00190 refExpr->getMemberLoc()); 00191 } 00192 }; 00193 00194 class PseudoOpBuilder { 00195 public: 00196 Sema &S; 00197 unsigned ResultIndex; 00198 SourceLocation GenericLoc; 00199 SmallVector<Expr *, 4> Semantics; 00200 00201 PseudoOpBuilder(Sema &S, SourceLocation genericLoc) 00202 : S(S), ResultIndex(PseudoObjectExpr::NoResult), 00203 GenericLoc(genericLoc) {} 00204 00205 virtual ~PseudoOpBuilder() {} 00206 00207 /// Add a normal semantic expression. 00208 void addSemanticExpr(Expr *semantic) { 00209 Semantics.push_back(semantic); 00210 } 00211 00212 /// Add the 'result' semantic expression. 00213 void addResultSemanticExpr(Expr *resultExpr) { 00214 assert(ResultIndex == PseudoObjectExpr::NoResult); 00215 ResultIndex = Semantics.size(); 00216 Semantics.push_back(resultExpr); 00217 } 00218 00219 ExprResult buildRValueOperation(Expr *op); 00220 ExprResult buildAssignmentOperation(Scope *Sc, 00221 SourceLocation opLoc, 00222 BinaryOperatorKind opcode, 00223 Expr *LHS, Expr *RHS); 00224 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 00225 UnaryOperatorKind opcode, 00226 Expr *op); 00227 00228 virtual ExprResult complete(Expr *syntacticForm); 00229 00230 OpaqueValueExpr *capture(Expr *op); 00231 OpaqueValueExpr *captureValueAsResult(Expr *op); 00232 00233 void setResultToLastSemantic() { 00234 assert(ResultIndex == PseudoObjectExpr::NoResult); 00235 ResultIndex = Semantics.size() - 1; 00236 } 00237 00238 /// Return true if assignments have a non-void result. 00239 bool CanCaptureValue(Expr *exp) { 00240 if (exp->isGLValue()) 00241 return true; 00242 QualType ty = exp->getType(); 00243 assert(!ty->isIncompleteType()); 00244 assert(!ty->isDependentType()); 00245 00246 if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl()) 00247 return ClassDecl->isTriviallyCopyable(); 00248 return true; 00249 } 00250 00251 virtual Expr *rebuildAndCaptureObject(Expr *) = 0; 00252 virtual ExprResult buildGet() = 0; 00253 virtual ExprResult buildSet(Expr *, SourceLocation, 00254 bool captureSetValueAsResult) = 0; 00255 }; 00256 00257 /// A PseudoOpBuilder for Objective-C \@properties. 00258 class ObjCPropertyOpBuilder : public PseudoOpBuilder { 00259 ObjCPropertyRefExpr *RefExpr; 00260 ObjCPropertyRefExpr *SyntacticRefExpr; 00261 OpaqueValueExpr *InstanceReceiver; 00262 ObjCMethodDecl *Getter; 00263 00264 ObjCMethodDecl *Setter; 00265 Selector SetterSelector; 00266 Selector GetterSelector; 00267 00268 public: 00269 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : 00270 PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), 00271 SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr), 00272 Setter(nullptr) { 00273 } 00274 00275 ExprResult buildRValueOperation(Expr *op); 00276 ExprResult buildAssignmentOperation(Scope *Sc, 00277 SourceLocation opLoc, 00278 BinaryOperatorKind opcode, 00279 Expr *LHS, Expr *RHS); 00280 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 00281 UnaryOperatorKind opcode, 00282 Expr *op); 00283 00284 bool tryBuildGetOfReference(Expr *op, ExprResult &result); 00285 bool findSetter(bool warn=true); 00286 bool findGetter(); 00287 void DiagnoseUnsupportedPropertyUse(); 00288 00289 Expr *rebuildAndCaptureObject(Expr *syntacticBase) override; 00290 ExprResult buildGet() override; 00291 ExprResult buildSet(Expr *op, SourceLocation, bool) override; 00292 ExprResult complete(Expr *SyntacticForm) override; 00293 00294 bool isWeakProperty() const; 00295 }; 00296 00297 /// A PseudoOpBuilder for Objective-C array/dictionary indexing. 00298 class ObjCSubscriptOpBuilder : public PseudoOpBuilder { 00299 ObjCSubscriptRefExpr *RefExpr; 00300 OpaqueValueExpr *InstanceBase; 00301 OpaqueValueExpr *InstanceKey; 00302 ObjCMethodDecl *AtIndexGetter; 00303 Selector AtIndexGetterSelector; 00304 00305 ObjCMethodDecl *AtIndexSetter; 00306 Selector AtIndexSetterSelector; 00307 00308 public: 00309 ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) : 00310 PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), 00311 RefExpr(refExpr), 00312 InstanceBase(nullptr), InstanceKey(nullptr), 00313 AtIndexGetter(nullptr), AtIndexSetter(nullptr) {} 00314 00315 ExprResult buildRValueOperation(Expr *op); 00316 ExprResult buildAssignmentOperation(Scope *Sc, 00317 SourceLocation opLoc, 00318 BinaryOperatorKind opcode, 00319 Expr *LHS, Expr *RHS); 00320 Expr *rebuildAndCaptureObject(Expr *syntacticBase) override; 00321 00322 bool findAtIndexGetter(); 00323 bool findAtIndexSetter(); 00324 00325 ExprResult buildGet() override; 00326 ExprResult buildSet(Expr *op, SourceLocation, bool) override; 00327 }; 00328 00329 class MSPropertyOpBuilder : public PseudoOpBuilder { 00330 MSPropertyRefExpr *RefExpr; 00331 00332 public: 00333 MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) : 00334 PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), 00335 RefExpr(refExpr) {} 00336 00337 Expr *rebuildAndCaptureObject(Expr *) override; 00338 ExprResult buildGet() override; 00339 ExprResult buildSet(Expr *op, SourceLocation, bool) override; 00340 }; 00341 } 00342 00343 /// Capture the given expression in an OpaqueValueExpr. 00344 OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { 00345 // Make a new OVE whose source is the given expression. 00346 OpaqueValueExpr *captured = 00347 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), 00348 e->getValueKind(), e->getObjectKind(), 00349 e); 00350 00351 // Make sure we bind that in the semantics. 00352 addSemanticExpr(captured); 00353 return captured; 00354 } 00355 00356 /// Capture the given expression as the result of this pseudo-object 00357 /// operation. This routine is safe against expressions which may 00358 /// already be captured. 00359 /// 00360 /// \returns the captured expression, which will be the 00361 /// same as the input if the input was already captured 00362 OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { 00363 assert(ResultIndex == PseudoObjectExpr::NoResult); 00364 00365 // If the expression hasn't already been captured, just capture it 00366 // and set the new semantic 00367 if (!isa<OpaqueValueExpr>(e)) { 00368 OpaqueValueExpr *cap = capture(e); 00369 setResultToLastSemantic(); 00370 return cap; 00371 } 00372 00373 // Otherwise, it must already be one of our semantic expressions; 00374 // set ResultIndex to its index. 00375 unsigned index = 0; 00376 for (;; ++index) { 00377 assert(index < Semantics.size() && 00378 "captured expression not found in semantics!"); 00379 if (e == Semantics[index]) break; 00380 } 00381 ResultIndex = index; 00382 return cast<OpaqueValueExpr>(e); 00383 } 00384 00385 /// The routine which creates the final PseudoObjectExpr. 00386 ExprResult PseudoOpBuilder::complete(Expr *syntactic) { 00387 return PseudoObjectExpr::Create(S.Context, syntactic, 00388 Semantics, ResultIndex); 00389 } 00390 00391 /// The main skeleton for building an r-value operation. 00392 ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { 00393 Expr *syntacticBase = rebuildAndCaptureObject(op); 00394 00395 ExprResult getExpr = buildGet(); 00396 if (getExpr.isInvalid()) return ExprError(); 00397 addResultSemanticExpr(getExpr.get()); 00398 00399 return complete(syntacticBase); 00400 } 00401 00402 /// The basic skeleton for building a simple or compound 00403 /// assignment operation. 00404 ExprResult 00405 PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 00406 BinaryOperatorKind opcode, 00407 Expr *LHS, Expr *RHS) { 00408 assert(BinaryOperator::isAssignmentOp(opcode)); 00409 00410 // Recover from user error 00411 if (isa<UnresolvedLookupExpr>(RHS)) 00412 return ExprError(); 00413 00414 Expr *syntacticLHS = rebuildAndCaptureObject(LHS); 00415 OpaqueValueExpr *capturedRHS = capture(RHS); 00416 00417 Expr *syntactic; 00418 00419 ExprResult result; 00420 if (opcode == BO_Assign) { 00421 result = capturedRHS; 00422 syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, 00423 opcode, capturedRHS->getType(), 00424 capturedRHS->getValueKind(), 00425 OK_Ordinary, opcLoc, false); 00426 } else { 00427 ExprResult opLHS = buildGet(); 00428 if (opLHS.isInvalid()) return ExprError(); 00429 00430 // Build an ordinary, non-compound operation. 00431 BinaryOperatorKind nonCompound = 00432 BinaryOperator::getOpForCompoundAssignment(opcode); 00433 result = S.BuildBinOp(Sc, opcLoc, nonCompound, 00434 opLHS.get(), capturedRHS); 00435 if (result.isInvalid()) return ExprError(); 00436 00437 syntactic = 00438 new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, 00439 result.get()->getType(), 00440 result.get()->getValueKind(), 00441 OK_Ordinary, 00442 opLHS.get()->getType(), 00443 result.get()->getType(), 00444 opcLoc, false); 00445 } 00446 00447 // The result of the assignment, if not void, is the value set into 00448 // the l-value. 00449 result = buildSet(result.get(), opcLoc, /*captureSetValueAsResult*/ true); 00450 if (result.isInvalid()) return ExprError(); 00451 addSemanticExpr(result.get()); 00452 00453 return complete(syntactic); 00454 } 00455 00456 /// The basic skeleton for building an increment or decrement 00457 /// operation. 00458 ExprResult 00459 PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 00460 UnaryOperatorKind opcode, 00461 Expr *op) { 00462 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 00463 00464 Expr *syntacticOp = rebuildAndCaptureObject(op); 00465 00466 // Load the value. 00467 ExprResult result = buildGet(); 00468 if (result.isInvalid()) return ExprError(); 00469 00470 QualType resultType = result.get()->getType(); 00471 00472 // That's the postfix result. 00473 if (UnaryOperator::isPostfix(opcode) && 00474 (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) { 00475 result = capture(result.get()); 00476 setResultToLastSemantic(); 00477 } 00478 00479 // Add or subtract a literal 1. 00480 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); 00481 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, 00482 GenericLoc); 00483 00484 if (UnaryOperator::isIncrementOp(opcode)) { 00485 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one); 00486 } else { 00487 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one); 00488 } 00489 if (result.isInvalid()) return ExprError(); 00490 00491 // Store that back into the result. The value stored is the result 00492 // of a prefix operation. 00493 result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode)); 00494 if (result.isInvalid()) return ExprError(); 00495 addSemanticExpr(result.get()); 00496 00497 UnaryOperator *syntactic = 00498 new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, 00499 VK_LValue, OK_Ordinary, opcLoc); 00500 return complete(syntactic); 00501 } 00502 00503 00504 //===----------------------------------------------------------------------===// 00505 // Objective-C @property and implicit property references 00506 //===----------------------------------------------------------------------===// 00507 00508 /// Look up a method in the receiver type of an Objective-C property 00509 /// reference. 00510 static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 00511 const ObjCPropertyRefExpr *PRE) { 00512 if (PRE->isObjectReceiver()) { 00513 const ObjCObjectPointerType *PT = 00514 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 00515 00516 // Special case for 'self' in class method implementations. 00517 if (PT->isObjCClassType() && 00518 S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) { 00519 // This cast is safe because isSelfExpr is only true within 00520 // methods. 00521 ObjCMethodDecl *method = 00522 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); 00523 return S.LookupMethodInObjectType(sel, 00524 S.Context.getObjCInterfaceType(method->getClassInterface()), 00525 /*instance*/ false); 00526 } 00527 00528 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 00529 } 00530 00531 if (PRE->isSuperReceiver()) { 00532 if (const ObjCObjectPointerType *PT = 00533 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 00534 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 00535 00536 return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); 00537 } 00538 00539 assert(PRE->isClassReceiver() && "Invalid expression"); 00540 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 00541 return S.LookupMethodInObjectType(sel, IT, false); 00542 } 00543 00544 bool ObjCPropertyOpBuilder::isWeakProperty() const { 00545 QualType T; 00546 if (RefExpr->isExplicitProperty()) { 00547 const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty(); 00548 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) 00549 return !Prop->hasAttr<IBOutletAttr>(); 00550 00551 T = Prop->getType(); 00552 } else if (Getter) { 00553 T = Getter->getReturnType(); 00554 } else { 00555 return false; 00556 } 00557 00558 return T.getObjCLifetime() == Qualifiers::OCL_Weak; 00559 } 00560 00561 bool ObjCPropertyOpBuilder::findGetter() { 00562 if (Getter) return true; 00563 00564 // For implicit properties, just trust the lookup we already did. 00565 if (RefExpr->isImplicitProperty()) { 00566 if ((Getter = RefExpr->getImplicitPropertyGetter())) { 00567 GetterSelector = Getter->getSelector(); 00568 return true; 00569 } 00570 else { 00571 // Must build the getter selector the hard way. 00572 ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter(); 00573 assert(setter && "both setter and getter are null - cannot happen"); 00574 IdentifierInfo *setterName = 00575 setter->getSelector().getIdentifierInfoForSlot(0); 00576 IdentifierInfo *getterName = 00577 &S.Context.Idents.get(setterName->getName().substr(3)); 00578 GetterSelector = 00579 S.PP.getSelectorTable().getNullarySelector(getterName); 00580 return false; 00581 } 00582 } 00583 00584 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 00585 Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); 00586 return (Getter != nullptr); 00587 } 00588 00589 /// Try to find the most accurate setter declaration for the property 00590 /// reference. 00591 /// 00592 /// \return true if a setter was found, in which case Setter 00593 bool ObjCPropertyOpBuilder::findSetter(bool warn) { 00594 // For implicit properties, just trust the lookup we already did. 00595 if (RefExpr->isImplicitProperty()) { 00596 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 00597 Setter = setter; 00598 SetterSelector = setter->getSelector(); 00599 return true; 00600 } else { 00601 IdentifierInfo *getterName = 00602 RefExpr->getImplicitPropertyGetter()->getSelector() 00603 .getIdentifierInfoForSlot(0); 00604 SetterSelector = 00605 SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), 00606 S.PP.getSelectorTable(), 00607 getterName); 00608 return false; 00609 } 00610 } 00611 00612 // For explicit properties, this is more involved. 00613 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 00614 SetterSelector = prop->getSetterName(); 00615 00616 // Do a normal method lookup first. 00617 if (ObjCMethodDecl *setter = 00618 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 00619 if (setter->isPropertyAccessor() && warn) 00620 if (const ObjCInterfaceDecl *IFace = 00621 dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { 00622 StringRef thisPropertyName = prop->getName(); 00623 // Try flipping the case of the first character. 00624 char front = thisPropertyName.front(); 00625 front = isLowercase(front) ? toUppercase(front) : toLowercase(front); 00626 SmallString<100> PropertyName = thisPropertyName; 00627 PropertyName[0] = front; 00628 IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); 00629 if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember)) 00630 if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) { 00631 S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use) 00632 << prop << prop1 << setter->getSelector(); 00633 S.Diag(prop->getLocation(), diag::note_property_declare); 00634 S.Diag(prop1->getLocation(), diag::note_property_declare); 00635 } 00636 } 00637 Setter = setter; 00638 return true; 00639 } 00640 00641 // That can fail in the somewhat crazy situation that we're 00642 // type-checking a message send within the @interface declaration 00643 // that declared the @property. But it's not clear that that's 00644 // valuable to support. 00645 00646 return false; 00647 } 00648 00649 void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() { 00650 if (S.getCurLexicalContext()->isObjCContainer() && 00651 S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl && 00652 S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) { 00653 if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) { 00654 S.Diag(RefExpr->getLocation(), 00655 diag::err_property_function_in_objc_container); 00656 S.Diag(prop->getLocation(), diag::note_property_declare); 00657 } 00658 } 00659 } 00660 00661 /// Capture the base object of an Objective-C property expression. 00662 Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 00663 assert(InstanceReceiver == nullptr); 00664 00665 // If we have a base, capture it in an OVE and rebuild the syntactic 00666 // form to use the OVE as its base. 00667 if (RefExpr->isObjectReceiver()) { 00668 InstanceReceiver = capture(RefExpr->getBase()); 00669 00670 syntacticBase = 00671 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); 00672 } 00673 00674 if (ObjCPropertyRefExpr * 00675 refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens())) 00676 SyntacticRefExpr = refE; 00677 00678 return syntacticBase; 00679 } 00680 00681 /// Load from an Objective-C property reference. 00682 ExprResult ObjCPropertyOpBuilder::buildGet() { 00683 findGetter(); 00684 if (!Getter) { 00685 DiagnoseUnsupportedPropertyUse(); 00686 return ExprError(); 00687 } 00688 00689 if (SyntacticRefExpr) 00690 SyntacticRefExpr->setIsMessagingGetter(); 00691 00692 QualType receiverType; 00693 if (RefExpr->isClassReceiver()) { 00694 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 00695 } else if (RefExpr->isSuperReceiver()) { 00696 receiverType = RefExpr->getSuperReceiverType(); 00697 } else { 00698 assert(InstanceReceiver); 00699 receiverType = InstanceReceiver->getType(); 00700 } 00701 if (!Getter->isImplicit()) 00702 S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true); 00703 // Build a message-send. 00704 ExprResult msg; 00705 if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) || 00706 RefExpr->isObjectReceiver()) { 00707 assert(InstanceReceiver || RefExpr->isSuperReceiver()); 00708 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 00709 GenericLoc, Getter->getSelector(), 00710 Getter, None); 00711 } else { 00712 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 00713 GenericLoc, Getter->getSelector(), 00714 Getter, None); 00715 } 00716 return msg; 00717 } 00718 00719 /// Store to an Objective-C property reference. 00720 /// 00721 /// \param captureSetValueAsResult If true, capture the actual 00722 /// value being set as the value of the property operation. 00723 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 00724 bool captureSetValueAsResult) { 00725 if (!findSetter(false)) { 00726 DiagnoseUnsupportedPropertyUse(); 00727 return ExprError(); 00728 } 00729 00730 if (SyntacticRefExpr) 00731 SyntacticRefExpr->setIsMessagingSetter(); 00732 00733 QualType receiverType; 00734 if (RefExpr->isClassReceiver()) { 00735 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 00736 } else if (RefExpr->isSuperReceiver()) { 00737 receiverType = RefExpr->getSuperReceiverType(); 00738 } else { 00739 assert(InstanceReceiver); 00740 receiverType = InstanceReceiver->getType(); 00741 } 00742 00743 // Use assignment constraints when possible; they give us better 00744 // diagnostics. "When possible" basically means anything except a 00745 // C++ class type. 00746 if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { 00747 QualType paramType = (*Setter->param_begin())->getType(); 00748 if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { 00749 ExprResult opResult = op; 00750 Sema::AssignConvertType assignResult 00751 = S.CheckSingleAssignmentConstraints(paramType, opResult); 00752 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 00753 op->getType(), opResult.get(), 00754 Sema::AA_Assigning)) 00755 return ExprError(); 00756 00757 op = opResult.get(); 00758 assert(op && "successful assignment left argument invalid?"); 00759 } 00760 else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) { 00761 Expr *Initializer = OVE->getSourceExpr(); 00762 // passing C++11 style initialized temporaries to objc++ properties 00763 // requires special treatment by removing OpaqueValueExpr so type 00764 // conversion takes place and adding the OpaqueValueExpr later on. 00765 if (isa<InitListExpr>(Initializer) && 00766 Initializer->getType()->isVoidType()) { 00767 op = Initializer; 00768 } 00769 } 00770 } 00771 00772 // Arguments. 00773 Expr *args[] = { op }; 00774 00775 // Build a message-send. 00776 ExprResult msg; 00777 if (!Setter->isImplicit()) 00778 S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true); 00779 if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) || 00780 RefExpr->isObjectReceiver()) { 00781 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 00782 GenericLoc, SetterSelector, Setter, 00783 MultiExprArg(args, 1)); 00784 } else { 00785 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 00786 GenericLoc, 00787 SetterSelector, Setter, 00788 MultiExprArg(args, 1)); 00789 } 00790 00791 if (!msg.isInvalid() && captureSetValueAsResult) { 00792 ObjCMessageExpr *msgExpr = 00793 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 00794 Expr *arg = msgExpr->getArg(0); 00795 if (CanCaptureValue(arg)) 00796 msgExpr->setArg(0, captureValueAsResult(arg)); 00797 } 00798 00799 return msg; 00800 } 00801 00802 /// @property-specific behavior for doing lvalue-to-rvalue conversion. 00803 ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 00804 // Explicit properties always have getters, but implicit ones don't. 00805 // Check that before proceeding. 00806 if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) { 00807 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 00808 << RefExpr->getSourceRange(); 00809 return ExprError(); 00810 } 00811 00812 ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 00813 if (result.isInvalid()) return ExprError(); 00814 00815 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 00816 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 00817 Getter, RefExpr->getLocation()); 00818 00819 // As a special case, if the method returns 'id', try to get 00820 // a better type from the property. 00821 if (RefExpr->isExplicitProperty() && result.get()->isRValue()) { 00822 QualType propType = RefExpr->getExplicitProperty()->getType(); 00823 if (result.get()->getType()->isObjCIdType()) { 00824 if (const ObjCObjectPointerType *ptr 00825 = propType->getAs<ObjCObjectPointerType>()) { 00826 if (!ptr->isObjCIdType()) 00827 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 00828 } 00829 } 00830 if (S.getLangOpts().ObjCAutoRefCount) { 00831 Qualifiers::ObjCLifetime LT = propType.getObjCLifetime(); 00832 if (LT == Qualifiers::OCL_Weak) 00833 if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation())) 00834 S.getCurFunction()->markSafeWeakUse(RefExpr); 00835 } 00836 } 00837 00838 return result; 00839 } 00840 00841 /// Try to build this as a call to a getter that returns a reference. 00842 /// 00843 /// \return true if it was possible, whether or not it actually 00844 /// succeeded 00845 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 00846 ExprResult &result) { 00847 if (!S.getLangOpts().CPlusPlus) return false; 00848 00849 findGetter(); 00850 if (!Getter) { 00851 // The property has no setter and no getter! This can happen if the type is 00852 // invalid. Error have already been reported. 00853 result = ExprError(); 00854 return true; 00855 } 00856 00857 // Only do this if the getter returns an l-value reference type. 00858 QualType resultType = Getter->getReturnType(); 00859 if (!resultType->isLValueReferenceType()) return false; 00860 00861 result = buildRValueOperation(op); 00862 return true; 00863 } 00864 00865 /// @property-specific behavior for doing assignments. 00866 ExprResult 00867 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 00868 SourceLocation opcLoc, 00869 BinaryOperatorKind opcode, 00870 Expr *LHS, Expr *RHS) { 00871 assert(BinaryOperator::isAssignmentOp(opcode)); 00872 00873 // If there's no setter, we have no choice but to try to assign to 00874 // the result of the getter. 00875 if (!findSetter()) { 00876 ExprResult result; 00877 if (tryBuildGetOfReference(LHS, result)) { 00878 if (result.isInvalid()) return ExprError(); 00879 return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS); 00880 } 00881 00882 // Otherwise, it's an error. 00883 S.Diag(opcLoc, diag::err_nosetter_property_assignment) 00884 << unsigned(RefExpr->isImplicitProperty()) 00885 << SetterSelector 00886 << LHS->getSourceRange() << RHS->getSourceRange(); 00887 return ExprError(); 00888 } 00889 00890 // If there is a setter, we definitely want to use it. 00891 00892 // Verify that we can do a compound assignment. 00893 if (opcode != BO_Assign && !findGetter()) { 00894 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 00895 << LHS->getSourceRange() << RHS->getSourceRange(); 00896 return ExprError(); 00897 } 00898 00899 ExprResult result = 00900 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 00901 if (result.isInvalid()) return ExprError(); 00902 00903 // Various warnings about property assignments in ARC. 00904 if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { 00905 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 00906 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 00907 } 00908 00909 return result; 00910 } 00911 00912 /// @property-specific behavior for doing increments and decrements. 00913 ExprResult 00914 ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 00915 UnaryOperatorKind opcode, 00916 Expr *op) { 00917 // If there's no setter, we have no choice but to try to assign to 00918 // the result of the getter. 00919 if (!findSetter()) { 00920 ExprResult result; 00921 if (tryBuildGetOfReference(op, result)) { 00922 if (result.isInvalid()) return ExprError(); 00923 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get()); 00924 } 00925 00926 // Otherwise, it's an error. 00927 S.Diag(opcLoc, diag::err_nosetter_property_incdec) 00928 << unsigned(RefExpr->isImplicitProperty()) 00929 << unsigned(UnaryOperator::isDecrementOp(opcode)) 00930 << SetterSelector 00931 << op->getSourceRange(); 00932 return ExprError(); 00933 } 00934 00935 // If there is a setter, we definitely want to use it. 00936 00937 // We also need a getter. 00938 if (!findGetter()) { 00939 assert(RefExpr->isImplicitProperty()); 00940 S.Diag(opcLoc, diag::err_nogetter_property_incdec) 00941 << unsigned(UnaryOperator::isDecrementOp(opcode)) 00942 << GetterSelector 00943 << op->getSourceRange(); 00944 return ExprError(); 00945 } 00946 00947 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 00948 } 00949 00950 ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { 00951 if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() && 00952 !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, 00953 SyntacticForm->getLocStart())) 00954 S.recordUseOfEvaluatedWeak(SyntacticRefExpr, 00955 SyntacticRefExpr->isMessagingGetter()); 00956 00957 return PseudoOpBuilder::complete(SyntacticForm); 00958 } 00959 00960 // ObjCSubscript build stuff. 00961 // 00962 00963 /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue 00964 /// conversion. 00965 /// FIXME. Remove this routine if it is proven that no additional 00966 /// specifity is needed. 00967 ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { 00968 ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 00969 if (result.isInvalid()) return ExprError(); 00970 return result; 00971 } 00972 00973 /// objective-c subscripting-specific behavior for doing assignments. 00974 ExprResult 00975 ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, 00976 SourceLocation opcLoc, 00977 BinaryOperatorKind opcode, 00978 Expr *LHS, Expr *RHS) { 00979 assert(BinaryOperator::isAssignmentOp(opcode)); 00980 // There must be a method to do the Index'ed assignment. 00981 if (!findAtIndexSetter()) 00982 return ExprError(); 00983 00984 // Verify that we can do a compound assignment. 00985 if (opcode != BO_Assign && !findAtIndexGetter()) 00986 return ExprError(); 00987 00988 ExprResult result = 00989 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 00990 if (result.isInvalid()) return ExprError(); 00991 00992 // Various warnings about objc Index'ed assignments in ARC. 00993 if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { 00994 S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS); 00995 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 00996 } 00997 00998 return result; 00999 } 01000 01001 /// Capture the base object of an Objective-C Index'ed expression. 01002 Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 01003 assert(InstanceBase == nullptr); 01004 01005 // Capture base expression in an OVE and rebuild the syntactic 01006 // form to use the OVE as its base expression. 01007 InstanceBase = capture(RefExpr->getBaseExpr()); 01008 InstanceKey = capture(RefExpr->getKeyExpr()); 01009 01010 syntacticBase = 01011 ObjCSubscriptRefRebuilder(S, InstanceBase, 01012 InstanceKey).rebuild(syntacticBase); 01013 01014 return syntacticBase; 01015 } 01016 01017 /// CheckSubscriptingKind - This routine decide what type 01018 /// of indexing represented by "FromE" is being done. 01019 Sema::ObjCSubscriptKind 01020 Sema::CheckSubscriptingKind(Expr *FromE) { 01021 // If the expression already has integral or enumeration type, we're golden. 01022 QualType T = FromE->getType(); 01023 if (T->isIntegralOrEnumerationType()) 01024 return OS_Array; 01025 01026 // If we don't have a class type in C++, there's no way we can get an 01027 // expression of integral or enumeration type. 01028 const RecordType *RecordTy = T->getAs<RecordType>(); 01029 if (!RecordTy && 01030 (T->isObjCObjectPointerType() || T->isVoidPointerType())) 01031 // All other scalar cases are assumed to be dictionary indexing which 01032 // caller handles, with diagnostics if needed. 01033 return OS_Dictionary; 01034 if (!getLangOpts().CPlusPlus || 01035 !RecordTy || RecordTy->isIncompleteType()) { 01036 // No indexing can be done. Issue diagnostics and quit. 01037 const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); 01038 if (isa<StringLiteral>(IndexExpr)) 01039 Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) 01040 << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); 01041 else 01042 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 01043 << T; 01044 return OS_Error; 01045 } 01046 01047 // We must have a complete class type. 01048 if (RequireCompleteType(FromE->getExprLoc(), T, 01049 diag::err_objc_index_incomplete_class_type, FromE)) 01050 return OS_Error; 01051 01052 // Look for a conversion to an integral, enumeration type, or 01053 // objective-C pointer type. 01054 std::pair<CXXRecordDecl::conversion_iterator, 01055 CXXRecordDecl::conversion_iterator> Conversions 01056 = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); 01057 01058 int NoIntegrals=0, NoObjCIdPointers=0; 01059 SmallVector<CXXConversionDecl *, 4> ConversionDecls; 01060 01061 for (CXXRecordDecl::conversion_iterator 01062 I = Conversions.first, E = Conversions.second; I != E; ++I) { 01063 if (CXXConversionDecl *Conversion 01064 = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { 01065 QualType CT = Conversion->getConversionType().getNonReferenceType(); 01066 if (CT->isIntegralOrEnumerationType()) { 01067 ++NoIntegrals; 01068 ConversionDecls.push_back(Conversion); 01069 } 01070 else if (CT->isObjCIdType() ||CT->isBlockPointerType()) { 01071 ++NoObjCIdPointers; 01072 ConversionDecls.push_back(Conversion); 01073 } 01074 } 01075 } 01076 if (NoIntegrals ==1 && NoObjCIdPointers == 0) 01077 return OS_Array; 01078 if (NoIntegrals == 0 && NoObjCIdPointers == 1) 01079 return OS_Dictionary; 01080 if (NoIntegrals == 0 && NoObjCIdPointers == 0) { 01081 // No conversion function was found. Issue diagnostic and return. 01082 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 01083 << FromE->getType(); 01084 return OS_Error; 01085 } 01086 Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) 01087 << FromE->getType(); 01088 for (unsigned int i = 0; i < ConversionDecls.size(); i++) 01089 Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at); 01090 01091 return OS_Error; 01092 } 01093 01094 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF 01095 /// objects used as dictionary subscript key objects. 01096 static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, 01097 Expr *Key) { 01098 if (ContainerT.isNull()) 01099 return; 01100 // dictionary subscripting. 01101 // - (id)objectForKeyedSubscript:(id)key; 01102 IdentifierInfo *KeyIdents[] = { 01103 &S.Context.Idents.get("objectForKeyedSubscript") 01104 }; 01105 Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 01106 ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT, 01107 true /*instance*/); 01108 if (!Getter) 01109 return; 01110 QualType T = Getter->parameters()[0]->getType(); 01111 S.CheckObjCARCConversion(Key->getSourceRange(), 01112 T, Key, Sema::CCK_ImplicitConversion); 01113 } 01114 01115 bool ObjCSubscriptOpBuilder::findAtIndexGetter() { 01116 if (AtIndexGetter) 01117 return true; 01118 01119 Expr *BaseExpr = RefExpr->getBaseExpr(); 01120 QualType BaseT = BaseExpr->getType(); 01121 01122 QualType ResultType; 01123 if (const ObjCObjectPointerType *PTy = 01124 BaseT->getAs<ObjCObjectPointerType>()) { 01125 ResultType = PTy->getPointeeType(); 01126 if (const ObjCObjectType *iQFaceTy = 01127 ResultType->getAsObjCQualifiedInterfaceType()) 01128 ResultType = iQFaceTy->getBaseType(); 01129 } 01130 Sema::ObjCSubscriptKind Res = 01131 S.CheckSubscriptingKind(RefExpr->getKeyExpr()); 01132 if (Res == Sema::OS_Error) { 01133 if (S.getLangOpts().ObjCAutoRefCount) 01134 CheckKeyForObjCARCConversion(S, ResultType, 01135 RefExpr->getKeyExpr()); 01136 return false; 01137 } 01138 bool arrayRef = (Res == Sema::OS_Array); 01139 01140 if (ResultType.isNull()) { 01141 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 01142 << BaseExpr->getType() << arrayRef; 01143 return false; 01144 } 01145 if (!arrayRef) { 01146 // dictionary subscripting. 01147 // - (id)objectForKeyedSubscript:(id)key; 01148 IdentifierInfo *KeyIdents[] = { 01149 &S.Context.Idents.get("objectForKeyedSubscript") 01150 }; 01151 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 01152 } 01153 else { 01154 // - (id)objectAtIndexedSubscript:(size_t)index; 01155 IdentifierInfo *KeyIdents[] = { 01156 &S.Context.Idents.get("objectAtIndexedSubscript") 01157 }; 01158 01159 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 01160 } 01161 01162 AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, 01163 true /*instance*/); 01164 bool receiverIdType = (BaseT->isObjCIdType() || 01165 BaseT->isObjCQualifiedIdType()); 01166 01167 if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { 01168 AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), 01169 SourceLocation(), AtIndexGetterSelector, 01170 S.Context.getObjCIdType() /*ReturnType*/, 01171 nullptr /*TypeSourceInfo */, 01172 S.Context.getTranslationUnitDecl(), 01173 true /*Instance*/, false/*isVariadic*/, 01174 /*isPropertyAccessor=*/false, 01175 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 01176 ObjCMethodDecl::Required, 01177 false); 01178 ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, 01179 SourceLocation(), SourceLocation(), 01180 arrayRef ? &S.Context.Idents.get("index") 01181 : &S.Context.Idents.get("key"), 01182 arrayRef ? S.Context.UnsignedLongTy 01183 : S.Context.getObjCIdType(), 01184 /*TInfo=*/nullptr, 01185 SC_None, 01186 nullptr); 01187 AtIndexGetter->setMethodParams(S.Context, Argument, None); 01188 } 01189 01190 if (!AtIndexGetter) { 01191 if (!receiverIdType) { 01192 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found) 01193 << BaseExpr->getType() << 0 << arrayRef; 01194 return false; 01195 } 01196 AtIndexGetter = 01197 S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, 01198 RefExpr->getSourceRange(), 01199 true, false); 01200 } 01201 01202 if (AtIndexGetter) { 01203 QualType T = AtIndexGetter->parameters()[0]->getType(); 01204 if ((arrayRef && !T->isIntegralOrEnumerationType()) || 01205 (!arrayRef && !T->isObjCObjectPointerType())) { 01206 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 01207 arrayRef ? diag::err_objc_subscript_index_type 01208 : diag::err_objc_subscript_key_type) << T; 01209 S.Diag(AtIndexGetter->parameters()[0]->getLocation(), 01210 diag::note_parameter_type) << T; 01211 return false; 01212 } 01213 QualType R = AtIndexGetter->getReturnType(); 01214 if (!R->isObjCObjectPointerType()) { 01215 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 01216 diag::err_objc_indexing_method_result_type) << R << arrayRef; 01217 S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) << 01218 AtIndexGetter->getDeclName(); 01219 } 01220 } 01221 return true; 01222 } 01223 01224 bool ObjCSubscriptOpBuilder::findAtIndexSetter() { 01225 if (AtIndexSetter) 01226 return true; 01227 01228 Expr *BaseExpr = RefExpr->getBaseExpr(); 01229 QualType BaseT = BaseExpr->getType(); 01230 01231 QualType ResultType; 01232 if (const ObjCObjectPointerType *PTy = 01233 BaseT->getAs<ObjCObjectPointerType>()) { 01234 ResultType = PTy->getPointeeType(); 01235 if (const ObjCObjectType *iQFaceTy = 01236 ResultType->getAsObjCQualifiedInterfaceType()) 01237 ResultType = iQFaceTy->getBaseType(); 01238 } 01239 01240 Sema::ObjCSubscriptKind Res = 01241 S.CheckSubscriptingKind(RefExpr->getKeyExpr()); 01242 if (Res == Sema::OS_Error) { 01243 if (S.getLangOpts().ObjCAutoRefCount) 01244 CheckKeyForObjCARCConversion(S, ResultType, 01245 RefExpr->getKeyExpr()); 01246 return false; 01247 } 01248 bool arrayRef = (Res == Sema::OS_Array); 01249 01250 if (ResultType.isNull()) { 01251 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 01252 << BaseExpr->getType() << arrayRef; 01253 return false; 01254 } 01255 01256 if (!arrayRef) { 01257 // dictionary subscripting. 01258 // - (void)setObject:(id)object forKeyedSubscript:(id)key; 01259 IdentifierInfo *KeyIdents[] = { 01260 &S.Context.Idents.get("setObject"), 01261 &S.Context.Idents.get("forKeyedSubscript") 01262 }; 01263 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 01264 } 01265 else { 01266 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 01267 IdentifierInfo *KeyIdents[] = { 01268 &S.Context.Idents.get("setObject"), 01269 &S.Context.Idents.get("atIndexedSubscript") 01270 }; 01271 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 01272 } 01273 AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, 01274 true /*instance*/); 01275 01276 bool receiverIdType = (BaseT->isObjCIdType() || 01277 BaseT->isObjCQualifiedIdType()); 01278 01279 if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { 01280 TypeSourceInfo *ReturnTInfo = nullptr; 01281 QualType ReturnType = S.Context.VoidTy; 01282 AtIndexSetter = ObjCMethodDecl::Create( 01283 S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector, 01284 ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(), 01285 true /*Instance*/, false /*isVariadic*/, 01286 /*isPropertyAccessor=*/false, 01287 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 01288 ObjCMethodDecl::Required, false); 01289 SmallVector<ParmVarDecl *, 2> Params; 01290 ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter, 01291 SourceLocation(), SourceLocation(), 01292 &S.Context.Idents.get("object"), 01293 S.Context.getObjCIdType(), 01294 /*TInfo=*/nullptr, 01295 SC_None, 01296 nullptr); 01297 Params.push_back(object); 01298 ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, 01299 SourceLocation(), SourceLocation(), 01300 arrayRef ? &S.Context.Idents.get("index") 01301 : &S.Context.Idents.get("key"), 01302 arrayRef ? S.Context.UnsignedLongTy 01303 : S.Context.getObjCIdType(), 01304 /*TInfo=*/nullptr, 01305 SC_None, 01306 nullptr); 01307 Params.push_back(key); 01308 AtIndexSetter->setMethodParams(S.Context, Params, None); 01309 } 01310 01311 if (!AtIndexSetter) { 01312 if (!receiverIdType) { 01313 S.Diag(BaseExpr->getExprLoc(), 01314 diag::err_objc_subscript_method_not_found) 01315 << BaseExpr->getType() << 1 << arrayRef; 01316 return false; 01317 } 01318 AtIndexSetter = 01319 S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, 01320 RefExpr->getSourceRange(), 01321 true, false); 01322 } 01323 01324 bool err = false; 01325 if (AtIndexSetter && arrayRef) { 01326 QualType T = AtIndexSetter->parameters()[1]->getType(); 01327 if (!T->isIntegralOrEnumerationType()) { 01328 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 01329 diag::err_objc_subscript_index_type) << T; 01330 S.Diag(AtIndexSetter->parameters()[1]->getLocation(), 01331 diag::note_parameter_type) << T; 01332 err = true; 01333 } 01334 T = AtIndexSetter->parameters()[0]->getType(); 01335 if (!T->isObjCObjectPointerType()) { 01336 S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 01337 diag::err_objc_subscript_object_type) << T << arrayRef; 01338 S.Diag(AtIndexSetter->parameters()[0]->getLocation(), 01339 diag::note_parameter_type) << T; 01340 err = true; 01341 } 01342 } 01343 else if (AtIndexSetter && !arrayRef) 01344 for (unsigned i=0; i <2; i++) { 01345 QualType T = AtIndexSetter->parameters()[i]->getType(); 01346 if (!T->isObjCObjectPointerType()) { 01347 if (i == 1) 01348 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 01349 diag::err_objc_subscript_key_type) << T; 01350 else 01351 S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 01352 diag::err_objc_subscript_dic_object_type) << T; 01353 S.Diag(AtIndexSetter->parameters()[i]->getLocation(), 01354 diag::note_parameter_type) << T; 01355 err = true; 01356 } 01357 } 01358 01359 return !err; 01360 } 01361 01362 // Get the object at "Index" position in the container. 01363 // [BaseExpr objectAtIndexedSubscript : IndexExpr]; 01364 ExprResult ObjCSubscriptOpBuilder::buildGet() { 01365 if (!findAtIndexGetter()) 01366 return ExprError(); 01367 01368 QualType receiverType = InstanceBase->getType(); 01369 01370 // Build a message-send. 01371 ExprResult msg; 01372 Expr *Index = InstanceKey; 01373 01374 // Arguments. 01375 Expr *args[] = { Index }; 01376 assert(InstanceBase); 01377 if (AtIndexGetter) 01378 S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc); 01379 msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, 01380 GenericLoc, 01381 AtIndexGetterSelector, AtIndexGetter, 01382 MultiExprArg(args, 1)); 01383 return msg; 01384 } 01385 01386 /// Store into the container the "op" object at "Index"'ed location 01387 /// by building this messaging expression: 01388 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 01389 /// \param captureSetValueAsResult If true, capture the actual 01390 /// value being set as the value of the property operation. 01391 ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 01392 bool captureSetValueAsResult) { 01393 if (!findAtIndexSetter()) 01394 return ExprError(); 01395 if (AtIndexSetter) 01396 S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc); 01397 QualType receiverType = InstanceBase->getType(); 01398 Expr *Index = InstanceKey; 01399 01400 // Arguments. 01401 Expr *args[] = { op, Index }; 01402 01403 // Build a message-send. 01404 ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, 01405 GenericLoc, 01406 AtIndexSetterSelector, 01407 AtIndexSetter, 01408 MultiExprArg(args, 2)); 01409 01410 if (!msg.isInvalid() && captureSetValueAsResult) { 01411 ObjCMessageExpr *msgExpr = 01412 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 01413 Expr *arg = msgExpr->getArg(0); 01414 if (CanCaptureValue(arg)) 01415 msgExpr->setArg(0, captureValueAsResult(arg)); 01416 } 01417 01418 return msg; 01419 } 01420 01421 //===----------------------------------------------------------------------===// 01422 // MSVC __declspec(property) references 01423 //===----------------------------------------------------------------------===// 01424 01425 Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 01426 Expr *NewBase = capture(RefExpr->getBaseExpr()); 01427 01428 syntacticBase = 01429 MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase); 01430 01431 return syntacticBase; 01432 } 01433 01434 ExprResult MSPropertyOpBuilder::buildGet() { 01435 if (!RefExpr->getPropertyDecl()->hasGetter()) { 01436 S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property) 01437 << 0 /* getter */ << RefExpr->getPropertyDecl(); 01438 return ExprError(); 01439 } 01440 01441 UnqualifiedId GetterName; 01442 IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId(); 01443 GetterName.setIdentifier(II, RefExpr->getMemberLoc()); 01444 CXXScopeSpec SS; 01445 SS.Adopt(RefExpr->getQualifierLoc()); 01446 ExprResult GetterExpr = S.ActOnMemberAccessExpr( 01447 S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), 01448 RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), 01449 GetterName, nullptr, true); 01450 if (GetterExpr.isInvalid()) { 01451 S.Diag(RefExpr->getMemberLoc(), 01452 diag::error_cannot_find_suitable_accessor) << 0 /* getter */ 01453 << RefExpr->getPropertyDecl(); 01454 return ExprError(); 01455 } 01456 01457 MultiExprArg ArgExprs; 01458 return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(), 01459 RefExpr->getSourceRange().getBegin(), ArgExprs, 01460 RefExpr->getSourceRange().getEnd()); 01461 } 01462 01463 ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, 01464 bool captureSetValueAsResult) { 01465 if (!RefExpr->getPropertyDecl()->hasSetter()) { 01466 S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property) 01467 << 1 /* setter */ << RefExpr->getPropertyDecl(); 01468 return ExprError(); 01469 } 01470 01471 UnqualifiedId SetterName; 01472 IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId(); 01473 SetterName.setIdentifier(II, RefExpr->getMemberLoc()); 01474 CXXScopeSpec SS; 01475 SS.Adopt(RefExpr->getQualifierLoc()); 01476 ExprResult SetterExpr = S.ActOnMemberAccessExpr( 01477 S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), 01478 RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), 01479 SetterName, nullptr, true); 01480 if (SetterExpr.isInvalid()) { 01481 S.Diag(RefExpr->getMemberLoc(), 01482 diag::error_cannot_find_suitable_accessor) << 1 /* setter */ 01483 << RefExpr->getPropertyDecl(); 01484 return ExprError(); 01485 } 01486 01487 SmallVector<Expr*, 1> ArgExprs; 01488 ArgExprs.push_back(op); 01489 return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(), 01490 RefExpr->getSourceRange().getBegin(), ArgExprs, 01491 op->getSourceRange().getEnd()); 01492 } 01493 01494 //===----------------------------------------------------------------------===// 01495 // General Sema routines. 01496 //===----------------------------------------------------------------------===// 01497 01498 ExprResult Sema::checkPseudoObjectRValue(Expr *E) { 01499 Expr *opaqueRef = E->IgnoreParens(); 01500 if (ObjCPropertyRefExpr *refExpr 01501 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 01502 ObjCPropertyOpBuilder builder(*this, refExpr); 01503 return builder.buildRValueOperation(E); 01504 } 01505 else if (ObjCSubscriptRefExpr *refExpr 01506 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 01507 ObjCSubscriptOpBuilder builder(*this, refExpr); 01508 return builder.buildRValueOperation(E); 01509 } else if (MSPropertyRefExpr *refExpr 01510 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 01511 MSPropertyOpBuilder builder(*this, refExpr); 01512 return builder.buildRValueOperation(E); 01513 } else { 01514 llvm_unreachable("unknown pseudo-object kind!"); 01515 } 01516 } 01517 01518 /// Check an increment or decrement of a pseudo-object expression. 01519 ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, 01520 UnaryOperatorKind opcode, Expr *op) { 01521 // Do nothing if the operand is dependent. 01522 if (op->isTypeDependent()) 01523 return new (Context) UnaryOperator(op, opcode, Context.DependentTy, 01524 VK_RValue, OK_Ordinary, opcLoc); 01525 01526 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 01527 Expr *opaqueRef = op->IgnoreParens(); 01528 if (ObjCPropertyRefExpr *refExpr 01529 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 01530 ObjCPropertyOpBuilder builder(*this, refExpr); 01531 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 01532 } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) { 01533 Diag(opcLoc, diag::err_illegal_container_subscripting_op); 01534 return ExprError(); 01535 } else if (MSPropertyRefExpr *refExpr 01536 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 01537 MSPropertyOpBuilder builder(*this, refExpr); 01538 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 01539 } else { 01540 llvm_unreachable("unknown pseudo-object kind!"); 01541 } 01542 } 01543 01544 ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 01545 BinaryOperatorKind opcode, 01546 Expr *LHS, Expr *RHS) { 01547 // Do nothing if either argument is dependent. 01548 if (LHS->isTypeDependent() || RHS->isTypeDependent()) 01549 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, 01550 VK_RValue, OK_Ordinary, opcLoc, false); 01551 01552 // Filter out non-overload placeholder types in the RHS. 01553 if (RHS->getType()->isNonOverloadPlaceholderType()) { 01554 ExprResult result = CheckPlaceholderExpr(RHS); 01555 if (result.isInvalid()) return ExprError(); 01556 RHS = result.get(); 01557 } 01558 01559 Expr *opaqueRef = LHS->IgnoreParens(); 01560 if (ObjCPropertyRefExpr *refExpr 01561 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 01562 ObjCPropertyOpBuilder builder(*this, refExpr); 01563 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 01564 } else if (ObjCSubscriptRefExpr *refExpr 01565 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 01566 ObjCSubscriptOpBuilder builder(*this, refExpr); 01567 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 01568 } else if (MSPropertyRefExpr *refExpr 01569 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 01570 MSPropertyOpBuilder builder(*this, refExpr); 01571 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 01572 } else { 01573 llvm_unreachable("unknown pseudo-object kind!"); 01574 } 01575 } 01576 01577 /// Given a pseudo-object reference, rebuild it without the opaque 01578 /// values. Basically, undo the behavior of rebuildAndCaptureObject. 01579 /// This should never operate in-place. 01580 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { 01581 Expr *opaqueRef = E->IgnoreParens(); 01582 if (ObjCPropertyRefExpr *refExpr 01583 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 01584 // Class and super property references don't have opaque values in them. 01585 if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) 01586 return E; 01587 01588 assert(refExpr->isObjectReceiver() && "Unknown receiver kind?"); 01589 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); 01590 return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); 01591 } else if (ObjCSubscriptRefExpr *refExpr 01592 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 01593 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); 01594 OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr()); 01595 return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), 01596 keyOVE->getSourceExpr()).rebuild(E); 01597 } else if (MSPropertyRefExpr *refExpr 01598 = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { 01599 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); 01600 return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); 01601 } else { 01602 llvm_unreachable("unknown pseudo-object kind!"); 01603 } 01604 } 01605 01606 /// Given a pseudo-object expression, recreate what it looks like 01607 /// syntactically without the attendant OpaqueValueExprs. 01608 /// 01609 /// This is a hack which should be removed when TreeTransform is 01610 /// capable of rebuilding a tree without stripping implicit 01611 /// operations. 01612 Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { 01613 Expr *syntax = E->getSyntacticForm(); 01614 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { 01615 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); 01616 return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), 01617 uop->getValueKind(), uop->getObjectKind(), 01618 uop->getOperatorLoc()); 01619 } else if (CompoundAssignOperator *cop 01620 = dyn_cast<CompoundAssignOperator>(syntax)) { 01621 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); 01622 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); 01623 return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), 01624 cop->getType(), 01625 cop->getValueKind(), 01626 cop->getObjectKind(), 01627 cop->getComputationLHSType(), 01628 cop->getComputationResultType(), 01629 cop->getOperatorLoc(), false); 01630 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { 01631 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); 01632 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); 01633 return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), 01634 bop->getType(), bop->getValueKind(), 01635 bop->getObjectKind(), 01636 bop->getOperatorLoc(), false); 01637 } else { 01638 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); 01639 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); 01640 } 01641 }