summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-12-20 00:26:33 +0000
committerChris Lattner <sabre@nondot.org>2007-12-20 00:26:33 +0000
commit2da14fb84f007009384d7d7eae5dda2f6516f5f1 (patch)
treed070c00a93f942b6ced052e3d924aa0409520718
parent6d279d484a5e883af1afe557421d63d1928d7d10 (diff)
downloadbcm5719-llvm-2da14fb84f007009384d7d7eae5dda2f6516f5f1.tar.gz
bcm5719-llvm-2da14fb84f007009384d7d7eae5dda2f6516f5f1.zip
implement semantic analysis for __builtin_islessequal and friends.
llvm-svn: 45239
-rw-r--r--clang/Sema/Sema.h2
-rw-r--r--clang/Sema/SemaChecking.cpp55
-rw-r--r--clang/Sema/SemaExpr.cpp4
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--clang/test/Sema/builtins.c33
-rw-r--r--clang/test/Sema/cfstring.c10
6 files changed, 85 insertions, 21 deletions
diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h
index 0f494034c53..b783f59a073 100644
--- a/clang/Sema/Sema.h
+++ b/clang/Sema/Sema.h
@@ -729,6 +729,8 @@ private:
bool CheckBuiltinCFStringArgument(Expr* Arg);
bool SemaBuiltinVAStart(Expr *Fn, Expr** Args, unsigned NumArgs);
+ bool SemaBuiltinUnorderedCompare(Expr *Fn, Expr** Args, unsigned NumArgs,
+ SourceLocation RParenLoc);
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
};
diff --git a/clang/Sema/SemaChecking.cpp b/clang/Sema/SemaChecking.cpp
index 46afe7fea9b..01314102d42 100644
--- a/clang/Sema/SemaChecking.cpp
+++ b/clang/Sema/SemaChecking.cpp
@@ -33,19 +33,26 @@ using namespace clang;
/// and safety properties not strictly enforced by the C type system.
bool
Sema::CheckFunctionCall(Expr *Fn, SourceLocation RParenLoc,
- FunctionDecl *FDecl,
- Expr** Args, unsigned NumArgsInCall) {
+ FunctionDecl *FDecl, Expr** Args, unsigned NumArgs) {
// Get the IdentifierInfo* for the called function.
IdentifierInfo *FnInfo = FDecl->getIdentifier();
switch (FnInfo->getBuiltinID()) {
case Builtin::BI__builtin___CFStringMakeConstantString:
- assert(NumArgsInCall == 1 &&
- "Wrong number of arguments to builtin CFStringMakeConstantString");
+ assert(NumArgs == 1 &&
+ "Wrong # arguments to builtin CFStringMakeConstantString");
return CheckBuiltinCFStringArgument(Args[0]);
case Builtin::BI__builtin_va_start:
- return SemaBuiltinVAStart(Fn, Args, NumArgsInCall);
+ return SemaBuiltinVAStart(Fn, Args, NumArgs);
+
+ case Builtin::BI__builtin_isgreater:
+ case Builtin::BI__builtin_isgreaterequal:
+ case Builtin::BI__builtin_isless:
+ case Builtin::BI__builtin_islessequal:
+ case Builtin::BI__builtin_islessgreater:
+ case Builtin::BI__builtin_isunordered:
+ return SemaBuiltinUnorderedCompare(Fn, Args, NumArgs, RParenLoc);
}
// Search the KnownFunctionIDs for the identifier.
@@ -75,7 +82,7 @@ Sema::CheckFunctionCall(Expr *Fn, SourceLocation RParenLoc,
}
CheckPrintfArguments(Fn, RParenLoc, HasVAListArg,
- FDecl, format_idx, Args, NumArgsInCall);
+ FDecl, format_idx, Args, NumArgs);
}
return false;
@@ -170,6 +177,36 @@ bool Sema::SemaBuiltinVAStart(Expr *Fn, Expr** Args, unsigned NumArgs) {
return false;
}
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
+/// friends. This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnorderedCompare(Expr *Fn, Expr** Args, unsigned NumArgs,
+ SourceLocation RParenLoc) {
+ if (NumArgs < 2)
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args);
+ if (NumArgs > 2)
+ return Diag(Args[2]->getLocStart(), diag::err_typecheck_call_too_many_args,
+ SourceRange(Args[2]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd()));
+
+ Expr *OrigArg0 = Args[0];
+ Expr *OrigArg1 = Args[1];
+
+ // Do standard promotions between the two arguments, returning their common
+ // type.
+ QualType Res = UsualArithmeticConversions(Args[0], Args[1], false);
+
+ // If the common type isn't a real floating type, then the arguments were
+ // invalid for this operation.
+ if (!Res->isRealFloatingType())
+ return Diag(Args[0]->getLocStart(),
+ diag::err_typecheck_call_invalid_ordered_compare,
+ OrigArg0->getType().getAsString(),
+ OrigArg1->getType().getAsString(),
+ SourceRange(Args[0]->getLocStart(), Args[1]->getLocEnd()));
+
+ return false;
+}
+
/// CheckPrintfArguments - Check calls to printf (and similar functions) for
/// correct use of format strings.
@@ -221,9 +258,9 @@ void
Sema::CheckPrintfArguments(Expr *Fn, SourceLocation RParenLoc,
bool HasVAListArg, FunctionDecl *FDecl,
unsigned format_idx, Expr** Args,
- unsigned NumArgsInCall) {
+ unsigned NumArgs) {
// CHECK: printf-like function is called with no format string.
- if (format_idx >= NumArgsInCall) {
+ if (format_idx >= NumArgs) {
Diag(RParenLoc, diag::warn_printf_missing_format_string,
Fn->getSourceRange());
return;
@@ -314,7 +351,7 @@ Sema::CheckPrintfArguments(Expr *Fn, SourceLocation RParenLoc,
// string. This can only be determined for non vprintf-like
// functions. For those functions, this value is 1 (the sole
// va_arg argument).
- unsigned numDataArgs = NumArgsInCall-(format_idx+1);
+ unsigned numDataArgs = NumArgs-(format_idx+1);
// Inspect the format string.
unsigned StrIdx = 0;
diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp
index 9ae52551550..6d1d6a62e68 100644
--- a/clang/Sema/SemaExpr.cpp
+++ b/clang/Sema/SemaExpr.cpp
@@ -647,8 +647,8 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
break;
case Incompatible:
return Diag(l, diag::err_typecheck_passing_incompatible,
- rhsType.getAsString(), lhsType.getAsString(),
- Fn->getSourceRange(), argExpr->getSourceRange());
+ rhsType.getAsString(), lhsType.getAsString(),
+ Fn->getSourceRange(), argExpr->getSourceRange());
}
}
if (NumArgsInCall > NumArgsInProto && proto->isVariadic()) {
diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def
index 264024b2d94..89b289b97e7 100644
--- a/clang/include/clang/Basic/DiagnosticKinds.def
+++ b/clang/include/clang/Basic/DiagnosticKinds.def
@@ -783,6 +783,8 @@ DIAG(err_typecheck_call_too_few_args, ERROR,
"too few arguments to function")
DIAG(err_typecheck_call_too_many_args, ERROR,
"too many arguments to function")
+DIAG(err_typecheck_call_invalid_ordered_compare, ERROR,
+ "ordered compare requires two args of floating point type ('%0' and '%1')")
DIAG(err_typecheck_passing_incompatible, ERROR,
"incompatible types passing '%0' to function expecting '%1'")
DIAG(ext_typecheck_passing_incompatible_pointer, WARNING,
diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c
new file mode 100644
index 00000000000..997a8ede0ea
--- /dev/null
+++ b/clang/test/Sema/builtins.c
@@ -0,0 +1,33 @@
+// RUN: clang %s -fsyntax-only -verify
+
+int test1(float a, int b) {
+ return __builtin_isless(a, b);
+}
+int test2(int a, int b) {
+ return __builtin_islessequal(a, b); // expected-error {{floating point type}}
+}
+
+int test3(double a, float b) {
+ return __builtin_isless(a, b);
+}
+int test4(int* a, double b) {
+ return __builtin_islessequal(a, b); // expected-error {{floating point type}}
+}
+
+int test5(float a, long double b) {
+ return __builtin_isless(a, b, b); // expected-error {{too many arguments}}
+}
+int test6(float a, long double b) {
+ return __builtin_islessequal(a); // expected-error {{too few arguments}}
+}
+
+
+#define CFSTR __builtin___CFStringMakeConstantString
+void cfstring() {
+ CFSTR("\242"); // expected-warning {{ CFString literal contains non-ASCII character }}
+ CFSTR("\0"); // expected-warning {{ CFString literal contains NUL character }}
+ CFSTR(242); // expected-error {{ CFString literal is not a string constant }} \
+ expected-warning {{incompatible types}}
+ CFSTR("foo", "bar"); // expected-error {{ error: too many arguments to function }}
+}
+
diff --git a/clang/test/Sema/cfstring.c b/clang/test/Sema/cfstring.c
deleted file mode 100644
index 5c815d0ae8c..00000000000
--- a/clang/test/Sema/cfstring.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#define CFSTR __builtin___CFStringMakeConstantString
-
-// RUN: clang %s -fsyntax-only -verify
-void f() {
- CFSTR("\242"); // expected-warning {{ CFString literal contains non-ASCII character }}
- CFSTR("\0"); // expected-warning {{ CFString literal contains NUL character }}
- CFSTR(242); // expected-error {{ CFString literal is not a string constant }} \
- expected-warning {{incompatible types}}
- CFSTR("foo", "bar"); // expected-error {{ error: too many arguments to function }}
-}
OpenPOWER on IntegriCloud