diff options
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 406 |
1 files changed, 273 insertions, 133 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 7029711..4f3f41b 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -75,14 +75,15 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, TheLexer.LexFromRawLexer(TheTok); // Use the StringLiteralParser to compute the length of the string in bytes. - StringLiteralParser SLP(&TheTok, 1, PP); + StringLiteralParser SLP(&TheTok, 1, PP, /*Complain=*/false); unsigned TokNumBytes = SLP.GetStringLength(); // If the byte is in this token, return the location of the byte. if (ByteNo < TokNumBytes || (ByteNo == TokNumBytes && TokNo == SL->getNumConcatenated())) { unsigned Offset = - StringLiteralParser::getOffsetOfStringByte(TheTok, ByteNo, PP); + StringLiteralParser::getOffsetOfStringByte(TheTok, ByteNo, PP, + /*Complain=*/false); // Now that we know the offset of the token in the spelling, use the // preprocessor to get the offset in the original source. @@ -607,12 +608,25 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { if (OrigArg->isTypeDependent()) return false; - // This operation requires a floating-point number + // This operation requires a non-_Complex floating-point number. if (!OrigArg->getType()->isRealFloatingType()) return Diag(OrigArg->getLocStart(), diag::err_typecheck_call_invalid_unary_fp) << OrigArg->getType() << OrigArg->getSourceRange(); + // If this is an implicit conversion from float -> double, remove it. + if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) { + Expr *CastArg = Cast->getSubExpr(); + if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { + assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && + "promotion from float to double is the only expected cast here"); + Cast->setSubExpr(0); + Cast->Destroy(Context); + TheCall->setArg(NumArgs-1, CastArg); + OrigArg = CastArg; + } + } + return false; } @@ -1718,8 +1732,14 @@ struct IntRange { 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()); @@ -1961,6 +1981,10 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { 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. @@ -1999,7 +2023,40 @@ bool IsSameFloatAfterCast(const APValue &value, 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. /// @@ -2007,138 +2064,85 @@ bool IsSameFloatAfterCast(const APValue &value, /// \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(); - - // Only warn if both operands are integral. - if (!lt->isIntegerType() || !rt->isIntegerType()) - return; - - // 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; +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); + + Expr *lex = E->getLHS()->IgnoreParenImpCasts(); + Expr *rex = E->getRHS()->IgnoreParenImpCasts(); + + // 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); + // Otherwise, calculate the effective range of the signed operand. + IntRange signedRange = GetExprRange(S.Context, signedOperand); - // 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; + // 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); - // 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; - } + // 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; +void CheckImplicitConversion(Sema &S, Expr *E, QualType T, + bool *ICContext = 0) { + if (E->isTypeDependent() || E->isValueDependent()) 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(); + 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)) @@ -2147,7 +2151,7 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) { // 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(); @@ -2156,7 +2160,7 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) { // 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(); @@ -2176,15 +2180,15 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) { // 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; } @@ -2192,7 +2196,7 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) { // 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; } @@ -2200,22 +2204,158 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) { 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 |