aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-02-14 18:57:46 +0000
committerDouglas Gregor <dgregor@apple.com>2009-02-14 18:57:46 +0000
commit3c385e5f8d9008fff18597ca302be19fa86e51f6 (patch)
tree8daddebd1007dcd0f23f8a442032c584da996663 /lib/Sema/SemaChecking.cpp
parentff975cfab9ada27df86038286d1678084aeb3428 (diff)
Add hook to add attributes to function declarations that we know
about, whether they are builtins or not. Use this to add the appropriate "format" attribute to NSLog, NSLogv, asprintf, and vasprintf, and to translate builtin attributes (from Builtins.def) into actual attributes on the function declaration. Use the "printf" format attribute on function declarations to determine whether we should do format string checking, rather than looking at an ad hoc list of builtins and "known" function names. Be a bit more careful about when we consider a function a "builtin" in C++. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp59
1 files changed, 26 insertions, 33 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 7ecc304fc9..e2ec2676c7 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
-#include "SemaUtil.h"
using namespace clang;
/// CheckFunctionCall - Check a direct function call for various correctness
@@ -34,7 +33,7 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
if (!FnInfo)
return move(TheCallResult);
- switch (FDecl->getBuiltinID()) {
+ switch (FDecl->getBuiltinID(Context)) {
case Builtin::BI__builtin___CFStringMakeConstantString:
assert(TheCall->getNumArgs() == 1 &&
"Wrong # arguments to builtin CFStringMakeConstantString");
@@ -78,27 +77,17 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
// handlers.
// Printf checking.
- unsigned format_idx = 0;
- bool HasVAListArg = false;
- if (FDecl->getBuiltinID() &&
- Context.BuiltinInfo.isPrintfLike(FDecl->getBuiltinID(), format_idx,
- HasVAListArg)) {
- // Found a printf builtin.
- } else if (FnInfo == KnownFunctionIDs[id_NSLog]) {
- format_idx = 0;
- HasVAListArg = false;
- } else if (FnInfo == KnownFunctionIDs[id_asprintf]) {
- format_idx = 1;
- HasVAListArg = false;
- } else if (FnInfo == KnownFunctionIDs[id_vasprintf]) {
- format_idx = 1;
- HasVAListArg = true;
- } else {
- return move(TheCallResult);
+ if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
+ if (Format->getType() == "printf") {
+ bool HasVAListArg = false;
+ if (const FunctionTypeProto *Proto
+ = FDecl->getType()->getAsFunctionTypeProto())
+ HasVAListArg = !Proto->isVariadic();
+ CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
+ Format->getFirstArg() - 1);
+ }
}
- CheckPrintfArguments(TheCall, HasVAListArg, format_idx);
-
return move(TheCallResult);
}
@@ -364,27 +353,27 @@ bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
// Handle i > 1 ? "x" : "y", recursivelly
bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx) {
+ unsigned format_idx, unsigned firstDataArg) {
switch (E->getStmtClass()) {
case Stmt::ConditionalOperatorClass: {
ConditionalOperator *C = cast<ConditionalOperator>(E);
return SemaCheckStringLiteral(C->getLHS(), TheCall,
- HasVAListArg, format_idx)
+ HasVAListArg, format_idx, firstDataArg)
&& SemaCheckStringLiteral(C->getRHS(), TheCall,
- HasVAListArg, format_idx);
+ HasVAListArg, format_idx, firstDataArg);
}
case Stmt::ImplicitCastExprClass: {
ImplicitCastExpr *Expr = dyn_cast<ImplicitCastExpr>(E);
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
- format_idx);
+ format_idx, firstDataArg);
}
case Stmt::ParenExprClass: {
ParenExpr *Expr = dyn_cast<ParenExpr>(E);
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
- format_idx);
+ format_idx, firstDataArg);
}
default: {
@@ -397,7 +386,8 @@ bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
StrE = dyn_cast<StringLiteral>(E);
if (StrE) {
- CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx);
+ CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx,
+ firstDataArg);
return true;
}
@@ -458,7 +448,7 @@ bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
/// For now, we ONLY do (1), (3), (5), (6), (7), and (8).
void
Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx) {
+ unsigned format_idx, unsigned firstDataArg) {
Expr *Fn = TheCall->getCallee();
// CHECK: printf-like function is called with no format string.
@@ -482,7 +472,9 @@ Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
// C string (e.g. "%d")
// ObjC string uses the same format specifiers as C string, so we can use
// the same format string checking logic for both ObjC and C strings.
- bool isFExpr = SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx);
+ bool isFExpr = SemaCheckStringLiteral(OrigFormatExpr, TheCall,
+ HasVAListArg, format_idx,
+ firstDataArg);
if (!isFExpr) {
// For vprintf* functions (i.e., HasVAListArg==true), we add a
@@ -516,7 +508,8 @@ Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
}
void Sema::CheckPrintfString(StringLiteral *FExpr, Expr *OrigFormatExpr,
- CallExpr *TheCall, bool HasVAListArg, unsigned format_idx) {
+ CallExpr *TheCall, bool HasVAListArg, unsigned format_idx,
+ unsigned firstDataArg) {
ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(OrigFormatExpr);
// CHECK: is the format string a wide literal?
@@ -554,7 +547,7 @@ void Sema::CheckPrintfString(StringLiteral *FExpr, Expr *OrigFormatExpr,
// 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 = TheCall->getNumArgs()-(format_idx+1);
+ unsigned numDataArgs = TheCall->getNumArgs()-firstDataArg;
// Inspect the format string.
unsigned StrIdx = 0;
@@ -1025,12 +1018,12 @@ void Sema::CheckFloatComparison(SourceLocation loc, Expr* lex, Expr *rex) {
// Check for comparisons with builtin types.
if (EmitWarning)
if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
- if (isCallBuiltin(CL))
+ if (CL->isBuiltinCall(Context))
EmitWarning = false;
if (EmitWarning)
if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
- if (isCallBuiltin(CR))
+ if (CR->isBuiltinCall(Context))
EmitWarning = false;
// Emit the diagnostic.