[cfe-commits] r165074 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/SemaCXX/uninitialized.cpp
Richard Trieu
rtrieu at google.com
Tue Oct 2 17:41:37 PDT 2012
Author: rtrieu
Date: Tue Oct 2 19:41:36 2012
New Revision: 165074
URL: http://llvm.org/viewvc/llvm-project?rev=165074&view=rev
Log:
Change how the SelfReferenceChecker handles MemberExpr. Instead of treating
each one separately, process a stack of MemberExpr's as a single unit so that
static calls and member access will not be warned on.
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/uninitialized.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=165074&r1=165073&r2=165074&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Oct 2 19:41:36 2012
@@ -6276,6 +6276,20 @@
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
HandleValue(CO->getTrueExpr());
HandleValue(CO->getFalseExpr());
+ return;
+ }
+
+ if (isa<MemberExpr>(E)) {
+ Expr *Base = E->IgnoreParenImpCasts();
+ while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
+ // Check for static member variables and don't warn on them.
+ if (!isa<FieldDecl>(ME->getMemberDecl()))
+ return;
+ Base = ME->getBase()->IgnoreParenImpCasts();
+ }
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base))
+ HandleDeclRefExpr(DRE);
+ return;
}
}
@@ -6287,7 +6301,7 @@
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
- if ((!isRecordType && E->getCastKind() == CK_LValueToRValue) ||
+ if (E->getCastKind() == CK_LValueToRValue ||
(isRecordType && E->getCastKind() == CK_NoOp))
HandleValue(E->getSubExpr());
@@ -6298,22 +6312,36 @@
// Don't warn on arrays since they can be treated as pointers.
if (E->getType()->canDecayToPointerType()) return;
- ValueDecl *VD = E->getMemberDecl();
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(VD);
- if (isa<FieldDecl>(VD) || (MD && !MD->isStatic()))
- if (DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) {
+ // Warn when a non-static method call is followed by non-static member
+ // field accesses, which is followed by a DeclRefExpr.
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl());
+ bool Warn = (MD && !MD->isStatic());
+ Expr *Base = E->getBase()->IgnoreParenImpCasts();
+ while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
+ if (!isa<FieldDecl>(ME->getMemberDecl()))
+ Warn = false;
+ Base = ME->getBase()->IgnoreParenImpCasts();
+ }
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (Warn)
HandleDeclRefExpr(DRE);
- return;
- }
+ return;
+ }
- Inherited::VisitMemberExpr(E);
+ // The base of a MemberExpr is not a MemberExpr or a DeclRefExpr.
+ // Visit that expression.
+ Visit(Base);
}
void VisitUnaryOperator(UnaryOperator *E) {
// For POD record types, addresses of its own members are well-defined.
- if (E->getOpcode() == UO_AddrOf && isRecordType && isPODType &&
- isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) return;
+ if (E->getOpcode() == UO_AddrOf && isRecordType &&
+ isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) {
+ if (!isPODType)
+ HandleValue(E->getSubExpr());
+ return;
+ }
Inherited::VisitUnaryOperator(E);
}
Modified: cfe/trunk/test/SemaCXX/uninitialized.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninitialized.cpp?rev=165074&r1=165073&r2=165074&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/uninitialized.cpp (original)
+++ cfe/trunk/test/SemaCXX/uninitialized.cpp Tue Oct 2 19:41:36 2012
@@ -116,6 +116,17 @@
A a19 = getA(x ? a19 : a17); // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}}
A a20{a20}; // expected-warning {{variable 'a20' is uninitialized when used within its own initialization}}
A a21 = {a21}; // expected-warning {{variable 'a21' is uninitialized when used within its own initialization}}
+
+ // FIXME: Make the local uninitialized warning consistant with the global
+ // uninitialized checking.
+ A *a22 = new A(a22->count); // expected-warning {{variable 'a22' is uninitialized when used within its own initialization}}
+ A *a23 = new A(a23->ONE); // expected-warning {{variable 'a23' is uninitialized when used within its own initialization}}
+ A *a24 = new A(a24->TWO); // expected-warning {{variable 'a24' is uninitialized when used within its own initialization}}
+ A *a25 = new A(a25->zero()); // expected-warning {{variable 'a25' is uninitialized when used within its own initialization}}
+
+ A *a26 = new A(a26->get()); // expected-warning {{variable 'a26' is uninitialized when used within its own initialization}}
+ A *a27 = new A(a27->get2()); // expected-warning {{variable 'a27' is uninitialized when used within its own initialization}}
+ A *a28 = new A(a28->num); // expected-warning {{variable 'a28' is uninitialized when used within its own initialization}}
}
bool x;
@@ -143,6 +154,15 @@
A a20{a20}; // expected-warning {{variable 'a20' is uninitialized when used within its own initialization}}
A a21 = {a21}; // expected-warning {{variable 'a21' is uninitialized when used within its own initialization}}
+A *a22 = new A(a22->count);
+A *a23 = new A(a23->ONE);
+A *a24 = new A(a24->TWO);
+A *a25 = new A(a25->zero());
+
+A *a26 = new A(a26->get()); // expected-warning {{variable 'a26' is uninitialized when used within its own initialization}}
+A *a27 = new A(a27->get2()); // expected-warning {{variable 'a27' is uninitialized when used within its own initialization}}
+A *a28 = new A(a28->num); // expected-warning {{variable 'a28' is uninitialized when used within its own initialization}}
+
struct B {
// POD struct.
int x;
@@ -154,6 +174,11 @@
B getB(int *x) { return B(); };
B getB(B *b) { return B(); };
+B* getPtrB() { return 0; };
+B* getPtrB(int x) { return 0; };
+B* getPtrB(int *x) { return 0; };
+B* getPtrB(B **b) { return 0; };
+
void setupB() {
B b1;
B b2(b1);
@@ -170,8 +195,46 @@
B b8 = getB(b8.x); // expected-warning {{variable 'b8' is uninitialized when used within its own initialization}}
B b9 = getB(b9.y); // expected-warning {{variable 'b9' is uninitialized when used within its own initialization}}
B b10 = getB(-b10.x); // expected-warning {{variable 'b10' is uninitialized when used within its own initialization}}
+
+ B* b11 = 0;
+ B* b12(b11);
+ B* b13 = getPtrB();
+ B* b14 = getPtrB(&b14);
+
+ (void) b12;
+ (void) b13;
+
+ B* b15 = getPtrB(b15->x); // expected-warning {{variable 'b15' is uninitialized when used within its own initialization}}
+ B* b16 = getPtrB(b16->y); // expected-warning {{variable 'b16' is uninitialized when used within its own initialization}}
+
+ B b17 = { b17.x = 5, b17.y = 0 };
+ B b18 = { b18.x + 1, b18.y }; // expected-warning 2{{variable 'b18' is uninitialized when used within its own initialization}}
}
+B b1;
+B b2(b1);
+B b3 = { 5, &b3.x };
+B b4 = getB();
+B b5 = getB(&b5);
+B b6 = getB(&b6.x);
+
+B b7(b7); // expected-warning {{variable 'b7' is uninitialized when used within its own initialization}}
+B b8 = getB(b8.x); // expected-warning {{variable 'b8' is uninitialized when used within its own initialization}}
+B b9 = getB(b9.y); // expected-warning {{variable 'b9' is uninitialized when used within its own initialization}}
+B b10 = getB(-b10.x); // expected-warning {{variable 'b10' is uninitialized when used within its own initialization}}
+
+B* b11 = 0;
+B* b12(b11);
+B* b13 = getPtrB();
+B* b14 = getPtrB(&b14);
+
+B* b15 = getPtrB(b15->x); // expected-warning {{variable 'b15' is uninitialized when used within its own initialization}}
+B* b16 = getPtrB(b16->y); // expected-warning {{variable 'b16' is uninitialized when used within its own initialization}}
+
+B b17 = { b17.x = 5, b17.y = 0 };
+B b18 = { b18.x + 1, b18.y }; // expected-warning 2{{variable 'b18' is uninitialized when used within its own initialization}}
+
+
// Also test similar constructs in a field's initializer.
struct S {
int x;
More information about the cfe-commits
mailing list