[cfe-commits] r145697 - in /cfe/trunk: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/FormatString.cpp lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp test/Sema/format-strings-int-typedefs.c
Hans Wennborg
hans at hanshq.net
Fri Dec 2 11:22:15 PST 2011
Author: hans
Date: Fri Dec 2 13:22:15 2011
New Revision: 145697
URL: http://llvm.org/viewvc/llvm-project?rev=145697&view=rev
Log:
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')"
Added:
cfe/trunk/test/Sema/format-strings-int-typedefs.c
Modified:
cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
cfe/trunk/lib/Analysis/FormatString.cpp
cfe/trunk/lib/Analysis/PrintfFormatString.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=145697&r1=145696&r2=145697&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Fri Dec 2 13:22:15 2011
@@ -23,6 +23,8 @@
namespace clang {
+class Sema;
+
//===----------------------------------------------------------------------===//
/// Common components of both fprintf and fscanf format strings.
namespace analyze_format_string {
@@ -448,7 +450,7 @@
/// will return null if the format specifier does not have
/// a matching data argument or the matching argument matches
/// more than one type.
- ArgTypeResult getArgType(ASTContext &Ctx) const;
+ ArgTypeResult getArgType(Sema &S) const;
const OptionalFlag &hasThousandsGrouping() const {
return HasThousandsGrouping;
Modified: cfe/trunk/lib/Analysis/FormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=145697&r1=145696&r2=145697&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/FormatString.cpp Fri Dec 2 13:22:15 2011
@@ -230,7 +230,8 @@
case SpecificTy: {
argTy = C.getCanonicalType(argTy).getUnqualifiedType();
- if (T == argTy)
+ QualType U = C.getCanonicalType(T);
+ if (U == argTy)
return true;
// Check for "compatible types".
if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
@@ -239,26 +240,26 @@
break;
case BuiltinType::Char_S:
case BuiltinType::SChar:
- return T == C.UnsignedCharTy;
+ return U == C.UnsignedCharTy;
case BuiltinType::Char_U:
case BuiltinType::UChar:
- return T == C.SignedCharTy;
+ return U == C.SignedCharTy;
case BuiltinType::Short:
- return T == C.UnsignedShortTy;
+ return U == C.UnsignedShortTy;
case BuiltinType::UShort:
- return T == C.ShortTy;
+ return U == C.ShortTy;
case BuiltinType::Int:
- return T == C.UnsignedIntTy;
+ return U == C.UnsignedIntTy;
case BuiltinType::UInt:
- return T == C.IntTy;
+ return U == C.IntTy;
case BuiltinType::Long:
- return T == C.UnsignedLongTy;
+ return U == C.UnsignedLongTy;
case BuiltinType::ULong:
- return T == C.LongTy;
+ return U == C.LongTy;
case BuiltinType::LongLong:
- return T == C.UnsignedLongLongTy;
+ return U == C.UnsignedLongLongTy;
case BuiltinType::ULongLong:
- return T == C.LongLongTy;
+ return U == C.LongLongTy;
}
return false;
}
@@ -485,5 +486,3 @@
}
return false;
}
-
-
Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=145697&r1=145696&r2=145697&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Fri Dec 2 13:22:15 2011
@@ -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 @@
// 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 @@
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 @@
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?
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=145697&r1=145696&r2=145697&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Dec 2 13:22:15 2011
@@ -2206,7 +2206,7 @@
// Now type check the data expression that matches the
// format specifier.
const Expr *Ex = getDataArg(argIndex);
- const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
+ const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S);
if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
// Check if we didn't match because of an implicit cast from a 'char'
// or 'short' to an 'int'. This is done because printf is a varargs
Added: cfe/trunk/test/Sema/format-strings-int-typedefs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-int-typedefs.c?rev=145697&view=auto
==============================================================================
--- cfe/trunk/test/Sema/format-strings-int-typedefs.c (added)
+++ cfe/trunk/test/Sema/format-strings-int-typedefs.c Fri Dec 2 13:22:15 2011
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s
+
+int printf(char const *, ...);
+
+void test(void) {
+ // size_t, et al. have not been declared yet,
+ // so the warning should refer to the builtin types.
+ printf("%jd", 42.0); // expected-warning {{conversion specifies type 'long long'}}
+ printf("%ju", 42.0); // expected-warning {{conversion specifies type 'unsigned long long'}}
+ printf("%zu", 42.0); // expected-warning {{conversion specifies type 'unsigned long'}}
+ printf("%td", 42.0); // expected-warning {{conversion specifies type 'int'}}
+
+ typedef __SIZE_TYPE__ size_t;
+ typedef __INTMAX_TYPE__ intmax_t;
+ typedef __UINTMAX_TYPE__ uintmax_t;
+ typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
+ printf("%jd", 42.0); // expected-warning {{conversion specifies type 'intmax_t' (aka 'long long')}}
+ 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')}}
+}
+
+void test2(void) {
+ typedef void *size_t;
+
+ // The typedef for size_t does not match the builtin type,
+ // so the warning should not refer to it.
+ printf("%zu", 42.0); // expected-warning {{conversion specifies type 'unsigned long'}}
+}
More information about the cfe-commits
mailing list