aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-08-19 00:52:13 +0000
committerTed Kremenek <kremenek@apple.com>2010-08-19 00:52:13 +0000
commit58f281f7d54976f23ed4fa23a10ff1ab9c7037fe (patch)
tree03322efd0175fe7850fae03b7a3d1f683a8bc63c
parentb56c1cc8ca593f832ca58d682876259c2ed9bec2 (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.td3
-rw-r--r--lib/Sema/SemaType.cpp15
-rw-r--r--test/Analysis/misc-ps.m2
-rw-r--r--test/Sema/attr-noreturn.c2
-rw-r--r--test/Sema/block-return.c4
-rw-r--r--test/Sema/return-noreturn.c4
-rw-r--r--test/Sema/return.c2
-rw-r--r--test/Sema/warn-unreachable.c2
-rw-r--r--test/SemaCXX/attr-noreturn.cpp2
-rw-r--r--test/SemaCXX/warn-unreachable.cpp4
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}}
}