<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">It doesn't look possible to reach the location I indicated under the conditions that now cause AT.matchesType() to indicate a pedantic mismatch. With the current code, reaching that location seems to require that the specifier be %C (IntendedTy must not equal ExprTy and ShouldNotPrintDirectly must be false, all of which can currently only be true by going through a check that the specifier is %C), but a pedantic mismatch occurs only for %p.</div><div class=""><br class=""></div><div class="">I've also looked again at the other usages of the warn_format_conversion_argument_type_mismatch; After your change they either already handle pedantic mismatches or depend on the specifier being something other than %p.</div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class="">On Mar 4, 2015, at 11:44 AM, Daniel Jasper <<a href="mailto:djasper@google.com" class="">djasper@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Thanks</div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Wed, Mar 4, 2015 at 5:33 PM, Seth Cantrell <span dir="ltr" class=""><<a href="mailto:seth.cantrell@gmail.com" target="_blank" class="">seth.cantrell@gmail.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">Thanks.<div class=""><br class=""></div><div class="">Looks like there could be another one:</div><div class=""><br class=""></div><div class=""><div class=""> } else {</div><div class=""> // In this case, the expression could be printed using a different</div><div class=""> // specifier, but we've decided that the specifier is probably correct </div><div class=""> // and we should cast instead. Just use the normal warning message.</div><div class=""> EmitFormatDiagnostic(</div><div class=""> S.PDiag(diag::warn_format_conversion_argument_type_mismatch)</div><div class=""> << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum</div><div class=""> << E->getSourceRange(),</div><div class=""> E->getLocStart(), /*IsStringLocation*/false,</div><div class=""> SpecRange, Hints);</div><div class=""> }</div><div class=""><br class=""></div><div class="">I'll take a look at fixing it later today.</div><div class=""><div class="h5"><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Mar 4, 2015, at 9:21 AM, Daniel Jasper <<a href="mailto:djasper@google.com" target="_blank" class="">djasper@google.com</a>> wrote:</div><br class=""><div class=""><div dir="ltr" class="">There are some cases that weren't correctly put into the new FormatPedantic group, but instead reported through the normal Format group. Fixed some in r231242. Could you double-check that there aren't more incorrect classifications?</div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Wed, Mar 4, 2015 at 4:12 AM, Seth Cantrell <span dir="ltr" class=""><<a href="mailto:seth.cantrell@gmail.com" target="_blank" class="">seth.cantrell@gmail.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: socantre<br class="">
Date: Tue Mar 3 21:12:10 2015<br class="">
New Revision: 231211<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=231211&view=rev" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=231211&view=rev</a><br class="">
Log:<br class="">
Add a format warning for "%p" with non-void* args<br class="">
<br class="">
GCC -pedantic produces a format warning when the "%p" specifier is used with<br class="">
arguments that are not void*. It's useful for portability to be able to<br class="">
catch such warnings with clang as well. The warning is off by default in<br class="">
both gcc and with this patch. This patch enables it either when extensions<br class="">
are disabled with -pedantic, or with the specific flag -Wformat-pedantic.<br class="">
<br class="">
The C99 and C11 specs do appear to require arguments corresponding to 'p'<br class="">
specifiers to be void*: "If any argument is not the correct type for the<br class="">
corresponding conversion specification, the behavior is undefined."<br class="">
[7.19.6.1 p9], and of the 'p' format specifier "The argument shall be a<br class="">
pointer to void." [7.19.6.1 p8]<br class="">
<br class="">
Both printf and scanf format checking are covered.<br class="">
<br class="">
Modified:<br class="">
cfe/trunk/include/clang/Analysis/Analyses/FormatString.h<br class="">
cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br class="">
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br class="">
cfe/trunk/lib/Analysis/FormatString.cpp<br class="">
cfe/trunk/lib/Sema/SemaChecking.cpp<br class="">
cfe/trunk/test/SemaCXX/format-strings-0x.cpp<br class="">
<br class="">
Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=231211&r1=231210&r2=231211&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=231211&r1=231210&r2=231211&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)<br class="">
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Tue Mar 3 21:12:10 2015<br class="">
@@ -231,6 +231,9 @@ class ArgType {<br class="">
public:<br class="">
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,<br class="">
AnyCharTy, CStrTy, WCStrTy, WIntTy };<br class="">
+<br class="">
+ enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };<br class="">
+<br class="">
private:<br class="">
const Kind K;<br class="">
QualType T;<br class="">
@@ -254,7 +257,7 @@ public:<br class="">
return Res;<br class="">
}<br class="">
<br class="">
- bool matchesType(ASTContext &C, QualType argTy) const;<br class="">
+ MatchKind matchesType(ASTContext &C, QualType argTy) const;<br class="">
<br class="">
QualType getRepresentativeType(ASTContext &C) const;<br class="">
<br class="">
<br class="">
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=231211&r1=231210&r2=231211&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=231211&r1=231210&r2=231211&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)<br class="">
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Mar 3 21:12:10 2015<br class="">
@@ -551,6 +551,7 @@ def FormatInvalidSpecifier : DiagGroup<"<br class="">
def FormatSecurity : DiagGroup<"format-security">;<br class="">
def FormatNonStandard : DiagGroup<"format-non-iso">;<br class="">
def FormatY2K : DiagGroup<"format-y2k">;<br class="">
+def FormatPedantic : DiagGroup<"format-pedantic">;<br class="">
def Format : DiagGroup<"format",<br class="">
[FormatExtraArgs, FormatZeroLength, NonNull,<br class="">
FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,<br class="">
<br class="">
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=231211&r1=231210&r2=231211&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=231211&r1=231210&r2=231211&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br class="">
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 3 21:12:10 2015<br class="">
@@ -6644,6 +6644,10 @@ def warn_format_conversion_argument_type<br class="">
"format specifies type %0 but the argument has "<br class="">
"%select{type|underlying type}2 %1">,<br class="">
InGroup<Format>;<br class="">
+def warn_format_conversion_argument_type_mismatch_pedantic : Extension<<br class="">
+ "format specifies type %0 but the argument has "<br class="">
+ "%select{type|underlying type}2 %1">,<br class="">
+ InGroup<FormatPedantic>;<br class="">
def warn_format_argument_needs_cast : Warning<<br class="">
"%select{values of type|enum values with underlying type}2 '%0' should not "<br class="">
"be used as format arguments; add an explicit cast to %1 instead">,<br class="">
<br class="">
Modified: cfe/trunk/lib/Analysis/FormatString.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=231211&r1=231210&r2=231211&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=231211&r1=231210&r2=231211&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)<br class="">
+++ cfe/trunk/lib/Analysis/FormatString.cpp Tue Mar 3 21:12:10 2015<br class="">
@@ -256,16 +256,17 @@ clang::analyze_format_string::ParseLengt<br class="">
// Methods on ArgType.<br class="">
//===----------------------------------------------------------------------===//<br class="">
<br class="">
-bool ArgType::matchesType(ASTContext &C, QualType argTy) const {<br class="">
+clang::analyze_format_string::ArgType::MatchKind<br class="">
+ArgType::matchesType(ASTContext &C, QualType argTy) const {<br class="">
if (Ptr) {<br class="">
// It has to be a pointer.<br class="">
const PointerType *PT = argTy->getAs<PointerType>();<br class="">
if (!PT)<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
<br class="">
// We cannot write through a const qualified pointer.<br class="">
if (PT->getPointeeType().isConstQualified())<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
<br class="">
argTy = PT->getPointeeType();<br class="">
}<br class="">
@@ -275,8 +276,8 @@ bool ArgType::matchesType(ASTContext &C,<br class="">
llvm_unreachable("ArgType must be valid");<br class="">
<br class="">
case UnknownTy:<br class="">
- return true;<br class="">
-<br class="">
+ return Match;<br class="">
+<br class="">
case AnyCharTy: {<br class="">
if (const EnumType *ETy = argTy->getAs<EnumType>())<br class="">
argTy = ETy->getDecl()->getIntegerType();<br class="">
@@ -289,18 +290,18 @@ bool ArgType::matchesType(ASTContext &C,<br class="">
case BuiltinType::SChar:<br class="">
case BuiltinType::UChar:<br class="">
case BuiltinType::Char_U:<br class="">
- return true;<br class="">
+ return Match;<br class="">
}<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
}<br class="">
-<br class="">
+<br class="">
case SpecificTy: {<br class="">
if (const EnumType *ETy = argTy->getAs<EnumType>())<br class="">
argTy = ETy->getDecl()->getIntegerType();<br class="">
argTy = C.getCanonicalType(argTy).getUnqualifiedType();<br class="">
<br class="">
if (T == argTy)<br class="">
- return true;<br class="">
+ return Match;<br class="">
// Check for "compatible types".<br class="">
if (const BuiltinType *BT = argTy->getAs<BuiltinType>())<br class="">
switch (BT->getKind()) {<br class="">
@@ -309,32 +310,33 @@ bool ArgType::matchesType(ASTContext &C,<br class="">
case BuiltinType::Char_S:<br class="">
case BuiltinType::SChar:<br class="">
case BuiltinType::Char_U:<br class="">
- case BuiltinType::UChar:<br class="">
- return T == C.UnsignedCharTy || T == C.SignedCharTy;<br class="">
+ case BuiltinType::UChar:<br class="">
+ return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match<br class="">
+ : NoMatch;<br class="">
case BuiltinType::Short:<br class="">
- return T == C.UnsignedShortTy;<br class="">
+ return T == C.UnsignedShortTy ? Match : NoMatch;<br class="">
case BuiltinType::UShort:<br class="">
- return T == C.ShortTy;<br class="">
+ return T == C.ShortTy ? Match : NoMatch;<br class="">
case BuiltinType::Int:<br class="">
- return T == C.UnsignedIntTy;<br class="">
+ return T == C.UnsignedIntTy ? Match : NoMatch;<br class="">
case BuiltinType::UInt:<br class="">
- return T == C.IntTy;<br class="">
+ return T == C.IntTy ? Match : NoMatch;<br class="">
case BuiltinType::Long:<br class="">
- return T == C.UnsignedLongTy;<br class="">
+ return T == C.UnsignedLongTy ? Match : NoMatch;<br class="">
case BuiltinType::ULong:<br class="">
- return T == C.LongTy;<br class="">
+ return T == C.LongTy ? Match : NoMatch;<br class="">
case BuiltinType::LongLong:<br class="">
- return T == C.UnsignedLongLongTy;<br class="">
+ return T == C.UnsignedLongLongTy ? Match : NoMatch;<br class="">
case BuiltinType::ULongLong:<br class="">
- return T == C.LongLongTy;<br class="">
+ return T == C.LongLongTy ? Match : NoMatch;<br class="">
}<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
}<br class="">
<br class="">
case CStrTy: {<br class="">
const PointerType *PT = argTy->getAs<PointerType>();<br class="">
if (!PT)<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
QualType pointeeTy = PT->getPointeeType();<br class="">
if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())<br class="">
switch (BT->getKind()) {<br class="">
@@ -343,50 +345,56 @@ bool ArgType::matchesType(ASTContext &C,<br class="">
case BuiltinType::UChar:<br class="">
case BuiltinType::Char_S:<br class="">
case BuiltinType::SChar:<br class="">
- return true;<br class="">
+ return Match;<br class="">
default:<br class="">
break;<br class="">
}<br class="">
<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
}<br class="">
<br class="">
case WCStrTy: {<br class="">
const PointerType *PT = argTy->getAs<PointerType>();<br class="">
if (!PT)<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
QualType pointeeTy =<br class="">
C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();<br class="">
- return pointeeTy == C.getWideCharType();<br class="">
+ return pointeeTy == C.getWideCharType() ? Match : NoMatch;<br class="">
}<br class="">
-<br class="">
+<br class="">
case WIntTy: {<br class="">
-<br class="">
+<br class="">
QualType PromoArg =<br class="">
argTy->isPromotableIntegerType()<br class="">
? C.getPromotedIntegerType(argTy) : argTy;<br class="">
-<br class="">
+<br class="">
QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();<br class="">
PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();<br class="">
-<br class="">
+<br class="">
// If the promoted argument is the corresponding signed type of the<br class="">
// wint_t type, then it should match.<br class="">
if (PromoArg->hasSignedIntegerRepresentation() &&<br class="">
C.getCorrespondingUnsignedType(PromoArg) == WInt)<br class="">
- return true;<br class="">
+ return Match;<br class="">
<br class="">
- return WInt == PromoArg;<br class="">
+ return WInt == PromoArg ? Match : NoMatch;<br class="">
}<br class="">
<br class="">
case CPointerTy:<br class="">
- return argTy->isPointerType() || argTy->isObjCObjectPointerType() ||<br class="">
- argTy->isBlockPointerType() || argTy->isNullPtrType();<br class="">
+ if (argTy->isVoidPointerType()) {<br class="">
+ return Match;<br class="">
+ } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||<br class="">
+ argTy->isBlockPointerType() || argTy->isNullPtrType()) {<br class="">
+ return NoMatchPedantic;<br class="">
+ } else {<br class="">
+ return NoMatch;<br class="">
+ }<br class="">
<br class="">
case ObjCPointerTy: {<br class="">
if (argTy->getAs<ObjCObjectPointerType>() ||<br class="">
argTy->getAs<BlockPointerType>())<br class="">
- return true;<br class="">
-<br class="">
+ return Match;<br class="">
+<br class="">
// Handle implicit toll-free bridging.<br class="">
if (const PointerType *PT = argTy->getAs<PointerType>()) {<br class="">
// Things such as CFTypeRef are really just opaque pointers<br class="">
@@ -395,9 +403,9 @@ bool ArgType::matchesType(ASTContext &C,<br class="">
// structs can be toll-free bridged, we just accept them all.<br class="">
QualType pointee = PT->getPointeeType();<br class="">
if (pointee->getAsStructureType() || pointee->isVoidType())<br class="">
- return true;<br class="">
+ return Match;<br class="">
}<br class="">
- return false;<br class="">
+ return NoMatch;<br class="">
}<br class="">
}<br class="">
<br class="">
<br class="">
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=231211&r1=231210&r2=231211&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=231211&r1=231210&r2=231211&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)<br class="">
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Mar 3 21:12:10 2015<br class="">
@@ -3669,8 +3669,11 @@ CheckPrintfHandler::checkFormatExpr(cons<br class="">
ExprTy = TET->getUnderlyingExpr()->getType();<br class="">
}<br class="">
<br class="">
- if (AT.matchesType(S.Context, ExprTy))<br class="">
+ analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy);<br class="">
+<br class="">
+ if (match == analyze_printf::ArgType::Match) {<br class="">
return true;<br class="">
+ }<br class="">
<br class="">
// Look through argument promotions for our error message's reported type.<br class="">
// This includes the integral and floating promotions, but excludes array<br class="">
@@ -3848,15 +3851,18 @@ CheckPrintfHandler::checkFormatExpr(cons<br class="">
// arguments here.<br class="">
switch (S.isValidVarArgType(ExprTy)) {<br class="">
case Sema::VAK_Valid:<br class="">
- case Sema::VAK_ValidInCXX11:<br class="">
+ case Sema::VAK_ValidInCXX11: {<br class="">
+ unsigned diag = diag::warn_format_conversion_argument_type_mismatch;<br class="">
+ if (match == analyze_printf::ArgType::NoMatchPedantic) {<br class="">
+ diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;<br class="">
+ }<br class="">
+<br class="">
EmitFormatDiagnostic(<br class="">
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)<br class="">
- << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum<br class="">
- << CSR<br class="">
- << E->getSourceRange(),<br class="">
- E->getLocStart(), /*IsStringLocation*/false, CSR);<br class="">
+ S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy<br class="">
+ << IsEnum << CSR << E->getSourceRange(),<br class="">
+ E->getLocStart(), /*IsStringLocation*/ false, CSR);<br class="">
break;<br class="">
-<br class="">
+ }<br class="">
case Sema::VAK_Undefined:<br class="">
case Sema::VAK_MSVCUndefined:<br class="">
EmitFormatDiagnostic(<br class="">
@@ -3988,13 +3994,13 @@ bool CheckScanfHandler::HandleScanfSpeci<br class="">
FixItHint::CreateRemoval(R));<br class="">
}<br class="">
}<br class="">
-<br class="">
+<br class="">
if (!FS.consumesDataArgument()) {<br class="">
// FIXME: Technically specifying a precision or field width here<br class="">
// makes no sense. Worth issuing a warning at some point.<br class="">
return true;<br class="">
}<br class="">
-<br class="">
+<br class="">
// Consume the argument.<br class="">
unsigned argIndex = FS.getArgIndex();<br class="">
if (argIndex < NumDataArgs) {<br class="">
@@ -4003,7 +4009,7 @@ bool CheckScanfHandler::HandleScanfSpeci<br class="">
// function if we encounter some other error.<br class="">
CoveredArgs.set(argIndex);<br class="">
}<br class="">
-<br class="">
+<br class="">
// Check the length modifier is valid with the given conversion specifier.<br class="">
if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo()))<br class="">
HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,<br class="">
@@ -4020,21 +4026,28 @@ bool CheckScanfHandler::HandleScanfSpeci<br class="">
// The remaining checks depend on the data arguments.<br class="">
if (HasVAListArg)<br class="">
return true;<br class="">
-<br class="">
+<br class="">
if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))<br class="">
return false;<br class="">
-<br class="">
+<br class="">
// Check that the argument type matches the format specifier.<br class="">
const Expr *Ex = getDataArg(argIndex);<br class="">
if (!Ex)<br class="">
return true;<br class="">
<br class="">
const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);<br class="">
- if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) {<br class="">
+ analyze_format_string::ArgType::MatchKind match =<br class="">
+ AT.matchesType(S.Context, Ex->getType());<br class="">
+ if (AT.isValid() && match != analyze_format_string::ArgType::Match) {<br class="">
ScanfSpecifier fixedFS = FS;<br class="">
- bool success = fixedFS.fixType(Ex->getType(),<br class="">
- Ex->IgnoreImpCasts()->getType(),<br class="">
- S.getLangOpts(), S.Context);<br class="">
+ bool success =<br class="">
+ fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),<br class="">
+ S.getLangOpts(), S.Context);<br class="">
+<br class="">
+ unsigned diag = diag::warn_format_conversion_argument_type_mismatch;<br class="">
+ if (match == analyze_format_string::ArgType::NoMatchPedantic) {<br class="">
+ diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;<br class="">
+ }<br class="">
<br class="">
if (success) {<br class="">
// Get the fix string from the fixed format specifier.<br class="">
@@ -4043,23 +4056,20 @@ bool CheckScanfHandler::HandleScanfSpeci<br class="">
fixedFS.toString(os);<br class="">
<br class="">
EmitFormatDiagnostic(<br class="">
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)<br class="">
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false<br class="">
- << Ex->getSourceRange(),<br class="">
- Ex->getLocStart(),<br class="">
- /*IsStringLocation*/false,<br class="">
- getSpecifierRange(startSpecifier, specifierLen),<br class="">
- FixItHint::CreateReplacement(<br class="">
+ S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context)<br class="">
+ << Ex->getType() << false << Ex->getSourceRange(),<br class="">
+ Ex->getLocStart(),<br class="">
+ /*IsStringLocation*/ false,<br class="">
getSpecifierRange(startSpecifier, specifierLen),<br class="">
- os.str()));<br class="">
+ FixItHint::CreateReplacement(<br class="">
+ getSpecifierRange(startSpecifier, specifierLen), os.str()));<br class="">
} else {<br class="">
EmitFormatDiagnostic(<br class="">
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)<br class="">
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false<br class="">
- << Ex->getSourceRange(),<br class="">
- Ex->getLocStart(),<br class="">
- /*IsStringLocation*/false,<br class="">
- getSpecifierRange(startSpecifier, specifierLen));<br class="">
+ S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context)<br class="">
+ << Ex->getType() << false << Ex->getSourceRange(),<br class="">
+ Ex->getLocStart(),<br class="">
+ /*IsStringLocation*/ false,<br class="">
+ getSpecifierRange(startSpecifier, specifierLen));<br class="">
}<br class="">
}<br class="">
<br class="">
<br class="">
Modified: cfe/trunk/test/SemaCXX/format-strings-0x.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/format-strings-0x.cpp?rev=231211&r1=231210&r2=231211&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/format-strings-0x.cpp?rev=231211&r1=231210&r2=231211&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/SemaCXX/format-strings-0x.cpp (original)<br class="">
+++ cfe/trunk/test/SemaCXX/format-strings-0x.cpp Tue Mar 3 21:12:10 2015<br class="">
@@ -8,6 +8,9 @@ extern int printf(const char *restrict,<br class="">
void f(char **sp, float *fp) {<br class="">
scanf("%as", sp); // expected-warning{{format specifies type 'float *' but the argument has type 'char **'}}<br class="">
<br class="">
+ printf("%p", sp); // expected-warning{{format specifies type 'void *' but the argument has type 'char **'}}<br class="">
+ scanf("%p", sp); // expected-warning{{format specifies type 'void **' but the argument has type 'char **'}}<br class="">
+<br class="">
printf("%a", 1.0);<br class="">
scanf("%afoobar", fp);<br class="">
printf(nullptr);<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank" class="">cfe-commits@cs.uiuc.edu</a><br class="">
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank" class="">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br class="">
</blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></div></div></div></div></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></body></html>