[Clang] Add a new warning to warn when passing uninitialized variables as const reference parameters to a function
Summary:
Add a new warning -Wuninitialized-const-reference as a subgroup of -Wuninitialized to address a bug filed here: https://bugs.llvm.org/show_bug.cgi?id=45624
This warning is controlled by -Wuninitialized and can be disabled by -Wno-uninitialized-const-reference.
The warning is diagnosed when passing uninitialized variables as const reference parameters to a function.
Differential Revision: https://reviews.llvm.org/D79895
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 04611da..995d776 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -974,6 +974,14 @@
<< Use.getUser()->getSourceRange();
}
+/// Diagnose uninitialized const reference usages.
+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 true;
+}
+
/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
/// uninitialized variable. This manages the different forms of diagnostic
/// emitted for particular types of uses. Returns true if the use was diagnosed
@@ -1506,13 +1514,14 @@
// order of diagnostics when calling flushDiagnostics().
typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
UsesMap uses;
+ UsesMap constRefUses;
public:
UninitValsDiagReporter(Sema &S) : S(S) {}
~UninitValsDiagReporter() override { flushDiagnostics(); }
- MappedType &getUses(const VarDecl *vd) {
- MappedType &V = uses[vd];
+ MappedType &getUses(UsesMap &um, const VarDecl *vd) {
+ MappedType &V = um[vd];
if (!V.getPointer())
V.setPointer(new UsesVec());
return V;
@@ -1520,11 +1529,17 @@
void handleUseOfUninitVariable(const VarDecl *vd,
const UninitUse &use) override {
- getUses(vd).getPointer()->push_back(use);
+ getUses(uses, vd).getPointer()->push_back(use);
+ }
+
+ void handleConstRefUseOfUninitVariable(const VarDecl *vd,
+ const UninitUse &use) override {
+ getUses(constRefUses, vd).getPointer()->push_back(use);
}
void handleSelfInit(const VarDecl *vd) override {
- getUses(vd).setInt(true);
+ getUses(uses, vd).setInt(true);
+ getUses(constRefUses, vd).setInt(true);
}
void flushDiagnostics() {
@@ -1571,6 +1586,32 @@
}
uses.clear();
+
+ // Flush all const reference uses diags.
+ for (const auto &P : constRefUses) {
+ const VarDecl *vd = P.first;
+ const MappedType &V = P.second;
+
+ UsesVec *vec = V.getPointer();
+ bool hasSelfInit = V.getInt();
+
+ if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
+ DiagnoseUninitializedUse(S, vd,
+ UninitUse(vd->getInit()->IgnoreParenCasts(),
+ /* isAlwaysUninit */ true),
+ /* alwaysReportSelfInit */ true);
+ else {
+ for (const auto &U : *vec) {
+ if (DiagnoseUninitializedConstRefUse(S, vd, U))
+ break;
+ }
+ }
+
+ // Release the uses vector.
+ delete vec;
+ }
+
+ constRefUses.clear();
}
private:
@@ -2184,7 +2225,8 @@
if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
!Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
- !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc())) {
+ !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
+ !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc())) {
if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
UninitVariablesAnalysisStats stats;