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) {

`