}
}
-static std::pair<QualType, StringRef>
-shouldNotPrintDirectly(const ASTContext &Context,
- QualType IntendedTy,
- const Expr *E) {
- // Use a 'while' to peel off layers of typedefs.
- QualType TyTy = IntendedTy;
- while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
- StringRef Name = UserTy->getDecl()->getName();
- QualType CastTy = llvm::StringSwitch<QualType>(Name)
- .Case("NSInteger", Context.LongTy)
- .Case("NSUInteger", Context.UnsignedLongTy)
- .Case("SInt32", Context.IntTy)
- .Case("UInt32", Context.UnsignedIntTy)
- .Default(QualType());
-
- if (!CastTy.isNull())
- return std::make_pair(CastTy, Name);
-
- TyTy = UserTy->desugar();
- }
-
- // Strip parens if necessary.
- if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
- return shouldNotPrintDirectly(Context,
- PE->getSubExpr()->getType(),
- PE->getSubExpr());
-
- // If this is a conditional expression, then its result type is constructed
- // via usual arithmetic conversions and thus there might be no necessary
- // typedef sugar there. Recurse to operands to check for NSInteger &
- // Co. usage condition.
- if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
- QualType TrueTy, FalseTy;
- StringRef TrueName, FalseName;
-
- std::tie(TrueTy, TrueName) =
- shouldNotPrintDirectly(Context,
- CO->getTrueExpr()->getType(),
- CO->getTrueExpr());
- std::tie(FalseTy, FalseName) =
- shouldNotPrintDirectly(Context,
- CO->getFalseExpr()->getType(),
- CO->getFalseExpr());
-
- if (TrueTy == FalseTy)
- return std::make_pair(TrueTy, TrueName);
- else if (TrueTy.isNull())
- return std::make_pair(FalseTy, FalseName);
- else if (FalseTy.isNull())
- return std::make_pair(TrueTy, TrueName);
- }
-
- return std::make_pair(QualType(), StringRef());
-}
-
bool
CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const char *StartSpecifier,
// Special-case some of Darwin's platform-independence types by suggesting
// casts to primitive types that are known to be large enough.
- bool ShouldNotPrintDirectly = false; StringRef CastTyName;
+ bool ShouldNotPrintDirectly = false;
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- QualType CastTy;
- std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
- if (!CastTy.isNull()) {
- IntendedTy = CastTy;
- ShouldNotPrintDirectly = true;
+ // Use a 'while' to peel off layers of typedefs.
+ QualType TyTy = IntendedTy;
+ while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
+ StringRef Name = UserTy->getDecl()->getName();
+ QualType CastTy = llvm::StringSwitch<QualType>(Name)
+ .Case("NSInteger", S.Context.LongTy)
+ .Case("NSUInteger", S.Context.UnsignedLongTy)
+ .Case("SInt32", S.Context.IntTy)
+ .Case("UInt32", S.Context.UnsignedIntTy)
+ .Default(QualType());
+
+ if (!CastTy.isNull()) {
+ ShouldNotPrintDirectly = true;
+ IntendedTy = CastTy;
+ break;
+ }
+ TyTy = UserTy->desugar();
}
}
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
- if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) {
+ if (IntendedTy == ExprTy) {
// In this case, the specifier is wrong and should be changed to match
// the argument.
EmitFormatDiagnostic(
// The expression has a type that should not be printed directly.
// We extract the name from the typedef because we don't want to show
// the underlying type in the diagnostic.
- StringRef Name;
- if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(ExprTy))
- Name = TypedefTy->getDecl()->getName();
- else
- Name = CastTyName;
+ StringRef Name = cast<TypedefType>(ExprTy)->getDecl()->getName();
+
EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
<< Name << IntendedTy << IsEnum
<< E->getSourceRange(),
RHS.get()->getType()->isVectorType())
return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
- QualType ResTy = UsualArithmeticConversions(LHS, RHS);
+ UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
- if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
- LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
- RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
-
- return ResTy;
- }
+ if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType())
+ return LHS.get()->getType();
// If both operands are the same structure or union type, the result is that
// type.