summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2014-11-14 21:41:07 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2014-11-14 21:41:07 +0000
commitdc12b367bc175ad5af56f4701a2ffb43a18db779 (patch)
tree71225dcb531f8f5a7d96ffeef02f8ffd1ee6c9b7 /clang/lib/Sema/SemaChecking.cpp
parent71aa1a9355d80ac3c9579a1277f07fd7b2a609f2 (diff)
downloadbcm5719-llvm-dc12b367bc175ad5af56f4701a2ffb43a18db779.tar.gz
bcm5719-llvm-dc12b367bc175ad5af56f4701a2ffb43a18db779.zip
Follow-up to D6217
Summary: Ok, here is somewhat addition to D6217 aiming to preserve old darwin behavior wrt the typedefed types. The actual change to SemaChecking turned out to be pretty gross, in particular: 1. We need to extract the typedef'ed type for proper diagnostics 2. We need to walk over paren expressions as well Reviewers: chandlerc, rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D6256 llvm-svn: 222044
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp88
1 files changed, 67 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 31b643f1385..b27ce7c7098 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3392,6 +3392,61 @@ static bool requiresParensToAddCast(const Expr *E) {
}
}
+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,
@@ -3483,25 +3538,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// 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;
+ bool ShouldNotPrintDirectly = false; StringRef CastTyName;
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- // 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();
+ QualType CastTy;
+ std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
+ if (!CastTy.isNull()) {
+ IntendedTy = CastTy;
+ ShouldNotPrintDirectly = true;
}
}
@@ -3518,7 +3561,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
- if (IntendedTy == ExprTy) {
+ if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) {
// In this case, the specifier is wrong and should be changed to match
// the argument.
EmitFormatDiagnostic(
@@ -3572,8 +3615,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// 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 = cast<TypedefType>(ExprTy)->getDecl()->getName();
-
+ StringRef Name;
+ if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(ExprTy))
+ Name = TypedefTy->getDecl()->getName();
+ else
+ Name = CastTyName;
EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
<< Name << IntendedTy << IsEnum
<< E->getSourceRange(),
OpenPOWER on IntegriCloud