From 30ce344307f8a8b00054021307015571f83c7364 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 19 Dec 2007 23:59:04 +0000 Subject: [PATCH] refactor some code that handles sema of direct function calls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45234 91177308-0d34-0410-b5e6-96231b3b80d8 --- Sema/Sema.h | 7 ++- Sema/SemaChecking.cpp | 112 +++++++++++++++++++++++------------------- Sema/SemaExpr.cpp | 3 +- 3 files changed, 65 insertions(+), 57 deletions(-) diff --git a/Sema/Sema.h b/Sema/Sema.h index 3722ec2560..0f494034c5 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -714,13 +714,11 @@ private: // Extra semantic analysis beyond the C type system private: - bool CheckFunctionCall(Expr *Fn, - SourceLocation LParenLoc, SourceLocation RParenLoc, + bool CheckFunctionCall(Expr *Fn, SourceLocation RParenLoc, FunctionDecl *FDecl, Expr** Args, unsigned NumArgsInCall); - void CheckPrintfArguments(Expr *Fn, - SourceLocation LParenLoc, SourceLocation RParenLoc, + void CheckPrintfArguments(Expr *Fn, SourceLocation RParenLoc, bool HasVAListArg, FunctionDecl *FDecl, unsigned format_idx, Expr** Args, unsigned NumArgsInCall); @@ -730,6 +728,7 @@ private: bool CheckBuiltinCFStringArgument(Expr* Arg); + bool SemaBuiltinVAStart(Expr *Fn, Expr** Args, unsigned NumArgs); void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); }; diff --git a/Sema/SemaChecking.cpp b/Sema/SemaChecking.cpp index 4d2e362038..8bb263e84e 100644 --- a/Sema/SemaChecking.cpp +++ b/Sema/SemaChecking.cpp @@ -32,52 +32,20 @@ using namespace clang; /// CheckFunctionCall - Check a direct function call for various correctness /// and safety properties not strictly enforced by the C type system. bool -Sema::CheckFunctionCall(Expr *Fn, - SourceLocation LParenLoc, SourceLocation RParenLoc, +Sema::CheckFunctionCall(Expr *Fn, SourceLocation RParenLoc, FunctionDecl *FDecl, Expr** Args, unsigned NumArgsInCall) { // Get the IdentifierInfo* for the called function. IdentifierInfo *FnInfo = FDecl->getIdentifier(); - if (FnInfo->getBuiltinID() == - Builtin::BI__builtin___CFStringMakeConstantString) { + switch (FnInfo->getBuiltinID()) { + case Builtin::BI__builtin___CFStringMakeConstantString: assert(NumArgsInCall == 1 && "Wrong number of arguments to builtin CFStringMakeConstantString"); return CheckBuiltinCFStringArgument(Args[0]); - } else if (FnInfo->getBuiltinID() == Builtin::BI__builtin_va_start) { - if (NumArgsInCall > 2) { - Diag(Args[2]->getLocStart(), - diag::err_typecheck_call_too_many_args, Fn->getSourceRange(), - SourceRange(Args[2]->getLocStart(), - Args[NumArgsInCall - 1]->getLocEnd())); - return true; - } - - FunctionTypeProto* proto = CurFunctionDecl ? - cast(CurFunctionDecl->getType()) : - cast(ObjcGetTypeForMethodDefinition(CurMethodDecl)); - if (!proto->isVariadic()) { - Diag(Fn->getLocStart(), - diag::err_va_start_used_in_non_variadic_function); - return true; - } - // FIXME: This isn't correct for methods (results in bogus warning). - bool SecondArgIsLastNamedArgument = false; - if (DeclRefExpr *DR = dyn_cast(Args[1])) { - if (ParmVarDecl *PV = dyn_cast(DR->getDecl())) { - ParmVarDecl *LastNamedArg = CurFunctionDecl ? - CurFunctionDecl->getParamDecl(CurFunctionDecl->getNumParams() - 1) : - CurMethodDecl->getParamDecl(CurMethodDecl->getNumParams() - 1); - - if (PV == LastNamedArg) - SecondArgIsLastNamedArgument = true; - } - } - - if (!SecondArgIsLastNamedArgument) - Diag(Args[1]->getLocStart(), - diag::warn_second_parameter_of_va_start_not_last_named_argument); + case Builtin::BI__builtin_va_start: + return SemaBuiltinVAStart(Fn, Args, NumArgsInCall); } // Search the KnownFunctionIDs for the identifier. @@ -93,20 +61,20 @@ Sema::CheckFunctionCall(Expr *Fn, bool HasVAListArg = false; switch (i) { - default: assert(false && "No format string argument index."); - case id_printf: format_idx = 0; break; - case id_fprintf: format_idx = 1; break; - case id_sprintf: format_idx = 1; break; - case id_snprintf: format_idx = 2; break; - case id_asprintf: format_idx = 1; break; - case id_vsnprintf: format_idx = 2; HasVAListArg = true; break; - case id_vasprintf: format_idx = 1; HasVAListArg = true; break; - case id_vfprintf: format_idx = 1; HasVAListArg = true; break; - case id_vsprintf: format_idx = 1; HasVAListArg = true; break; - case id_vprintf: format_idx = 0; HasVAListArg = true; break; + default: assert(false && "No format string argument index."); + case id_printf: format_idx = 0; break; + case id_fprintf: format_idx = 1; break; + case id_sprintf: format_idx = 1; break; + case id_snprintf: format_idx = 2; break; + case id_asprintf: format_idx = 1; break; + case id_vsnprintf: format_idx = 2; HasVAListArg = true; break; + case id_vasprintf: format_idx = 1; HasVAListArg = true; break; + case id_vfprintf: format_idx = 1; HasVAListArg = true; break; + case id_vsprintf: format_idx = 1; HasVAListArg = true; break; + case id_vprintf: format_idx = 0; HasVAListArg = true; break; } - CheckPrintfArguments(Fn, LParenLoc, RParenLoc, HasVAListArg, + CheckPrintfArguments(Fn, RParenLoc, HasVAListArg, FDecl, format_idx, Args, NumArgsInCall); } @@ -157,6 +125,49 @@ bool Sema::CheckBuiltinCFStringArgument(Expr* Arg) { return false; } +bool Sema::SemaBuiltinVAStart(Expr *Fn, Expr** Args, unsigned NumArgs) { + if (NumArgs > 2) { + Diag(Args[2]->getLocStart(), + diag::err_typecheck_call_too_many_args, Fn->getSourceRange(), + SourceRange(Args[2]->getLocStart(), Args[NumArgs-1]->getLocEnd())); + return true; + } + + FunctionTypeProto *Proto; + if (CurFunctionDecl) + Proto = cast(CurFunctionDecl->getType()); + else + Proto = + cast(ObjcGetTypeForMethodDefinition(CurMethodDecl)); + + if (!Proto->isVariadic()) { + Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function); + return true; + } + + // Verify that the second argument to the builtin is the last argument of the + // current function or method. + bool SecondArgIsLastNamedArgument = false; + if (DeclRefExpr *DR = dyn_cast(Args[1])) { + if (ParmVarDecl *PV = dyn_cast(DR->getDecl())) { + // FIXME: This isn't correct for methods (results in bogus warning). + // Get the last formal in the current function. + ParmVarDecl *LastArg; + if (CurFunctionDecl) + LastArg = *(CurFunctionDecl->param_end()-1); + else + LastArg = *(CurMethodDecl->param_end()-1); + SecondArgIsLastNamedArgument = PV == LastArg; + } + } + + if (!SecondArgIsLastNamedArgument) + Diag(Args[1]->getLocStart(), + diag::warn_second_parameter_of_va_start_not_last_named_argument); + return false; +} + + /// CheckPrintfArguments - Check calls to printf (and similar functions) for /// correct use of format strings. /// @@ -204,8 +215,7 @@ bool Sema::CheckBuiltinCFStringArgument(Expr* Arg) { /// /// For now, we ONLY do (1), (3), (5), (6), (7), and (8). void -Sema::CheckPrintfArguments(Expr *Fn, - SourceLocation LParenLoc, SourceLocation RParenLoc, +Sema::CheckPrintfArguments(Expr *Fn, SourceLocation RParenLoc, bool HasVAListArg, FunctionDecl *FDecl, unsigned format_idx, Expr** Args, unsigned NumArgsInCall) { diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 53049c6dec..8ca2879b00 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -680,8 +680,7 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc, if (ImplicitCastExpr *IcExpr = dyn_cast(Fn)) if (DeclRefExpr *DRExpr = dyn_cast(IcExpr->getSubExpr())) if (FunctionDecl *FDecl = dyn_cast(DRExpr->getDecl())) - if (CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args, - NumArgsInCall)) + if (CheckFunctionCall(Fn, RParenLoc, FDecl, Args, NumArgsInCall)) return true; return new CallExpr(Fn, Args, NumArgsInCall, resultType, RParenLoc); -- 2.40.0