Teach format string checking about compile-time CFString constants.
Within the guts of CheckFormatHandler, the IsObjCLiteral flag was being used in
two ways: to see if null bytes were allowed, and to see if the '%@' specifier
is allowed.* The former usage has been changed to an explicit test and the
latter pushed down to CheckPrintfHandler and renamed ObjCContext, since it
applies to CFStrings as well.
* This also changes how wide chars are interpreted; in OS X Foundation, the
wide character type is 'unichar', a typedef for short, rather than wchar_t.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157968 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 0046b86..e818f5f 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1636,6 +1636,15 @@
return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
format_idx, firstDataArg, Type,
inFunctionCall);
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ unsigned BuiltinID = FD->getBuiltinID();
+ if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
+ BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
+ const Expr *Arg = CE->getArg(0);
+ return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
+ format_idx, firstDataArg, Type,
+ inFunctionCall);
+ }
}
}
@@ -1780,7 +1789,6 @@
const Expr *OrigFormatExpr;
const unsigned FirstDataArg;
const unsigned NumDataArgs;
- const bool IsObjCLiteral;
const char *Beg; // Start of format string.
const bool HasVAListArg;
const Expr * const *Args;
@@ -1793,15 +1801,12 @@
public:
CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
- unsigned numDataArgs, bool isObjCLiteral,
- const char *beg, bool hasVAListArg,
+ unsigned numDataArgs, const char *beg, bool hasVAListArg,
Expr **args, unsigned numArgs,
unsigned formatIdx, bool inFunctionCall)
: S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
- FirstDataArg(firstDataArg),
- NumDataArgs(numDataArgs),
- IsObjCLiteral(isObjCLiteral), Beg(beg),
- HasVAListArg(hasVAListArg),
+ FirstDataArg(firstDataArg), NumDataArgs(numDataArgs),
+ Beg(beg), HasVAListArg(hasVAListArg),
Args(args), NumArgs(numArgs), FormatIdx(formatIdx),
usesPositionalArgs(false), atFirstArg(true),
inFunctionCall(inFunctionCall) {
@@ -1961,7 +1966,7 @@
}
void CheckFormatHandler::HandleNullChar(const char *nullCharacter) {
- if (!IsObjCLiteral) {
+ if (!isa<ObjCStringLiteral>(OrigFormatExpr)) {
// The presence of a null character is likely an error.
EmitFormatDiagnostic(
S.PDiag(diag::warn_printf_format_string_contains_null_char),
@@ -2112,16 +2117,17 @@
namespace {
class CheckPrintfHandler : public CheckFormatHandler {
+ bool ObjCContext;
public:
CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
- unsigned numDataArgs, bool isObjCLiteral,
+ unsigned numDataArgs, bool isObjC,
const char *beg, bool hasVAListArg,
Expr **Args, unsigned NumArgs,
unsigned formatIdx, bool inFunctionCall)
: CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, isObjCLiteral, beg, hasVAListArg,
- Args, NumArgs, formatIdx, inFunctionCall) {}
+ numDataArgs, beg, hasVAListArg, Args, NumArgs,
+ formatIdx, inFunctionCall), ObjCContext(isObjC) {}
bool HandleInvalidPrintfConversionSpecifier(
@@ -2314,7 +2320,7 @@
// Check for using an Objective-C specific conversion specifier
// in a non-ObjC literal.
- if (!IsObjCLiteral && CS.isObjCArg()) {
+ if (!ObjCContext && CS.isObjCArg()) {
return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
specifierLen);
}
@@ -2394,7 +2400,7 @@
// format specifier.
const Expr *Ex = getDataArg(argIndex);
const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context,
- IsObjCLiteral);
+ ObjCContext);
if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
// Look through argument promotions for our error message's reported type.
// This includes the integral and floating promotions, but excludes array
@@ -2420,7 +2426,7 @@
// We may be able to offer a FixItHint if it is a supported type.
PrintfSpecifier fixedFS = FS;
bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
- S.Context, IsObjCLiteral);
+ S.Context, ObjCContext);
if (success) {
// Get the fix string from the fixed format specifier
@@ -2461,12 +2467,11 @@
public:
CheckScanfHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
- unsigned numDataArgs, bool isObjCLiteral,
- const char *beg, bool hasVAListArg,
+ unsigned numDataArgs, const char *beg, bool hasVAListArg,
Expr **Args, unsigned NumArgs,
unsigned formatIdx, bool inFunctionCall)
: CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, isObjCLiteral, beg, hasVAListArg,
+ numDataArgs, beg, hasVAListArg,
Args, NumArgs, formatIdx, inFunctionCall) {}
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
@@ -2653,7 +2658,7 @@
if (Type == FST_Printf || Type == FST_NSString) {
CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
- numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr),
+ numDataArgs, (Type == FST_NSString),
Str, HasVAListArg, Args, NumArgs, format_idx,
inFunctionCall);
@@ -2661,8 +2666,7 @@
getLangOpts()))
H.DoneProcessing();
} else if (Type == FST_Scanf) {
- CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
- numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr),
+ CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
Str, HasVAListArg, Args, NumArgs, format_idx,
inFunctionCall);