From: Richard Trieu Date: Tue, 12 Aug 2014 21:05:04 +0000 (+0000) Subject: Improve -Wuninitialized to catch const classes being used in their own copy X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4443509597918ac81bb85955349d701ee313e980;p=clang Improve -Wuninitialized to catch const classes being used in their own copy constructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215471 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 53a647149a..9c0be3e76f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8276,6 +8276,15 @@ namespace { void VisitObjCMessageExpr(ObjCMessageExpr *E) { return; } + void VisitCXXConstructExpr(CXXConstructExpr *E) { + if (E->getConstructor()->isCopyConstructor()) { + if (DeclRefExpr *DRE = dyn_cast(E->getArg(0))) { + HandleDeclRefExpr(DRE); + } + } + Inherited::VisitCXXConstructExpr(E); + } + void HandleDeclRefExpr(DeclRefExpr *DRE) { Decl* ReferenceDecl = DRE->getDecl(); if (OrigDecl != ReferenceDecl) return; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 77285edbc0..e676466e4e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2314,12 +2314,18 @@ namespace { } void VisitCXXConstructExpr(CXXConstructExpr *E) { - if (E->getConstructor()->isCopyConstructor()) - if (ImplicitCastExpr* ICE = dyn_cast(E->getArg(0))) - if (ICE->getCastKind() == CK_NoOp) - if (MemberExpr *ME = dyn_cast(ICE->getSubExpr())) - HandleMemberExpr(ME, false /*CheckReferenceOnly*/); - + if (E->getConstructor()->isCopyConstructor()) { + Expr *ArgExpr = E->getArg(0); + if (ImplicitCastExpr* ICE = dyn_cast(ArgExpr)) { + if (ICE->getCastKind() == CK_NoOp) { + ArgExpr = ICE->getSubExpr(); + } + } + + if (MemberExpr *ME = dyn_cast(ArgExpr)) { + HandleMemberExpr(ME, false /*CheckReferenceOnly*/); + } + } Inherited::VisitCXXConstructExpr(E); } diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 677a141f3e..7b89e5adc9 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -127,6 +127,9 @@ void setupA(bool x) { 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}} + + const A a29(a29); // expected-warning {{variable 'a29' is uninitialized when used within its own initialization}} + const A a30 = a30; // expected-warning {{variable 'a30' is uninitialized when used within its own initialization}} } bool x; @@ -163,6 +166,9 @@ A *a26 = new A(a26->get()); // expected-warning {{variable 'a26' is uninitial 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}} +const A a29(a29); // expected-warning {{variable 'a29' is uninitialized when used within its own initialization}} +const A a30 = a30; // expected-warning {{variable 'a30' is uninitialized when used within its own initialization}} + struct B { // POD struct. int x; @@ -209,6 +215,10 @@ void setupB() { 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}} + + const B b19 = b19; // expected-warning {{variable 'b19' is uninitialized when used within its own initialization}} + const B b20(b20); // expected-warning {{variable 'b20' is uninitialized when used within its own initialization}} + } B b1; @@ -234,6 +244,8 @@ B* b16 = getPtrB(b16->y); // expected-warning {{variable 'b16' is uninitialized 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}} +const B b19 = b19; // expected-warning {{variable 'b19' is uninitialized when used within its own initialization}} +const B b20(b20); // expected-warning {{variable 'b20' is uninitialized when used within its own initialization}} // Also test similar constructs in a field's initializer. struct S { @@ -385,6 +397,11 @@ namespace { G(char (*)[7]) : f3(f3->*f_ptr) {} // expected-warning {{field 'f3' is uninitialized when used here}} G(char (*)[8]) : f3(new F(f3->*ptr)) {} // expected-warning {{field 'f3' is uninitialized when used here}} }; + + struct H { + H() : a(a) {} // expected-warning {{field 'a' is uninitialized when used here}} + const A a; + }; } namespace statics { @@ -555,7 +572,7 @@ namespace record_fields { B(char (*)[9]) : a(normal(a)) {} // expected-warning {{uninitialized}} }; struct C { - C() {} // expected-note4{{in this constructor}} + C() {} // expected-note5{{in this constructor}} A a1 = a1; // expected-warning {{uninitialized}} A a2 = a2.get(); // expected-warning {{uninitialized}} A a3 = a3.num(); @@ -565,8 +582,9 @@ namespace record_fields { A a7 = const_ref(a7); A a8 = pointer(&a8); A a9 = normal(a9); // expected-warning {{uninitialized}} + const A a10 = a10; // expected-warning {{uninitialized}} }; - struct D { // expected-note4{{in the implicit default constructor}} + struct D { // expected-note5{{in the implicit default constructor}} A a1 = a1; // expected-warning {{uninitialized}} A a2 = a2.get(); // expected-warning {{uninitialized}} A a3 = a3.num(); @@ -576,6 +594,7 @@ namespace record_fields { A a7 = const_ref(a7); A a8 = pointer(&a8); A a9 = normal(a9); // expected-warning {{uninitialized}} + const A a10 = a10; // expected-warning {{uninitialized}} }; D d; struct E { @@ -588,6 +607,7 @@ namespace record_fields { A a7 = const_ref(a7); A a8 = pointer(&a8); A a9 = normal(a9); + const A a10 = a10; }; }