bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
bool hasStandardLengthConversionCombination() const;
+
+ /// For a TypedefType QT, if it is a named integer type such as size_t,
+ /// assign the appropriate value to LM and return true.
+ static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
};
} // end analyze_format_string namespace
}
return true;
}
+
+bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
+ LengthModifier &LM) {
+ assert(isa<TypedefType>(QT) && "Expected a TypedefType");
+ const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
+
+ for (;;) {
+ const IdentifierInfo *Identifier = Typedef->getIdentifier();
+ if (Identifier->getName() == "size_t") {
+ LM.setKind(LengthModifier::AsSizeT);
+ return true;
+ } else if (Identifier->getName() == "ssize_t") {
+ // Not C99, but common in Unix.
+ LM.setKind(LengthModifier::AsSizeT);
+ return true;
+ } else if (Identifier->getName() == "intmax_t") {
+ LM.setKind(LengthModifier::AsIntMax);
+ return true;
+ } else if (Identifier->getName() == "uintmax_t") {
+ LM.setKind(LengthModifier::AsIntMax);
+ return true;
+ } else if (Identifier->getName() == "ptrdiff_t") {
+ LM.setKind(LengthModifier::AsPtrDiff);
+ return true;
+ }
+
+ QualType T = Typedef->getUnderlyingType();
+ if (!isa<TypedefType>(T))
+ break;
+
+ Typedef = cast<TypedefType>(T)->getDecl();
+ }
+ return false;
+}
}
// Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
- if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) {
- const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier();
- if (Identifier->getName() == "size_t") {
- LM.setKind(LengthModifier::AsSizeT);
- } else if (Identifier->getName() == "ssize_t") {
- // Not C99, but common in Unix.
- LM.setKind(LengthModifier::AsSizeT);
- } else if (Identifier->getName() == "intmax_t") {
- LM.setKind(LengthModifier::AsIntMax);
- } else if (Identifier->getName() == "uintmax_t") {
- LM.setKind(LengthModifier::AsIntMax);
- } else if (Identifier->getName() == "ptrdiff_t") {
- LM.setKind(LengthModifier::AsPtrDiff);
- }
- }
+ if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x))
+ namedTypeToLengthModifier(QT, LM);
// If fixing the length modifier was enough, we are done.
const analyze_printf::ArgTypeResult &ATR = getArgType(Ctx, IsObjCLiteral);
}
// Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
- if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) {
- const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier();
- if (Identifier->getName() == "size_t") {
- LM.setKind(LengthModifier::AsSizeT);
- } else if (Identifier->getName() == "ssize_t") {
- // Not C99, but common in Unix.
- LM.setKind(LengthModifier::AsSizeT);
- } else if (Identifier->getName() == "intmax_t") {
- LM.setKind(LengthModifier::AsIntMax);
- } else if (Identifier->getName() == "uintmax_t") {
- LM.setKind(LengthModifier::AsIntMax);
- } else if (Identifier->getName() == "ptrdiff_t") {
- LM.setKind(LengthModifier::AsPtrDiff);
- }
- }
+ if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x))
+ namedTypeToLengthModifier(PT, LM);
// If fixing the length modifier was enough, we are done.
const analyze_scanf::ScanfArgTypeResult &ATR = getArgType(Ctx);
printf("%f", (uintmax_t) 42);
printf("%f", (ptrdiff_t) 42);
+ // Look beyond the first typedef.
+ typedef size_t my_size_type;
+ typedef intmax_t my_intmax_type;
+ typedef uintmax_t my_uintmax_type;
+ typedef ptrdiff_t my_ptrdiff_type;
+ typedef int my_int_type;
+ printf("%f", (my_size_type) 42);
+ printf("%f", (my_intmax_type) 42);
+ printf("%f", (my_uintmax_type) 42);
+ printf("%f", (my_ptrdiff_type) 42);
+ printf("%f", (my_int_type) 42);
+
// string
printf("%ld", "foo");
scanf("%f", &uIntmaxVar);
scanf("%f", &ptrdiffVar);
+ // Look beyond the first typedef for named integer types.
+ typedef size_t my_size_type;
+ typedef intmax_t my_intmax_type;
+ typedef uintmax_t my_uintmax_type;
+ typedef ptrdiff_t my_ptrdiff_type;
+ typedef int my_int_type;
+ scanf("%f", (my_size_type*)&sizeVar);
+ scanf("%f", (my_intmax_type*)&intmaxVar);
+ scanf("%f", (my_uintmax_type*)&uIntmaxVar);
+ scanf("%f", (my_ptrdiff_type*)&ptrdiffVar);
+ scanf("%f", (my_int_type*)&intVar);
+
// Preserve the original formatting.
scanf("%o", &longVar);
scanf("%u", &longVar);
// CHECK: printf("%jd", (intmax_t) 42);
// CHECK: printf("%ju", (uintmax_t) 42);
// CHECK: printf("%td", (ptrdiff_t) 42);
+// CHECK: printf("%zu", (my_size_type) 42);
+// CHECK: printf("%jd", (my_intmax_type) 42);
+// CHECK: printf("%ju", (my_uintmax_type) 42);
+// CHECK: printf("%td", (my_ptrdiff_type) 42);
+// CHECK: printf("%d", (my_int_type) 42);
// CHECK: printf("%s", "foo");
// CHECK: printf("%lo", (long) 42);
// CHECK: printf("%lu", (long) 42);
// CHECK: scanf("%jd", &intmaxVar);
// CHECK: scanf("%ju", &uIntmaxVar);
// CHECK: scanf("%td", &ptrdiffVar);
+// CHECK: scanf("%zu", (my_size_type*)&sizeVar);
+// CHECK: scanf("%jd", (my_intmax_type*)&intmaxVar);
+// CHECK: scanf("%ju", (my_uintmax_type*)&uIntmaxVar);
+// CHECK: scanf("%td", (my_ptrdiff_type*)&ptrdiffVar);
+// CHECK: scanf("%d", (my_int_type*)&intVar);
// CHECK: scanf("%lo", &longVar);
// CHECK: scanf("%lu", &longVar);
// CHECK: scanf("%lx", &longVar);