aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/AnalysisBasedWarnings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp95
1 files changed, 52 insertions, 43 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index c818d40c77..6c95b60003 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1,9 +1,8 @@
//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -250,6 +249,10 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
CFG *cfg = AC.getCFG();
if (!cfg) return;
+ // If the exit block is unreachable, skip processing the function.
+ if (cfg->getExit().pred_empty())
+ return;
+
// Emit diagnostic if a recursive function call is detected for all paths.
if (checkForRecursiveFunctionCall(FD, cfg))
S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function);
@@ -995,7 +998,8 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
S.Diag(BE->getBeginLoc(),
diag::warn_uninit_byref_blockvar_captured_by_block)
- << VD->getDeclName();
+ << VD->getDeclName()
+ << VD->getType().getQualifiers().hasObjCLifetime();
else
DiagUninitUse(S, VD, Use, true);
}
@@ -1639,15 +1643,11 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
return ONS;
}
- // Helper functions
- void warnLockMismatch(unsigned DiagID, StringRef Kind, Name LockName,
- SourceLocation Loc) {
- // Gracefully handle rare cases when the analysis can't get a more
- // precise source location.
- if (!Loc.isValid())
- Loc = FunLocation;
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName);
- Warnings.emplace_back(std::move(Warning), getNotes());
+ OptionalNotes makeLockedHereNote(SourceLocation LocLocked, StringRef Kind) {
+ return LocLocked.isValid()
+ ? getNotes(PartialDiagnosticAt(
+ LocLocked, S.PDiag(diag::note_locked_here) << Kind))
+ : getNotes();
}
public:
@@ -1678,22 +1678,34 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
void handleUnmatchedUnlock(StringRef Kind, Name LockName,
SourceLocation Loc) override {
- warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
- }
-
- void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
- LockKind Expected, LockKind Received,
- SourceLocation Loc) override {
if (Loc.isInvalid())
Loc = FunLocation;
- PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch)
- << Kind << LockName << Received
- << Expected);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_but_no_lock)
+ << Kind << LockName);
Warnings.emplace_back(std::move(Warning), getNotes());
}
- void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override {
- warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
+ void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
+ LockKind Expected, LockKind Received,
+ SourceLocation LocLocked,
+ SourceLocation LocUnlock) override {
+ if (LocUnlock.isInvalid())
+ LocUnlock = FunLocation;
+ PartialDiagnosticAt Warning(
+ LocUnlock, S.PDiag(diag::warn_unlock_kind_mismatch)
+ << Kind << LockName << Received << Expected);
+ Warnings.emplace_back(std::move(Warning),
+ makeLockedHereNote(LocLocked, Kind));
+ }
+
+ void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked,
+ SourceLocation LocDoubleLock) override {
+ if (LocDoubleLock.isInvalid())
+ LocDoubleLock = FunLocation;
+ PartialDiagnosticAt Warning(LocDoubleLock, S.PDiag(diag::warn_double_lock)
+ << Kind << LockName);
+ Warnings.emplace_back(std::move(Warning),
+ makeLockedHereNote(LocLocked, Kind));
}
void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
@@ -1720,13 +1732,8 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind
<< LockName);
- if (LocLocked.isValid()) {
- PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)
- << Kind);
- Warnings.emplace_back(std::move(Warning), getNotes(Note));
- return;
- }
- Warnings.emplace_back(std::move(Warning), getNotes());
+ Warnings.emplace_back(std::move(Warning),
+ makeLockedHereNote(LocLocked, Kind));
}
void handleExclusiveAndShared(StringRef Kind, Name LockName,
@@ -2082,16 +2089,16 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// Register the expressions with the CFGBuilder.
for (const auto &D : fscope->PossiblyUnreachableDiags) {
- if (D.stmt)
- AC.registerForcedBlockExpression(D.stmt);
+ for (const Stmt *S : D.Stmts)
+ AC.registerForcedBlockExpression(S);
}
if (AC.getCFG()) {
analyzed = true;
for (const auto &D : fscope->PossiblyUnreachableDiags) {
- bool processed = false;
- if (D.stmt) {
- const CFGBlock *block = AC.getBlockForRegisteredExpression(D.stmt);
+ 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
@@ -2099,15 +2106,17 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// 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))
- S.Diag(D.Loc, D.PD);
- processed = true;
+ if (!cra->isReachable(&AC.getCFG()->getEntry(), block)) {
+ AllReachable = false;
+ break;
+ }
}
+ // If we cannot map to a basic block, assume the statement is
+ // reachable.
}
- if (!processed) {
- // Emit the warning anyway if we cannot map to a basic block.
+
+ if (AllReachable)
S.Diag(D.Loc, D.PD);
- }
}
}