diff options
-rw-r--r-- | include/clang/Analysis/Analyses/FormatString.h | 5 | ||||
-rw-r--r-- | lib/Analysis/FormatString.cpp | 9 | ||||
-rw-r--r-- | lib/Analysis/PrintfFormatString.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | test/Sema/format-strings-int-typedefs.c | 5 |
5 files changed, 21 insertions, 16 deletions
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index c7dfbf8cb8..2edbc8c296 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -199,7 +199,7 @@ protected: class ArgTypeResult { public: enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, - AnyCharTy, CStrTy, WCStrTy, WIntTy, TypedefTy }; + AnyCharTy, CStrTy, WCStrTy, WIntTy }; private: const Kind K; QualType T; @@ -207,8 +207,9 @@ private: ArgTypeResult(bool) : K(InvalidTy), Name(0) {} public: ArgTypeResult(Kind k = UnknownTy) : K(k), Name(0) {} + ArgTypeResult(Kind k, const char *n) : K(k), Name(n) {} ArgTypeResult(QualType t) : K(SpecificTy), T(t), Name(0) {} - ArgTypeResult(QualType t, const char *n) : K(TypedefTy), T(t), Name(n) {} + ArgTypeResult(QualType t, const char *n) : K(SpecificTy), T(t), Name(n) {} ArgTypeResult(CanQualType t) : K(SpecificTy), T(t), Name(0) {} static ArgTypeResult Invalid() { return ArgTypeResult(true); } diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp index fe308471bd..2d56c233b6 100644 --- a/lib/Analysis/FormatString.cpp +++ b/lib/Analysis/FormatString.cpp @@ -228,7 +228,6 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { return false; } - case TypedefTy: case SpecificTy: { argTy = C.getCanonicalType(argTy).getUnqualifiedType(); if (T == argTy) @@ -332,7 +331,6 @@ QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { case AnyCharTy: return C.CharTy; case SpecificTy: - case TypedefTy: return T; case CStrTy: return C.getPointerType(C.CharTy); @@ -354,9 +352,10 @@ QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { } std::string ArgTypeResult::getRepresentativeTypeName(ASTContext &C) const { - if (K != TypedefTy) - return std::string("'") + getRepresentativeType(C).getAsString() + "'"; - return std::string("'") + Name + "' (aka '" + T.getAsString() + "')"; + std::string S = getRepresentativeType(C).getAsString(); + if (Name) + return std::string("'") + Name + "' (aka '" + S + "')"; + return std::string("'") + S + "'"; } diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 3b8c45b7e2..2dd9bf7b2e 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -247,7 +247,8 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const { if (CS.getKind() == ConversionSpecifier::cArg) switch (LM.getKind()) { case LengthModifier::None: return Ctx.IntTy; - case LengthModifier::AsLong: return ArgTypeResult::WIntTy; + case LengthModifier::AsLong: + return ArgTypeResult(ArgTypeResult::WIntTy, "wint_t"); default: return ArgTypeResult::Invalid(); } @@ -296,14 +297,16 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const { } switch (CS.getKind()) { - case ConversionSpecifier::sArg: - return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ? - ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); + case ConversionSpecifier::sArg: { + if (LM.getKind() == LengthModifier::AsWideChar) + return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *"); + return ArgTypeResult::CStrTy; + } case ConversionSpecifier::SArg: // FIXME: This appears to be Mac OS X specific. - return ArgTypeResult::WCStrTy; + return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *"); case ConversionSpecifier::CArg: - return Ctx.WCharTy; + return ArgTypeResult(Ctx.WCharTy, "wchar_t"); case ConversionSpecifier::pArg: return ArgTypeResult::CPointerTy; default: diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index f635afcc30..a0138d8723 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2229,9 +2229,6 @@ 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). EmitFormatDiagnostic( S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() diff --git a/test/Sema/format-strings-int-typedefs.c b/test/Sema/format-strings-int-typedefs.c index 29565e69ad..2568b8d69f 100644 --- a/test/Sema/format-strings-int-typedefs.c +++ b/test/Sema/format-strings-int-typedefs.c @@ -7,6 +7,11 @@ void test(void) { printf("%ju", 42.0); // expected-warning {{conversion specifies type 'uintmax_t' (aka 'unsigned long long')}} printf("%zu", 42.0); // expected-warning {{conversion specifies type 'size_t' (aka 'unsigned long')}} printf("%td", 42.0); // expected-warning {{conversion specifies type 'ptrdiff_t' (aka 'int')}} + printf("%lc", 42.0); // expected-warning {{conversion specifies type 'wint_t' (aka 'int')}} + printf("%ls", 42.0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}} + printf("%S", 42.0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}} + printf("%C", 42.0); // expected-warning {{conversion specifies type 'wchar_t' (aka 'int')}} + // typedef size_t et al. to something crazy. typedef void *size_t; |