diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-12-21 18:19:17 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-12-21 18:19:17 +0000 |
commit | 51874dd2eda9e160b3413873459e31d32ffb7820 (patch) | |
tree | 707a994db2d2406190b490ddb57435eb0a262b3e | |
parent | 2b194418b83ecbe670a6e5a8e57b84f32d8b123b (diff) |
Allow comparison of 'void *' with function pointer
as a g++ extension (fixes radar 7481987).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91827 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 13 | ||||
-rw-r--r-- | test/SemaObjCXX/function-pointer-void-star.mm | 9 |
2 files changed, 21 insertions, 1 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 791948fb2b..f67a7a6bb9 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5170,7 +5170,18 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (getLangOptions().CPlusPlus) { if (LCanPointeeTy == RCanPointeeTy) return ResultTy; - + if (!isRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + // This is a gcc extension compatibility comparison. + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + return ResultTy; + } + } // C++ [expr.rel]p2: // [...] Pointer conversions (4.10) and qualification // conversions (4.4) are performed on pointer operands (or on diff --git a/test/SemaObjCXX/function-pointer-void-star.mm b/test/SemaObjCXX/function-pointer-void-star.mm new file mode 100644 index 0000000000..8d3d625173 --- /dev/null +++ b/test/SemaObjCXX/function-pointer-void-star.mm @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern "C" id (*_dealloc)(id) ; + +void foo() { + extern void *_original_dealloc; + if (_dealloc == _original_dealloc) { } + if (_dealloc != _original_dealloc) { } +} |