summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-02-14 00:32:47 +0000
committerDouglas Gregor <dgregor@apple.com>2009-02-14 00:32:47 +0000
commitac5d4c5f8ec84453fe22a3c3b1bdb8ffd765423e (patch)
tree146387c45453bb4edb7bdff4ba294e2d7baa521f /clang/lib
parent6e1b2e36a5a8e27b07c9c3061621fe48d11fc031 (diff)
downloadbcm5719-llvm-ac5d4c5f8ec84453fe22a3c3b1bdb8ffd765423e.tar.gz
bcm5719-llvm-ac5d4c5f8ec84453fe22a3c3b1bdb8ffd765423e.zip
Extend builtin "attribute" syntax to include a notation for
printf-like functions, both builtin functions and those in the C library. The function-call checker now queries this attribute do determine if we have a printf-like function, rather than scanning through the list of "known functions IDs". However, there are 5 functions they are not yet "builtins", so the function-call checker handles them specifically still: - fprintf and vfprintf: the builtins mechanism cannot (yet) express FILE* arguments, so these can't be encoded. - NSLog: the builtins mechanism cannot (yet) express NSString* arguments, so this (and NSLogv) can't be encoded. - asprintf and vasprintf: these aren't part of the C99 standard library, so we really shouldn't be defining them as builtins in the general case (and we don't seem to have the machinery to make them builtins only on certain targets and depending on whether extensions are enabled). llvm-svn: 64512
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Builtins.cpp35
-rw-r--r--clang/lib/Sema/Sema.cpp15
-rw-r--r--clang/lib/Sema/Sema.h12
-rw-r--r--clang/lib/Sema/SemaChecking.cpp52
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
5 files changed, 60 insertions, 56 deletions
diff --git a/clang/lib/AST/Builtins.cpp b/clang/lib/AST/Builtins.cpp
index b675c729738..e7ec1372a8e 100644
--- a/clang/lib/AST/Builtins.cpp
+++ b/clang/lib/AST/Builtins.cpp
@@ -49,6 +49,41 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
}
+std::string Builtin::Context::getHeaderName(unsigned ID) const {
+ char *Name = strchr(GetRecord(ID).Attributes, 'f');
+ if (!Name)
+ return 0;
+ ++Name;
+
+ if (*Name != ':')
+ return 0;
+
+ ++Name;
+ char *NameEnd = strchr(Name, ':');
+ assert(NameEnd && "Missing ':' after header name");
+ return std::string(Name, NameEnd);
+}
+
+bool
+Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg) {
+ char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
+ if (!Printf)
+ return false;
+
+ HasVAListArg = (*Printf == 'P');
+
+ ++Printf;
+ assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
+ ++Printf;
+
+ char *PrintfEnd = strchr(Printf, ':');
+ assert(PrintfEnd && "printf specifier must end with a ':'");
+
+ FormatIdx = strtol(Printf, 0, 10);
+ return true;
+}
+
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
/// pointer over the consumed characters. This returns the resultant type.
static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 8667ee28e25..45ef03506f2 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -131,22 +131,11 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
// do extra checking.
IdentifierTable &IT = PP.getIdentifierTable();
- KnownFunctionIDs[id_printf] = &IT.get("printf");
- KnownFunctionIDs[id_fprintf] = &IT.get("fprintf");
- KnownFunctionIDs[id_sprintf] = &IT.get("sprintf");
- KnownFunctionIDs[id_sprintf_chk] = &IT.get("__builtin___sprintf_chk");
- KnownFunctionIDs[id_snprintf] = &IT.get("snprintf");
- KnownFunctionIDs[id_snprintf_chk] = &IT.get("__builtin___snprintf_chk");
- KnownFunctionIDs[id_asprintf] = &IT.get("asprintf");
KnownFunctionIDs[id_NSLog] = &IT.get("NSLog");
- KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf");
+ KnownFunctionIDs[id_asprintf] = &IT.get("asprintf");
+ KnownFunctionIDs[id_fprintf] = &IT.get("fprintf");
KnownFunctionIDs[id_vasprintf] = &IT.get("vasprintf");
KnownFunctionIDs[id_vfprintf] = &IT.get("vfprintf");
- KnownFunctionIDs[id_vsprintf] = &IT.get("vsprintf");
- KnownFunctionIDs[id_vsprintf_chk] = &IT.get("__builtin___vsprintf_chk");
- KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf");
- KnownFunctionIDs[id_vsnprintf_chk] = &IT.get("__builtin___vsnprintf_chk");
- KnownFunctionIDs[id_vprintf] = &IT.get("vprintf");
StdNamespace = 0;
TUScope = 0;
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index fdd4c304fb2..db0837710f6 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -183,18 +183,8 @@ public:
id_NSLog,
id_asprintf,
id_fprintf,
- id_printf,
- id_snprintf,
- id_snprintf_chk,
- id_sprintf,
- id_sprintf_chk,
id_vasprintf,
- id_vfprintf,
- id_vsnprintf,
- id_vsnprintf_chk,
- id_vsprintf,
- id_vsprintf_chk,
- id_vprintf,
+ id_vfprintf,
id_num_known_functions
};
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e058861283f..ab712554965 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -77,40 +77,30 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
// more efficient. For example, just map function ids to custom
// handlers.
- // Search the KnownFunctionIDs for the identifier.
- unsigned i = 0, e = id_num_known_functions;
- for (; i != e; ++i) { if (KnownFunctionIDs[i] == FnInfo) break; }
- if (i == e) return move(TheCallResult);
-
// Printf checking.
- if (i <= id_vprintf) {
- // Retrieve the index of the format string parameter and determine
- // if the function is passed a va_arg argument.
- unsigned format_idx = 0;
- bool HasVAListArg = false;
-
- switch (i) {
- default: assert(false && "No format string argument index.");
- case id_NSLog: format_idx = 0; break;
- case id_asprintf: format_idx = 1; break;
- case id_fprintf: format_idx = 1; break;
- case id_printf: format_idx = 0; break;
- case id_snprintf: format_idx = 2; break;
- case id_snprintf_chk: format_idx = 4; break;
- case id_sprintf: format_idx = 1; break;
- case id_sprintf_chk: format_idx = 3; break;
- case id_vasprintf: format_idx = 1; HasVAListArg = true; break;
- case id_vfprintf: format_idx = 1; HasVAListArg = true; break;
- case id_vsnprintf: format_idx = 2; HasVAListArg = true; break;
- case id_vsnprintf_chk: format_idx = 4; HasVAListArg = true; break;
- case id_vsprintf: format_idx = 1; HasVAListArg = true; break;
- case id_vsprintf_chk: format_idx = 3; HasVAListArg = true; break;
- case id_vprintf: format_idx = 0; HasVAListArg = true; break;
- }
-
- CheckPrintfArguments(TheCall, HasVAListArg, format_idx);
+ 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] ||
+ FnInfo == KnownFunctionIDs[id_fprintf]) {
+ format_idx = 1;
+ HasVAListArg = false;
+ } else if (FnInfo == KnownFunctionIDs[id_vasprintf] ||
+ FnInfo == KnownFunctionIDs[id_vfprintf]) {
+ format_idx = 1;
+ HasVAListArg = true;
+ } else {
+ return move(TheCallResult);
}
+ CheckPrintfArguments(TheCall, HasVAListArg, format_idx);
+
return move(TheCallResult);
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d0997b03ebe..3c02d4b2946 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -304,7 +304,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Diag(Loc, diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.GetName(BID)
<< R;
- if (Context.BuiltinInfo.getHeaderName(BID) &&
+ if (!Context.BuiltinInfo.getHeaderName(BID).empty() &&
Diags.getDiagnosticMapping(diag::ext_implicit_lib_function_decl)
!= diag::MAP_IGNORE)
Diag(Loc, diag::note_please_include_header)
OpenPOWER on IntegriCloud