aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/PrintfFormatString.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2011-12-02 19:22:15 +0000
committerHans Wennborg <hans@hanshq.net>2011-12-02 19:22:15 +0000
commit5fdc1b993dcb01e8a994fdacfc4eb089832c82e3 (patch)
treea078ac926e2c72f691155aa3045a6876d3159714 /lib/Analysis/PrintfFormatString.cpp
parent07165b9e3b78ed76a7db561f392335e4a54c9e51 (diff)
Make conversion specifier warning refer to typedef if possible.
For example, the warning for printf("%zu", 42.0); changes from "conversion specifies type 'unsigned long'" to "conversion specifies type 'size_t' (aka 'unsigned long')" git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145697 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/PrintfFormatString.cpp')
-rw-r--r--lib/Analysis/PrintfFormatString.cpp33
1 files changed, 28 insertions, 5 deletions
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index 70dbfd30ce..b37b23f3b1 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Sema/Sema.h"
#include "FormatStringParsing.h"
using clang::analyze_format_string::ArgTypeResult;
@@ -278,8 +279,27 @@ const char *ConversionSpecifier::toString() const {
// Methods on PrintfSpecifier.
//===----------------------------------------------------------------------===//
-ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
+/// \brief Try to find and return a typedef type named Name whose actual type
+/// is Underlying. Return Underlying if such a typedef cannot be found.
+static QualType FindTypedef(Sema &S, const char *Name, QualType Underlying) {
+ ASTContext &Ctx = S.getASTContext();
+ IdentifierInfo &II = Ctx.Idents.get(Name);
+
+ NamedDecl *D = S.LookupSingleName(S.getCurScope(), DeclarationName(&II),
+ SourceLocation(), Sema::LookupOrdinaryName);
+
+ if (TypedefDecl *TD = dyn_cast_or_null<TypedefDecl>(D)) {
+ QualType TypedefType = Ctx.getTypedefType(TD, QualType());
+ if (TD->getUnderlyingType() == Underlying)
+ return TypedefType;
+ }
+
+ return Underlying;
+}
+
+ArgTypeResult PrintfSpecifier::getArgType(Sema &S) const {
const PrintfConversionSpecifier &CS = getConversionSpecifier();
+ ASTContext &Ctx = S.getASTContext();
if (!CS.consumesDataArgument())
return ArgTypeResult::Invalid();
@@ -301,11 +321,13 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsShort: return Ctx.ShortTy;
case LengthModifier::AsLong: return Ctx.LongTy;
case LengthModifier::AsLongLong: return Ctx.LongLongTy;
- case LengthModifier::AsIntMax: return Ctx.getIntMaxType();
+ case LengthModifier::AsIntMax:
+ return FindTypedef(S, "intmax_t", Ctx.getIntMaxType());
case LengthModifier::AsSizeT:
// FIXME: How to get the corresponding signed version of size_t?
return ArgTypeResult();
- case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType();
+ case LengthModifier::AsPtrDiff:
+ return FindTypedef(S, "ptrdiff_t", Ctx.getPointerDiffType());
}
if (CS.isUIntArg())
@@ -317,9 +339,10 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
- case LengthModifier::AsIntMax: return Ctx.getUIntMaxType();
+ case LengthModifier::AsIntMax:
+ return FindTypedef(S, "uintmax_t", Ctx.getUIntMaxType());
case LengthModifier::AsSizeT:
- return Ctx.getSizeType();
+ return FindTypedef(S, "size_t", Ctx.getSizeType());
case LengthModifier::AsPtrDiff:
// FIXME: How to get the corresponding unsigned
// version of ptrdiff_t?