[cfe-commits] r103174 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/Sema/compare.c test/Sema/conditional-expr.c test/Sema/conversion.c test/SemaCXX/compare.cpp test/SemaCXX/conditional-expr.cpp
John McCall
rjmccall at apple.com
Thu May 6 01:58:33 PDT 2010
Author: rjmccall
Date: Thu May 6 03:58:33 2010
New Revision: 103174
URL: http://llvm.org/viewvc/llvm-project?rev=103174&view=rev
Log:
Rearchitect -Wconversion and -Wsign-compare. Instead of computing them
"bottom-up" when implicit casts and comparisons are inserted, compute them
"top-down" when the full expression is finished. Makes it easier to
coordinate warnings and thus implement -Wconversion for signedness
conversions without double-warning with -Wsign-compare. Also makes it possible
to realize that a signedness conversion is okay because the context is
performing the inverse conversion. Also simplifies some logic that was
trying to calculate the ultimate comparison/result type and getting it wrong.
Also fixes a problem with the C++ explicit casts which are often "implemented"
in the AST with a series of implicit cast expressions.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/Sema/compare.c
cfe/trunk/test/Sema/conditional-expr.c
cfe/trunk/test/Sema/conversion.c
cfe/trunk/test/SemaCXX/compare.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu May 6 03:58:33 2010
@@ -883,6 +883,12 @@
def warn_impcast_float_integer : Warning<
"implicit cast turns floating-point number into integer: %0 to %1">,
InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_sign : Warning<
+ "implicit cast changes signedness: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_sign_conditional : Warning<
+ "operand of ? changes signedness: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
def warn_impcast_integer_precision : Warning<
"implicit cast loses integer precision: %0 to %1">,
InGroup<DiagGroup<"conversion">>, DefaultIgnore;
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu May 6 03:58:33 2010
@@ -175,8 +175,6 @@
}
}
- CheckImplicitConversion(Expr, Ty);
-
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
if (ImpCast->getCastKind() == Kind && BasePath.empty()) {
ImpCast->setType(Ty);
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu May 6 03:58:33 2010
@@ -4456,9 +4456,7 @@
void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc);
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
- void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
- const BinaryOperator::Opcode* BinOpc = 0);
- void CheckImplicitConversion(Expr *E, QualType Target);
+ void CheckImplicitConversions(Expr *E);
};
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu May 6 03:58:33 2010
@@ -1731,8 +1731,14 @@
T = VT->getElementType().getTypePtr();
if (const ComplexType *CT = dyn_cast<ComplexType>(T))
T = CT->getElementType().getTypePtr();
- if (const EnumType *ET = dyn_cast<EnumType>(T))
- T = ET->getDecl()->getIntegerType().getTypePtr();
+
+ if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+ EnumDecl *Enum = ET->getDecl();
+ unsigned NumPositive = Enum->getNumPositiveBits();
+ unsigned NumNegative = Enum->getNumNegativeBits();
+
+ return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0);
+ }
const BuiltinType *BT = cast<BuiltinType>(T);
assert(BT->isInteger());
@@ -1974,6 +1980,10 @@
return IntRange::forType(C, E->getType());
}
+IntRange GetExprRange(ASTContext &C, Expr *E) {
+ return GetExprRange(C, E, C.getIntWidth(E->getType()));
+}
+
/// Checks whether the given value, which currently has the given
/// source semantics, has the same value when coerced through the
/// target semantics.
@@ -2012,7 +2022,40 @@
IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
}
-} // end anonymous namespace
+void AnalyzeImplicitConversions(Sema &S, Expr *E);
+
+bool IsZero(Sema &S, Expr *E) {
+ llvm::APSInt Value;
+ return E->isIntegerConstantExpr(Value, S.Context) && Value == 0;
+}
+
+void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
+ BinaryOperator::Opcode op = E->getOpcode();
+ if (op == BinaryOperator::LT && IsZero(S, E->getRHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
+ << "< 0" << "false"
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ } else if (op == BinaryOperator::GE && IsZero(S, E->getRHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
+ << ">= 0" << "true"
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ } else if (op == BinaryOperator::GT && IsZero(S, E->getLHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
+ << "0 >" << "false"
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ } else if (op == BinaryOperator::LE && IsZero(S, E->getLHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
+ << "0 <=" << "true"
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ }
+}
+
+/// Analyze the operands of the given comparison. Implements the
+/// fallback case from AnalyzeComparison.
+void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
+ AnalyzeImplicitConversions(S, E->getLHS());
+ AnalyzeImplicitConversions(S, E->getRHS());
+}
/// \brief Implements -Wsign-compare.
///
@@ -2020,138 +2063,85 @@
/// \param rex the right-hand expression
/// \param OpLoc the location of the joining operator
/// \param BinOpc binary opcode or 0
-void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
- const BinaryOperator::Opcode* BinOpc) {
- // Don't warn if we're in an unevaluated context.
- if (ExprEvalContexts.back().Context == Unevaluated)
- return;
-
- // If either expression is value-dependent, don't warn. We'll get another
- // chance at instantiation time.
- if (lex->isValueDependent() || rex->isValueDependent())
- return;
-
- QualType lt = lex->getType(), rt = rex->getType();
+void AnalyzeComparison(Sema &S, BinaryOperator *E) {
+ // The type the comparison is being performed in.
+ QualType T = E->getLHS()->getType();
+ assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType())
+ && "comparison with mismatched types");
+
+ // We don't do anything special if this isn't an unsigned integral
+ // comparison: we're only interested in integral comparisons, and
+ // signed comparisons only happen in cases we don't care to warn about.
+ if (!T->isUnsignedIntegerType())
+ return AnalyzeImpConvsInComparison(S, E);
- // Only warn if both operands are integral.
- if (!lt->isIntegerType() || !rt->isIntegerType())
- return;
+ Expr *lex = E->getLHS()->IgnoreParenImpCasts();
+ Expr *rex = E->getRHS()->IgnoreParenImpCasts();
- // In C, the width of a bitfield determines its type, and the
- // declared type only contributes the signedness. This duplicates
- // the work that will later be done by UsualUnaryConversions.
- // Eventually, this check will be reorganized in a way that avoids
- // this duplication.
- if (!getLangOptions().CPlusPlus) {
- QualType tmp;
- tmp = Context.isPromotableBitField(lex);
- if (!tmp.isNull()) lt = tmp;
- tmp = Context.isPromotableBitField(rex);
- if (!tmp.isNull()) rt = tmp;
- }
-
- if (const EnumType *E = lt->getAs<EnumType>())
- lt = E->getDecl()->getPromotionType();
- if (const EnumType *E = rt->getAs<EnumType>())
- rt = E->getDecl()->getPromotionType();
-
- // The rule is that the signed operand becomes unsigned, so isolate the
- // signed operand.
- Expr *signedOperand = lex, *unsignedOperand = rex;
- QualType signedType = lt, unsignedType = rt;
- if (lt->isSignedIntegerType()) {
- if (rt->isSignedIntegerType()) return;
+ // Check to see if one of the (unmodified) operands is of different
+ // signedness.
+ Expr *signedOperand, *unsignedOperand;
+ if (lex->getType()->isSignedIntegerType()) {
+ assert(!rex->getType()->isSignedIntegerType() &&
+ "unsigned comparison between two signed integer expressions?");
+ signedOperand = lex;
+ unsignedOperand = rex;
+ } else if (rex->getType()->isSignedIntegerType()) {
+ signedOperand = rex;
+ unsignedOperand = lex;
} else {
- if (!rt->isSignedIntegerType()) return;
- std::swap(signedOperand, unsignedOperand);
- std::swap(signedType, unsignedType);
+ CheckTrivialUnsignedComparison(S, E);
+ return AnalyzeImpConvsInComparison(S, E);
}
- unsigned unsignedWidth = Context.getIntWidth(unsignedType);
- unsigned signedWidth = Context.getIntWidth(signedType);
-
- // If the unsigned type is strictly smaller than the signed type,
- // then (1) the result type will be signed and (2) the unsigned
- // value will fit fully within the signed type, and thus the result
- // of the comparison will be exact.
- if (signedWidth > unsignedWidth)
- return;
+ // Otherwise, calculate the effective range of the signed operand.
+ IntRange signedRange = GetExprRange(S.Context, signedOperand);
- // Otherwise, calculate the effective ranges.
- IntRange signedRange = GetExprRange(Context, signedOperand, signedWidth);
- IntRange unsignedRange = GetExprRange(Context, unsignedOperand, unsignedWidth);
-
- // We should never be unable to prove that the unsigned operand is
- // non-negative.
- assert(unsignedRange.NonNegative && "unsigned range includes negative?");
-
- // If the signed operand is non-negative, then the signed->unsigned
- // conversion won't change it.
- if (signedRange.NonNegative) {
- // Emit warnings for comparisons of unsigned to integer constant 0.
- // always false: x < 0 (or 0 > x)
- // always true: x >= 0 (or 0 <= x)
- llvm::APSInt X;
- if (BinOpc && signedOperand->isIntegerConstantExpr(X, Context) && X == 0) {
- if (signedOperand != lex) {
- if (*BinOpc == BinaryOperator::LT) {
- Diag(OpLoc, diag::warn_lunsigned_always_true_comparison)
- << "< 0" << "false"
- << lex->getSourceRange() << rex->getSourceRange();
- }
- else if (*BinOpc == BinaryOperator::GE) {
- Diag(OpLoc, diag::warn_lunsigned_always_true_comparison)
- << ">= 0" << "true"
- << lex->getSourceRange() << rex->getSourceRange();
- }
- }
- else {
- if (*BinOpc == BinaryOperator::GT) {
- Diag(OpLoc, diag::warn_runsigned_always_true_comparison)
- << "0 >" << "false"
- << lex->getSourceRange() << rex->getSourceRange();
- }
- else if (*BinOpc == BinaryOperator::LE) {
- Diag(OpLoc, diag::warn_runsigned_always_true_comparison)
- << "0 <=" << "true"
- << lex->getSourceRange() << rex->getSourceRange();
- }
- }
- }
- return;
- }
+ // Go ahead and analyze implicit conversions in the operands. Note
+ // that we skip the implicit conversions on both sides.
+ AnalyzeImplicitConversions(S, lex);
+ AnalyzeImplicitConversions(S, rex);
+
+ // If the signed range is non-negative, -Wsign-compare won't fire,
+ // but we should still check for comparisons which are always true
+ // or false.
+ if (signedRange.NonNegative)
+ return CheckTrivialUnsignedComparison(S, E);
// For (in)equality comparisons, if the unsigned operand is a
// constant which cannot collide with a overflowed signed operand,
// then reinterpreting the signed operand as unsigned will not
// change the result of the comparison.
- if (BinOpc &&
- (*BinOpc == BinaryOperator::EQ || *BinOpc == BinaryOperator::NE) &&
- unsignedRange.Width < unsignedWidth)
- return;
+ if (E->isEqualityOp()) {
+ unsigned comparisonWidth = S.Context.getIntWidth(T);
+ IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand);
+
+ // We should never be unable to prove that the unsigned operand is
+ // non-negative.
+ assert(unsignedRange.NonNegative && "unsigned range includes negative?");
+
+ if (unsignedRange.Width < comparisonWidth)
+ return;
+ }
- Diag(OpLoc, BinOpc ? diag::warn_mixed_sign_comparison
- : diag::warn_mixed_sign_conditional)
- << lt << rt << lex->getSourceRange() << rex->getSourceRange();
+ S.Diag(E->getOperatorLoc(), diag::warn_mixed_sign_comparison)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
}
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
-static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
+void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
}
-/// Implements -Wconversion.
-void Sema::CheckImplicitConversion(Expr *E, QualType T) {
- // Don't diagnose in unevaluated contexts.
- if (ExprEvalContexts.back().Context == Sema::Unevaluated)
- return;
-
- // Don't diagnose for value-dependent expressions.
- if (E->isValueDependent())
- return;
-
- const Type *Source = Context.getCanonicalType(E->getType()).getTypePtr();
- const Type *Target = Context.getCanonicalType(T).getTypePtr();
+void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
+ bool *ICContext = 0) {
+ if (E->isTypeDependent() || E->isValueDependent()) return;
+
+ const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
+ const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
+ if (Source == Target) return;
+ if (Target->isDependentType()) return;
// Never diagnose implicit casts to bool.
if (Target->isSpecificBuiltinType(BuiltinType::Bool))
@@ -2160,7 +2150,7 @@
// Strip vector types.
if (isa<VectorType>(Source)) {
if (!isa<VectorType>(Target))
- return DiagnoseImpCast(*this, E, T, diag::warn_impcast_vector_scalar);
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_vector_scalar);
Source = cast<VectorType>(Source)->getElementType().getTypePtr();
Target = cast<VectorType>(Target)->getElementType().getTypePtr();
@@ -2169,7 +2159,7 @@
// Strip complex types.
if (isa<ComplexType>(Source)) {
if (!isa<ComplexType>(Target))
- return DiagnoseImpCast(*this, E, T, diag::warn_impcast_complex_scalar);
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_complex_scalar);
Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
@@ -2189,15 +2179,15 @@
// Don't warn about float constants that are precisely
// representable in the target type.
Expr::EvalResult result;
- if (E->Evaluate(result, Context)) {
+ if (E->Evaluate(result, S.Context)) {
// Value might be a float, a float vector, or a float complex.
if (IsSameFloatAfterCast(result.Val,
- Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
- Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
+ S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
+ S.Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
return;
}
- DiagnoseImpCast(*this, E, T, diag::warn_impcast_float_precision);
+ DiagnoseImpCast(S, E, T, diag::warn_impcast_float_precision);
}
return;
}
@@ -2205,7 +2195,7 @@
// If the target is integral, always warn.
if ((TargetBT && TargetBT->isInteger()))
// TODO: don't warn for integer values?
- return DiagnoseImpCast(*this, E, T, diag::warn_impcast_float_integer);
+ DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer);
return;
}
@@ -2213,22 +2203,158 @@
if (!Source->isIntegerType() || !Target->isIntegerType())
return;
- IntRange SourceRange = GetExprRange(Context, E, Context.getIntWidth(E->getType()));
- IntRange TargetRange = IntRange::forCanonicalType(Context, Target);
-
- // FIXME: also signed<->unsigned?
+ IntRange SourceRange = GetExprRange(S.Context, E);
+ IntRange TargetRange = IntRange::forCanonicalType(S.Context, Target);
if (SourceRange.Width > TargetRange.Width) {
// People want to build with -Wshorten-64-to-32 and not -Wconversion
// and by god we'll let them.
if (SourceRange.Width == 64 && TargetRange.Width == 32)
- return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_64_32);
- return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_precision);
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_64_32);
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_precision);
+ }
+
+ if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
+ (!TargetRange.NonNegative && SourceRange.NonNegative &&
+ SourceRange.Width == TargetRange.Width)) {
+ unsigned DiagID = diag::warn_impcast_integer_sign;
+
+ // Traditionally, gcc has warned about this under -Wsign-compare.
+ // We also want to warn about it in -Wconversion.
+ // So if -Wconversion is off, use a completely identical diagnostic
+ // in the sign-compare group.
+ // The conditional-checking code will
+ if (ICContext) {
+ DiagID = diag::warn_impcast_integer_sign_conditional;
+ *ICContext = true;
+ }
+
+ return DiagnoseImpCast(S, E, T, DiagID);
}
return;
}
+void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T);
+
+void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
+ bool &ICContext) {
+ E = E->IgnoreParenImpCasts();
+
+ if (isa<ConditionalOperator>(E))
+ return CheckConditionalOperator(S, cast<ConditionalOperator>(E), T);
+
+ AnalyzeImplicitConversions(S, E);
+ if (E->getType() != T)
+ return CheckImplicitConversion(S, E, T, &ICContext);
+ return;
+}
+
+void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) {
+ AnalyzeImplicitConversions(S, E->getCond());
+
+ bool Suspicious = false;
+ CheckConditionalOperand(S, E->getTrueExpr(), T, Suspicious);
+ CheckConditionalOperand(S, E->getFalseExpr(), T, Suspicious);
+
+ // If -Wconversion would have warned about either of the candidates
+ // for a signedness conversion to the context type...
+ if (!Suspicious) return;
+
+ // ...but it's currently ignored...
+ if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional))
+ return;
+
+ // ...and -Wsign-compare isn't...
+ if (!S.Diags.getDiagnosticLevel(diag::warn_mixed_sign_conditional))
+ return;
+
+ // ...then check whether it would have warned about either of the
+ // candidates for a signedness conversion to the condition type.
+ if (E->getType() != T) {
+ Suspicious = false;
+ CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(),
+ E->getType(), &Suspicious);
+ if (!Suspicious)
+ CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(),
+ E->getType(), &Suspicious);
+ if (!Suspicious)
+ return;
+ }
+
+ // If so, emit a diagnostic under -Wsign-compare.
+ Expr *lex = E->getTrueExpr()->IgnoreParenImpCasts();
+ Expr *rex = E->getFalseExpr()->IgnoreParenImpCasts();
+ S.Diag(E->getQuestionLoc(), diag::warn_mixed_sign_conditional)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+}
+
+/// AnalyzeImplicitConversions - Find and report any interesting
+/// implicit conversions in the given expression. There are a couple
+/// of competing diagnostics here, -Wconversion and -Wsign-compare.
+void AnalyzeImplicitConversions(Sema &S, Expr *OrigE) {
+ QualType T = OrigE->getType();
+ Expr *E = OrigE->IgnoreParenImpCasts();
+
+ // For conditional operators, we analyze the arguments as if they
+ // were being fed directly into the output.
+ if (isa<ConditionalOperator>(E)) {
+ ConditionalOperator *CO = cast<ConditionalOperator>(E);
+ CheckConditionalOperator(S, CO, T);
+ return;
+ }
+
+ // Go ahead and check any implicit conversions we might have skipped.
+ // The non-canonical typecheck is just an optimization;
+ // CheckImplicitConversion will filter out dead implicit conversions.
+ if (E->getType() != T)
+ CheckImplicitConversion(S, E, T);
+
+ // Now continue drilling into this expression.
+
+ // Skip past explicit casts.
+ if (isa<ExplicitCastExpr>(E)) {
+ E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
+ return AnalyzeImplicitConversions(S, E);
+ }
+
+ // Do a somewhat different check with comparison operators.
+ if (isa<BinaryOperator>(E) && cast<BinaryOperator>(E)->isComparisonOp())
+ return AnalyzeComparison(S, cast<BinaryOperator>(E));
+
+ // These break the otherwise-useful invariant below. Fortunately,
+ // we don't really need to recurse into them, because any internal
+ // expressions should have been analyzed already when they were
+ // built into statements.
+ if (isa<StmtExpr>(E)) return;
+
+ // Don't descend into unevaluated contexts.
+ if (isa<SizeOfAlignOfExpr>(E)) return;
+
+ // Now just recurse over the expression's children.
+ for (Stmt::child_iterator I = E->child_begin(), IE = E->child_end();
+ I != IE; ++I)
+ AnalyzeImplicitConversions(S, cast<Expr>(*I));
+}
+
+} // end anonymous namespace
+
+/// Diagnoses "dangerous" implicit conversions within the given
+/// expression (which is a full expression). Implements -Wconversion
+/// and -Wsign-compare.
+void Sema::CheckImplicitConversions(Expr *E) {
+ // Don't diagnose in unevaluated contexts.
+ if (ExprEvalContexts.back().Context == Sema::Unevaluated)
+ return;
+
+ // Don't diagnose for value- or type-dependent expressions.
+ if (E->isTypeDependent() || E->isValueDependent())
+ return;
+
+ AnalyzeImplicitConversions(*this, E);
+}
+
/// CheckParmsForFunctionDef - Check that the parameters of the given
/// function are appropriate for the definition of a function. This
/// takes care of any checks that cannot be performed on the
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu May 6 03:58:33 2010
@@ -4081,8 +4081,6 @@
if (getLangOptions().CPlusPlus)
return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc);
- CheckSignCompare(LHS, RHS, QuestionLoc);
-
UsualUnaryConversions(Cond);
UsualUnaryConversions(LHS);
UsualUnaryConversions(RHS);
@@ -5274,8 +5272,6 @@
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
- CheckSignCompare(lex, rex, Loc, &Opc);
-
// C99 6.5.8p3 / C99 6.5.9p4
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
UsualArithmeticConversions(lex, rex);
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu May 6 03:58:33 2010
@@ -2113,8 +2113,6 @@
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return Context.DependentTy;
- CheckSignCompare(LHS, RHS, QuestionLoc);
-
// C++0x 5.16p2
// If either the second or the third operand has type (cv) void, ...
QualType LTy = LHS->getType();
@@ -2529,6 +2527,9 @@
Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) {
assert(SubExpr && "sub expression can't be null!");
+ // Check any implicit conversions within the expression.
+ CheckImplicitConversions(SubExpr);
+
unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
assert(ExprTemporaries.size() >= FirstTemporary);
if (ExprTemporaries.size() == FirstTemporary)
Modified: cfe/trunk/test/Sema/compare.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/compare.c?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/test/Sema/compare.c (original)
+++ cfe/trunk/test/Sema/compare.c Thu May 6 03:58:33 2010
@@ -23,8 +23,8 @@
((signed char) a == b) + // expected-warning {{comparison of integers of different signs}}
((long) a == (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
((int) a == (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
- ((short) a == (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a == (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a == (unsigned short) b) +
+ ((signed char) a == (unsigned char) b) +
(a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
(a < (unsigned int) b) +
(a < (unsigned short) b) +
@@ -35,8 +35,8 @@
((signed char) a < b) + // expected-warning {{comparison of integers of different signs}}
((long) a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) b) +
+ ((signed char) a < (unsigned char) b) +
// (A,b)
(A == (unsigned long) b) +
@@ -87,8 +87,8 @@
((signed char) a < B) +
((long) a < (unsigned long) B) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) B) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) B) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) B) +
+ ((signed char) a < (unsigned char) B) +
// (C,b)
(C == (unsigned long) b) +
@@ -139,8 +139,8 @@
((signed char) a < C) +
((long) a < (unsigned long) C) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) C) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) C) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) C) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) C) +
+ ((signed char) a < (unsigned char) C) +
// (0x80000,b)
(0x80000 == (unsigned long) b) +
@@ -191,8 +191,8 @@
((signed char) a < 0x80000) +
((long) a < (unsigned long) 0x80000) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) 0x80000) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) 0x80000) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) 0x80000) +
+ ((signed char) a < (unsigned char) 0x80000) +
// We should be able to avoid warning about this.
(b != (a < 4 ? 1 : 2)) +
Modified: cfe/trunk/test/Sema/conditional-expr.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conditional-expr.c?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/test/Sema/conditional-expr.c (original)
+++ cfe/trunk/test/Sema/conditional-expr.c Thu May 6 03:58:33 2010
@@ -52,7 +52,9 @@
enum Enum { EVal };
test0 = test0 ? EVal : test0;
test0 = test0 ? EVal : (int) test0; // okay: EVal is an int
- test0 = test0 ? (unsigned) EVal : (int) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? // expected-warning {{operands of ? are integers of different signs}}
+ (unsigned) EVal
+ : (int) test0;
}
int Postgresql() {
@@ -68,3 +70,8 @@
// GCC considers this a warning.
return a ? f1() : nil; // expected-warning {{pointer/integer type mismatch in conditional expression ('int' and 'void *')}} expected-warning {{incompatible pointer to integer conversion returning 'void *' from a function with result type 'int'}}
}
+
+int f2(int x) {
+ // We can suppress this because the immediate context wants an int.
+ return (x != 0) ? 0U : x;
+}
Modified: cfe/trunk/test/Sema/conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conversion.c?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/test/Sema/conversion.c (original)
+++ cfe/trunk/test/Sema/conversion.c Thu May 6 03:58:33 2010
@@ -287,3 +287,13 @@
char c = 5;
f7676608(c *= q);
}
+
+// <rdar://problem/7904686>
+void test_7904686(void) {
+ const int i = -1;
+ unsigned u1 = i; // expected-warning {{implicit cast changes signedness}}
+ u1 = i; // expected-warning {{implicit cast changes signedness}}
+
+ unsigned u2 = -1; // expected-warning {{implicit cast changes signedness}}
+ u2 = -1; // expected-warning {{implicit cast changes signedness}}
+}
Modified: cfe/trunk/test/SemaCXX/compare.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/compare.cpp?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/compare.cpp (original)
+++ cfe/trunk/test/SemaCXX/compare.cpp Thu May 6 03:58:33 2010
@@ -19,8 +19,8 @@
((signed char) a == b) + // expected-warning {{comparison of integers of different signs}}
((long) a == (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
((int) a == (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
- ((short) a == (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a == (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a == (unsigned short) b) +
+ ((signed char) a == (unsigned char) b) +
(a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
(a < (unsigned int) b) +
(a < (unsigned short) b) +
@@ -31,8 +31,8 @@
((signed char) a < b) + // expected-warning {{comparison of integers of different signs}}
((long) a < (unsigned long) b) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) b) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) b) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) b) +
+ ((signed char) a < (unsigned char) b) +
// (A,b)
(A == (unsigned long) b) +
@@ -83,8 +83,8 @@
((signed char) a < B) +
((long) a < (unsigned long) B) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) B) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) B) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) B) +
+ ((signed char) a < (unsigned char) B) +
// (C,b)
(C == (unsigned long) b) +
@@ -135,8 +135,8 @@
((signed char) a < C) +
((long) a < (unsigned long) C) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) C) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) C) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) C) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) C) +
+ ((signed char) a < (unsigned char) C) +
// (0x80000,b)
(0x80000 == (unsigned long) b) +
@@ -187,8 +187,8 @@
((signed char) a < 0x80000) +
((long) a < (unsigned long) 0x80000) + // expected-warning {{comparison of integers of different signs}}
((int) a < (unsigned int) 0x80000) + // expected-warning {{comparison of integers of different signs}}
- ((short) a < (unsigned short) 0x80000) + // expected-warning {{comparison of integers of different signs}}
- ((signed char) a < (unsigned char) 0x80000) + // expected-warning {{comparison of integers of different signs}}
+ ((short) a < (unsigned short) 0x80000) +
+ ((signed char) a < (unsigned char) 0x80000) +
10
;
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=103174&r1=103173&r2=103174&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Thu May 6 03:58:33 2010
@@ -238,3 +238,20 @@
(void)(true ? Bar() : Foo3()); // expected-error{{no viable constructor copying temporary}}
}
}
+
+// Reduced from selfhost.
+namespace test1 {
+ struct A {
+ enum Foo {
+ fa, fb, fc, fd, fe, ff
+ };
+
+ Foo x();
+ };
+
+ void foo(int);
+
+ void test(A *a) {
+ foo(a ? a->x() : 0);
+ }
+}
More information about the cfe-commits
mailing list