19
19
#include " llvm/Support/Compiler.h"
20
20
using namespace clang ;
21
21
using llvm::APSInt;
22
+ using llvm::APFloat;
22
23
23
24
// / EvalInfo - This is a private struct used by the evaluator to capture
24
25
// / information about a subexpression as it is folded. It retains information
@@ -63,7 +64,7 @@ struct EvalInfo {
63
64
64
65
static bool EvaluatePointer (const Expr *E, APValue &Result, EvalInfo &Info);
65
66
static bool EvaluateInteger (const Expr *E, APSInt &Result, EvalInfo &Info);
66
-
67
+ static bool EvaluateFloat ( const Expr *E, APFloat &Result, EvalInfo &Info);
67
68
68
69
// ===----------------------------------------------------------------------===//
69
70
// Pointer Evaluation
@@ -477,23 +478,13 @@ bool IntExprEvaluator::HandleCast(SourceLocation CastLoc,
477
478
if (!SubExpr->getType ()->isRealFloatingType ())
478
479
return Error (CastLoc, diag::err_expr_not_constant);
479
480
480
- // FIXME: Generalize floating point constant folding! For now we just permit
481
- // which is allowed by integer constant expressions.
482
-
483
- // Allow floating constants that are the immediate operands of casts or that
484
- // are parenthesized.
485
- const Expr *Operand = SubExpr;
486
- while (const ParenExpr *PE = dyn_cast<ParenExpr>(Operand))
487
- Operand = PE->getSubExpr ();
488
-
489
- // If this isn't a floating literal, we can't handle it.
490
- const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(Operand);
491
- if (!FL)
481
+ APFloat F (0.0 );
482
+ if (!EvaluateFloat (SubExpr, F, Info))
492
483
return Error (CastLoc, diag::err_expr_not_constant);
493
-
484
+
494
485
// If the destination is boolean, compare against zero.
495
486
if (DestType->isBooleanType ()) {
496
- Result = !FL-> getValue () .isZero ();
487
+ Result = !F .isZero ();
497
488
Result.zextOrTrunc (DestWidth);
498
489
Result.setIsUnsigned (DestType->isUnsignedIntegerType ());
499
490
return true ;
@@ -504,28 +495,98 @@ bool IntExprEvaluator::HandleCast(SourceLocation CastLoc,
504
495
505
496
// FIXME: Warning for overflow.
506
497
uint64_t Space[4 ];
507
- (void )FL-> getValue () .convertToInteger (Space, DestWidth, DestSigned,
508
- llvm::APFloat::rmTowardZero);
498
+ (void )F .convertToInteger (Space, DestWidth, DestSigned,
499
+ llvm::APFloat::rmTowardZero);
509
500
Result = llvm::APInt (DestWidth, 4 , Space);
510
501
Result.setIsUnsigned (!DestSigned);
511
502
return true ;
512
503
}
513
504
505
+ // ===----------------------------------------------------------------------===//
506
+ // Float Evaluation
507
+ // ===----------------------------------------------------------------------===//
508
+
509
+ namespace {
510
+ class VISIBILITY_HIDDEN FloatExprEvaluator
511
+ : public StmtVisitor<FloatExprEvaluator, bool > {
512
+ EvalInfo &Info;
513
+ APFloat &Result;
514
+ public:
515
+ FloatExprEvaluator (EvalInfo &info, APFloat &result)
516
+ : Info(info), Result(result) {}
517
+
518
+ bool VisitStmt (Stmt *S) {
519
+ return false ;
520
+ }
521
+
522
+ bool VisitParenExpr (ParenExpr *E) { return Visit (E->getSubExpr ()); }
523
+
524
+ bool VisitBinaryOperator (const BinaryOperator *E);
525
+ bool VisitFloatingLiteral (const FloatingLiteral *E);
526
+ };
527
+ } // end anonymous namespace
528
+
529
+ static bool EvaluateFloat (const Expr* E, APFloat& Result, EvalInfo &Info) {
530
+ return FloatExprEvaluator (Info, Result).Visit (const_cast <Expr*>(E));
531
+ }
532
+
533
+ bool FloatExprEvaluator::VisitBinaryOperator (const BinaryOperator *E) {
534
+ // FIXME: Diagnostics? I really don't understand how the warnings
535
+ // and errors are supposed to work.
536
+ APFloat LHS (0.0 ), RHS (0.0 );
537
+ if (!EvaluateFloat (E->getLHS (), Result, Info))
538
+ return false ;
539
+ if (!EvaluateFloat (E->getRHS (), RHS, Info))
540
+ return false ;
541
+
542
+ switch (E->getOpcode ()) {
543
+ default : return false ;
544
+ case BinaryOperator::Mul:
545
+ Result.multiply (RHS, APFloat::rmNearestTiesToEven);
546
+ return true ;
547
+ case BinaryOperator::Add:
548
+ Result.add (RHS, APFloat::rmNearestTiesToEven);
549
+ return true ;
550
+ case BinaryOperator::Sub:
551
+ Result.subtract (RHS, APFloat::rmNearestTiesToEven);
552
+ return true ;
553
+ case BinaryOperator::Div:
554
+ Result.divide (RHS, APFloat::rmNearestTiesToEven);
555
+ return true ;
556
+ case BinaryOperator::Rem:
557
+ Result.mod (RHS, APFloat::rmNearestTiesToEven);
558
+ return true ;
559
+ }
560
+ }
561
+
562
+ bool FloatExprEvaluator::VisitFloatingLiteral (const FloatingLiteral *E) {
563
+ Result = E->getValue ();
564
+ return true ;
565
+ }
566
+
514
567
// ===----------------------------------------------------------------------===//
515
568
// Top level TryEvaluate.
516
569
// ===----------------------------------------------------------------------===//
517
570
518
571
bool Expr::tryEvaluate (APValue &Result, ASTContext &Ctx) const {
519
- llvm::APSInt sInt (32 );
520
-
521
572
EvalInfo Info (Ctx);
522
573
if (getType ()->isIntegerType ()) {
574
+ llvm::APSInt sInt (32 );
523
575
if (EvaluateInteger (this , sInt , Info)) {
524
576
Result = APValue (sInt );
525
577
return true ;
526
578
}
527
- } else
528
- return false ;
579
+ } else if (getType ()->isPointerType ()) {
580
+ if (EvaluatePointer (this , Result, Info)) {
581
+ return true ;
582
+ }
583
+ } else if (getType ()->isRealFloatingType ()) {
584
+ llvm::APFloat f (0.0 );
585
+ if (EvaluateFloat (this , f, Info)) {
586
+ Result = APValue (f);
587
+ return true ;
588
+ }
589
+ }
529
590
530
591
return false ;
531
592
}
0 commit comments