const LocationContext *LCtx = C.getLocationContext();
- // Process OSDynamicCast: should just return the first argument.
- // For now, tresting the cast as a no-op, and disregarding the case where
- // the output becomes null due to the type mismatch.
- if (FD->getNameAsString() == "safeMetaCast") {
- state = state->BindExpr(CE, LCtx,
- state->getSVal(CE->getArg(0), LCtx));
- C.addTransition(state);
- return true;
- }
-
// See if it's one of the specific functions we know how to eval.
if (!SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation))
return false;
// Bind the return value.
- SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
- if (RetVal.isUnknown() ||
- (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
+ // For now, all the functions which we can evaluate and which take
+ // at least one argument are identities.
+ if (CE->getNumArgs() >= 1) {
+ SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
+
// If the receiver is unknown or the function has
// 'rc_ownership_trusted_implementation' annotate attribute, conjure a
// return value.
- SValBuilder &SVB = C.getSValBuilder();
- RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
+ if (RetVal.isUnknown() ||
+ (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
+ SValBuilder &SVB = C.getSValBuilder();
+ RetVal =
+ SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
+ }
+ state = state->BindExpr(CE, LCtx, RetVal, false);
}
- state = state->BindExpr(CE, LCtx, RetVal, false);
C.addTransition(state);
return true;
return getPersistentStopSummary();
}
- // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
- // function's type.
- const FunctionType *FT = FD->getType()->getAs<FunctionType>();
const IdentifierInfo *II = FD->getIdentifier();
if (!II)
return getDefaultSummary();
// down below.
FName = FName.substr(FName.find_first_not_of('_'));
- // Inspect the result type.
+ // Inspect the result type. Strip away any typedefs.
+ const auto *FT = FD->getType()->getAs<FunctionType>();
QualType RetTy = FT->getReturnType();
std::string RetTyName = RetTy.getAsString();
bool RetainSummaryManager::canEval(const CallExpr *CE,
const FunctionDecl *FD,
bool &hasTrustedImplementationAnnotation) {
- // For now, we're only handling the functions that return aliases of their
- // arguments: CFRetain (and its families).
- // Eventually we should add other functions we can model entirely,
- // such as CFRelease, which don't invalidate their arguments or globals.
- if (CE->getNumArgs() != 1)
- return false;
IdentifierInfo *II = FD->getIdentifier();
if (!II)
return isRetain(FD, FName) || isAutorelease(FD, FName) ||
isMakeCollectable(FName);
+ // Process OSDynamicCast: should just return the first argument.
+ // For now, treating the cast as a no-op, and disregarding the case where
+ // the output becomes null due to the type mismatch.
+ if (TrackOSObjects && FName == "safeMetaCast") {
+ return true;
+ }
+
const FunctionDecl* FDD = FD->getDefinition();
if (FDD && isTrustedReferenceCountImplementation(FDD)) {
hasTrustedImplementationAnnotation = true;
}
}
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *Parent = MD->getParent();
+ if (TrackOSObjects && Parent && isOSObjectSubclass(Parent))
+ return FName == "release" || FName == "retain";
+ }
+
return false;
}