Move the -Wconversion logic into SemaChecking.cpp. There's a fair am… · llvm/llvm-project@263a48b (original) (raw)
`@@ -368,315 +368,6 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
`
368
368
`ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
`
369
369
`}
`
370
370
``
371
``
`-
/// Retrieves the width and signedness of the given integer type,
`
372
``
`-
/// or returns false if it is not an integer type.
`
373
``
`-
///
`
374
``
`-
/// \param T must be canonical
`
375
``
`-
static bool getIntProperties(ASTContext &C, const Type *T,
`
376
``
`-
unsigned &BitWidth, bool &Signed) {
`
377
``
`-
assert(T->isCanonicalUnqualified());
`
378
``
-
379
``
`-
if (const VectorType *VT = dyn_cast(T))
`
380
``
`-
T = VT->getElementType().getTypePtr();
`
381
``
`-
if (const ComplexType *CT = dyn_cast(T))
`
382
``
`-
T = CT->getElementType().getTypePtr();
`
383
``
-
384
``
`-
if (const BuiltinType *BT = dyn_cast(T)) {
`
385
``
`-
if (!BT->isInteger()) return false;
`
386
``
-
387
``
`-
BitWidth = C.getIntWidth(QualType(T, 0));
`
388
``
`-
Signed = BT->isSignedInteger();
`
389
``
`-
return true;
`
390
``
`-
}
`
391
``
-
392
``
`-
return false;
`
393
``
`-
}
`
394
``
-
395
``
`-
/// Checks whether the given value will have the same value if it it
`
396
``
`-
/// is truncated to the given width, then extended back to the
`
397
``
`-
/// original width.
`
398
``
`-
static bool IsSameIntAfterCast(const llvm::APSInt &value,
`
399
``
`-
unsigned TargetWidth) {
`
400
``
`-
unsigned SourceWidth = value.getBitWidth();
`
401
``
`-
llvm::APSInt truncated = value;
`
402
``
`-
truncated.trunc(TargetWidth);
`
403
``
`-
truncated.extend(SourceWidth);
`
404
``
`-
return (truncated == value);
`
405
``
`-
}
`
406
``
-
407
``
`-
/// Checks whether the given value will have the same value if it
`
408
``
`-
/// is truncated to the given width, then extended back to the original
`
409
``
`-
/// width.
`
410
``
`-
///
`
411
``
`-
/// The value might be a vector or a complex.
`
412
``
`-
static bool IsSameIntAfterCast(const APValue &value, unsigned TargetWidth) {
`
413
``
`-
if (value.isInt())
`
414
``
`-
return IsSameIntAfterCast(value.getInt(), TargetWidth);
`
415
``
-
416
``
`-
if (value.isVector()) {
`
417
``
`-
for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
`
418
``
`-
if (!IsSameIntAfterCast(value.getVectorElt(i), TargetWidth))
`
419
``
`-
return false;
`
420
``
`-
return true;
`
421
``
`-
}
`
422
``
-
423
``
`-
if (value.isComplexInt()) {
`
424
``
`-
return IsSameIntAfterCast(value.getComplexIntReal(), TargetWidth) &&
`
425
``
`-
IsSameIntAfterCast(value.getComplexIntImag(), TargetWidth);
`
426
``
`-
}
`
427
``
-
428
``
`-
// This can happen with lossless casts to intptr_t of "based" lvalues.
`
429
``
`-
// Assume it might use arbitrary bits.
`
430
``
`-
assert(value.isLValue());
`
431
``
`-
return false;
`
432
``
`-
}
`
433
``
-
434
``
-
435
``
`-
/// Checks whether the given value, which currently has the given
`
436
``
`-
/// source semantics, has the same value when coerced through the
`
437
``
`-
/// target semantics.
`
438
``
`-
static bool IsSameFloatAfterCast(const llvm::APFloat &value,
`
439
``
`-
const llvm::fltSemantics &Src,
`
440
``
`-
const llvm::fltSemantics &Tgt) {
`
441
``
`-
llvm::APFloat truncated = value;
`
442
``
-
443
``
`-
bool ignored;
`
444
``
`-
truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
`
445
``
`-
truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
`
446
``
-
447
``
`-
return truncated.bitwiseIsEqual(value);
`
448
``
`-
}
`
449
``
-
450
``
`-
/// Checks whether the given value, which currently has the given
`
451
``
`-
/// source semantics, has the same value when coerced through the
`
452
``
`-
/// target semantics.
`
453
``
`-
///
`
454
``
`-
/// The value might be a vector of floats (or a complex number).
`
455
``
`-
static bool IsSameFloatAfterCast(const APValue &value,
`
456
``
`-
const llvm::fltSemantics &Src,
`
457
``
`-
const llvm::fltSemantics &Tgt) {
`
458
``
`-
if (value.isFloat())
`
459
``
`-
return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
`
460
``
-
461
``
`-
if (value.isVector()) {
`
462
``
`-
for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
`
463
``
`-
if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
`
464
``
`-
return false;
`
465
``
`-
return true;
`
466
``
`-
}
`
467
``
-
468
``
`-
assert(value.isComplexFloat());
`
469
``
`-
return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
`
470
``
`-
IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
`
471
``
`-
}
`
472
``
-
473
``
`-
/// Determines if it's reasonable for the given expression to be truncated
`
474
``
`-
/// down to the given integer width.
`
475
``
`-
/// * Boolean expressions are automatically white-listed.
`
476
``
`-
/// * Arithmetic operations on implicitly-promoted operands of the
`
477
``
`-
/// target width or less are okay --- not because the results are
`
478
``
`-
/// actually guaranteed to fit within the width, but because the
`
479
``
`-
/// user is effectively pretending that the operations are closed
`
480
``
`-
/// within the implicitly-promoted type.
`
481
``
`-
static bool IsExprValueWithinWidth(ASTContext &C, Expr *E, unsigned Width) {
`
482
``
`-
E = E->IgnoreParens();
`
483
``
-
484
``
`-
#ifndef NDEBUG
`
485
``
`-
{
`
486
``
`-
const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
`
487
``
`-
unsigned EWidth;
`
488
``
`-
bool ESigned;
`
489
``
-
490
``
`-
if (!getIntProperties(C, ETy, EWidth, ESigned))
`
491
``
`-
assert(0 && "expression not of integer type");
`
492
``
-
493
``
`-
// The caller should never let this happen.
`
494
``
`-
assert(EWidth > Width && "called on expr whose type is too small");
`
495
``
`-
}
`
496
``
`-
#endif
`
497
``
-
498
``
`-
// Strip implicit casts off.
`
499
``
`-
while (isa(E)) {
`
500
``
`-
E = cast(E)->getSubExpr();
`
501
``
-
502
``
`-
const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
`
503
``
-
504
``
`-
unsigned EWidth;
`
505
``
`-
bool ESigned;
`
506
``
`-
if (!getIntProperties(C, ETy, EWidth, ESigned))
`
507
``
`-
return false;
`
508
``
-
509
``
`-
if (EWidth <= Width)
`
510
``
`-
return true;
`
511
``
`-
}
`
512
``
-
513
``
`-
if (BinaryOperator *BO = dyn_cast(E)) {
`
514
``
`-
switch (BO->getOpcode()) {
`
515
``
-
516
``
`-
// Boolean-valued operations are white-listed.
`
517
``
`-
case BinaryOperator::LAnd:
`
518
``
`-
case BinaryOperator::LOr:
`
519
``
`-
case BinaryOperator::LT:
`
520
``
`-
case BinaryOperator::GT:
`
521
``
`-
case BinaryOperator::LE:
`
522
``
`-
case BinaryOperator::GE:
`
523
``
`-
case BinaryOperator::EQ:
`
524
``
`-
case BinaryOperator::NE:
`
525
``
`-
return true;
`
526
``
-
527
``
`-
// Operations with opaque sources are black-listed.
`
528
``
`-
case BinaryOperator::PtrMemD:
`
529
``
`-
case BinaryOperator::PtrMemI:
`
530
``
`-
return false;
`
531
``
-
532
``
`-
// Left shift gets black-listed based on a judgement call.
`
533
``
`-
case BinaryOperator::Shl:
`
534
``
`-
return false;
`
535
``
-
536
``
`-
// Various special cases.
`
537
``
`-
case BinaryOperator::Shr:
`
538
``
`-
return IsExprValueWithinWidth(C, BO->getLHS(), Width);
`
539
``
`-
case BinaryOperator::Comma:
`
540
``
`-
return IsExprValueWithinWidth(C, BO->getRHS(), Width);
`
541
``
`-
case BinaryOperator::Sub:
`
542
``
`-
if (BO->getLHS()->getType()->isPointerType())
`
543
``
`-
return false;
`
544
``
`-
// fallthrough
`
545
``
-
546
``
`-
// Any other operator is okay if the operands are
`
547
``
`-
// promoted from expressions of appropriate size.
`
548
``
`-
default:
`
549
``
`-
return IsExprValueWithinWidth(C, BO->getLHS(), Width) &&
`
550
``
`-
IsExprValueWithinWidth(C, BO->getRHS(), Width);
`
551
``
`-
}
`
552
``
`-
}
`
553
``
-
554
``
`-
if (UnaryOperator *UO = dyn_cast(E)) {
`
555
``
`-
switch (UO->getOpcode()) {
`
556
``
`-
// Boolean-valued operations are white-listed.
`
557
``
`-
case UnaryOperator::LNot:
`
558
``
`-
return true;
`
559
``
-
560
``
`-
// Operations with opaque sources are black-listed.
`
561
``
`-
case UnaryOperator::Deref:
`
562
``
`-
case UnaryOperator::AddrOf: // should be impossible
`
563
``
`-
return false;
`
564
``
-
565
``
`-
case UnaryOperator::OffsetOf:
`
566
``
`-
return false;
`
567
``
-
568
``
`-
default:
`
569
``
`-
return IsExprValueWithinWidth(C, UO->getSubExpr(), Width);
`
570
``
`-
}
`
571
``
`-
}
`
572
``
-
573
``
`-
// Don't diagnose if the expression is an integer constant
`
574
``
`-
// whose value in the target type is the same as it was
`
575
``
`-
// in the original type.
`
576
``
`-
Expr::EvalResult result;
`
577
``
`-
if (E->Evaluate(result, C))
`
578
``
`-
if (IsSameIntAfterCast(result.Val, Width))
`
579
``
`-
return true;
`
580
``
-
581
``
`-
return false;
`
582
``
`-
}
`
583
``
-
584
``
`-
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
`
585
``
`-
static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
`
586
``
`-
S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
`
587
``
`-
}
`
588
``
-
589
``
`-
/// Implements -Wconversion.
`
590
``
`-
static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) {
`
591
``
`-
// Don't diagnose in unevaluated contexts.
`
592
``
`-
if (S.ExprEvalContexts.back().Context == Sema::Unevaluated)
`
593
``
`-
return;
`
594
``
-
595
``
`-
// Don't diagnose for value-dependent expressions.
`
596
``
`-
if (E->isValueDependent())
`
597
``
`-
return;
`
598
``
-
599
``
`-
const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
`
600
``
`-
const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
`
601
``
-
602
``
`-
// Never diagnose implicit casts to bool.
`
603
``
`-
if (Target->isSpecificBuiltinType(BuiltinType::Bool))
`
604
``
`-
return;
`
605
``
-
606
``
`-
// Strip vector types.
`
607
``
`-
if (isa(Source)) {
`
608
``
`-
if (!isa(Target))
`
609
``
`-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_vector_scalar);
`
610
``
-
611
``
`-
Source = cast(Source)->getElementType().getTypePtr();
`
612
``
`-
Target = cast(Target)->getElementType().getTypePtr();
`
613
``
`-
}
`
614
``
-
615
``
`-
// Strip complex types.
`
616
``
`-
if (isa(Source)) {
`
617
``
`-
if (!isa(Target))
`
618
``
`-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_complex_scalar);
`
619
``
-
620
``
`-
Source = cast(Source)->getElementType().getTypePtr();
`
621
``
`-
Target = cast(Target)->getElementType().getTypePtr();
`
622
``
`-
}
`
623
``
-
624
``
`-
const BuiltinType *SourceBT = dyn_cast(Source);
`
625
``
`-
const BuiltinType *TargetBT = dyn_cast(Target);
`
626
``
-
627
``
`-
// If the source is floating point...
`
628
``
`-
if (SourceBT && SourceBT->isFloatingPoint()) {
`
629
``
`-
// ...and the target is floating point...
`
630
``
`-
if (TargetBT && TargetBT->isFloatingPoint()) {
`
631
``
`-
// ...then warn if we're dropping FP rank.
`
632
``
-
633
``
`-
// Builtin FP kinds are ordered by increasing FP rank.
`
634
``
`-
if (SourceBT->getKind() > TargetBT->getKind()) {
`
635
``
`-
// Don't warn about float constants that are precisely
`
636
``
`-
// representable in the target type.
`
637
``
`-
Expr::EvalResult result;
`
638
``
`-
if (E->Evaluate(result, S.Context)) {
`
639
``
`-
// Value might be a float, a float vector, or a float complex.
`
640
``
`-
if (IsSameFloatAfterCast(result.Val,
`
641
``
`-
S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
`
642
``
`-
S.Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
`
643
``
`-
return;
`
644
``
`-
}
`
645
``
-
646
``
`-
DiagnoseImpCast(S, E, T, diag::warn_impcast_float_precision);
`
647
``
`-
}
`
648
``
`-
return;
`
649
``
`-
}
`
650
``
-
651
``
`-
// If the target is integral, always warn.
`
652
``
`-
if ((TargetBT && TargetBT->isInteger()))
`
653
``
`-
// TODO: don't warn for integer values?
`
654
``
`-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer);
`
655
``
-
656
``
`-
return;
`
657
``
`-
}
`
658
``
-
659
``
`-
unsigned SourceWidth, TargetWidth;
`
660
``
`-
bool SourceSigned, TargetSigned;
`
661
``
-
662
``
`-
if (!getIntProperties(S.Context, Source, SourceWidth, SourceSigned) ||
`
663
``
`-
!getIntProperties(S.Context, Target, TargetWidth, TargetSigned))
`
664
``
`-
return;
`
665
``
-
666
``
`-
if (SourceWidth > TargetWidth) {
`
667
``
`-
if (IsExprValueWithinWidth(S.Context, E, TargetWidth))
`
668
``
`-
return;
`
669
``
-
670
``
`-
// People want to build with -Wshorten-64-to-32 and not -Wconversion
`
671
``
`-
// and by god we'll let them.
`
672
``
`-
if (SourceWidth == 64 && TargetWidth == 32)
`
673
``
`-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_64_32);
`
674
``
`-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_precision);
`
675
``
`-
}
`
676
``
-
677
``
`-
return;
`
678
``
`-
}
`
679
``
-
680
371
`/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
`
681
372
`/// If there is already an implicit cast, merge into the existing one.
`
682
373
`/// If isLvalue, the result of the cast is an lvalue.
`
`@@ -697,7 +388,7 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
`
697
388
` }
`
698
389
` }
`
699
390
``
700
``
`-
CheckImplicitConversion(*this, Expr, Ty);
`
``
391
`+
CheckImplicitConversion(Expr, Ty);
`
701
392
``
702
393
`if (ImplicitCastExpr *ImpCast = dyn_cast(Expr)) {
`
703
394
`if (ImpCast->getCastKind() == Kind) {
`