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:
Douglas Gregor 2011-05-27 21:28:00 +00:00
Родитель 0903421e36
Коммит f61103ef33
4 изменённых файлов: 103 добавлений и 29 удалений

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

@ -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;
}