150 const Expr *E,
bool StopAtFirstRefCountedObj,
bool FollowLifetimeBound,
158 bool OriginDependsOnFullExpressionTemporary,
159 bool PtrIsLifetimeBoundToOrigin) {
161 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
162 if (
auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl())) {
163 auto QT = VD->getType();
165 if (VD->hasGlobalStorage() && (IsImmortal || QT.isConstQualified()))
166 return callback(E,
true,
167 OriginDependsOnFullExpressionTemporary,
168 PtrIsLifetimeBoundToOrigin);
169 if (VD->hasGlobalStorage() && isSafeGlobalDecl(VD))
170 return callback(E,
true,
171 OriginDependsOnFullExpressionTemporary,
172 PtrIsLifetimeBoundToOrigin);
174 if (FollowLifetimeBound && VD->isImplicit() && VD->isLocalVarDecl()) {
175 if (
auto *
Init = VD->getInit()) {
182 if (
auto *Cleanups = dyn_cast<ExprWithCleanups>(E)) {
183 E = Cleanups->getSubExpr();
186 if (
auto *tempExpr = dyn_cast<MaterializeTemporaryExpr>(E)) {
188 OriginDependsOnFullExpressionTemporary =
true;
189 E = tempExpr->getSubExpr();
192 if (
auto *tempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) {
193 E = tempExpr->getSubExpr();
196 if (
auto *tempExpr = dyn_cast<CXXConstructExpr>(E)) {
197 if (
auto *
C = tempExpr->getConstructor()) {
199 return callback(E,
true,
200 OriginDependsOnFullExpressionTemporary,
201 PtrIsLifetimeBoundToOrigin);
203 if (FollowLifetimeBound) {
205 findLifetimeBoundArgs(tempExpr, LifetimeBoundArgs);
206 if (!LifetimeBoundArgs.empty())
207 return tryToFindPtrOriginOfEach(
208 LifetimeBoundArgs, StopAtFirstRefCountedObj,
isSafePtr,
209 isSafePtrType, isSafeGlobalDecl, callback,
216 if (
auto *TempExpr = dyn_cast<CXXUnresolvedConstructExpr>(E)) {
217 if (isSafePtrType(TempExpr->getTypeAsWritten()))
218 return callback(TempExpr,
true,
219 OriginDependsOnFullExpressionTemporary,
220 PtrIsLifetimeBoundToOrigin);
222 if (
auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
223 if (
auto *RF = POE->getResultExpr()) {
228 if (
auto *tempExpr = dyn_cast<ParenExpr>(E)) {
229 E = tempExpr->getSubExpr();
232 if (
auto *OpaqueValue = dyn_cast<OpaqueValueExpr>(E)) {
233 E = OpaqueValue->getSourceExpr();
236 if (
auto *
Expr = dyn_cast<ConditionalOperator>(E)) {
238 StopAtFirstRefCountedObj,
240 isSafePtrType, isSafeGlobalDecl, callback,
241 OriginDependsOnFullExpressionTemporary,
242 PtrIsLifetimeBoundToOrigin) &&
244 StopAtFirstRefCountedObj,
246 isSafePtrType, isSafeGlobalDecl, callback,
247 OriginDependsOnFullExpressionTemporary,
248 PtrIsLifetimeBoundToOrigin);
250 if (
auto *
cast = dyn_cast<CastExpr>(E)) {
251 if (StopAtFirstRefCountedObj) {
252 if (
auto *ConversionFunc =
253 dyn_cast_or_null<FunctionDecl>(
cast->getConversionFunction())) {
255 return callback(E,
true,
256 OriginDependsOnFullExpressionTemporary,
257 PtrIsLifetimeBoundToOrigin);
260 return callback(E,
true,
261 OriginDependsOnFullExpressionTemporary,
262 PtrIsLifetimeBoundToOrigin);
266 E =
cast->getSubExpr();
269 if (
auto *call = dyn_cast<CallExpr>(E)) {
270 if (
auto *Callee = call->getCalleeDecl()) {
271 if (Callee->hasAttr<CFReturnsRetainedAttr>() ||
272 Callee->hasAttr<NSReturnsRetainedAttr>() ||
273 Callee->hasAttr<NSReturnsAutoreleasedAttr>()) {
274 return callback(E,
true,
275 OriginDependsOnFullExpressionTemporary,
276 PtrIsLifetimeBoundToOrigin);
280 if (isSafePtrType(call->getType()))
281 return callback(E,
true,
282 OriginDependsOnFullExpressionTemporary,
283 PtrIsLifetimeBoundToOrigin);
285 if (
auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) {
286 if (
auto *
decl = memberCall->getMethodDecl()) {
288 if (IsGetterOfRefCt && *IsGetterOfRefCt) {
289 E = memberCall->getImplicitObjectArgument();
290 if (StopAtFirstRefCountedObj) {
291 return callback(E,
true,
292 OriginDependsOnFullExpressionTemporary,
293 PtrIsLifetimeBoundToOrigin);
298 E = memberCall->getImplicitObjectArgument();
304 if (
auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(E)) {
305 if (
auto *Callee = operatorCall->getDirectCallee()) {
309 ClsName ==
"UniqueRef" || ClsName ==
"WeakPtr" ||
310 ClsName ==
"WeakRef") {
311 if (operatorCall->getNumArgs() == 1) {
312 E = operatorCall->getArg(0);
319 if (
auto *callee = call->getDirectCallee()) {
321 if (StopAtFirstRefCountedObj)
322 return callback(E,
true,
323 OriginDependsOnFullExpressionTemporary,
324 PtrIsLifetimeBoundToOrigin);
335 if (isSafePtrType(callee->getReturnType()))
336 return callback(E,
true,
337 OriginDependsOnFullExpressionTemporary,
338 PtrIsLifetimeBoundToOrigin);
341 return callback(E,
true,
342 OriginDependsOnFullExpressionTemporary,
343 PtrIsLifetimeBoundToOrigin);
345 if (callee->isInStdNamespace() &&
safeGetName(callee) ==
"forward") {
356 if (Name ==
"__builtin___CFStringMakeConstantString" ||
357 Name ==
"NSStringFromSelector" || Name ==
"NSSelectorFromString" ||
358 Name ==
"NSStringFromClass" || Name ==
"NSClassFromString" ||
359 Name ==
"NSStringFromProtocol" || Name ==
"NSProtocolFromString")
360 return callback(E,
true,
361 OriginDependsOnFullExpressionTemporary,
362 PtrIsLifetimeBoundToOrigin);
363 }
else if (
auto *CalleeE = call->getCallee()) {
364 if (
auto *E = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
366 return callback(E,
true,
367 OriginDependsOnFullExpressionTemporary,
368 PtrIsLifetimeBoundToOrigin);
371 if (
auto *
MemberExpr = dyn_cast<CXXDependentScopeMemberExpr>(CalleeE)) {
373 auto MemberName =
MemberExpr->getMember().getAsString();
374 bool IsGetter = MemberName ==
"get" || MemberName ==
"ptr";
375 if (
Base && isSafePtrType(
Base->getType()) && IsGetter)
376 return callback(E,
true,
377 OriginDependsOnFullExpressionTemporary,
378 PtrIsLifetimeBoundToOrigin);
385 if (
auto *CalleeDecl = call->getCalleeDecl()) {
386 if (
auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
387 auto RetType = FD->getReturnType();
388 if (
auto *Subst = dyn_cast<SubstTemplateTypeParmType>(RetType)) {
389 if (
auto *SubstType = Subst->desugar().getTypePtr()) {
390 if (
auto *RD = dyn_cast<RecordType>(SubstType)) {
391 if (
auto *
CXX = dyn_cast<CXXRecordDecl>(RD->getDecl()))
393 return callback(E,
true,
394 OriginDependsOnFullExpressionTemporary,
395 PtrIsLifetimeBoundToOrigin);
402 if (FollowLifetimeBound) {
404 findLifetimeBoundArgs(call, LifetimeBoundArgs);
405 if (!LifetimeBoundArgs.empty())
406 return tryToFindPtrOriginOfEach(
407 LifetimeBoundArgs, StopAtFirstRefCountedObj,
isSafePtr,
408 isSafePtrType, isSafeGlobalDecl, callback,
413 if (
auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
414 if (
auto *
Method = ObjCMsgExpr->getMethodDecl()) {
415 if (isSafePtrType(
Method->getReturnType()))
416 return callback(E,
true,
417 OriginDependsOnFullExpressionTemporary,
418 PtrIsLifetimeBoundToOrigin);
420 auto Selector = ObjCMsgExpr->getSelector();
422 if ((NameForFirstSlot ==
"class" || NameForFirstSlot ==
"superclass") &&
424 return callback(E,
true,
425 OriginDependsOnFullExpressionTemporary,
426 PtrIsLifetimeBoundToOrigin);
428 if (
auto *ObjCProtocol = dyn_cast<ObjCProtocolExpr>(E))
429 return callback(ObjCProtocol,
true,
430 OriginDependsOnFullExpressionTemporary,
431 PtrIsLifetimeBoundToOrigin);
432 if (
auto *ObjCDict = dyn_cast<ObjCDictionaryLiteral>(E))
433 return callback(ObjCDict,
true,
434 OriginDependsOnFullExpressionTemporary,
435 PtrIsLifetimeBoundToOrigin);
436 if (
auto *ObjCArray = dyn_cast<ObjCArrayLiteral>(E))
437 return callback(ObjCArray,
true,
438 OriginDependsOnFullExpressionTemporary,
439 PtrIsLifetimeBoundToOrigin);
440 if (
auto *ObjCStr = dyn_cast<ObjCStringLiteral>(E))
441 return callback(ObjCStr,
true,
442 OriginDependsOnFullExpressionTemporary,
443 PtrIsLifetimeBoundToOrigin);
444 if (
auto *unaryOp = dyn_cast<UnaryOperator>(E)) {
446 E = unaryOp->getSubExpr();
449 if (
auto *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
450 if (StopAtFirstRefCountedObj)
451 return callback(BoxedExpr,
true,
452 OriginDependsOnFullExpressionTemporary,
453 PtrIsLifetimeBoundToOrigin);
454 E = BoxedExpr->getSubExpr();
460 return callback(E,
false, OriginDependsOnFullExpressionTemporary,
461 PtrIsLifetimeBoundToOrigin);