[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