diff options
author | Chris Lattner <sabre@nondot.org> | 2007-12-20 00:26:33 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-12-20 00:26:33 +0000 |
commit | 2da14fb84f007009384d7d7eae5dda2f6516f5f1 (patch) | |
tree | d070c00a93f942b6ced052e3d924aa0409520718 | |
parent | 6d279d484a5e883af1afe557421d63d1928d7d10 (diff) | |
download | bcm5719-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.h | 2 | ||||
-rw-r--r-- | clang/Sema/SemaChecking.cpp | 55 | ||||
-rw-r--r-- | clang/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticKinds.def | 2 | ||||
-rw-r--r-- | clang/test/Sema/builtins.c | 33 | ||||
-rw-r--r-- | clang/test/Sema/cfstring.c | 10 |
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 }} -} |