diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -520,11 +520,11 @@ namespace { struct CheckFallThroughDiagnostics { - unsigned diag_MaybeFallThrough_HasNoReturn; - unsigned diag_MaybeFallThrough_ReturnsNonVoid; - unsigned diag_AlwaysFallThrough_HasNoReturn; - unsigned diag_AlwaysFallThrough_ReturnsNonVoid; - unsigned diag_NeverFallThroughOrReturn; + unsigned diag_MaybeFallThrough_HasNoReturn = 0; + unsigned diag_MaybeFallThrough_ReturnsNonVoid = 0; + unsigned diag_AlwaysFallThrough_HasNoReturn = 0; + unsigned diag_AlwaysFallThrough_ReturnsNonVoid = 0; + unsigned diag_NeverFallThroughOrReturn = 0; enum { Function, Block, Lambda, Coroutine } funMode; SourceLocation FuncLoc; @@ -554,8 +554,6 @@ if (!isVirtualMethod && !isTemplateInstantiation) D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function; - else - D.diag_NeverFallThroughOrReturn = 0; D.funMode = Function; return D; @@ -564,10 +562,8 @@ static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) { CheckFallThroughDiagnostics D; D.FuncLoc = Func->getLocation(); - D.diag_MaybeFallThrough_HasNoReturn = 0; D.diag_MaybeFallThrough_ReturnsNonVoid = diag::warn_maybe_falloff_nonvoid_coroutine; - D.diag_AlwaysFallThrough_HasNoReturn = 0; D.diag_AlwaysFallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid_coroutine; D.funMode = Coroutine; @@ -584,7 +580,6 @@ diag::err_noreturn_block_has_return_expr; D.diag_AlwaysFallThrough_ReturnsNonVoid = diag::err_falloff_nonvoid_block; - D.diag_NeverFallThroughOrReturn = 0; D.funMode = Block; return D; } @@ -599,7 +594,6 @@ diag::err_noreturn_lambda_has_return_expr; D.diag_AlwaysFallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid_lambda; - D.diag_NeverFallThroughOrReturn = 0; D.funMode = Lambda; return D; } @@ -700,7 +694,7 @@ EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid); break; case NeverFallThroughOrReturn: - if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { + if (!HasNoReturn && CD.diag_NeverFallThroughOrReturn) { if (const FunctionDecl *FD = dyn_cast(D)) { S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD; } else if (const ObjCMethodDecl *MD = dyn_cast(D)) { diff --git a/clang/test/SemaCXX/return-noreturn.cpp b/clang/test/SemaCXX/return-noreturn.cpp --- a/clang/test/SemaCXX/return-noreturn.cpp +++ b/clang/test/SemaCXX/return-noreturn.cpp @@ -15,28 +15,28 @@ // the presence of switches, case statements, labels, and blocks. These tests // try to cover bugs reported in both PR6884 and PR10063. namespace abort_struct_complex_cfgs { - int basic(int x) { + __attribute__((noreturn)) int basic(int x) { switch (x) { default: pr6884_abort(); } } - int f1(int x) { + __attribute__((noreturn)) int f1(int x) { switch (x) default: pr6884_abort_struct(); } - int f2(int x) { + __attribute__((noreturn)) int f2(int x) { switch (x) { default: pr6884_abort_struct(); } } int f2_positive(int x) { switch (x) { default: ; } } // expected-warning {{non-void function does not return a value}} - int f3(int x) { + __attribute__((noreturn)) int f3(int x) { switch (x) { default: { pr6884_abort_struct(); } } } - int f4(int x) { + __attribute__((noreturn)) int f4(int x) { switch (x) default: L1: L2: case 4: pr6884_abort_struct(); } - int f5(int x) { + __attribute__((noreturn)) int f5(int x) { switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); } } - int f6(int x) { + __attribute__((noreturn)) int f6(int x) { switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } } @@ -50,11 +50,11 @@ // Test that these constructs work even when extraneous blocks are created // before and after the switch due to implicit destructors. - int g1(int x) { + __attribute__((noreturn)) int g1(int x) { other o; switch (x) default: pr6884_abort_struct(); } - int g2(int x) { + __attribute__((noreturn)) int g2(int x) { other o; switch (x) { default: pr6884_abort_struct(); } } @@ -62,46 +62,46 @@ other o; switch (x) { default: ; } } // expected-warning {{non-void function does not return a value}} - int g3(int x) { + __attribute__((noreturn)) int g3(int x) { other o; switch (x) { default: { pr6884_abort_struct(); } } } - int g4(int x) { + __attribute__((noreturn)) int g4(int x) { other o; switch (x) default: L1: L2: case 4: pr6884_abort_struct(); } - int g5(int x) { + __attribute__((noreturn)) int g5(int x) { other o; switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); } } - int g6(int x) { + __attribute__((noreturn)) int g6(int x) { other o; switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } } // Test that these constructs work even with variables carrying the no-return // destructor instead of temporaries. - int h1(int x) { + __attribute__((noreturn)) int h1(int x) { other o; switch (x) default: pr6884_abort_struct a; } - int h2(int x) { + __attribute__((noreturn)) int h2(int x) { other o; switch (x) { default: pr6884_abort_struct a; } } - int h3(int x) { + __attribute__((noreturn)) int h3(int x) { other o; switch (x) { default: { pr6884_abort_struct a; } } } - int h4(int x) { + __attribute__((noreturn)) int h4(int x) { other o; switch (x) default: L1: L2: case 4: pr6884_abort_struct a; } - int h5(int x) { + __attribute__((noreturn)) int h5(int x) { other o; switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; } } - int h6(int x) { + __attribute__((noreturn)) int h6(int x) { other o; switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; } } @@ -155,11 +155,11 @@ operator bool() const; }; -int testTernaryUnconditionalNoreturn() { +__attribute__((noreturn)) int testTernaryUnconditionalNoreturn() { true ? NoReturn() : NoReturn(); } -int testTernaryStaticallyConditionalNoretrunOnTrue() { +__attribute__((noreturn)) int testTernaryStaticallyConditionalNoretrunOnTrue() { true ? NoReturn() : Return(); } @@ -167,7 +167,7 @@ true ? Return() : NoReturn(); } // expected-warning {{non-void function does not return a value}} -int testTernaryStaticallyConditionalNoretrunOnFalse() { +__attribute__((noreturn)) int testTernaryStaticallyConditionalNoretrunOnFalse() { false ? Return() : NoReturn(); } @@ -191,11 +191,11 @@ value || (false ? true : NoReturn()); } // expected-warning {{non-void function does not return a value in all control paths}} -int testStaticallyExecutedLogicalOrBranch() { +__attribute__((noreturn)) int testStaticallyExecutedLogicalOrBranch() { false || NoReturn(); } -int testStaticallyExecutedLogicalAndBranch() { +__attribute__((noreturn)) int testStaticallyExecutedLogicalAndBranch() { true && NoReturn(); } @@ -215,11 +215,11 @@ (true && value) || (true && NoReturn()); } // expected-warning {{non-void function does not return a value in all control paths}} -int testConditionallyExecutedComplexLogicalBranch3(bool value) { +__attribute__((noreturn)) int testConditionallyExecutedComplexLogicalBranch3(bool value) { (false && (Return() || true)) || (true && NoReturn()); } -int testConditionallyExecutedComplexLogicalBranch4(bool value) { +__attribute__((noreturn)) int testConditionallyExecutedComplexLogicalBranch4(bool value) { false || ((Return() || true) && (true && NoReturn())); } @@ -238,7 +238,7 @@ foo(); } // expected-warning {{non-void function does not return a value}} - int baz() { + __attribute__((noreturn)) int baz() { FatalCopy fc; X work([fc](){}); foo(); diff --git a/clang/test/SemaObjC/return.m b/clang/test/SemaObjC/return.m --- a/clang/test/SemaObjC/return.m +++ b/clang/test/SemaObjC/return.m @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-noreturn -fobjc-exceptions -Wno-objc-root-class %s -int test1(void) { +__attribute__((noreturn)) int test1(void) { id a; @throw a; }