зеркало из https://github.com/microsoft/clang-1.git
Clean up my changes to jump-diagnostic handling for local variables of
class type (or array thereof), eliminating some redundant checks (thanks Eli!) and adding some tests where the behavior differs in C++98/03 vs. C++0x. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132218 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0903421e36
Коммит
f61103ef33
|
@ -140,35 +140,33 @@ static std::pair<unsigned,unsigned>
|
|||
// a trivial default constructor and a trivial destructor, a
|
||||
// cv-qualified version of one of these types, or an array of one of
|
||||
// the preceding types and is declared without an initializer (8.5).
|
||||
if (VD->hasLocalStorage() && Context.getLangOptions().CPlusPlus) {
|
||||
// Check whether this is a C++ class.
|
||||
CXXRecordDecl *Record = T->getAsCXXRecordDecl();
|
||||
|
||||
if (const Expr *Init = VD->getInit()) {
|
||||
bool CallsTrivialConstructor = false;
|
||||
if (Record) {
|
||||
// FIXME: With generalized initializer lists, this may
|
||||
// classify "X x{};" as having no initializer.
|
||||
if (const CXXConstructExpr *Construct
|
||||
= dyn_cast<CXXConstructExpr>(Init))
|
||||
if (const CXXConstructorDecl *Constructor
|
||||
= Construct->getConstructor())
|
||||
if (Constructor->isDefaultConstructor() &&
|
||||
((Context.getLangOptions().CPlusPlus0x &&
|
||||
Record->hasTrivialDefaultConstructor()) ||
|
||||
(!Context.getLangOptions().CPlusPlus0x &&
|
||||
Record->isPOD())))
|
||||
CallsTrivialConstructor = true;
|
||||
}
|
||||
|
||||
if (!CallsTrivialConstructor)
|
||||
InDiag = diag::note_protected_by_variable_init;
|
||||
// Check whether this is a C++ class.
|
||||
CXXRecordDecl *Record = T->getAsCXXRecordDecl();
|
||||
|
||||
if (const Expr *Init = VD->getInit()) {
|
||||
bool CallsTrivialConstructor = false;
|
||||
if (Record) {
|
||||
// FIXME: With generalized initializer lists, this may
|
||||
// classify "X x{};" as having no initializer.
|
||||
if (const CXXConstructExpr *Construct
|
||||
= dyn_cast<CXXConstructExpr>(Init))
|
||||
if (const CXXConstructorDecl *Constructor
|
||||
= Construct->getConstructor())
|
||||
if (Constructor->isDefaultConstructor() &&
|
||||
((Context.getLangOptions().CPlusPlus0x &&
|
||||
Record->hasTrivialDefaultConstructor()) ||
|
||||
(!Context.getLangOptions().CPlusPlus0x &&
|
||||
Record->isPOD())))
|
||||
CallsTrivialConstructor = true;
|
||||
}
|
||||
|
||||
// Note whether we have a class with a non-trivial destructor.
|
||||
if (Record && !Record->hasTrivialDestructor())
|
||||
OutDiag = diag::note_exits_dtor;
|
||||
if (!CallsTrivialConstructor)
|
||||
InDiag = diag::note_protected_by_variable_init;
|
||||
}
|
||||
|
||||
// Note whether we have a class with a non-trivial destructor.
|
||||
if (Record && !Record->hasTrivialDestructor())
|
||||
OutDiag = diag::note_exits_dtor;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5646,7 +5646,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
|
|||
if ((!getLangOptions().CPlusPlus0x && !CXXRecord->isPOD()) ||
|
||||
(getLangOptions().CPlusPlus0x &&
|
||||
(!CXXRecord->hasTrivialDefaultConstructor() ||
|
||||
(!CXXRecord->hasTrivialDestructor()))))
|
||||
!CXXRecord->hasTrivialDestructor())))
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
// PR10034
|
||||
struct X {};
|
||||
|
||||
void exx(X) {}
|
||||
|
||||
int test_ptr10034(int argc, char **argv)
|
||||
{
|
||||
if (argc > 3)
|
||||
goto end;
|
||||
|
||||
X x;
|
||||
X xs[16];
|
||||
exx(x);
|
||||
|
||||
end:
|
||||
if (argc > 1) {
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Y {
|
||||
~Y();
|
||||
};
|
||||
|
||||
void f();
|
||||
void test_Y() {
|
||||
goto end;
|
||||
Y y;
|
||||
end:
|
||||
f();
|
||||
goto inner;
|
||||
{
|
||||
Y y2;
|
||||
inner:
|
||||
f();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct Z {
|
||||
Z operator=(const Z&);
|
||||
};
|
||||
|
||||
void test_Z() {
|
||||
goto end;
|
||||
Z z;
|
||||
end:
|
||||
return;
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
// PR10034
|
||||
struct X {};
|
||||
|
||||
void exx(X) {}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int test_ptr10034(int argc, char **argv)
|
||||
{
|
||||
if (argc > 3)
|
||||
goto end;
|
||||
|
@ -24,3 +23,25 @@ int main(int argc, char **argv)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Y {
|
||||
~Y();
|
||||
};
|
||||
|
||||
void test_Y() {
|
||||
goto end; // expected-error{{goto into protected scope}}
|
||||
Y y; // expected-note{{jump bypasses variable initialization}}
|
||||
end:
|
||||
return;
|
||||
}
|
||||
|
||||
struct Z {
|
||||
Z operator=(const Z&);
|
||||
};
|
||||
|
||||
void test_Z() {
|
||||
goto end; // expected-error{{goto into protected scope}}
|
||||
Z z; // expected-note{{jump bypasses variable initialization}}
|
||||
end:
|
||||
return;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче