diff options
Diffstat (limited to 'clang/lib/Sema/AnalysisBasedWarnings.cpp')
| -rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 105 |
1 files changed, 66 insertions, 39 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 140b709..41a9832 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2734,6 +2734,70 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { S.Diag(D.Loc, D.PD); } +template <typename Iterator> +static void emitPossiblyUnreachableDiags(Sema &S, AnalysisDeclContext &AC, + std::pair<Iterator, Iterator> PUDs) { + + if (PUDs.first == PUDs.second) + return; + + for (auto I = PUDs.first; I != PUDs.second; ++I) { + for (const Stmt *S : I->Stmts) + AC.registerForcedBlockExpression(S); + } + + if (AC.getCFG()) { + CFGReverseBlockReachabilityAnalysis *Analysis = + AC.getCFGReachablityAnalysis(); + + for (auto I = PUDs.first; I != PUDs.second; ++I) { + const auto &D = *I; + if (llvm::all_of(D.Stmts, [&](const Stmt *St) { + const CFGBlock *Block = AC.getBlockForRegisteredExpression(St); + // FIXME: We should be able to assert that block is non-null, but + // the CFG analysis can skip potentially-evaluated expressions in + // edge cases; see test/Sema/vla-2.c. + if (Block && Analysis) + if (!Analysis->isReachable(&AC.getCFG()->getEntry(), Block)) + return false; + return true; + })) { + S.Diag(D.Loc, D.PD); + } + } + } else { + for (auto I = PUDs.first; I != PUDs.second; ++I) + S.Diag(I->Loc, I->PD); + } +} + +void sema::AnalysisBasedWarnings::registerVarDeclWarning( + VarDecl *VD, clang::sema::PossiblyUnreachableDiag PUD) { + VarDeclPossiblyUnreachableDiags.emplace(VD, PUD); +} + +void sema::AnalysisBasedWarnings::issueWarningsForRegisteredVarDecl( + VarDecl *VD) { + if (!llvm::is_contained(VarDeclPossiblyUnreachableDiags, VD)) + return; + + AnalysisDeclContext AC(/*Mgr=*/nullptr, VD); + + AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; + AC.getCFGBuildOptions().AddEHEdges = false; + AC.getCFGBuildOptions().AddInitializers = true; + AC.getCFGBuildOptions().AddImplicitDtors = true; + AC.getCFGBuildOptions().AddTemporaryDtors = true; + AC.getCFGBuildOptions().AddCXXNewAllocator = false; + AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true; + + auto Range = VarDeclPossiblyUnreachableDiags.equal_range(VD); + auto SecondRange = + llvm::make_second_range(llvm::make_range(Range.first, Range.second)); + emitPossiblyUnreachableDiags( + S, AC, std::make_pair(SecondRange.begin(), SecondRange.end())); +} + // An AST Visitor that calls a callback function on each callable DEFINITION // that is NOT in a dependent context: class CallableVisitor : public DynamicRecursiveASTVisitor { @@ -2945,45 +3009,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( } // Emit delayed diagnostics. - if (!fscope->PossiblyUnreachableDiags.empty()) { - bool analyzed = false; - - // Register the expressions with the CFGBuilder. - for (const auto &D : fscope->PossiblyUnreachableDiags) { - for (const Stmt *S : D.Stmts) - AC.registerForcedBlockExpression(S); - } - - if (AC.getCFG()) { - analyzed = true; - for (const auto &D : fscope->PossiblyUnreachableDiags) { - bool AllReachable = true; - for (const Stmt *S : D.Stmts) { - const CFGBlock *block = AC.getBlockForRegisteredExpression(S); - CFGReverseBlockReachabilityAnalysis *cra = - AC.getCFGReachablityAnalysis(); - // FIXME: We should be able to assert that block is non-null, but - // the CFG analysis can skip potentially-evaluated expressions in - // edge cases; see test/Sema/vla-2.c. - if (block && cra) { - // Can this block be reached from the entrance? - if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) { - AllReachable = false; - break; - } - } - // If we cannot map to a basic block, assume the statement is - // reachable. - } - - if (AllReachable) - S.Diag(D.Loc, D.PD); - } - } - - if (!analyzed) - flushDiagnostics(S, fscope); - } + auto &PUDs = fscope->PossiblyUnreachableDiags; + emitPossiblyUnreachableDiags(S, AC, std::make_pair(PUDs.begin(), PUDs.end())); // Warning: check missing 'return' if (P.enableCheckFallThrough) { |
