]> granicus.if.org Git - clang/commitdiff
Fix handling of wint_t - we can't assume wint_t is purely an integer promotion of...
authorJames Molloy <james.molloy@arm.com>
Fri, 4 May 2012 10:55:22 +0000 (10:55 +0000)
committerJames Molloy <james.molloy@arm.com>
Fri, 4 May 2012 10:55:22 +0000 (10:55 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156165 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/Analysis/FormatString.cpp
lib/Sema/SemaChecking.cpp
test/Sema/format-strings.c

index 96e41c5d0357da9f78e6863c79c55d7fad352d7c..a7d4543a59d8969198c92b7dfcad11a62b3c09eb 100644 (file)
@@ -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;
index e4308df65351b5ea92a55f8498daefb3b43cf060..d80f5b828fecbd3162bc55cb56b306cbb15f020f 100644 (file)
@@ -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
index ba45865af875237c5adadcd87514ca30684c7c39..ab69c069114b3242eb2d87573e5dbf0d20809a6d 100644 (file)
@@ -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();
     }
   }
 
index dad082748827cf5a5a1df7a7846df7cc28437616..0c8309e58e5df417334b879126eaddb6863102a2 100644 (file)
@@ -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()))
index 7e968899ac236e4fb1e6027f0ea57804a2d3d444..d1dca7e2fb023b874a65f107cc35e30d0ae52dac 100644 (file)
@@ -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
 }