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 return callback(E,
true,
175 OriginDependsOnFullExpressionTemporary,
176 PtrIsLifetimeBoundToOrigin);
178 if (FollowLifetimeBound && VD->isImplicit() && VD->isLocalVarDecl()) {
179 if (
auto *
Init = VD->getInit()) {
186 if (
auto *Cleanups = dyn_cast<ExprWithCleanups>(E)) {
187 E = Cleanups->getSubExpr();
190 if (
auto *tempExpr = dyn_cast<MaterializeTemporaryExpr>(E)) {
192 OriginDependsOnFullExpressionTemporary =
true;
193 E = tempExpr->getSubExpr();
196 if (
auto *tempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) {
197 E = tempExpr->getSubExpr();
200 if (
auto *tempExpr = dyn_cast<CXXConstructExpr>(E)) {
201 if (
auto *
C = tempExpr->getConstructor()) {
203 return callback(E,
true,
204 OriginDependsOnFullExpressionTemporary,
205 PtrIsLifetimeBoundToOrigin);
207 if (FollowLifetimeBound) {
209 findLifetimeBoundArgs(tempExpr, LifetimeBoundArgs);
210 if (!LifetimeBoundArgs.empty())
211 return tryToFindPtrOriginOfEach(
212 LifetimeBoundArgs, StopAtFirstRefCountedObj,
isSafePtr,
213 isSafePtrType, isSafeGlobalDecl, callback,
220 if (
auto *TempExpr = dyn_cast<CXXUnresolvedConstructExpr>(E)) {
221 if (isSafePtrType(TempExpr->getTypeAsWritten()))
222 return callback(TempExpr,
true,
223 OriginDependsOnFullExpressionTemporary,
224 PtrIsLifetimeBoundToOrigin);
226 if (
auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
227 if (
auto *RF = POE->getResultExpr()) {
232 if (
auto *tempExpr = dyn_cast<ParenExpr>(E)) {
233 E = tempExpr->getSubExpr();
236 if (
auto *OpaqueValue = dyn_cast<OpaqueValueExpr>(E)) {
237 E = OpaqueValue->getSourceExpr();
240 if (
auto *
Expr = dyn_cast<ConditionalOperator>(E)) {
242 StopAtFirstRefCountedObj,
244 isSafePtrType, isSafeGlobalDecl, callback,
245 OriginDependsOnFullExpressionTemporary,
246 PtrIsLifetimeBoundToOrigin) &&
248 StopAtFirstRefCountedObj,
250 isSafePtrType, isSafeGlobalDecl, callback,
251 OriginDependsOnFullExpressionTemporary,
252 PtrIsLifetimeBoundToOrigin);
254 if (
auto *
cast = dyn_cast<CastExpr>(E)) {
255 if (StopAtFirstRefCountedObj) {
256 if (
auto *ConversionFunc =
257 dyn_cast_or_null<FunctionDecl>(
cast->getConversionFunction())) {
259 return callback(E,
true,
260 OriginDependsOnFullExpressionTemporary,
261 PtrIsLifetimeBoundToOrigin);
264 return callback(E,
true,
265 OriginDependsOnFullExpressionTemporary,
266 PtrIsLifetimeBoundToOrigin);
270 E =
cast->getSubExpr();
273 if (
auto *call = dyn_cast<CallExpr>(E)) {
274 if (
auto *Callee = call->getCalleeDecl()) {
275 if (Callee->hasAttr<CFReturnsRetainedAttr>() ||
276 Callee->hasAttr<NSReturnsRetainedAttr>() ||
277 Callee->hasAttr<NSReturnsAutoreleasedAttr>()) {
278 return callback(E,
true,
279 OriginDependsOnFullExpressionTemporary,
280 PtrIsLifetimeBoundToOrigin);
284 if (call->isPRValue() && isSafePtrType(call->getType()))
285 return callback(E,
true,
286 OriginDependsOnFullExpressionTemporary,
287 PtrIsLifetimeBoundToOrigin);
289 if (
auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) {
290 if (
auto *
decl = memberCall->getMethodDecl()) {
292 if (IsGetterOfRefCt && *IsGetterOfRefCt) {
293 E = memberCall->getImplicitObjectArgument();
294 if (StopAtFirstRefCountedObj) {
295 return callback(E,
true,
296 OriginDependsOnFullExpressionTemporary,
297 PtrIsLifetimeBoundToOrigin);
302 E = memberCall->getImplicitObjectArgument();
306 E = memberCall->getImplicitObjectArgument();
312 if (
auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(E)) {
313 if (
auto *Callee = operatorCall->getDirectCallee()) {
317 ClsName ==
"UniqueRef" || ClsName ==
"WeakPtr" ||
318 ClsName ==
"WeakRef") {
319 if (operatorCall->getNumArgs() == 1) {
320 E = operatorCall->getArg(0);
324 auto *
Method = dyn_cast<CXXMethodDecl>(Callee);
326 operatorCall->getNumArgs() == 1) {
327 E = operatorCall->getArg(0);
333 if (
auto *callee = call->getDirectCallee()) {
335 if (StopAtFirstRefCountedObj)
336 return callback(E,
true,
337 OriginDependsOnFullExpressionTemporary,
338 PtrIsLifetimeBoundToOrigin);
349 if (isSafePtrType(callee->getReturnType()))
350 return callback(E,
true,
351 OriginDependsOnFullExpressionTemporary,
352 PtrIsLifetimeBoundToOrigin);
355 return callback(E,
true,
356 OriginDependsOnFullExpressionTemporary,
357 PtrIsLifetimeBoundToOrigin);
359 if (callee->isInStdNamespace() &&
safeGetName(callee) ==
"forward") {
370 if (Name ==
"__builtin___CFStringMakeConstantString" ||
371 Name ==
"NSStringFromSelector" || Name ==
"NSSelectorFromString" ||
372 Name ==
"NSStringFromClass" || Name ==
"NSClassFromString" ||
373 Name ==
"NSStringFromProtocol" || Name ==
"NSProtocolFromString")
374 return callback(E,
true,
375 OriginDependsOnFullExpressionTemporary,
376 PtrIsLifetimeBoundToOrigin);
377 }
else if (
auto *CalleeE = call->getCallee()) {
378 if (
auto *E = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
380 return callback(E,
true,
381 OriginDependsOnFullExpressionTemporary,
382 PtrIsLifetimeBoundToOrigin);
385 if (
auto *
MemberExpr = dyn_cast<CXXDependentScopeMemberExpr>(CalleeE)) {
387 auto MemberName =
MemberExpr->getMember().getAsString();
388 bool IsGetter = MemberName ==
"get" || MemberName ==
"ptr";
389 if (
Base && isSafePtrType(
Base->getType()) && IsGetter)
390 return callback(E,
true,
391 OriginDependsOnFullExpressionTemporary,
392 PtrIsLifetimeBoundToOrigin);
399 if (
auto *CalleeDecl = call->getCalleeDecl()) {
400 if (
auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
401 auto RetType = FD->getReturnType();
402 if (
auto *Subst = dyn_cast<SubstTemplateTypeParmType>(RetType)) {
403 if (
auto *SubstType = Subst->desugar().getTypePtr()) {
404 if (
auto *RD = dyn_cast<RecordType>(SubstType)) {
405 if (
auto *
CXX = dyn_cast<CXXRecordDecl>(RD->getDecl()))
407 return callback(E,
true,
408 OriginDependsOnFullExpressionTemporary,
409 PtrIsLifetimeBoundToOrigin);
416 if (FollowLifetimeBound) {
418 findLifetimeBoundArgs(call, LifetimeBoundArgs);
419 if (!LifetimeBoundArgs.empty())
420 return tryToFindPtrOriginOfEach(
421 LifetimeBoundArgs, StopAtFirstRefCountedObj,
isSafePtr,
422 isSafePtrType, isSafeGlobalDecl, callback,
427 if (
auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
428 if (
auto *
Method = ObjCMsgExpr->getMethodDecl()) {
429 if (isSafePtrType(
Method->getReturnType()))
430 return callback(E,
true,
431 OriginDependsOnFullExpressionTemporary,
432 PtrIsLifetimeBoundToOrigin);
434 auto Selector = ObjCMsgExpr->getSelector();
436 if ((NameForFirstSlot ==
"class" || NameForFirstSlot ==
"superclass") &&
438 return callback(E,
true,
439 OriginDependsOnFullExpressionTemporary,
440 PtrIsLifetimeBoundToOrigin);
442 if (
auto *ObjCProtocol = dyn_cast<ObjCProtocolExpr>(E))
443 return callback(ObjCProtocol,
true,
444 OriginDependsOnFullExpressionTemporary,
445 PtrIsLifetimeBoundToOrigin);
446 if (
auto *ObjCDict = dyn_cast<ObjCDictionaryLiteral>(E))
447 return callback(ObjCDict,
true,
448 OriginDependsOnFullExpressionTemporary,
449 PtrIsLifetimeBoundToOrigin);
450 if (
auto *ObjCArray = dyn_cast<ObjCArrayLiteral>(E))
451 return callback(ObjCArray,
true,
452 OriginDependsOnFullExpressionTemporary,
453 PtrIsLifetimeBoundToOrigin);
454 if (
auto *ObjCStr = dyn_cast<ObjCStringLiteral>(E))
455 return callback(ObjCStr,
true,
456 OriginDependsOnFullExpressionTemporary,
457 PtrIsLifetimeBoundToOrigin);
458 if (
auto *unaryOp = dyn_cast<UnaryOperator>(E)) {
460 E = unaryOp->getSubExpr();
463 if (
auto *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
464 if (StopAtFirstRefCountedObj)
465 return callback(BoxedExpr,
true,
466 OriginDependsOnFullExpressionTemporary,
467 PtrIsLifetimeBoundToOrigin);
468 E = BoxedExpr->getSubExpr();
474 return callback(E,
false, OriginDependsOnFullExpressionTemporary,
475 PtrIsLifetimeBoundToOrigin);