]> granicus.if.org Git - clang/commitdiff
c: assignment/init of a function pointer whose function(s)
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 5 Oct 2011 00:05:34 +0000 (00:05 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 5 Oct 2011 00:05:34 +0000 (00:05 +0000)
return to one which does not return (has noreturn attribute)
should warn as it is an unsafe assignment. // rdar://10095762
c++ already handles this. This is the c version.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141141 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/Sema/SemaExpr.cpp
test/Sema/initialize-noreturn.c [new file with mode: 0644]

index 5e0c78409dae506f4b6a8fc53af6d94031fcbe3a..6f68c2dc2f4a7a4f181451844e576627f88a889d 100644 (file)
@@ -5543,13 +5543,13 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
   if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
     return QualType();
 
-  // It's noreturn if either type is.
-  // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
-  bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
-  if (NoReturn != lbaseInfo.getNoReturn())
+  // functypes which return are preferred over those that do not.
+  if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn())
     allLTypes = false;
-  if (NoReturn != rbaseInfo.getNoReturn())
+  else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn())
     allRTypes = false;
+  // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
+  bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
 
   FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
 
index 707d577f6136fac37f2659265ef1020bfccf595b..242fcfacde561da6279ee4c264dc9e6c99663133 100644 (file)
@@ -5277,6 +5277,9 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
     // General pointer incompatibility takes priority over qualifiers.
     return Sema::IncompatiblePointer;
   }
+  if (!S.getLangOptions().CPlusPlus &&
+      S.IsNoReturnConversion(ltrans, rtrans, ltrans))
+    return Sema::IncompatiblePointer;
   return ConvTy;
 }
 
diff --git a/test/Sema/initialize-noreturn.c b/test/Sema/initialize-noreturn.c
new file mode 100644 (file)
index 0000000..5557862
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+// rdar://10095762
+
+typedef void (*Fn_noret)(void) __attribute__((noreturn));
+typedef void (*Fn_ret)(void);
+
+void foo(void);
+void foo_noret(void)  __attribute__((noreturn));
+
+void test() {
+  Fn_noret fn2 = &foo; // expected-warning {{incompatible pointer types initializing 'Fn_noret'}}
+  Fn_noret fn3 = &foo_noret; 
+  Fn_ret fn4 = &foo_noret; 
+  Fn_ret fn5 = &foo;
+}
+