From: Rafael Espindola Date: Fri, 6 Jan 2012 04:54:01 +0000 (+0000) Subject: Improvements to the uninitialized variable warning: Check if the constructor X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1a5d35539a16f3b2eb2426f3f23a8376b190741c;p=clang Improvements to the uninitialized variable warning: Check if the constructor call is elidable or if the constructor is trivial instead of checking if it is user declared. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147652 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fecfce4d2d..d1bf3db19c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1107,7 +1107,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; // Types of valid local variables should be complete, so this should succeed. - if (const ValueDecl *VD = dyn_cast(D)) { + if (const VarDecl *VD = dyn_cast(D)) { // White-list anything with an __attribute__((unused)) type. QualType Ty = VD->getType(); @@ -1129,11 +1129,18 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; if (const CXXRecordDecl *RD = dyn_cast(Tag)) { - // FIXME: Checking for the presence of a user-declared constructor - // isn't completely accurate; we'd prefer to check that the initializer - // has no side effects. - if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor()) + if (!RD->hasTrivialDestructor()) return false; + + if (const Expr *Init = VD->getInit()) { + const CXXConstructExpr *Construct = + dyn_cast(Init); + if (Construct && !Construct->isElidable()) { + CXXConstructorDecl *CD = Construct->getConstructor(); + if (!CD->isTrivial()) + return false; + } + } } } diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index c3a5994af4..ec037cbb78 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -41,6 +41,7 @@ class A { A(int x) {} A(int *x) {} A(A *a) {} + ~A(); }; A getA() { return A(); } diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 5ba1f2a5f3..582701957e 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -80,3 +80,45 @@ namespace PR10168 { f(); // expected-note {{here}} } } + +namespace PR11550 { + struct S1 { + S1(); + }; + S1 makeS1(); + void testS1(S1 a) { + // This constructor call can be elided. + S1 x = makeS1(); // expected-warning {{unused variable 'x'}} + + // This one cannot, so no warning. + S1 y; + + // This call cannot, but the constructor is trivial. + S1 z = a; // expected-warning {{unused variable 'z'}} + } + + // The same is true even when we know thet constructor has side effects. + void foo(); + struct S2 { + S2() { + foo(); + } + }; + S2 makeS2(); + void testS2(S2 a) { + S2 x = makeS2(); // expected-warning {{unused variable 'x'}} + S2 y; + S2 z = a; // expected-warning {{unused variable 'z'}} + } + + // Or when the constructor is not declared by the user. + struct S3 { + S1 m; + }; + S3 makeS3(); + void testS3(S3 a) { + S3 x = makeS3(); // expected-warning {{unused variable 'x'}} + S3 y; + S3 z = a; // expected-warning {{unused variable 'z'}} + } +}