From: Richard Smith Date: Mon, 3 Jun 2013 01:05:37 +0000 (+0000) Subject: Fix a couple of bugs where jump diagnostics would not notice that a variable X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b45a4d217cf1513b14a143143a2c3af8738a3cd7;p=clang Fix a couple of bugs where jump diagnostics would not notice that a variable has an initializer. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183092 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 8e446f8b9b..d3de173276 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -172,10 +172,6 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { if (EWC) Init = EWC->getSubExpr(); - // FIXME: Why are we looking through reference initialization? - // This causes us to incorrectly accept invalid code such as: - // struct S { int n; }; - // int f() { goto x; S &&s = S(); x: return x.n; } const MaterializeTemporaryExpr *M = NULL; Init = Init->findMaterializedTemporary(M); @@ -184,7 +180,7 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { Init = Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); QualType QT = Init->getType(); - if (QT.isNull() || !CommaLHSs.empty()) + if (QT.isNull()) return ScopePair(diag::note_protected_by_variable_init, 0); const Type *T = QT.getTypePtr(); @@ -203,7 +199,11 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { if (const CXXConstructExpr *cce = dyn_cast(Init)) { const CXXConstructorDecl *ctor = cce->getConstructor(); - if (ctor->isTrivial() && ctor->isDefaultConstructor()) { + // For a variable declared without an initializer, we will have + // call-style initialization and the initializer will be the + // CXXConstructExpr with no intervening nodes. + if (ctor->isTrivial() && ctor->isDefaultConstructor() && + VD->getInit() == Init && VD->getInitStyle() == VarDecl::CallInit) { if (OutDiag) InDiag = diag::note_protected_by_variable_nontriv_destructor; else if (!Record->isPOD()) diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index de276ae3d3..90c9317ecd 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -276,6 +276,27 @@ namespace test15 { } namespace test16 { + struct S { int n; }; + int f() { + goto x; // expected-error {{goto into protected scope}} + const S &s = S(); // expected-note {{jump bypasses variable initialization}} +x: return s.n; + } +} + +#if __cplusplus >= 201103L +namespace test17 { + struct S { int get(); private: int n; }; + int f() { + goto x; // expected-error {{goto into protected scope}} + S s = {}; // expected-note {{jump bypasses variable initialization}} +x: return s.get(); + } +} +#endif + +// This test must be last, because the error prohibits further jump diagnostics. +namespace testInvalid { Invalid inv; // expected-error {{unknown type name}} // Make sure this doesn't assert. void fn()