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
This commit is contained in:
Rafael Espindola 2012-01-06 04:54:01 +00:00
Родитель 906a7e1c0f
Коммит 1a5d35539a
3 изменённых файлов: 55 добавлений и 5 удалений

Просмотреть файл

@ -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<ValueDecl>(D)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(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<CXXRecordDecl>(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<CXXConstructExpr>(Init);
if (Construct && !Construct->isElidable()) {
CXXConstructorDecl *CD = Construct->getConstructor();
if (!CD->isTrivial())
return false;
}
}
}
}

Просмотреть файл

@ -41,6 +41,7 @@ class A {
A(int x) {}
A(int *x) {}
A(A *a) {}
~A();
};
A getA() { return A(); }

Просмотреть файл

@ -80,3 +80,45 @@ namespace PR10168 {
f<char>(); // 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'}}
}
}