diff options
author | Hans Wennborg <hans@hanshq.net> | 2011-12-02 19:22:15 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2011-12-02 19:22:15 +0000 |
commit | 70f7213d2cf81b2dba91ec939e44f07c975e684e (patch) | |
tree | e5a5631a3e31b83df77f4b04bce499b8fd49fce6 /clang/lib/Analysis/PrintfFormatString.cpp | |
parent | 541392832f742f9a79bb0179d515a79924b2c71a (diff) | |
download | bcm5719-llvm-70f7213d2cf81b2dba91ec939e44f07c975e684e.tar.gz bcm5719-llvm-70f7213d2cf81b2dba91ec939e44f07c975e684e.zip |
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')"
llvm-svn: 145697
Diffstat (limited to 'clang/lib/Analysis/PrintfFormatString.cpp')
-rw-r--r-- | clang/lib/Analysis/PrintfFormatString.cpp | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp index 70dbfd30cee..b37b23f3b18 100644 --- a/clang/lib/Analysis/PrintfFormatString.cpp +++ b/clang/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? |