[cfe-commits] Patch for evaluating FP constant expressions

Chris Lattner clattner at apple.com
Thu Nov 29 11:51:03 PST 2007

On Nov 28, 2007, at 10:18 PM, Christopher Lamb wrote:

> I needed this to support negation of FP literals, which is pretty  
> unambiguous. It looks like GCC evaluates more complex constant  
> expressions too, so I put in support for some of that (though  
> rounding mode is an issue). All of this is modeled on the work for  
> integer expressions and uses APFloat.

Very interesting, I didn't realize that this was non-conforming:

double x = -1.0;

A couple of comments:

+  /// isRealFloatingConstantExpr - Return true if this expression is  
a valid
+  /// floating point constant expression, and, if so, return its  
value in
+  /// Result.  If not a valid rfce, return false and fill in Loc (if  
+  /// with the location of the invalid expression.
+  bool isRealFloatingConstantExpr(llvm::APFloat &Result, ASTContext  
+                                  SourceLocation *Loc = 0,
+                                  bool isEvaluated = true) const;

Please add a comment that states this can only be used for statically  
initialized values.  For non-static initializers, the code should be  
evaluated in its current context, which could be affected by rounding  
mode etc.

+    // FIXME: How to choose the rounding mode? Emulate GCC behavior?

This codegen routine should only be used for static initializers.   
Static inits are evaluated before main and static ctors run (e.g. at  
compile time ;-), so they can only be evaluated with the default  
rounding mode.  Please add a comment to this effect.

+  case BinaryOperatorClass: {
+    const BinaryOperator *Exp = cast<BinaryOperator>(this);
+    // The LHS of a constant expr is always evaluated and needed.
+    if (!Exp->getLHS()->isRealFloatingConstantExpr(Result, Ctx, Loc,
+                                                   isEvaluated))
+      return false;
+    llvm::APFloat RHS(Result);
+    // The short-circuiting &&/|| operators don't necessarily  
evaluate their
+    // RHS.  Make sure to pass isEvaluated down correctly.
+    if (Exp->isLogicalOp()) {
+      bool RHSEval;
+      if (Exp->getOpcode() == BinaryOperator::LAnd)
+        RHSEval = Result.isNonZero();
+      else {
+        assert(Exp->getOpcode() == BinaryOperator::LOr &&"Unexpected  
+        RHSEval = Result.isZero();
+      }

Logical ops like && always return bool, not an fp type, so I think  
this code is dead.

It would probably also be worthwhile to handle int <-> fp casts as  
well, but that can be a follow-on patch if you prefer.

+    case BinaryOperator::Div:
+      if (llvm::APFloat::opOK !=
+          Result.divide(RHS, llvm::APFloat::rmNearestTiesToEven)) {
+        if (!isEvaluated) break;
+        if (Loc) *Loc = getLocStart();
+        return false;
+      }

It would be "nice" if this reported diagnostics for overflow etc as  

Thanks for tackling this!

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20071129/185bbbfb/attachment.html>

More information about the cfe-commits mailing list