From: Douglas Gregor Date: Fri, 27 May 2011 21:28:00 +0000 (+0000) Subject: Clean up my changes to jump-diagnostic handling for local variables of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f61103ef335fb273a98c1389e6fddaf796feb4b3;p=clang 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 --- diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 44ba103fe0..c1bcbef146 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -140,35 +140,33 @@ static std::pair // 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(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(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; } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 77bd5b79ae..5a3f6328ca 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5646,7 +5646,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, if ((!getLangOptions().CPlusPlus0x && !CXXRecord->isPOD()) || (getLangOptions().CPlusPlus0x && (!CXXRecord->hasTrivialDefaultConstructor() || - (!CXXRecord->hasTrivialDestructor())))) + !CXXRecord->hasTrivialDestructor()))) getCurFunction()->setHasBranchProtectedScope(); } } diff --git a/test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp b/test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp new file mode 100644 index 0000000000..b41504488e --- /dev/null +++ b/test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp @@ -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; +} diff --git a/test/CXX/stmt.stmt/stmt.dcl/p3.cpp b/test/CXX/stmt.stmt/stmt.dcl/p3.cpp index 2cf745e450..18fd34039e 100644 --- a/test/CXX/stmt.stmt/stmt.dcl/p3.cpp +++ b/test/CXX/stmt.stmt/stmt.dcl/p3.cpp @@ -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; +}