summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Analysis/ReachableCode.cpp20
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp10
2 files changed, 25 insertions, 5 deletions
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index 69d000c03ba..a2f3203762f 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -218,11 +218,21 @@ static bool isConfigurationValue(const Stmt *S,
}
case Stmt::UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(S);
- if (SilenceableCondVal)
- *SilenceableCondVal = UO->getSourceRange();
- return UO->getOpcode() == UO_LNot &&
- isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal,
- IncludeIntegers, WrappedInParens);
+ if (UO->getOpcode() != UO_LNot)
+ return false;
+ bool SilenceableCondValNotSet =
+ SilenceableCondVal && SilenceableCondVal->getBegin().isInvalid();
+ bool IsSubExprConfigValue =
+ isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal,
+ IncludeIntegers, WrappedInParens);
+ // Update the silenceable condition value source range only if the range
+ // was set directly by the child expression.
+ if (SilenceableCondValNotSet &&
+ SilenceableCondVal->getBegin().isValid() &&
+ *SilenceableCondVal ==
+ UO->getSubExpr()->IgnoreCasts()->getSourceRange())
+ *SilenceableCondVal = UO->getSourceRange();
+ return IsSubExprConfigValue;
}
default:
return false;
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 5953d020b4f..a987a8ce0b3 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -56,6 +56,8 @@ using namespace clang;
namespace {
class UnreachableCodeHandler : public reachable_code::Callback {
Sema &S;
+ SourceRange PreviousSilenceableCondVal;
+
public:
UnreachableCodeHandler(Sema &s) : S(s) {}
@@ -64,6 +66,14 @@ namespace {
SourceRange SilenceableCondVal,
SourceRange R1,
SourceRange R2) override {
+ // Avoid reporting multiple unreachable code diagnostics that are
+ // triggered by the same conditional value.
+ if (PreviousSilenceableCondVal.isValid() &&
+ SilenceableCondVal.isValid() &&
+ PreviousSilenceableCondVal == SilenceableCondVal)
+ return;
+ PreviousSilenceableCondVal = SilenceableCondVal;
+
unsigned diag = diag::warn_unreachable;
switch (UK) {
case reachable_code::UK_Break:
OpenPOWER on IntegriCloud