зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
906a7e1c0f
Коммит
1a5d35539a
|
@ -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'}}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче