From: Rafael Espindola Date: Sat, 27 Oct 2012 16:49:47 +0000 (+0000) Subject: Revert 166876 while I debug a bootstrap problem. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a92afb611c015196541edd53347aa23dba1949ac;p=clang Revert 166876 while I debug a bootstrap problem. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166878 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 6b82f15a95..a48779a1c3 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -123,7 +123,7 @@ typedef std::pair ScopePair; /// diagnostic that should be emitted if control goes over it. If not, return 0. static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { if (const VarDecl *VD = dyn_cast(D)) { - unsigned InDiag = 0; + unsigned InDiag = 0, OutDiag = 0; if (VD->getType()->isVariablyModifiedType()) InDiag = diag::note_protected_by_vla; @@ -164,53 +164,43 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { // where it is in scope is ill-formed unless the variable has // POD type and is declared without an initializer. - const Expr *Init = VD->getInit(); - if (!Init) - return ScopePair(InDiag, 0); - - const ExprWithCleanups *EWC = dyn_cast(Init); - if (EWC) - Init = EWC->getSubExpr(); - - const MaterializeTemporaryExpr *M = NULL; - Init = Init->findMaterializedTemporary(M); - - SmallVector Adjustments; - Init = Init->skipRValueSubobjectAdjustments(Adjustments); - - QualType QT = Init->getType(); - if (QT.isNull()) - return ScopePair(diag::note_protected_by_variable_init, 0); - - const Type *T = QT.getTypePtr(); - if (T->isArrayType()) - T = T->getBaseElementTypeUnsafe(); - - const CXXRecordDecl *Record = T->getAsCXXRecordDecl(); - if (!Record) - return ScopePair(diag::note_protected_by_variable_init, 0); - - // If we need to call a non trivial destructor for this variable, - // record an out diagnostic. - unsigned OutDiag = 0; - if (!Record->hasTrivialDestructor() && !Init->isGLValue()) - OutDiag = diag::note_exits_dtor; - - if (const CXXConstructExpr *cce = dyn_cast(Init)) { - const CXXConstructorDecl *ctor = cce->getConstructor(); - if (ctor->isTrivial() && ctor->isDefaultConstructor()) { - if (OutDiag) - InDiag = diag::note_protected_by_variable_nontriv_destructor; - else if (!Record->isPOD()) - InDiag = diag::note_protected_by_variable_non_pod; - return ScopePair(InDiag, OutDiag); + if (const Expr *init = VD->getInit()) { + // We actually give variables of record type (or array thereof) + // an initializer even if that initializer only calls a trivial + // ctor. Detect that case. + // FIXME: With generalized initializer lists, this may + // classify "X x{};" as having no initializer. + unsigned inDiagToUse = diag::note_protected_by_variable_init; + + const CXXRecordDecl *record = 0; + + if (const CXXConstructExpr *cce = dyn_cast(init)) { + const CXXConstructorDecl *ctor = cce->getConstructor(); + record = ctor->getParent(); + + if (ctor->isTrivial() && ctor->isDefaultConstructor()) { + if (!record->hasTrivialDestructor()) + inDiagToUse = diag::note_protected_by_variable_nontriv_destructor; + else if (!record->isPOD()) + inDiagToUse = diag::note_protected_by_variable_non_pod; + else + inDiagToUse = 0; + } + } else if (VD->getType()->isArrayType()) { + record = VD->getType()->getBaseElementTypeUnsafe() + ->getAsCXXRecordDecl(); } - } - return ScopePair(diag::note_protected_by_variable_init, OutDiag); - } + if (inDiagToUse) + InDiag = inDiagToUse; - return ScopePair(InDiag, 0); + // Also object to indirect jumps which leave scopes with dtors. + if (record && !record->hasTrivialDestructor()) + OutDiag = diag::note_exits_dtor; + } + } + + return ScopePair(InDiag, OutDiag); } if (const TypedefDecl *TD = dyn_cast(D)) { diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index 78228c0dc5..86d1bd8960 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -202,61 +202,3 @@ namespace test10 { return 0; } } - -// pr13812 -namespace test11 { - struct C { - C(int x); - ~C(); - }; - void f(void **ip) { - static void *ips[] = { &&l0 }; - l0: // expected-note {{possible target of indirect goto}} - C c0 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}} - goto *ip; // expected-error {{indirect goto might cross protected scopes}} - } -} - -namespace test12 { - struct C { - C(int x); - ~C(); - }; - void f(void **ip) { - static void *ips[] = { &&l0 }; - const C c0 = 17; - l0: // expected-note {{possible target of indirect goto}} - const C &c1 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}} - const C &c2 = c0; - goto *ip; // expected-error {{indirect goto might cross protected scopes}} - } -} - -namespace test13 { - struct C { - C(int x); - ~C(); - int i; - }; - void f(void **ip) { - static void *ips[] = { &&l0 }; - l0: // expected-note {{possible target of indirect goto}} - const int &c1 = C(1).i; // expected-note {{jump exits scope of variable with non-trivial destructor}} - goto *ip; // expected-error {{indirect goto might cross protected scopes}} - } -} - -namespace test14 { - struct C { - C(int x); - ~C(); - operator int&() const; - }; - void f(void **ip) { - static void *ips[] = { &&l0 }; - l0: - // no warning since the C temporary is destructed before the goto. - const int &c1 = C(1); - goto *ip; - } -}