diff options
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 70 |
1 files changed, 40 insertions, 30 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 1f57b26c9e..519a5ca3fd 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -499,7 +499,8 @@ void Sema::checkCall(NamedDecl *FDecl, Expr **Args, for (specific_attr_iterator<FormatAttr> I = FDecl->specific_attr_begin<FormatAttr>(), E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I) - if (CheckFormatArguments(*I, Args, NumArgs, IsMemberFunction, Loc, Range)) + if (CheckFormatArguments(*I, Args, NumArgs, IsMemberFunction, CallType, + Loc, Range)) HandledFormatString = true; // Refuse POD arguments that weren't caught by the format string @@ -1610,7 +1611,8 @@ Sema::StringLiteralCheckType Sema::checkFormatStringExpr(const Expr *E, Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, - FormatStringType Type, bool inFunctionCall) { + FormatStringType Type, VariadicCallType CallType, + bool inFunctionCall) { tryAgain: if (E->isTypeDependent() || E->isValueDependent()) return SLCT_NotALiteral; @@ -1634,13 +1636,13 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, StringLiteralCheckType Left = checkFormatStringExpr(C->getTrueExpr(), Args, NumArgs, HasVAListArg, format_idx, firstDataArg, - Type, inFunctionCall); + Type, CallType, inFunctionCall); if (Left == SLCT_NotALiteral) return SLCT_NotALiteral; StringLiteralCheckType Right = checkFormatStringExpr(C->getFalseExpr(), Args, NumArgs, HasVAListArg, format_idx, firstDataArg, - Type, inFunctionCall); + Type, CallType, inFunctionCall); return Left < Right ? Left : Right; } @@ -1691,7 +1693,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, } return checkFormatStringExpr(Init, Args, NumArgs, HasVAListArg, format_idx, - firstDataArg, Type, + firstDataArg, Type, CallType, /*inFunctionCall*/false); } } @@ -1749,7 +1751,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, return checkFormatStringExpr(Arg, Args, NumArgs, HasVAListArg, format_idx, firstDataArg, - Type, inFunctionCall); + Type, CallType, inFunctionCall); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { unsigned BuiltinID = FD->getBuiltinID(); if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString || @@ -1757,7 +1759,8 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, const Expr *Arg = CE->getArg(0); return checkFormatStringExpr(Arg, Args, NumArgs, HasVAListArg, format_idx, - firstDataArg, Type, inFunctionCall); + firstDataArg, Type, CallType, + inFunctionCall); } } } @@ -1775,7 +1778,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, if (StrE) { CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx, - firstDataArg, Type, inFunctionCall); + firstDataArg, Type, inFunctionCall, CallType); return SLCT_CheckedLiteral; } @@ -1812,31 +1815,25 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { .Default(FST_Unknown); } -/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar +/// CheckFormatArguments - Check calls to printf and scanf (and similar /// functions) for correct use of format strings. /// Returns true if a format string has been fully checked. -bool Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) { - bool IsCXXMember = isa<CXXMemberCallExpr>(TheCall); - return CheckFormatArguments(Format, TheCall->getArgs(), - TheCall->getNumArgs(), - IsCXXMember, TheCall->getRParenLoc(), - TheCall->getCallee()->getSourceRange()); -} - bool Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args, unsigned NumArgs, bool IsCXXMember, + VariadicCallType CallType, SourceLocation Loc, SourceRange Range) { FormatStringInfo FSI; if (getFormatStringInfo(Format, IsCXXMember, &FSI)) return CheckFormatArguments(Args, NumArgs, FSI.HasVAListArg, FSI.FormatIdx, FSI.FirstDataArg, GetFormatStringType(Format), - Loc, Range); + CallType, Loc, Range); return false; } bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, + VariadicCallType CallType, SourceLocation Loc, SourceRange Range) { // CHECK: printf/scanf-like function is called with no format string. if (format_idx >= NumArgs) { @@ -1860,7 +1857,7 @@ bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, // the same format string checking logic for both ObjC and C strings. StringLiteralCheckType CT = checkFormatStringExpr(OrigFormatExpr, Args, NumArgs, HasVAListArg, - format_idx, firstDataArg, Type); + format_idx, firstDataArg, Type, CallType); if (CT != SLCT_NotALiteral) // Literal format string found, check done! return CT == SLCT_CheckedLiteral; @@ -1908,18 +1905,20 @@ protected: bool usesPositionalArgs; bool atFirstArg; bool inFunctionCall; + Sema::VariadicCallType CallType; public: CheckFormatHandler(Sema &s, const StringLiteral *fexpr, const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, const char *beg, bool hasVAListArg, Expr **args, unsigned numArgs, - unsigned formatIdx, bool inFunctionCall) + unsigned formatIdx, bool inFunctionCall, + Sema::VariadicCallType callType) : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg), HasVAListArg(hasVAListArg), Args(args), NumArgs(numArgs), FormatIdx(formatIdx), usesPositionalArgs(false), atFirstArg(true), - inFunctionCall(inFunctionCall) { + inFunctionCall(inFunctionCall), CallType(callType) { CoveredArgs.resize(numDataArgs); CoveredArgs.reset(); } @@ -2238,11 +2237,13 @@ public: unsigned numDataArgs, bool isObjC, const char *beg, bool hasVAListArg, Expr **Args, unsigned NumArgs, - unsigned formatIdx, bool inFunctionCall) + unsigned formatIdx, bool inFunctionCall, + Sema::VariadicCallType CallType) : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, numDataArgs, beg, hasVAListArg, Args, NumArgs, - formatIdx, inFunctionCall), ObjCContext(isObjC) {} - + formatIdx, inFunctionCall, CallType), ObjCContext(isObjC) + {} + bool HandleInvalidPrintfConversionSpecifier( const analyze_printf::PrintfSpecifier &FS, @@ -2646,10 +2647,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // was deferred until now, we emit a warning for non-POD // arguments here. if (S.isValidVarArgType(E->getType()) == Sema::VAK_Invalid) { + unsigned DiagKind; + if (E->getType()->isObjCObjectType()) + DiagKind = diag::err_cannot_pass_objc_interface_to_vararg_format; + else + DiagKind = diag::warn_non_pod_vararg_with_format_string; + EmitFormatDiagnostic( - S.PDiag(diag::warn_non_pod_vararg_with_format_string) + S.PDiag(DiagKind) << S.getLangOpts().CPlusPlus0x << E->getType() + << CallType << ATR.getRepresentativeTypeName(S.Context) << CSR << E->getSourceRange(), @@ -2678,10 +2686,12 @@ public: const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, const char *beg, bool hasVAListArg, Expr **Args, unsigned NumArgs, - unsigned formatIdx, bool inFunctionCall) + unsigned formatIdx, bool inFunctionCall, + Sema::VariadicCallType CallType) : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, numDataArgs, beg, hasVAListArg, - Args, NumArgs, formatIdx, inFunctionCall) {} + Args, NumArgs, formatIdx, inFunctionCall, CallType) + {} bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, @@ -2842,7 +2852,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, - bool inFunctionCall) { + bool inFunctionCall, VariadicCallType CallType) { // CHECK: is the format string a wide literal? if (!FExpr->isAscii() && !FExpr->isUTF8()) { @@ -2872,7 +2882,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, (Type == FST_NSString), Str, HasVAListArg, Args, NumArgs, format_idx, - inFunctionCall); + inFunctionCall, CallType); if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, getLangOpts())) @@ -2880,7 +2890,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, Str, HasVAListArg, Args, NumArgs, format_idx, - inFunctionCall); + inFunctionCall, CallType); if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, getLangOpts())) |