-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang] Add -Wuninitialized-const-pointer #148337
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
[clang] Add -Wuninitialized-const-pointer #148337
Conversation
This option is similar to -Wuninitialized-const-reference, but diagnoses the passing of an uninitialized value via a const pointer, like in the following code: ``` void foo(const int *); void test() { int v; foo(&v); } ```
@llvm/pr-subscribers-libcxx @llvm/pr-subscribers-clang-analysis Author: Igor Kudrin (igorkudrin) ChangesThis option is similar to -Wuninitialized-const-reference, but diagnoses the passing of an uninitialized value via a const pointer, like in the following code:
Full diff: https://github.com/llvm/llvm-project/pull/148337.diff 9 Files Affected:
diff --git a/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/clang/include/clang/Analysis/Analyses/UninitializedValues.h
index b151bc3f58321..a9b9caf38e518 100644
--- a/clang/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/clang/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -50,6 +50,9 @@ class UninitUse {
/// Is this use a const reference to this variable?
bool ConstRefUse = false;
+ /// Is this use a const pointer to this variable?
+ bool ConstPtrUse = false;
+
/// This use is always uninitialized if it occurs after any of these branches
/// is taken.
SmallVector<Branch, 2> UninitBranches;
@@ -65,11 +68,14 @@ class UninitUse {
void setUninitAfterCall() { UninitAfterCall = true; }
void setUninitAfterDecl() { UninitAfterDecl = true; }
void setConstRefUse() { ConstRefUse = true; }
+ void setConstPtrUse() { ConstPtrUse = true; }
/// Get the expression containing the uninitialized use.
const Expr *getUser() const { return User; }
bool isConstRefUse() const { return ConstRefUse; }
+ bool isConstPtrUse() const { return ConstPtrUse; }
+ bool isConstRefOrPtrUse() const { return ConstRefUse || ConstPtrUse; }
/// The kind of uninitialized use.
enum Kind {
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 9a7a308600763..c28a919e35d08 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -952,9 +952,11 @@ def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
def UninitializedConstReference : DiagGroup<"uninitialized-const-reference">;
+def UninitializedConstPointer : DiagGroup<"uninitialized-const-pointer">;
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
UninitializedStaticSelfInit,
- UninitializedConstReference]>;
+ UninitializedConstReference,
+ UninitializedConstPointer]>;
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
// #pragma optimize is often used to avoid to work around MSVC codegen bugs or
// to disable inlining. It's not completely clear what alternative to suggest
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f1290738d46b2..42e351c3fd697 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2548,6 +2548,10 @@ def warn_uninit_const_reference : Warning<
"variable %0 is uninitialized when passed as a const reference argument "
"here">, InGroup<UninitializedConstReference>, DefaultIgnore;
+def warn_uninit_const_pointer : Warning<
+ "variable %0 is uninitialized when passed as a const pointer argument here">,
+ InGroup<UninitializedConstPointer>, DefaultIgnore;
+
def warn_unsequenced_mod_mod : Warning<
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
def warn_unsequenced_mod_use : Warning<
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index 8c9cf8dac79ed..9f031c402eddb 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -281,6 +281,7 @@ class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
Use,
SelfInit,
ConstRefUse,
+ ConstPtrUse,
Ignore
};
@@ -451,8 +452,9 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
const auto *UO = dyn_cast<UnaryOperator>(Ex);
if (UO && UO->getOpcode() == UO_AddrOf)
- Ex = UO->getSubExpr();
- classify(Ex, Ignore);
+ classify(UO->getSubExpr(), isTrivialBody ? Ignore : ConstPtrUse);
+ else
+ classify(Ex, Ignore);
}
}
}
@@ -496,6 +498,7 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
void reportUse(const Expr *ex, const VarDecl *vd);
void reportConstRefUse(const Expr *ex, const VarDecl *vd);
+ void reportConstPtrUse(const Expr *ex, const VarDecl *vd);
void VisitBinaryOperator(BinaryOperator *bo);
void VisitBlockExpr(BlockExpr *be);
@@ -682,6 +685,15 @@ void TransferFunctions::reportConstRefUse(const Expr *ex, const VarDecl *vd) {
}
}
+void TransferFunctions::reportConstPtrUse(const Expr *ex, const VarDecl *vd) {
+ Value v = vals[vd];
+ if (isAlwaysUninit(v)) {
+ auto use = getUninitUse(ex, vd, v);
+ use.setConstPtrUse();
+ handler.handleUseOfUninitVariable(vd, use);
+ }
+}
+
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
// This represents an initialization of the 'element' value.
if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) {
@@ -754,6 +766,9 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
case ClassifyRefs::ConstRefUse:
reportConstRefUse(dr, cast<VarDecl>(dr->getDecl()));
break;
+ case ClassifyRefs::ConstPtrUse:
+ reportConstPtrUse(dr, cast<VarDecl>(dr->getDecl()));
+ break;
}
}
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index ec8acbdff3b49..11e3a3cbd7909 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -993,6 +993,13 @@ static void DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
<< VD->getDeclName() << Use.getUser()->getSourceRange();
}
+/// Diagnose uninitialized const pointer usages.
+static void DiagnoseUninitializedConstPtrUse(Sema &S, const VarDecl *VD,
+ const UninitUse &Use) {
+ S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_pointer)
+ << VD->getDeclName() << Use.getUser()->getSourceRange();
+}
+
/// 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
@@ -1572,9 +1579,9 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
// 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();
+ // Move ConstRef and ConstPtr uses to the back.
+ if (a.isConstRefOrPtrUse() != b.isConstRefOrPtrUse())
+ return b.isConstRefOrPtrUse();
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
@@ -1587,6 +1594,11 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
break;
}
+ if (U.isConstPtrUse()) {
+ DiagnoseUninitializedConstPtrUse(S, vd, U);
+ break;
+ }
+
// If we have self-init, downgrade all uses to 'may be uninitialized'.
UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
@@ -2820,7 +2832,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
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_uninit_const_reference, D->getBeginLoc())) {
+ !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
+ !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
UninitVariablesAnalysisStats stats;
diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c
index 91de843f88c91..689868c62f6a7 100644
--- a/clang/test/Misc/warning-wall.c
+++ b/clang/test/Misc/warning-wall.c
@@ -66,6 +66,7 @@ CHECK-NEXT: -Wuninitialized
CHECK-NEXT: -Wsometimes-uninitialized
CHECK-NEXT: -Wstatic-self-init
CHECK-NEXT: -Wuninitialized-const-reference
+CHECK-NEXT: -Wuninitialized-const-pointer
CHECK-NEXT: -Wunknown-pragmas
CHECK-NEXT: -Wunused
CHECK-NEXT: -Wunused-argument
diff --git a/clang/test/SemaCXX/warn-uninitialized-const-pointer.cpp b/clang/test/SemaCXX/warn-uninitialized-const-pointer.cpp
new file mode 100644
index 0000000000000..62802ba7375cc
--- /dev/null
+++ b/clang/test/SemaCXX/warn-uninitialized-const-pointer.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -Wuninitialized-const-pointer -verify %s
+
+template <class T>
+void ignore_template(const T *) {}
+void ignore(const int *) {}
+void dont_ignore_non_empty(const int *) { ; }
+void dont_ignore_block(const int *) { {} }
+void dont_ignore_try_block(const int *) try {
+} catch (...) {
+}
+int const_ptr_use(const int *);
+
+void f(int a) {
+ int i;
+ const_ptr_use(&i); // expected-warning {{variable 'i' is uninitialized when passed as a const pointer argument here}}
+ int j = j + const_ptr_use(&j); // expected-warning {{variable 'j' is uninitialized when used within its own initialization}}
+ int k = k; // expected-warning {{variable 'k' is uninitialized when used within its own initialization}}
+ const_ptr_use(&k);
+
+ // Only report if a variable is always uninitialized at the point of use
+ int l;
+ if (a < 42)
+ l = 1;
+ const_ptr_use(&l);
+
+ // Don't report if the called function is known to be empty.
+ int m;
+ ignore_template(&m);
+ ignore(&m);
+ dont_ignore_non_empty(&m); // expected-warning {{variable 'm' is uninitialized when passed as a const pointer argument here}}
+ int n;
+ dont_ignore_block(&n); // expected-warning {{variable 'n' is uninitialized when passed as a const pointer argument here}}
+ int o;
+ dont_ignore_try_block(&o); // expected-warning {{variable 'o' is uninitialized when passed as a const pointer argument here}}
+}
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp
index 61fd0a804ecd3..f15f1b96b4b27 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp
@@ -62,14 +62,14 @@ int main(int, char**)
{
testbuf<char> sb1;
std::ostream os1(&sb1);
- int n1;
+ int n1 = 0;
os1 << &n1;
assert(os1.good());
std::string s1(sb1.str());
testbuf<char> sb2;
std::ostream os2(&sb2);
- int n2;
+ int n2 = 0;
os2 << &n2;
assert(os2.good());
std::string s2(sb2.str());
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp
index 69d84f640d54e..6a1cde15a69bd 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp
@@ -61,7 +61,7 @@ class testbuf : public std::basic_streambuf<CharT> {
int main(int, char**) {
testbuf<char> sb1;
std::ostream os1(&sb1);
- int n1;
+ int n1 = 0;
os1 << &n1;
assert(os1.good());
std::string s1 = sb1.str();
@@ -74,7 +74,7 @@ int main(int, char**) {
testbuf<char> sb3;
std::ostream os3(&sb3);
- volatile int n3;
+ volatile int n3 = 0;
os3 << &n3;
assert(os3.good());
std::string s3 = sb3.str();
|
@llvm/pr-subscribers-clang Author: Igor Kudrin (igorkudrin) ChangesThis option is similar to -Wuninitialized-const-reference, but diagnoses the passing of an uninitialized value via a const pointer, like in the following code:
Full diff: https://github.com/llvm/llvm-project/pull/148337.diff 9 Files Affected:
diff --git a/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/clang/include/clang/Analysis/Analyses/UninitializedValues.h
index b151bc3f58321..a9b9caf38e518 100644
--- a/clang/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/clang/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -50,6 +50,9 @@ class UninitUse {
/// Is this use a const reference to this variable?
bool ConstRefUse = false;
+ /// Is this use a const pointer to this variable?
+ bool ConstPtrUse = false;
+
/// This use is always uninitialized if it occurs after any of these branches
/// is taken.
SmallVector<Branch, 2> UninitBranches;
@@ -65,11 +68,14 @@ class UninitUse {
void setUninitAfterCall() { UninitAfterCall = true; }
void setUninitAfterDecl() { UninitAfterDecl = true; }
void setConstRefUse() { ConstRefUse = true; }
+ void setConstPtrUse() { ConstPtrUse = true; }
/// Get the expression containing the uninitialized use.
const Expr *getUser() const { return User; }
bool isConstRefUse() const { return ConstRefUse; }
+ bool isConstPtrUse() const { return ConstPtrUse; }
+ bool isConstRefOrPtrUse() const { return ConstRefUse || ConstPtrUse; }
/// The kind of uninitialized use.
enum Kind {
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 9a7a308600763..c28a919e35d08 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -952,9 +952,11 @@ def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
def UninitializedConstReference : DiagGroup<"uninitialized-const-reference">;
+def UninitializedConstPointer : DiagGroup<"uninitialized-const-pointer">;
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
UninitializedStaticSelfInit,
- UninitializedConstReference]>;
+ UninitializedConstReference,
+ UninitializedConstPointer]>;
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
// #pragma optimize is often used to avoid to work around MSVC codegen bugs or
// to disable inlining. It's not completely clear what alternative to suggest
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f1290738d46b2..42e351c3fd697 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2548,6 +2548,10 @@ def warn_uninit_const_reference : Warning<
"variable %0 is uninitialized when passed as a const reference argument "
"here">, InGroup<UninitializedConstReference>, DefaultIgnore;
+def warn_uninit_const_pointer : Warning<
+ "variable %0 is uninitialized when passed as a const pointer argument here">,
+ InGroup<UninitializedConstPointer>, DefaultIgnore;
+
def warn_unsequenced_mod_mod : Warning<
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
def warn_unsequenced_mod_use : Warning<
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index 8c9cf8dac79ed..9f031c402eddb 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -281,6 +281,7 @@ class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
Use,
SelfInit,
ConstRefUse,
+ ConstPtrUse,
Ignore
};
@@ -451,8 +452,9 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
const auto *UO = dyn_cast<UnaryOperator>(Ex);
if (UO && UO->getOpcode() == UO_AddrOf)
- Ex = UO->getSubExpr();
- classify(Ex, Ignore);
+ classify(UO->getSubExpr(), isTrivialBody ? Ignore : ConstPtrUse);
+ else
+ classify(Ex, Ignore);
}
}
}
@@ -496,6 +498,7 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
void reportUse(const Expr *ex, const VarDecl *vd);
void reportConstRefUse(const Expr *ex, const VarDecl *vd);
+ void reportConstPtrUse(const Expr *ex, const VarDecl *vd);
void VisitBinaryOperator(BinaryOperator *bo);
void VisitBlockExpr(BlockExpr *be);
@@ -682,6 +685,15 @@ void TransferFunctions::reportConstRefUse(const Expr *ex, const VarDecl *vd) {
}
}
+void TransferFunctions::reportConstPtrUse(const Expr *ex, const VarDecl *vd) {
+ Value v = vals[vd];
+ if (isAlwaysUninit(v)) {
+ auto use = getUninitUse(ex, vd, v);
+ use.setConstPtrUse();
+ handler.handleUseOfUninitVariable(vd, use);
+ }
+}
+
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
// This represents an initialization of the 'element' value.
if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) {
@@ -754,6 +766,9 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
case ClassifyRefs::ConstRefUse:
reportConstRefUse(dr, cast<VarDecl>(dr->getDecl()));
break;
+ case ClassifyRefs::ConstPtrUse:
+ reportConstPtrUse(dr, cast<VarDecl>(dr->getDecl()));
+ break;
}
}
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index ec8acbdff3b49..11e3a3cbd7909 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -993,6 +993,13 @@ static void DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
<< VD->getDeclName() << Use.getUser()->getSourceRange();
}
+/// Diagnose uninitialized const pointer usages.
+static void DiagnoseUninitializedConstPtrUse(Sema &S, const VarDecl *VD,
+ const UninitUse &Use) {
+ S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_pointer)
+ << VD->getDeclName() << Use.getUser()->getSourceRange();
+}
+
/// 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
@@ -1572,9 +1579,9 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
// 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();
+ // Move ConstRef and ConstPtr uses to the back.
+ if (a.isConstRefOrPtrUse() != b.isConstRefOrPtrUse())
+ return b.isConstRefOrPtrUse();
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
@@ -1587,6 +1594,11 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
break;
}
+ if (U.isConstPtrUse()) {
+ DiagnoseUninitializedConstPtrUse(S, vd, U);
+ break;
+ }
+
// If we have self-init, downgrade all uses to 'may be uninitialized'.
UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
@@ -2820,7 +2832,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
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_uninit_const_reference, D->getBeginLoc())) {
+ !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
+ !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
UninitVariablesAnalysisStats stats;
diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c
index 91de843f88c91..689868c62f6a7 100644
--- a/clang/test/Misc/warning-wall.c
+++ b/clang/test/Misc/warning-wall.c
@@ -66,6 +66,7 @@ CHECK-NEXT: -Wuninitialized
CHECK-NEXT: -Wsometimes-uninitialized
CHECK-NEXT: -Wstatic-self-init
CHECK-NEXT: -Wuninitialized-const-reference
+CHECK-NEXT: -Wuninitialized-const-pointer
CHECK-NEXT: -Wunknown-pragmas
CHECK-NEXT: -Wunused
CHECK-NEXT: -Wunused-argument
diff --git a/clang/test/SemaCXX/warn-uninitialized-const-pointer.cpp b/clang/test/SemaCXX/warn-uninitialized-const-pointer.cpp
new file mode 100644
index 0000000000000..62802ba7375cc
--- /dev/null
+++ b/clang/test/SemaCXX/warn-uninitialized-const-pointer.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -Wuninitialized-const-pointer -verify %s
+
+template <class T>
+void ignore_template(const T *) {}
+void ignore(const int *) {}
+void dont_ignore_non_empty(const int *) { ; }
+void dont_ignore_block(const int *) { {} }
+void dont_ignore_try_block(const int *) try {
+} catch (...) {
+}
+int const_ptr_use(const int *);
+
+void f(int a) {
+ int i;
+ const_ptr_use(&i); // expected-warning {{variable 'i' is uninitialized when passed as a const pointer argument here}}
+ int j = j + const_ptr_use(&j); // expected-warning {{variable 'j' is uninitialized when used within its own initialization}}
+ int k = k; // expected-warning {{variable 'k' is uninitialized when used within its own initialization}}
+ const_ptr_use(&k);
+
+ // Only report if a variable is always uninitialized at the point of use
+ int l;
+ if (a < 42)
+ l = 1;
+ const_ptr_use(&l);
+
+ // Don't report if the called function is known to be empty.
+ int m;
+ ignore_template(&m);
+ ignore(&m);
+ dont_ignore_non_empty(&m); // expected-warning {{variable 'm' is uninitialized when passed as a const pointer argument here}}
+ int n;
+ dont_ignore_block(&n); // expected-warning {{variable 'n' is uninitialized when passed as a const pointer argument here}}
+ int o;
+ dont_ignore_try_block(&o); // expected-warning {{variable 'o' is uninitialized when passed as a const pointer argument here}}
+}
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp
index 61fd0a804ecd3..f15f1b96b4b27 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.pass.cpp
@@ -62,14 +62,14 @@ int main(int, char**)
{
testbuf<char> sb1;
std::ostream os1(&sb1);
- int n1;
+ int n1 = 0;
os1 << &n1;
assert(os1.good());
std::string s1(sb1.str());
testbuf<char> sb2;
std::ostream os2(&sb2);
- int n2;
+ int n2 = 0;
os2 << &n2;
assert(os2.good());
std::string s2(sb2.str());
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp
index 69d84f640d54e..6a1cde15a69bd 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.inserters.arithmetic/pointer.volatile.pass.cpp
@@ -61,7 +61,7 @@ class testbuf : public std::basic_streambuf<CharT> {
int main(int, char**) {
testbuf<char> sb1;
std::ostream os1(&sb1);
- int n1;
+ int n1 = 0;
os1 << &n1;
assert(os1.good());
std::string s1 = sb1.str();
@@ -74,7 +74,7 @@ int main(int, char**) {
testbuf<char> sb3;
std::ostream os3(&sb3);
- volatile int n3;
+ volatile int n3 = 0;
os3 << &n3;
assert(os3.good());
std::string s3 = sb3.str();
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
This reverts commit 00dacf8.
This option is similar to -Wuninitialized-const-reference, but diagnoses the passing of an uninitialized value via a const pointer, like in the following code:
This is an extract from #147221 as suggested in this comment.