forked from OSchip/llvm-project
Fix printf format string checking for '%lc' (which expects a wint_t or compatible argument). Fixes PR 7981.
llvm-svn: 111978
This commit is contained in:
parent
e0fd5a9299
commit
5f0c066062
|
@ -199,7 +199,7 @@ protected:
|
|||
class ArgTypeResult {
|
||||
public:
|
||||
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
|
||||
CStrTy, WCStrTy };
|
||||
CStrTy, WCStrTy, WIntTy };
|
||||
private:
|
||||
const Kind K;
|
||||
QualType T;
|
||||
|
|
|
@ -277,6 +277,23 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
|
|||
C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
|
||||
return pointeeTy == C.getWCharType();
|
||||
}
|
||||
|
||||
case WIntTy: {
|
||||
// Instead of doing a lookup for the definition of 'wint_t' (which
|
||||
// is defined by the system headers) instead see if wchar_t and
|
||||
// the argument type promote to the same type.
|
||||
QualType PromoWChar =
|
||||
C.getWCharType()->isPromotableIntegerType()
|
||||
? C.getPromotedIntegerType(C.getWCharType()) : C.getWCharType();
|
||||
QualType PromoArg =
|
||||
argTy->isPromotableIntegerType()
|
||||
? C.getPromotedIntegerType(argTy) : argTy;
|
||||
|
||||
PromoWChar = C.getCanonicalType(PromoWChar).getUnqualifiedType();
|
||||
PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
|
||||
|
||||
return PromoWChar == PromoArg;
|
||||
}
|
||||
|
||||
case CPointerTy:
|
||||
return argTy->getAs<PointerType>() != NULL ||
|
||||
|
@ -308,6 +325,10 @@ QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
|
|||
return C.ObjCBuiltinIdTy;
|
||||
case CPointerTy:
|
||||
return C.VoidPtrTy;
|
||||
case WIntTy: {
|
||||
QualType WC = C.getWCharType();
|
||||
return WC->isPromotableIntegerType() ? C.getPromotedIntegerType(WC) : WC;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Should be unreachable, but Clang is currently emitting
|
||||
|
|
|
@ -281,6 +281,14 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
|
|||
if (!CS.consumesDataArgument())
|
||||
return ArgTypeResult::Invalid();
|
||||
|
||||
if (CS.getKind() == ConversionSpecifier::cArg)
|
||||
switch (LM.getKind()) {
|
||||
case LengthModifier::None: return Ctx.IntTy;
|
||||
case LengthModifier::AsLong: return ArgTypeResult::WIntTy;
|
||||
default:
|
||||
return ArgTypeResult::Invalid();
|
||||
}
|
||||
|
||||
if (CS.isIntArg())
|
||||
switch (LM.getKind()) {
|
||||
case LengthModifier::AsLongDouble:
|
||||
|
|
|
@ -1595,6 +1595,9 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
|
|||
llvm::raw_svector_ostream os(buf);
|
||||
fixedFS.toString(os);
|
||||
|
||||
// FIXME: getRepresentativeType() perhaps should return a string
|
||||
// instead of a QualType to better handle when the representative
|
||||
// type is 'wint_t' (which is defined in the system headers).
|
||||
S.Diag(getLocationOfByte(CS.getStart()),
|
||||
diag::warn_printf_conversion_argument_type_mismatch)
|
||||
<< ATR.getRepresentativeType(S.Context) << Ex->getType()
|
||||
|
|
|
@ -286,3 +286,18 @@ void bug7377_bad_length_mod_usage() {
|
|||
printf("%-0f", 1.23); // expected-warning{{flag '0' is ignored when flag '-' is present}}
|
||||
printf("%-+f", 1.23); // no-warning
|
||||
}
|
||||
|
||||
// PR 7981 - handle '%lc' (wint_t)
|
||||
#ifndef wint_t
|
||||
typedef int __darwin_wint_t;
|
||||
typedef __darwin_wint_t wint_t;
|
||||
#endif
|
||||
|
||||
void pr7981(wint_t c, wchar_t c2) {
|
||||
printf("%lc", c); // no-warning
|
||||
printf("%lc", 1.0); // expected-warning{{the argument has type 'double'}}
|
||||
printf("%lc", (char) 1); // no-warning
|
||||
printf("%lc", &c); // expected-warning{{the argument has type 'wint_t *' (aka 'int *')}}
|
||||
printf("%lc", c2); // no-warning
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue