r222049 - Recommit r222044 with a test fix - it does not make sense to hunt
Anton Korobeynikov
asl at math.spbu.ru
Fri Nov 14 14:09:15 PST 2014
Author: asl
Date: Fri Nov 14 16:09:15 2014
New Revision: 222049
URL: http://llvm.org/viewvc/llvm-project?rev=222049&view=rev
Log:
Recommit r222044 with a test fix - it does not make sense to hunt
for a typedef before arithmetic conversion in all rare corner cases.
Modified:
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/CodeGen/complex.c
cfe/trunk/test/SemaObjC/format-strings-objc.m
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=222049&r1=222048&r2=222049&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Nov 14 16:09:15 2014
@@ -3392,6 +3392,61 @@ static bool requiresParensToAddCast(cons
}
}
+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(cons
// 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(cons
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(cons
// 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(),
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=222049&r1=222048&r2=222049&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Nov 14 16:09:15 2014
@@ -5711,7 +5711,7 @@ QualType Sema::CheckConditionalOperands(
RHS.get()->getType()->isVectorType())
return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
- UsualArithmeticConversions(LHS, RHS);
+ QualType ResTy = UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
@@ -5728,8 +5728,12 @@ QualType Sema::CheckConditionalOperands(
// 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())
- return LHS.get()->getType();
+ if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
+ LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
+ RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
+
+ return ResTy;
+ }
// If both operands are the same structure or union type, the result is that
// type.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=222049&r1=222048&r2=222049&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Nov 14 16:09:15 2014
@@ -4561,10 +4561,14 @@ QualType Sema::CXXCheckConditionalOperan
// the usual arithmetic conversions are performed to bring them to a
// common type, and the result is of that type.
if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
- UsualArithmeticConversions(LHS, RHS);
+ QualType ResTy = UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- return LHS.get()->getType();
+
+ LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
+ RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
+
+ return ResTy;
}
// -- The second and third operands have pointer type, or one has pointer
Modified: cfe/trunk/test/CodeGen/complex.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/complex.c?rev=222049&r1=222048&r2=222049&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/complex.c (original)
+++ cfe/trunk/test/CodeGen/complex.c Fri Nov 14 16:09:15 2014
@@ -98,3 +98,19 @@ void t8() {
const _Complex double test9const = 0;
_Complex double test9func() { return test9const; }
+
+// D6217
+void t91() {
+ // Check for proper type promotion of conditional expression
+ char c[(int)(sizeof(typeof((0 ? 2.0f : (_Complex double) 2.0f))) - sizeof(_Complex double))];
+ // Check for proper codegen
+ (0 ? 2.0f : (_Complex double) 2.0f);
+}
+
+void t92() {
+ // Check for proper type promotion of conditional expression
+ char c[(int)(sizeof(typeof((0 ? (_Complex double) 2.0f : 2.0f))) - sizeof(_Complex double))];
+ // Check for proper codegen
+ (0 ? (_Complex double) 2.0f : 2.0f);
+}
+
Modified: cfe/trunk/test/SemaObjC/format-strings-objc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/format-strings-objc.m?rev=222049&r1=222048&r2=222049&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/format-strings-objc.m (original)
+++ cfe/trunk/test/SemaObjC/format-strings-objc.m Fri Nov 14 16:09:15 2014
@@ -243,7 +243,7 @@ void testByValueObjectInFormat(Foo *obj)
// <rdar://problem/13557053>
void testTypeOf(NSInteger dW, NSInteger dH) {
- NSLog(@"dW %d dH %d",({ __typeof__(dW) __a = (dW); __a < 0 ? -__a : __a; }),({ __typeof__(dH) __a = (dH); __a < 0 ? -__a : __a; })); // expected-warning 2 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}
+ NSLog(@"dW %d dH %d",({ __typeof__(dW) __a = (dW); __a < 0 ? -__a : __a; }),({ __typeof__(dH) __a = (dH); __a < 0 ? -__a : __a; })); // expected-warning 2 {{format specifies type 'int' but the argument has type 'long'}}
}
void testUnicode() {
More information about the cfe-commits
mailing list