if (!FD)
return false;
- IdentifierInfo *II = FD->getIdentifier();
- if (!II)
- return false;
-
- // 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;
-
- // Get the name of the function.
- StringRef FName = II->getName();
- FName = FName.substr(FName.find_first_not_of('_'));
+ RetainSummaryManager &SmrMgr = getSummaryManager(C);
+ QualType ResultTy = CE->getCallReturnType(C.getASTContext());
- // See if it's one of the specific functions we know how to eval.
- bool canEval = false;
// See if the function has 'rc_ownership_trusted_implementation'
// annotate attribute. If it does, we will not inline it.
bool hasTrustedImplementationAnnotation = false;
- QualType ResultTy = CE->getCallReturnType(C.getASTContext());
- if (ResultTy->isPointerType()) {
- // Handle: (CF|CG|CV)Retain
- // CFAutorelease
- // It's okay to be a little sloppy here.
- if (cocoa::isRefType(ResultTy, "CF", FName) ||
- cocoa::isRefType(ResultTy, "CG", FName) ||
- cocoa::isRefType(ResultTy, "CV", FName)) {
- canEval = RetainSummary::isRetain(FD, FName) ||
- RetainSummary::isAutorelease(FD, FName);
- } else {
- if (FD->getDefinition()) {
- canEval = RetainSummary::isTrustedReferenceCountImplementation(
- FD->getDefinition());
- hasTrustedImplementationAnnotation = canEval;
- }
- }
- }
+ // See if it's one of the specific functions we know how to eval.
+ bool canEval = SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
if (!canEval)
return false;
if (!Ctx.inTopFrame())
return;
+ RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
const LocationContext *LCtx = Ctx.getLocationContext();
const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
- if (!FD || RetainSummary::isTrustedReferenceCountImplementation(FD))
+ if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
return;
ProgramStateRef state = Ctx.getState();
-
- const RetainSummary *FunctionSummary =
- getSummaryManager(Ctx).getFunctionSummary(FD);
+ const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
return Summ;
}
+static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
+ for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
+ if (Ann->getAnnotation() == rcAnnotation)
+ return true;
+ }
+ return false;
+}
+
+static bool isRetain(const FunctionDecl *FD, StringRef FName) {
+ return FName.startswith_lower("retain") || FName.endswith_lower("retain");
+}
+
+static bool isRelease(const FunctionDecl *FD, StringRef FName) {
+ return FName.startswith_lower("release") || FName.endswith_lower("release");
+}
+
+static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
+ return FName.startswith_lower("autorelease") ||
+ FName.endswith_lower("autorelease");
+}
+
const RetainSummary *
RetainSummaryManager::generateSummary(const FunctionDecl *FD,
bool &AllowAnnotations) {
if (RetTy->isPointerType()) {
// For CoreFoundation ('CF') types.
if (cocoa::isRefType(RetTy, "CF", FName)) {
- if (RetainSummary::isRetain(FD, FName)) {
+ if (isRetain(FD, FName)) {
// CFRetain isn't supposed to be annotated. However, this may as well
// be a user-made "safe" CFRetain function that is incorrectly
// annotated as cf_returns_retained due to lack of better options.
AllowAnnotations = false;
return getUnarySummary(FT, cfretain);
- } else if (RetainSummary::isAutorelease(FD, FName)) {
+ } else if (isAutorelease(FD, FName)) {
// The headers use cf_consumed, but we can fully model CFAutorelease
// ourselves.
AllowAnnotations = false;
// For CoreGraphics ('CG') and CoreVideo ('CV') types.
if (cocoa::isRefType(RetTy, "CG", FName) ||
cocoa::isRefType(RetTy, "CV", FName)) {
- if (RetainSummary::isRetain(FD, FName))
+ if (isRetain(FD, FName))
return getUnarySummary(FT, cfretain);
else
return getCFCreateGetRuleSummary(FD);
// Test for 'CGCF'.
FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
- if (RetainSummary::isRelease(FD, FName))
+ if (isRelease(FD, FName))
return getUnarySummary(FT, cfrelease);
else {
assert(ScratchArgs.isEmpty());
return getCFSummaryGetRule(FD);
}
+bool RetainSummaryManager::isTrustedReferenceCountImplementation(
+ const FunctionDecl *FD) {
+ return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
+}
+
+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 false;
+
+ StringRef FName = II->getName();
+ FName = FName.substr(FName.find_first_not_of('_'));
+
+ QualType ResultTy = CE->getCallReturnType(Ctx);
+ if (ResultTy->isPointerType()) {
+ // Handle: (CF|CG|CV)Retain
+ // CFAutorelease
+ // It's okay to be a little sloppy here.
+ if (cocoa::isRefType(ResultTy, "CF", FName) ||
+ cocoa::isRefType(ResultTy, "CG", FName) ||
+ cocoa::isRefType(ResultTy, "CV", FName))
+ return isRetain(FD, FName) || isAutorelease(FD, FName);
+
+ if (FD->getDefinition()) {
+ bool out = isTrustedReferenceCountImplementation(FD->getDefinition());
+ hasTrustedImplementationAnnotation = out;
+ return out;
+ }
+ }
+
+ return false;
+
+}
+
const RetainSummary *
RetainSummaryManager::getUnarySummary(const FunctionType* FT,
UnaryFuncKind func) {
if (D->hasAttr<CFReturnsRetainedAttr>())
return RetEffect::MakeOwned(RetEffect::CF);
- else if (RetainSummary::hasRCAnnotation(D, "rc_ownership_returns_retained"))
+ else if (hasRCAnnotation(D, "rc_ownership_returns_retained"))
return RetEffect::MakeOwned(RetEffect::Generalized);
if (D->hasAttr<CFReturnsNotRetainedAttr>())
if (pd->hasAttr<NSConsumedAttr>())
Template->addArg(AF, parm_idx, DecRefMsg);
else if (pd->hasAttr<CFConsumedAttr>() ||
- RetainSummary::hasRCAnnotation(pd, "rc_ownership_consumed"))
+ hasRCAnnotation(pd, "rc_ownership_consumed"))
Template->addArg(AF, parm_idx, DecRef);
else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
- RetainSummary::hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
+ hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull())
if (coreFoundation::isCFObjectRef(PointeeTy))
return Args.isEmpty();
}
-
- static bool isRetain(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("retain") || FName.endswith_lower("retain");
- }
-
- static bool isRelease(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("release") || FName.endswith_lower("release");
- }
-
- static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("autorelease") ||
- FName.endswith_lower("autorelease");
- }
-
- static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
- for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
- if (Ann->getAnnotation() == rcAnnotation)
- return true;
- }
- return false;
- }
-
- static bool isTrustedReferenceCountImplementation(const FunctionDecl *FD) {
- return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
- }
-
private:
ArgEffects getArgEffects() const { return Args; }
ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
void InitializeClassMethodSummaries();
void InitializeMethodSummaries();
-private:
+
void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
ObjCClassMethodSummaries[S] = Summ;
}
InitializeMethodSummaries();
}
+ bool canEval(const CallExpr *CE,
+ const FunctionDecl *FD,
+ bool &hasTrustedImplementationAnnotation);
+
+ bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
+
const RetainSummary *getSummary(const CallEvent &Call,
ProgramStateRef State = nullptr);