]> granicus.if.org Git - clang/commitdiff
PR4836, part 1: add Sema support for __builtin_isnan and friends; they
authorEli Friedman <eli.friedman@gmail.com>
Mon, 31 Aug 2009 20:06:00 +0000 (20:06 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 31 Aug 2009 20:06:00 +0000 (20:06 +0000)
are apparently used by Solaris libc despite the fact that clang claims
to be compatible with gcc 4.2, which doesn't support them.

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

include/clang/Basic/Builtins.def
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaChecking.cpp
test/Sema/builtin-unary-fp.c [new file with mode: 0644]

index d30a7c84ef17ef09b075f4c6000a7e05fbe4cb75..e0268b7122d10a48d24be63ed156f438c373820a 100644 (file)
@@ -106,6 +106,14 @@ BUILTIN(__builtin_islessequal   , "i.", "nc")
 BUILTIN(__builtin_islessgreater , "i.", "nc")
 BUILTIN(__builtin_isunordered   , "i.", "nc")
 
+// Unary FP classification
+// BUILTIN(__builtin_fpclassify, "iiiii.", "nc")
+BUILTIN(__builtin_isfinite,   "i.", "nc")
+BUILTIN(__builtin_isinf,      "i.", "nc")
+BUILTIN(__builtin_isinf_sign, "i.", "nc")
+BUILTIN(__builtin_isnan,      "i.", "nc")
+BUILTIN(__builtin_isnormal,   "i.", "nc")
+
 // Builtins for arithmetic.
 BUILTIN(__builtin_clz  , "iUi"  , "nc")
 BUILTIN(__builtin_clzl , "iULi" , "nc")
index 564eacb4b4d935d2a52bac66dad9f03196937766..5e9c7486d34b5c505df7df1c82d9e8e2658e903d 100644 (file)
@@ -1681,6 +1681,9 @@ def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
 
 def err_typecheck_call_invalid_ordered_compare : Error<
   "ordered compare requires two args of floating point type (%0 and %1)">;
+def err_typecheck_call_invalid_unary_fp : Error<
+  "floating point classification requires argument of floating point type "
+  "(passed in %0)">;
 def err_typecheck_cond_expect_scalar : Error<
   "used type %0 where arithmetic or pointer type is required">;
 def ext_typecheck_cond_one_void : Extension<
index f9c893f0a04da889e130884f709bba40fab37408..2a2515ff1142bcfe7958c35b64c24860156d96d9 100644 (file)
@@ -3494,6 +3494,7 @@ private:
                                                     CallExpr *TheCall);
   bool SemaBuiltinVAStart(CallExpr *TheCall);
   bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+  bool SemaBuiltinUnaryFP(CallExpr *TheCall);
   bool SemaBuiltinStackAddress(CallExpr *TheCall);
 
 public:
index e6fa3727369e9d275c98337b6cb2ff253523d17a..449c5f338400612319ef0f2340ab03b25e9a9dd9 100644 (file)
@@ -125,6 +125,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     if (SemaBuiltinUnorderedCompare(TheCall))
       return ExprError();
     break;
+  case Builtin::BI__builtin_isfinite:
+  case Builtin::BI__builtin_isinf:
+  case Builtin::BI__builtin_isinf_sign:
+  case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnormal:
+    if (SemaBuiltinUnaryFP(TheCall))
+      return ExprError();
+    break;
   case Builtin::BI__builtin_return_address:
   case Builtin::BI__builtin_frame_address:
     if (SemaBuiltinStackAddress(TheCall))
@@ -557,6 +565,33 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
   return false;
 }
 
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isnan and
+/// friends.  This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnaryFP(CallExpr *TheCall) {
+  if (TheCall->getNumArgs() < 1)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 /*function call*/;
+  if (TheCall->getNumArgs() > 1)
+    return Diag(TheCall->getArg(1)->getLocStart(), 
+                diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/
+      << SourceRange(TheCall->getArg(1)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+
+  Expr *OrigArg = TheCall->getArg(0);
+  
+  if (OrigArg->isTypeDependent())
+    return false;
+
+  // This operation requires a floating-point number
+  if (!OrigArg->getType()->isRealFloatingType())
+    return Diag(OrigArg->getLocStart(), 
+                diag::err_typecheck_call_invalid_unary_fp)
+      << OrigArg->getType() << OrigArg->getSourceRange();
+  
+  return false;
+}
+
 bool Sema::SemaBuiltinStackAddress(CallExpr *TheCall) {
   // The signature for these builtins is exact; the only thing we need
   // to check is that the argument is a constant.
diff --git a/test/Sema/builtin-unary-fp.c b/test/Sema/builtin-unary-fp.c
new file mode 100644 (file)
index 0000000..70c7a29
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: clang-cc %s -fsyntax-only -verify -pedantic
+void check(int);
+void a() {
+  check(__builtin_isfinite(1.0f));
+  check(__builtin_isinf(1.0));
+  check(__builtin_isinf_sign(1.0L));
+  check(__builtin_isnan(1.0f));
+  check(__builtin_isnormal(1.0f));
+  check(__builtin_isfinite(1)); // expected-error{{requires argument of floating point type}}
+  check(__builtin_isinf()); // expected-error{{too few arguments}}
+  check(__builtin_isnan(1,2)); // expected-error{{too many arguments}}
+}