[PATCH] Make -Wuninitialized warn on pointer-to-member and comma operators.
Enrico Pertoso
epertoso at google.com
Wed Dec 11 09:32:05 PST 2013
Hi rsmith,
A few lines taken from in http://llvm-reviews.chandlerc.com/D2181 that are unrelated to the main goal of that patch.
`isTrackedVar` has been updated to also track records.
`DeclRefExpr`s appearing on the left side of a comma operator are ignored, while those appearing on the right side are classified as `Use`.
http://llvm-reviews.chandlerc.com/D2387
Files:
lib/Analysis/UninitializedValues.cpp
test/SemaCXX/uninitialized.cpp
Index: lib/Analysis/UninitializedValues.cpp
===================================================================
--- lib/Analysis/UninitializedValues.cpp
+++ lib/Analysis/UninitializedValues.cpp
@@ -37,7 +37,7 @@
!vd->isExceptionVariable() &&
vd->getDeclContext() == dc) {
QualType ty = vd->getType();
- return ty->isScalarType() || ty->isVectorType();
+ return ty->isScalarType() || ty->isVectorType() || ty->isRecordType();
}
return false;
}
@@ -359,14 +359,31 @@
void ClassifyRefs::classify(const Expr *E, Class C) {
// The result of a ?: could also be an lvalue.
E = E->IgnoreParens();
- if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
- const Expr *TrueExpr = CO->getTrueExpr();
+ if (const AbstractConditionalOperator *ACO =
+ dyn_cast<AbstractConditionalOperator>(E)) {
+ if (isa<BinaryConditionalOperator>(ACO))
+ classify(cast<BinaryConditionalOperator>(ACO)->getCommon(), Use);
+ const Expr *TrueExpr = ACO->getTrueExpr();
if (!isa<OpaqueValueExpr>(TrueExpr))
classify(TrueExpr, C);
- classify(CO->getFalseExpr(), C);
+ classify(ACO->getFalseExpr(), C);
return;
}
+ if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ switch (BO->getOpcode()) {
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ classify(BO->getLHS(), C);
+ return;
+ case BO_Comma:
+ classify(BO->getRHS(), C);
+ return;
+ default:
+ return;
+ }
+ }
+
FindVarResult Var = findVar(E, DC);
if (const DeclRefExpr *DRE = Var.getDeclRefExpr())
Classification[DRE] = std::max(Classification[DRE], C);
@@ -390,7 +407,7 @@
// use.
if (BO->isCompoundAssignmentOp())
classify(BO->getLHS(), Use);
- else if (BO->getOpcode() == BO_Assign)
+ else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma)
classify(BO->getLHS(), Ignore);
}
@@ -401,14 +418,28 @@
classify(UO->getSubExpr(), Use);
}
+static bool IsPointerToConst(const QualType &QT) {
+ return QT->isAnyPointerType() && QT->getPointeeType().isConstQualified();
+}
+
void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
- // If a value is passed by const reference to a function, we should not assume
- // that it is initialized by the call, and we conservatively do not assume
- // that it is used.
- for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
- I != E; ++I)
- if ((*I)->getType().isConstQualified() && (*I)->isGLValue())
- classify(*I, Ignore);
+ // If a value is passed by const pointer or by const reference to a function,
+ // we should not assume that it is initialized by the call, and we
+ // conservatively do not assume that it is used.
+ for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+ I != E; ++I) {
+ if ((*I)->isGLValue()) {
+ if ((*I)->getType().isConstQualified())
+ classify((*I), Ignore);
+ continue;
+ } else if (IsPointerToConst((*I)->getType())) {
+ const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
+ const UnaryOperator *UO = dyn_cast<UnaryOperator>(Ex);
+ if (UO && UO->getOpcode() == UO_AddrOf)
+ Ex = UO->getSubExpr();
+ classify(Ex, Ignore);
+ }
+ }
}
void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
Index: test/SemaCXX/uninitialized.cpp
===================================================================
--- test/SemaCXX/uninitialized.cpp
+++ test/SemaCXX/uninitialized.cpp
@@ -67,6 +67,25 @@
}
}
+void test_comma () {
+ int a; // expected-note {{initialize the variable 'a' to silence this warning}}
+ int b = (a, a ?: 2); // expected-warning {{variable 'a' is uninitialized when used here}}
+ int c = (a, a, b, c); // expected-warning {{variable 'c' is uninitialized when used within its own initialization}}
+}
+
+namespace mem_ptr {
+struct A {
+ int x;
+ int y;
+};
+
+void foo() {
+ int A::* px = &A::x;
+ A a{ 1, a.*px }; // expected-warning {{variable 'a' is uninitialized when used within its own initialization}}
+ A b = b; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}}
+}
+}
+
// Test self-references with record types.
class A {
// Non-POD class.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2387.1.patch
Type: text/x-patch
Size: 4236 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131211/7add00ce/attachment.bin>
More information about the cfe-commits
mailing list