[PATCH] Sema: Eliminate recursion from checkForFunctionCall()
Vedant Kumar
vsk at apple.com
Thu Jul 23 08:57:33 PDT 2015
Ok! The NFC preparatory patch is in part1, and the behavior-changing work is in part2.
No problems with check-clang.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: checkForFunctionCall-part1.patch
Type: application/octet-stream
Size: 3741 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150723/0a542d98/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: checkForFunctionCall-part2.patch
Type: application/octet-stream
Size: 1890 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150723/0a542d98/attachment-0001.obj>
-------------- next part --------------
> On Jul 22, 2015, at 4:22 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
>
>
>> On 2015-Jul-22, at 14:31, Vedant Kumar <vsk at apple.com> wrote:
>>
>>> This is a fairly large block of code to further indent. Can you
>>> move this to a helper function as a separate, preparatory patch
>>> with no functionality change (NFC) that returns the new value of
>>> `State`?
>>
>> I’ve attached a patch which separates the state update logic in checkForFunctionCall into a helper routine.
>>
>> I’ll send a follow-up patch with the rest of the changes you requested shortly.
>>
>>
>> <checkForFunctionCall-1.patch>
>>
>
>
>> diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
>> index f2ff48a..60bf5a0 100644
>> --- a/lib/Sema/AnalysisBasedWarnings.cpp
>> +++ b/lib/Sema/AnalysisBasedWarnings.cpp
>> @@ -171,21 +171,14 @@ enum RecursiveState {
>> FoundPathWithNoRecursiveCall
>> };
>>
>> -static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
>> - CFGBlock &Block, unsigned ExitID,
>> - llvm::SmallVectorImpl<RecursiveState> &States,
>> - RecursiveState State) {
>> +static RecursiveState updateRecursiveState(const FunctionDecl *FD,
>
> Sounds like it mutates an inout parameter, and the name doesn't describe
> the context. Maybe `computeRecursiveStateForSuccessors()`? That's
> rather long, so feel free to come up with something better.
>
>> + CFGBlock &Block, unsigned ExitID,
>> + RecursiveState State) {
>> unsigned ID = Block.getBlockID();
>>
>> - // A block's state can only move to a higher state.
>> - if (States[ID] >= State)
>> - return;
>> -
>> - States[ID] = State;
>> -
>> // Found a path to the exit node without a recursive call.
>> if (ID == ExitID && State == FoundPathWithNoRecursiveCall)
>> - return;
>> + return State;
>
> I think you need to leave this condition in `checkForFunctionCall()`,
> since otherwise you're losing the early return.
>
> With that out of the function, you don't need `ExitID` here at all.
>
>>
>> if (State == FoundPathWithNoRecursiveCall) {
>
> Can you convert this to an early return?
>
> if (State != FoundPathWithNoRecursiveCall)
> return State;
>
> Alternatively, since this is right at the top of the function, maybe you
> shouldn't call this helper at all if it's not in the right state? Then
> you don't need to pass `State` in at all, just assume that it's
> `FoundPathWithNoRecursiveCall`.
>
>> // If the current state is FoundPathWithNoRecursiveCall, the successors
>> @@ -200,12 +193,12 @@ static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
>> CE->getCalleeDecl()->getCanonicalDecl() == FD) {
>
> Can you reduce nesting here? I'm thinking something like:
>
> - const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
> - if (CE && CE->getCalleeDecl() &&
> - CE->getCalleeDecl()->getCanonicalDecl() == FD) {
> + const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
> + if (!CE || !CE->getCalleeDecl() ||
> + CE->getCalleeDecl()->getCanonicalDecl() != FD)
> + continue;
>
> would clean things up a fair bit.
>
>>
>> // Skip function calls which are qualified with a templated class.
>> - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
>> - CE->getCallee()->IgnoreParenImpCasts())) {
>> + if (const DeclRefExpr *DRE =
>> + dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
>> if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
>> if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
>> isa<TemplateSpecializationType>(NNS->getAsType())) {
>> - continue;
>> + continue;
>> }
>> }
>> }
>
> Please clean up the rest of the new helper function as well. There are
> some `break`s that should just be `return`s, etc.
>
>> @@ -224,6 +217,23 @@ static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
>> }
>> }
>>
>> + return State;
>> +}
>> +
>> +static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
>> + CFGBlock &Block, unsigned ExitID,
>> + llvm::SmallVectorImpl<RecursiveState> &States,
>> + RecursiveState State) {
>> + unsigned ID = Block.getBlockID();
>> +
>> + // A block's state can only move to a higher state.
>> + if (States[ID] >= State)
>> + return;
>> +
>> + States[ID] = State;
>
> (This is where the return for `ID == ExitID` is missing.)
>
>> +
>> + State = updateRecursiveState(FD, Block, ExitID, State);
>> +
>> for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
>> I != E; ++I)
>> if (*I)
>>
>
More information about the cfe-commits
mailing list