diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-10-05 00:05:34 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-10-05 00:05:34 +0000 |
commit | 48c69106e4ce1759b6df61d5e6a59a22768944a8 (patch) | |
tree | f3e0771f7294ad9b77b408624aabaa49e968065e /clang | |
parent | 202803e39c74418b216f49f61d0941c9a651e301 (diff) | |
download | bcm5719-llvm-48c69106e4ce1759b6df61d5e6a59a22768944a8.tar.gz bcm5719-llvm-48c69106e4ce1759b6df61d5e6a59a22768944a8.zip |
c: assignment/init of a function pointer whose function(s)
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.
llvm-svn: 141141
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 3 | ||||
-rw-r--r-- | clang/test/Sema/initialize-noreturn.c | 16 |
3 files changed, 24 insertions, 5 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5e0c78409da..6f68c2dc2f4 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -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); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 707d577f613..242fcfacde5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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/clang/test/Sema/initialize-noreturn.c b/clang/test/Sema/initialize-noreturn.c new file mode 100644 index 00000000000..55578628716 --- /dev/null +++ b/clang/test/Sema/initialize-noreturn.c @@ -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; +} + |