-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang] Fix suppressing diagnostics for uninitialized variables #148336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
When one kind of diagnostics is disabled, this should not preclude other diagnostics from displaying, even if they have lower priority. For example, this should print a warning about passing an uninitialized variable as a const reference: ``` > cat test.cpp void foo(const int &); int f(bool a) { int v; if (a) { foo(v); v = 5; } return v; } > clang test.cpp -fsyntax-only -Wuninitialized -Wno-sometimes-uninitialized ```
@llvm/pr-subscribers-clang-analysis Author: Igor Kudrin (igorkudrin) ChangesWhen one kind of diagnostics is disabled, this should not preclude other diagnostics from displaying, even if they have lower priority. For example, this should print a warning about passing an uninitialized variable as a const reference:
Full diff: https://github.com/llvm/llvm-project/pull/148336.diff 2 Files Affected:
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index ec8acbdff3b49..a4e5519f13d18 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -987,10 +987,11 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
}
/// Diagnose uninitialized const reference usages.
-static void DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
+static bool DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
const UninitUse &Use) {
S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)
<< VD->getDeclName() << Use.getUser()->getSourceRange();
+ return !S.getDiagnostics().isLastDiagnosticIgnored();
}
/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
@@ -1022,7 +1023,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
if (CR.doesContainReference()) {
S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
<< VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
- return true;
+ return !S.getDiagnostics().isLastDiagnosticIgnored();
}
}
@@ -1045,7 +1046,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
<< VD->getDeclName();
- return true;
+ return !S.getDiagnostics().isLastDiagnosticIgnored();
}
namespace {
@@ -1559,43 +1560,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
UsesVec *vec = V.getPointer();
bool hasSelfInit = V.getInt();
- // Specially handle the case where we have uses of an uninitialized
- // variable, but the root cause is an idiomatic self-init. We want
- // to report the diagnostic at the self-init since that is the root cause.
- if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
- DiagnoseUninitializedUse(S, vd,
- UninitUse(vd->getInit()->IgnoreParenCasts(),
- /* isAlwaysUninit */ true),
- /* alwaysReportSelfInit */ true);
- else {
- // Sort the uses by their SourceLocations. While not strictly
- // guaranteed to produce them in line/column order, this will provide
- // a stable ordering.
- llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
- // Move ConstRef uses to the back.
- if (a.isConstRefUse() != b.isConstRefUse())
- return b.isConstRefUse();
- // Prefer a more confident report over a less confident one.
- if (a.getKind() != b.getKind())
- return a.getKind() > b.getKind();
- return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
- });
-
- for (const auto &U : *vec) {
- if (U.isConstRefUse()) {
- DiagnoseUninitializedConstRefUse(S, vd, U);
- break;
- }
-
- // If we have self-init, downgrade all uses to 'may be uninitialized'.
- UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
-
- if (DiagnoseUninitializedUse(S, vd, Use))
- // Skip further diagnostics for this variable. We try to warn only
- // on the first point at which a variable is used uninitialized.
- break;
- }
- }
+ diagnoseUnitializedVar(vd, hasSelfInit, vec);
// Release the uses vector.
delete vec;
@@ -1612,6 +1577,49 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
U.getKind() == UninitUse::AfterDecl;
});
}
+
+ // Print the diagnostic for the variable. We try to warn only on the first
+ // point at which a variable is used uninitialized. After the first
+ // diagnostic is printed, further diagnostics for this variable are skipped.
+ void diagnoseUnitializedVar(const VarDecl *vd, bool hasSelfInit,
+ UsesVec *vec) {
+ // Specially handle the case where we have uses of an uninitialized
+ // variable, but the root cause is an idiomatic self-init. We want
+ // to report the diagnostic at the self-init since that is the root cause.
+ if (hasSelfInit && hasAlwaysUninitializedUse(vec)) {
+ if (DiagnoseUninitializedUse(S, vd,
+ UninitUse(vd->getInit()->IgnoreParenCasts(),
+ /*isAlwaysUninit=*/true),
+ /*alwaysReportSelfInit=*/true))
+ return;
+ }
+
+ // Sort the uses by their SourceLocations. While not strictly
+ // guaranteed to produce them in line/column order, this will provide
+ // a stable ordering.
+ llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
+ // Prefer the direct use of an uninitialized variable over its use via
+ // constant reference.
+ if (a.isConstRefUse() != b.isConstRefUse())
+ return b.isConstRefUse();
+ // Prefer a more confident report over a less confident one.
+ if (a.getKind() != b.getKind())
+ return a.getKind() > b.getKind();
+ return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
+ });
+
+ for (const auto &U : *vec) {
+ if (U.isConstRefUse()) {
+ if (DiagnoseUninitializedConstRefUse(S, vd, U))
+ return;
+ } else {
+ // If we have self-init, downgrade all uses to 'may be uninitialized'.
+ UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
+ if (DiagnoseUninitializedUse(S, vd, Use))
+ return;
+ }
+ }
+ }
};
/// Inter-procedural data for the called-once checker.
diff --git a/clang/test/SemaCXX/warn-no-sometimes-uninitialized.cpp b/clang/test/SemaCXX/warn-no-sometimes-uninitialized.cpp
new file mode 100644
index 0000000000000..71e5faeec63fb
--- /dev/null
+++ b/clang/test/SemaCXX/warn-no-sometimes-uninitialized.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wno-sometimes-uninitialized -verify %s
+
+void foo(const int &);
+
+int f(bool a) {
+ int v;
+ if (a) {
+ foo(v); // expected-warning {{variable 'v' is uninitialized when passed as a const reference argument here}}
+ v = 5;
+ }
+ return v;
+}
|
@llvm/pr-subscribers-clang Author: Igor Kudrin (igorkudrin) ChangesWhen one kind of diagnostics is disabled, this should not preclude other diagnostics from displaying, even if they have lower priority. For example, this should print a warning about passing an uninitialized variable as a const reference:
Full diff: https://github.com/llvm/llvm-project/pull/148336.diff 2 Files Affected:
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index ec8acbdff3b49..a4e5519f13d18 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -987,10 +987,11 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
}
/// Diagnose uninitialized const reference usages.
-static void DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
+static bool DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
const UninitUse &Use) {
S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)
<< VD->getDeclName() << Use.getUser()->getSourceRange();
+ return !S.getDiagnostics().isLastDiagnosticIgnored();
}
/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
@@ -1022,7 +1023,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
if (CR.doesContainReference()) {
S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
<< VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
- return true;
+ return !S.getDiagnostics().isLastDiagnosticIgnored();
}
}
@@ -1045,7 +1046,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
<< VD->getDeclName();
- return true;
+ return !S.getDiagnostics().isLastDiagnosticIgnored();
}
namespace {
@@ -1559,43 +1560,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
UsesVec *vec = V.getPointer();
bool hasSelfInit = V.getInt();
- // Specially handle the case where we have uses of an uninitialized
- // variable, but the root cause is an idiomatic self-init. We want
- // to report the diagnostic at the self-init since that is the root cause.
- if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
- DiagnoseUninitializedUse(S, vd,
- UninitUse(vd->getInit()->IgnoreParenCasts(),
- /* isAlwaysUninit */ true),
- /* alwaysReportSelfInit */ true);
- else {
- // Sort the uses by their SourceLocations. While not strictly
- // guaranteed to produce them in line/column order, this will provide
- // a stable ordering.
- llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
- // Move ConstRef uses to the back.
- if (a.isConstRefUse() != b.isConstRefUse())
- return b.isConstRefUse();
- // Prefer a more confident report over a less confident one.
- if (a.getKind() != b.getKind())
- return a.getKind() > b.getKind();
- return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
- });
-
- for (const auto &U : *vec) {
- if (U.isConstRefUse()) {
- DiagnoseUninitializedConstRefUse(S, vd, U);
- break;
- }
-
- // If we have self-init, downgrade all uses to 'may be uninitialized'.
- UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
-
- if (DiagnoseUninitializedUse(S, vd, Use))
- // Skip further diagnostics for this variable. We try to warn only
- // on the first point at which a variable is used uninitialized.
- break;
- }
- }
+ diagnoseUnitializedVar(vd, hasSelfInit, vec);
// Release the uses vector.
delete vec;
@@ -1612,6 +1577,49 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
U.getKind() == UninitUse::AfterDecl;
});
}
+
+ // Print the diagnostic for the variable. We try to warn only on the first
+ // point at which a variable is used uninitialized. After the first
+ // diagnostic is printed, further diagnostics for this variable are skipped.
+ void diagnoseUnitializedVar(const VarDecl *vd, bool hasSelfInit,
+ UsesVec *vec) {
+ // Specially handle the case where we have uses of an uninitialized
+ // variable, but the root cause is an idiomatic self-init. We want
+ // to report the diagnostic at the self-init since that is the root cause.
+ if (hasSelfInit && hasAlwaysUninitializedUse(vec)) {
+ if (DiagnoseUninitializedUse(S, vd,
+ UninitUse(vd->getInit()->IgnoreParenCasts(),
+ /*isAlwaysUninit=*/true),
+ /*alwaysReportSelfInit=*/true))
+ return;
+ }
+
+ // Sort the uses by their SourceLocations. While not strictly
+ // guaranteed to produce them in line/column order, this will provide
+ // a stable ordering.
+ llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
+ // Prefer the direct use of an uninitialized variable over its use via
+ // constant reference.
+ if (a.isConstRefUse() != b.isConstRefUse())
+ return b.isConstRefUse();
+ // Prefer a more confident report over a less confident one.
+ if (a.getKind() != b.getKind())
+ return a.getKind() > b.getKind();
+ return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
+ });
+
+ for (const auto &U : *vec) {
+ if (U.isConstRefUse()) {
+ if (DiagnoseUninitializedConstRefUse(S, vd, U))
+ return;
+ } else {
+ // If we have self-init, downgrade all uses to 'may be uninitialized'.
+ UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
+ if (DiagnoseUninitializedUse(S, vd, Use))
+ return;
+ }
+ }
+ }
};
/// Inter-procedural data for the called-once checker.
diff --git a/clang/test/SemaCXX/warn-no-sometimes-uninitialized.cpp b/clang/test/SemaCXX/warn-no-sometimes-uninitialized.cpp
new file mode 100644
index 0000000000000..71e5faeec63fb
--- /dev/null
+++ b/clang/test/SemaCXX/warn-no-sometimes-uninitialized.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wno-sometimes-uninitialized -verify %s
+
+void foo(const int &);
+
+int f(bool a) {
+ int v;
+ if (a) {
+ foo(v); // expected-warning {{variable 'v' is uninitialized when passed as a const reference argument here}}
+ v = 5;
+ }
+ return v;
+}
|
When one kind of diagnostics is disabled, this should not preclude other diagnostics from displaying, even if they have lower priority. For example, this should print a warning about passing an uninitialized variable as a const reference: