]> granicus.if.org Git - clang/commitdiff
This is the final step/commit for implementing exlicit implicit casts. Unlike the
authorSteve Naroff <snaroff@apple.com>
Sun, 15 Jul 2007 02:02:06 +0000 (02:02 +0000)
committerSteve Naroff <snaroff@apple.com>
Sun, 15 Jul 2007 02:02:06 +0000 (02:02 +0000)
previous two checkins, which involved lot's of tedious refactoring, this checkin is nice and clean:-)

- Hacked UsualUnaryConversions, UsualArithmeticConversions, and DefaultFunctionArrayConversion
to create the AST node (using a helper function promoteExprToType).
- Added a setType method to Expr.
- Changed Expr::isIntegerConstantExpr to allow for the new node.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39866 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Expr.cpp
Sema/SemaExpr.cpp
include/clang/AST/Expr.h

index e22e80e76e1aaffe3a15171e330ba562bbdbd28a..7638d21ed5ec2841e10a96138eb45cc16c339329 100644 (file)
@@ -278,6 +278,9 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, SourceLocation *Loc,
   default:
     if (Loc) *Loc = getLocStart();
     return false;
+  case ImplicitCastExprClass:
+    return cast<ImplicitCastExpr>(this)->getSubExpr()->
+                     isIntegerConstantExpr(Result, Loc, isEvaluated);
   case ParenExprClass:
     return cast<ParenExpr>(this)->getSubExpr()->
                      isIntegerConstantExpr(Result, Loc, isEvaluated);
index 60b07a7915ba6014113de59497988bd6a97df5df..cde73ce7d63db26e68c12ca8127d25e3e204ab34 100644 (file)
@@ -567,14 +567,25 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
   return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
 }
 
-QualType Sema::DefaultFunctionArrayConversion(Expr *&expr) {
-  QualType t = expr->getType();
+// promoteExprToType - a helper function to ensure we create exactly one 
+// ImplicitCastExpr. As a convenience (to the caller), we return the type.
+static QualType promoteExprToType(Expr *&expr, QualType type) {
+  if (ImplicitCastExpr *impCast = dyn_cast<ImplicitCastExpr>(expr))
+    impCast->setType(type);
+  else 
+    expr = new ImplicitCastExpr(type, expr);
+  return type;
+}
+
+/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
+QualType Sema::DefaultFunctionArrayConversion(Expr *&e) {
+  QualType t = e->getType();
   assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
   
-  if (t->isFunctionType()) // C99 6.3.2.1p4
-    return Context.getPointerType(t);
+  if (t->isFunctionType())
+    return promoteExprToType(e, Context.getPointerType(t));
   if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
-    return Context.getPointerType(ary->getElementType()); // C99 6.3.2.1p3
+    return promoteExprToType(e, Context.getPointerType(ary->getElementType())); 
   return t;
 }
 
@@ -587,10 +598,8 @@ QualType Sema::UsualUnaryConversions(Expr *&expr) {
   QualType t = expr->getType();
   assert(!t.isNull() && "UsualUnaryConversions - missing type");
   
-  if (t->isPromotableIntegerType()) { // C99 6.3.1.1p2
-    // expr = new ImplicitCastExpr(Context.IntTy, expr);
-    return Context.IntTy;
-  }
+  if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
+    return promoteExprToType(expr, Context.IntTy);
   return DefaultFunctionArrayConversion(expr);
 }
 
@@ -619,26 +628,36 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
   // Handle complex types first (C99 6.3.1.8p1).
   if (lhs->isComplexType() || rhs->isComplexType()) {
     // if we have an integer operand, the result is the complex type.
-    if (rhs->isIntegerType())
-      return lhs;
-    if (lhs->isIntegerType())
-      return rhs;
+    if (rhs->isIntegerType()) // convert the rhs to the lhs complex type.
+      return promoteExprToType(rhsExpr, lhs);
+
+    if (lhs->isIntegerType()) // convert the lhs to the rhs complex type.
+      return promoteExprToType(lhsExpr, rhs);
 
-    return Context.maxComplexType(lhs, rhs);
+    // Two complex types. Convert the smaller operand to the bigger result.
+    if (Context.maxComplexType(lhs, rhs) == lhs) // convert the rhs
+      return promoteExprToType(rhsExpr, lhs);
+    return promoteExprToType(lhsExpr, rhs); // convert the lhs
   }
-  
   // Now handle "real" floating types (i.e. float, double, long double).
   if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
     // if we have an integer operand, the result is the real floating type.
-    if (rhs->isIntegerType())
-      return lhs;
-    if (lhs->isIntegerType())
-      return rhs;
+    if (rhs->isIntegerType()) // convert the rhs to the lhs floating point type.
+      return promoteExprToType(rhsExpr, lhs);
+
+    if (lhs->isIntegerType()) // convert the lhs to the rhs floating point type.
+      return promoteExprToType(lhsExpr, rhs);
 
-    // we have two real floating types, float/complex combos were handled above.
-    return Context.maxFloatingType(lhs, rhs);
+    // We have two real floating types, float/complex combos were handled above.
+    // Convert the smaller operand to the bigger result.
+    if (Context.maxFloatingType(lhs, rhs) == lhs) // convert the rhs
+      return promoteExprToType(rhsExpr, lhs);
+    return promoteExprToType(lhsExpr, rhs); // convert the lhs
   }
-  return Context.maxIntegerType(lhs, rhs);
+  // Finally, we have two differing integer types.
+  if (Context.maxIntegerType(lhs, rhs) == lhs) // convert the rhs
+    return promoteExprToType(rhsExpr, lhs);
+  return promoteExprToType(lhsExpr, rhs); // convert the lhs
 }
 
 // CheckPointerTypesForAssignment - This is a very tricky routine (despite
index 802f6a6d8786c42cd84daded67ca0585546e62ef..7e288110f517b41dedd6b688e0c932e19beee539 100644 (file)
@@ -34,6 +34,7 @@ protected:
   ~Expr() {}
 public:  
   QualType getType() const { return TR; }
+  void setType(QualType t) { TR = t; }
   
   /// SourceLocation tokens are not useful in isolation - they are low level
   /// value objects created/interpreted by SourceManager. We assume AST