diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-08-19 00:52:13 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-08-19 00:52:13 +0000 |
commit | 58f281f7d54976f23ed4fa23a10ff1ab9c7037fe (patch) | |
tree | 03322efd0175fe7850fae03b7a3d1f683a8bc63c | |
parent | b56c1cc8ca593f832ca58d682876259c2ed9bec2 (diff) |
Add warning for functions/blocks that have attribute 'noreturn' but return a non-void result. (<rdar://problem/7562925>)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111492 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 15 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 2 | ||||
-rw-r--r-- | test/Sema/attr-noreturn.c | 2 | ||||
-rw-r--r-- | test/Sema/block-return.c | 4 | ||||
-rw-r--r-- | test/Sema/return-noreturn.c | 4 | ||||
-rw-r--r-- | test/Sema/return.c | 2 | ||||
-rw-r--r-- | test/Sema/warn-unreachable.c | 2 | ||||
-rw-r--r-- | test/SemaCXX/attr-noreturn.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/warn-unreachable.cpp | 4 |
10 files changed, 28 insertions, 12 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b333a833b0..2a262980a9 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3135,6 +3135,9 @@ def ext_return_has_void_expr : Extension< def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, InGroup<DiagGroup<"invalid-noreturn">>; +def warn_noreturn_function_has_nonvoid_result : Warning< + "%select{functions|blocks}0 declared 'noreturn' should have a 'void' result type">, + InGroup<DiagGroup<"invalid-noreturn">>; def warn_falloff_noreturn_function : Warning< "function declared 'noreturn' should not return">, InGroup<DiagGroup<"invalid-noreturn">>; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index accd7e63ed..e3628c1d5f 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1833,6 +1833,14 @@ static void HandleObjCGCTypeAttribute(QualType &Type, Type = S.Context.getObjCGCQualType(Type, GCAttr); } +static QualType GetResultType(QualType T) { + if (const PointerType *PT = T->getAs<PointerType>()) + T = PT->getPointeeType(); + else if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) + T = BT->getPointeeType(); + return T->getAs<FunctionType>()->getResultType(); +} + /// Process an individual function attribute. Returns true if the /// attribute does not make sense to apply to this type. bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { @@ -1849,7 +1857,12 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { && !Type->isBlockPointerType() && !Type->isFunctionType()) return true; - + + if (!GetResultType(Type)->isVoidType()) { + S.Diag(Attr.getLoc(), diag::warn_noreturn_function_has_nonvoid_result) + << (Type->isBlockPointerType() ? /* blocks */ 1 : /* functions */ 0); + } + // Otherwise we can process right away. Type = S.Context.getNoReturnType(Type); return false; diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index f6a92831d7..b4fa77ef3e 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -323,7 +323,7 @@ int test_invalidate_by_ref() { // was the block containing the merge for '?', which would trigger an // assertion failure. int rdar_7027684_aux(); -int rdar_7027684_aux_2() __attribute__((noreturn)); +int rdar_7027684_aux_2() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} void rdar_7027684(int x, int y) { {}; // this empty compound statement is critical. (rdar_7027684_aux() ? rdar_7027684_aux_2() : (void) 0); diff --git a/test/Sema/attr-noreturn.c b/test/Sema/attr-noreturn.c index 5333a2c13f..927df7f412 100644 --- a/test/Sema/attr-noreturn.c +++ b/test/Sema/attr-noreturn.c @@ -9,7 +9,7 @@ static void __attribute__((noreturn)) f0(void) { } // expected-warning {{function declared 'noreturn' should not return}} // On K&R -int f1() __attribute__((noreturn)); +int f1() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} int g0 __attribute__((noreturn)); // expected-warning {{'noreturn' only applies to function types; type here is 'int'}} diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c index 5a4ec010d3..d40cef18d2 100644 --- a/test/Sema/block-return.c +++ b/test/Sema/block-return.c @@ -100,10 +100,10 @@ int (*funcptr3[5])(long); int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{block declared as returning an array}} void foo6() { - int (^b)(int) __attribute__((noreturn)); + int (^b)(int) __attribute__((noreturn)); // expected-warning{{blocks declared 'noreturn' should have a 'void' result type}} b = ^ (int i) __attribute__((noreturn)) { return 1; }; // expected-error {{block declared 'noreturn' should not return}} b(1); - int (^c)(void) __attribute__((noreturn)) = ^ __attribute__((noreturn)) { return 100; }; // expected-error {{block declared 'noreturn' should not return}} + int (^c)(void) __attribute__((noreturn)) = ^ __attribute__((noreturn)) { return 100; }; // expected-error {{block declared 'noreturn' should not return}} expected-warning{{blocks declared 'noreturn' should have a 'void' result type}} } diff --git a/test/Sema/return-noreturn.c b/test/Sema/return-noreturn.c index ff43754a42..a7f4e6f216 100644 --- a/test/Sema/return-noreturn.c +++ b/test/Sema/return-noreturn.c @@ -20,11 +20,11 @@ void test2_positive() { // This test case illustrates that we don't warn about the missing return // because the function is marked noreturn and there is an infinite loop. extern int foo_test_3(); -__attribute__((__noreturn__)) void* test3(int arg) { +__attribute__((__noreturn__)) void* test3(int arg) { // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} while (1) foo_test_3(); } -__attribute__((__noreturn__)) void* test3_positive(int arg) { +__attribute__((__noreturn__)) void* test3_positive(int arg) { // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} while (0) foo_test_3(); } // expected-warning{{function declared 'noreturn' should not return}} diff --git a/test/Sema/return.c b/test/Sema/return.c index 54c340634d..af78b41051 100644 --- a/test/Sema/return.c +++ b/test/Sema/return.c @@ -60,7 +60,7 @@ int test8() { (void)(1 + unknown()); } // expected-warning {{control reaches end of non-void function}} -int halt3() __attribute__((noreturn)); +int halt3() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} int test9() { (void)(halt3() + unknown()); diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c index 10ed6961a5..0d2efe95d6 100644 --- a/test/Sema/warn-unreachable.c +++ b/test/Sema/warn-unreachable.c @@ -1,6 +1,6 @@ // RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code -Wno-unused-value -int halt() __attribute__((noreturn)); +int halt() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} int live(); int dead(); diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp index b7d39992b8..dbf73fbae8 100644 --- a/test/SemaCXX/attr-noreturn.cpp +++ b/test/SemaCXX/attr-noreturn.cpp @@ -31,7 +31,7 @@ void test_f3() { class xpto { - int blah() __attribute__((noreturn)); + int blah() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} }; int xpto::blah() { diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index f5601cd2df..827dc48ce7 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -fblocks -Wunreachable-code -Wno-unused-value -int &halt() __attribute__((noreturn)); +int &halt() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} int &live(); int dead(); int liveti() throw(int); @@ -60,7 +60,7 @@ void test5() { struct S { int mem; } s; - S &foor() __attribute__((noreturn)); + S &foor() __attribute__((noreturn)); // expected-warning{{functions declared 'noreturn' should have a 'void' result type}} foor() .mem; // expected-warning {{will never be executed}} } |