-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[alpha.webkit.UncountedLocalVarsChecker] Allow uncounted object references within trivial statements #82229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[alpha.webkit.UncountedLocalVarsChecker] Allow uncounted object references within trivial statements #82229
Changes from all commits
234e301
7140c62
7b54a40
285f64e
3a3448f
8d722ac
1a0f6a0
5d0fe1f
710ec2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,28 +26,6 @@ using namespace ento; | |
|
||
namespace { | ||
|
||
// for ( int a = ...) ... true | ||
// for ( int a : ...) ... true | ||
// if ( int* a = ) ... true | ||
// anything else ... false | ||
bool isDeclaredInForOrIf(const VarDecl *Var) { | ||
assert(Var); | ||
auto &ASTCtx = Var->getASTContext(); | ||
auto parent = ASTCtx.getParents(*Var); | ||
|
||
if (parent.size() == 1) { | ||
if (auto *DS = parent.begin()->get<DeclStmt>()) { | ||
DynTypedNodeList grandParent = ASTCtx.getParents(*DS); | ||
if (grandParent.size() == 1) { | ||
return grandParent.begin()->get<ForStmt>() || | ||
grandParent.begin()->get<IfStmt>() || | ||
grandParent.begin()->get<CXXForRangeStmt>(); | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
// FIXME: should be defined by anotations in the future | ||
bool isRefcountedStringsHack(const VarDecl *V) { | ||
assert(V); | ||
|
@@ -143,6 +121,11 @@ class UncountedLocalVarsChecker | |
// want to visit those, so we make our own RecursiveASTVisitor. | ||
struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> { | ||
const UncountedLocalVarsChecker *Checker; | ||
|
||
TrivialFunctionAnalysis TFA; | ||
|
||
using Base = RecursiveASTVisitor<LocalVisitor>; | ||
|
||
explicit LocalVisitor(const UncountedLocalVarsChecker *Checker) | ||
: Checker(Checker) { | ||
assert(Checker); | ||
|
@@ -155,6 +138,36 @@ class UncountedLocalVarsChecker | |
Checker->visitVarDecl(V); | ||
return true; | ||
} | ||
|
||
bool TraverseIfStmt(IfStmt *IS) { | ||
if (!TFA.isTrivial(IS)) | ||
return Base::TraverseIfStmt(IS); | ||
return true; | ||
} | ||
|
||
bool TraverseForStmt(ForStmt *FS) { | ||
if (!TFA.isTrivial(FS)) | ||
return Base::TraverseForStmt(FS); | ||
return true; | ||
} | ||
|
||
bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) { | ||
if (!TFA.isTrivial(FRS)) | ||
return Base::TraverseCXXForRangeStmt(FRS); | ||
return true; | ||
} | ||
|
||
bool TraverseWhileStmt(WhileStmt *WS) { | ||
if (!TFA.isTrivial(WS)) | ||
return Base::TraverseWhileStmt(WS); | ||
return true; | ||
} | ||
|
||
bool TraverseCompoundStmt(CompoundStmt *CS) { | ||
if (!TFA.isTrivial(CS)) | ||
return Base::TraverseCompoundStmt(CS); | ||
return true; | ||
} | ||
}; | ||
|
||
LocalVisitor visitor(this); | ||
|
@@ -189,18 +202,16 @@ class UncountedLocalVarsChecker | |
dyn_cast_or_null<VarDecl>(Ref->getFoundDecl())) { | ||
const auto *MaybeGuardianArgType = | ||
MaybeGuardian->getType().getTypePtr(); | ||
if (!MaybeGuardianArgType) | ||
return; | ||
const CXXRecordDecl *const MaybeGuardianArgCXXRecord = | ||
MaybeGuardianArgType->getAsCXXRecordDecl(); | ||
if (!MaybeGuardianArgCXXRecord) | ||
return; | ||
|
||
if (MaybeGuardian->isLocalVarDecl() && | ||
(isRefCounted(MaybeGuardianArgCXXRecord) || | ||
isRefcountedStringsHack(MaybeGuardian)) && | ||
isGuardedScopeEmbeddedInGuardianScope(V, MaybeGuardian)) { | ||
return; | ||
if (MaybeGuardianArgType) { | ||
const CXXRecordDecl *const MaybeGuardianArgCXXRecord = | ||
MaybeGuardianArgType->getAsCXXRecordDecl(); | ||
if (MaybeGuardianArgCXXRecord) { | ||
if (MaybeGuardian->isLocalVarDecl() && | ||
(isRefCounted(MaybeGuardianArgCXXRecord) || | ||
isRefcountedStringsHack(MaybeGuardian)) && | ||
isGuardedScopeEmbeddedInGuardianScope(V, MaybeGuardian)) | ||
return; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nothing really changed here right? Also coding guidelines actually prefer early returns (https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So before this PR, those early exits took place when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Specifically, without this change, we'd get the following error:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh right ok! |
||
} | ||
|
||
// Parameters are guaranteed to be safe for the duration of the call | ||
|
@@ -219,9 +230,6 @@ class UncountedLocalVarsChecker | |
if (!V->isLocalVarDecl()) | ||
return true; | ||
|
||
if (isDeclaredInForOrIf(V)) | ||
return true; | ||
|
||
return false; | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.