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
This commit is contained in:
@@ -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?
|
||||
|
||||
Reference in New Issue
Block a user