Fix handling of wint_t - we can't assume wint_t is purely an integer promotion of wchar_t - they may differ in signedness.
Teach ASTContext about WIntType, and have it taken from TargetInfo like WCharType. Should fix test/Sema/format-strings.c for ARM, with the exception of one subtest which will fail if wint_t and wchar_t are the same size and wint_t is signed, wchar_t is unsigned. There'll be a followup commit to fix that. Reviewed by Chandler and Hans at http://llvm.org/reviews/r/8 llvm-svn: 156165
This commit is contained in:
parent
2f5d0191f7
commit
3636554b63
|
@ -557,6 +557,7 @@ public:
|
|||
CanQualType BoolTy;
|
||||
CanQualType CharTy;
|
||||
CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
|
||||
CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions.
|
||||
CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
|
||||
CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
|
||||
CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
|
||||
|
@ -929,6 +930,10 @@ public:
|
|||
/// Used when in C++, as a GCC extension.
|
||||
QualType getUnsignedWCharType() const;
|
||||
|
||||
/// getWIntType - In C99, this returns a type compatible with the type
|
||||
/// defined in <stddef.h> as defined by the target.
|
||||
QualType getWIntType() const { return WIntTy; }
|
||||
|
||||
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
|
||||
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
|
||||
QualType getPointerDiffType() const;
|
||||
|
|
|
@ -436,6 +436,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
|
|||
} else // C99
|
||||
WCharTy = getFromTargetType(Target.getWCharType());
|
||||
|
||||
WIntTy = getFromTargetType(Target.getWIntType());
|
||||
|
||||
if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++
|
||||
InitBuiltinType(Char16Ty, BuiltinType::Char16);
|
||||
else // C99
|
||||
|
|
|
@ -319,20 +319,21 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
|
|||
}
|
||||
|
||||
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();
|
||||
QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
|
||||
PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
|
||||
|
||||
return PromoWChar == PromoArg;
|
||||
// If the promoted argument is the corresponding signed type of the
|
||||
// wint_t type, then it should match.
|
||||
if (PromoArg->hasSignedIntegerRepresentation() &&
|
||||
C.getCorrespondingUnsignedType(PromoArg) == WInt)
|
||||
return true;
|
||||
|
||||
return WInt == PromoArg;
|
||||
}
|
||||
|
||||
case CPointerTy:
|
||||
|
@ -380,8 +381,7 @@ QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
|
|||
case CPointerTy:
|
||||
return C.VoidPtrTy;
|
||||
case WIntTy: {
|
||||
QualType WC = C.getWCharType();
|
||||
return WC->isPromotableIntegerType() ? C.getPromotedIntegerType(WC) : WC;
|
||||
return C.getWIntType();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2392,7 +2392,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
|
|||
// or 'short' to an 'int'. This is done because printf is a varargs
|
||||
// function.
|
||||
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
|
||||
if (ICE->getType() == S.Context.IntTy) {
|
||||
if (ICE->getType() == S.Context.IntTy ||
|
||||
ICE->getType() == S.Context.UnsignedIntTy) {
|
||||
// All further checking is done on the subexpression.
|
||||
Ex = ICE->getSubExpr();
|
||||
if (ATR.matchesType(S.Context, Ex->getType()))
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s
|
||||
|
||||
#define __need_wint_t
|
||||
#include <stdarg.h>
|
||||
typedef __typeof(sizeof(int)) size_t;
|
||||
#include <stddef.h> // For wint_t and wchar_t
|
||||
|
||||
typedef struct _FILE FILE;
|
||||
int fprintf(FILE *, const char *restrict, ...);
|
||||
int printf(const char *restrict, ...); // expected-note{{passing argument to parameter here}}
|
||||
|
@ -258,7 +260,6 @@ void f0(int_t x) { printf("%d\n", x); }
|
|||
|
||||
// Unicode test cases. These are possibly specific to Mac OS X. If so, they should
|
||||
// eventually be moved into a separate test.
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
|
||||
void test_unicode_conversions(wchar_t *s) {
|
||||
printf("%S", s); // no-warning
|
||||
|
@ -332,16 +333,12 @@ void bug7377_bad_length_mod_usage() {
|
|||
}
|
||||
|
||||
// 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", &c); // expected-warning{{the argument has type 'wint_t *'}}
|
||||
printf("%lc", c2); // no-warning
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue