diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 2 |
4 files changed, 78 insertions, 15 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index adfa690a64..6a422242a9 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" #include "clang/AST/DeclObjC.h" @@ -26,6 +27,8 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Analyses/UninitializedValuesV2.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/Casting.h" @@ -478,6 +481,16 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) { Diagnostic::Ignored); } +static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + S.Diag(D.Loc, D.PD); + } +} + void clang::sema:: AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, sema::FunctionScopeInfo *fscope, @@ -491,9 +504,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // time. Diagnostic &Diags = S.getDiagnostics(); - if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) - return; - // Do not do any analysis for declarations in system headers if we are // going to just ignore them. if (Diags.getSuppressSystemWarnings() && @@ -504,6 +514,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (cast<DeclContext>(D)->isDependentContext()) return; + if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { + // Flush out any possibly unreachable diagnostics. + flushDiagnostics(S, fscope); + return; + } + const Stmt *Body = D->getBody(); assert(Body); @@ -512,6 +528,34 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false, /*addImplicitDtors=*/true, /*addInitializers=*/true); + // Emit delayed diagnostics. + if (!fscope->PossiblyUnreachableDiags.empty()) { + bool analyzed = false; + if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) + if (CFGStmtMap *csm = AC.getCFGStmtMap()) { + analyzed = true; + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + if (const CFGBlock *blk = csm->getBlock(D.stmt)) { + // Can this block be reached from the entrance? + if (cra->isReachable(&AC.getCFG()->getEntry(), blk)) + S.Diag(D.Loc, D.PD); + } + else { + // Emit the warning anyway if we cannot map to a basic block. + S.Diag(D.Loc, D.PD); + } + } + } + + if (!analyzed) + flushDiagnostics(S, fscope); + } + + // Warning: check missing 'return' if (P.enableCheckFallThrough) { const CheckFallThroughDiagnostics &CD = diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 0827597abd..0c39e13253 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -48,6 +48,7 @@ void FunctionScopeInfo::Clear() { SwitchStack.clear(); Returns.clear(); ErrorTrap.reset(); + PossiblyUnreachableDiags.clear(); } BlockScopeInfo::~BlockScopeInfo() { } @@ -639,9 +640,19 @@ void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP, // Issue any analysis-based warnings. if (WP && D) AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr); + else { + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = Scope->PossiblyUnreachableDiags.begin(), + e = Scope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + Diag(D.Loc, D.PD); + } + } - if (FunctionScopes.back() != Scope) + if (FunctionScopes.back() != Scope) { delete Scope; + } } /// \brief Determine whether any errors occurred within this function/method/ diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ac747910dc..9e2b21aca2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -387,13 +387,13 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, return false; if (Expr->getType()->isObjCObjectType() && - DiagRuntimeBehavior(Expr->getLocStart(), Expr, + DiagRuntimeBehavior(Expr->getLocStart(), 0, PDiag(diag::err_cannot_pass_objc_interface_to_vararg) << Expr->getType() << CT)) return true; if (!Expr->getType()->isPODType() && - DiagRuntimeBehavior(Expr->getLocStart(), Expr, + DiagRuntimeBehavior(Expr->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) << Expr->getType() << CT)) return true; @@ -6721,7 +6721,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) { if (DRL->getDecl() == DRR->getDecl() && !IsWithinTemplateSpecialization(DRL->getDecl())) { - DiagRuntimeBehavior(Loc, lex, PDiag(diag::warn_comparison_always) + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) << 0 // self- << (Opc == BO_EQ || Opc == BO_LE @@ -6743,7 +6743,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, always_evals_to = 2; // e.g. array1 <= array2 break; } - DiagRuntimeBehavior(Loc, lex, PDiag(diag::warn_comparison_always) + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) << 1 // array << always_evals_to); } @@ -6784,7 +6784,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, default: assert(false && "Invalid comparison operator"); } - DiagRuntimeBehavior(Loc, literalString, + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_stringcompare) << isa<ObjCEncodeExpr>(literalStringStripped) << literalString->getSourceRange()); @@ -7094,7 +7094,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens())) if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens())) if (DRL->getDecl() == DRR->getDecl()) - DiagRuntimeBehavior(Loc, rex, + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) << 0 // self- << 2 // "a constant" @@ -7355,9 +7355,11 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, UO->getSubExpr()->IgnoreParenCasts()-> isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && !UO->getType().isVolatileQualified()) { - Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null) - << UO->getSubExpr()->getSourceRange(); - Diag(UO->getOperatorLoc(), diag::note_indirection_through_null); + DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + PDiag(diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange()); + DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + PDiag(diag::note_indirection_through_null)); } // Check for trivial buffer overflows. @@ -9475,7 +9477,13 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt, case PotentiallyEvaluated: case PotentiallyEvaluatedIfUsed: - Diag(Loc, PD); + if (stmt && getCurFunctionOrMethodDecl()) { + FunctionScopes.back()->PossiblyUnreachableDiags. + push_back(sema::PossiblyUnreachableDiag(PD, Loc, stmt)); + } + else + Diag(Loc, PD); + return true; case PotentiallyPotentiallyEvaluated: diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 94ba93d5c2..0abd79a696 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -146,7 +146,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { } } - DiagRuntimeBehavior(Loc, S, PDiag(DiagID) << R1 << R2); + DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); } StmtResult |