[cfe-commits] r39418 - in /cfe/cfe/trunk: AST/ASTContext.cpp AST/SemaExpr.cpp Driver/clang.cpp Sema/SemaExpr.cpp include/clang/AST/ASTContext.h include/clang/AST/Expr.h include/clang/Basic/DiagnosticKinds.def

Steve Naroff snaroff at apple.com
Wed Jul 11 09:44:09 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:44:08 2007
New Revision: 39418

URL: http://llvm.org/viewvc/llvm-project?rev=39418&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
More typechecking, refactoring...
- Implemented the following routines...CheckAdditiveOperands,
CheckCommaOperands, CheckLogicalOperands.
- Added maxComplexType, maxFloatingType, & maxIntegerType to ASTContext.
Ranking helper functions moved to ASTContext as well (they are private:-)
- Simplified UsualArithmeticConversions using the new ASTContext hooks.
- Fixed isAssignmentOp()...is was preventing comma exprs from ever being created:-(
- Changed a GCC compat extension to truly be an extension (and turned extensions
on by default). This now produces a warning by default.

Modified:
    cfe/cfe/trunk/AST/ASTContext.cpp
    cfe/cfe/trunk/AST/SemaExpr.cpp
    cfe/cfe/trunk/Driver/clang.cpp
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/include/clang/AST/ASTContext.h
    cfe/cfe/trunk/include/clang/AST/Expr.h
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/ASTContext.cpp?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/cfe/trunk/AST/ASTContext.cpp Wed Jul 11 11:44:08 2007
@@ -293,3 +293,116 @@
   return UnsignedLongTy; 
 }
 
+/// getIntegerRank - Helper function for UsualArithmeticConversions().
+int ASTContext::getIntegerRank(QualType t) {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
+    switch (BT->getKind()) {
+    case BuiltinType::SChar:
+    case BuiltinType::UChar:
+      return 1;
+    case BuiltinType::Short:
+    case BuiltinType::UShort:
+      return 2;
+    case BuiltinType::Int:
+    case BuiltinType::UInt:
+      return 3;
+    case BuiltinType::Long:
+    case BuiltinType::ULong:
+      return 4;
+    case BuiltinType::LongLong:
+    case BuiltinType::ULongLong:
+      return 5;
+    default:
+      assert(0 && "GetIntegerRank(): not an integer type");
+    }
+  }
+  return 0;
+}
+
+/// getFloatingRank - Helper function for UsualArithmeticConversions().
+int ASTContext::getFloatingRank(QualType t) {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
+    switch (BT->getKind()) {
+    case BuiltinType::Float:
+    case BuiltinType::FloatComplex:
+      return 1;
+    case BuiltinType::Double:
+    case BuiltinType::DoubleComplex:
+      return 2;
+    case BuiltinType::LongDouble:
+    case BuiltinType::LongDoubleComplex:
+      return 3;
+    default:
+      assert(0 && "getFloatingPointRank(): not a floating type");
+    }
+  }
+  return 0;
+}
+
+QualType ASTContext::convertSignedWithGreaterRankThanUnsigned(
+  QualType signedType, QualType unsignedType) {
+  // FIXME: Need to check if the signed type can represent all values of the 
+  // unsigned type. If it can, then the result is the signed type. If it can't, 
+  // then the result is the unsigned version of the signed type.
+  return signedType; 
+}
+
+
+/// ConvertFloatingRankToComplexType - Another helper for converting floats.
+QualType ASTContext::convertFloatingRankToComplexType(int rank) {
+  switch (rank) {
+  case 1:
+    return FloatComplexTy;
+  case 2:
+    return DoubleComplexTy;
+  case 3:
+    return LongDoubleComplexTy;
+  default:
+    assert(0 && "convertRankToComplex(): illegal value for rank");
+  }
+}
+
+// maxComplexType - the following code handles 3 different combinations:
+// complex/complex, complex/float, float/complex. 
+// When both operands are complex, the shorter operand is converted to the 
+// type of the longer, and that is the type of the result. This corresponds 
+// to what is done when combining two real floating-point operands. 
+// The fun begins when size promotion occur across type domains. g
+// getFloatingRank & convertFloatingRankToComplexType handle this without 
+// enumerating all permutations. 
+// It also allows us to add new types without breakage.
+// From H&S 6.3.4: When one operand is complex and the other is a real
+// floating-point type, the less precise type is converted, within it's 
+// real or complex domain, to the precision of the other type. For example,
+// when combining a "long double" with a "double _Complex", the 
+// "double _Complex" is promoted to "long double _Complex".
+
+QualType ASTContext::maxComplexType(QualType lt, QualType rt) {
+  int lhsRank = getFloatingRank(lt);
+  int rhsRank = getFloatingRank(rt);
+  
+  return convertFloatingRankToComplexType(std::max(lhsRank, rhsRank));
+}
+
+// maxFloatingType - handles the simple case, both operands are floats.
+QualType ASTContext::maxFloatingType(QualType lt, QualType rt) {
+  return getFloatingRank(lt) > getFloatingRank(rt) ? lt : rt;
+}
+
+QualType ASTContext::maxIntegerType(QualType lhs, QualType rhs) {
+  // Lastly, handle two integers (C99 6.3.1.8p1)
+  bool t1Unsigned = lhs->isUnsignedIntegerType();
+  bool t2Unsigned = rhs->isUnsignedIntegerType();
+  
+  if ((t1Unsigned && t2Unsigned) || (!t1Unsigned && !t2Unsigned))
+    return getIntegerRank(lhs) >= getIntegerRank(rhs) ? lhs : rhs; 
+  
+  // We have two integer types with differing signs
+  QualType unsignedType = t1Unsigned ? lhs : rhs;
+  QualType signedType = t1Unsigned ? rhs : lhs;
+  
+  if (getIntegerRank(unsignedType) >= getIntegerRank(signedType))
+    return unsignedType;
+  else 
+    return convertSignedWithGreaterRankThanUnsigned(signedType, unsignedType); 
+}

Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:08 2007
@@ -25,6 +25,12 @@
 using namespace llvm;
 using namespace clang;
 
+// Sema.h avoids including Expr.h. As a result, all the Check* functions take 
+// an unsigned which is really an enum. These typedefs provide a short hand
+// notiation for casting (to keep the lines within 80 columns:-)
+typedef BinaryOperator::Opcode BOP;
+typedef UnaryOperator::Opcode UOP;
+
 /// ParseStringLiteral - The specified tokens were lexed as pasted string
 /// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
 /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
@@ -88,8 +94,7 @@
   switch (Kind) {
   default:
     assert(0 && "Unknown simple primary expr!");
-  case tok::char_constant:     // constant: character-constant
-    // TODO: MOVE this to be some other callback.
+  // TODO: MOVE this to be some other callback.
   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
   case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU]
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
@@ -411,7 +416,7 @@
     return CheckAssignmentOperands(lhs, rhs, TokLoc, Opc);
   else if (Opc == BinaryOperator::Comma)
     return CheckCommaOperands(lhs, rhs, TokLoc);
-    
+
   assert(0 && "ParseBinOp(): illegal binary op");
 }
 
@@ -427,7 +432,7 @@
   assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
   assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
 
-  QualType canonType = rhs.getCanonicalType(); // TEMPORARY
+  QualType canonType = rhs.getCanonicalType(); // FIXME
   return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, canonType);
 }
 
@@ -448,75 +453,6 @@
   return t;
 }
 
-/// GetIntegerRank - Helper function for UsualArithmeticConversions().
-static inline int GetIntegerRank(QualType t) {
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
-    switch (BT->getKind()) {
-    case BuiltinType::SChar:
-    case BuiltinType::UChar:
-      return 1;
-    case BuiltinType::Short:
-    case BuiltinType::UShort:
-      return 2;
-    case BuiltinType::Int:
-    case BuiltinType::UInt:
-      return 3;
-    case BuiltinType::Long:
-    case BuiltinType::ULong:
-      return 4;
-    case BuiltinType::LongLong:
-    case BuiltinType::ULongLong:
-      return 5;
-    default:
-      assert(0 && "getFloatingPointRank(): not a floating type");
-    }
-  }
-  return 0;
-}
-
-static inline QualType ConvertSignedWithGreaterRankThanUnsigned(
-  QualType signedType, QualType unsignedType) {
-  // FIXME: Need to check if the signed type can represent all values of the 
-  // unsigned type. If it can, then the result is the signed type. If it can't, 
-  // then the result is the unsigned version of the signed type.
-  return signedType; 
-}
-
-/// GetFloatingRank - Helper function for UsualArithmeticConversions().
-static inline int GetFloatingRank(QualType t) {
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
-    switch (BT->getKind()) {
-    case BuiltinType::Float:
-    case BuiltinType::FloatComplex:
-      return 1;
-    case BuiltinType::Double:
-    case BuiltinType::DoubleComplex:
-      return 2;
-    case BuiltinType::LongDouble:
-    case BuiltinType::LongDoubleComplex:
-      return 3;
-    default:
-      assert(0 && "getFloatingPointRank(): not a floating type");
-    }
-  }
-  return 0;
-}
-
-/// ConvertFloatingRankToComplexType - Another helper for converting floats.
-static inline QualType ConvertFloatingRankToComplexType(int rank, 
-                                                        ASTContext &C) {
-  switch (rank) {
-  case 1:
-    return C.FloatComplexTy;
-  case 2:
-    return C.DoubleComplexTy;
-  case 3:
-    return C.LongDoubleComplexTy;
-  default:
-    assert(0 && "convertRankToComplex(): illegal value for rank");
-  }
-}
-
 /// UsualArithmeticConversions - Performs various conversions that are common to 
 /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
 /// routine returns the first non-arithmetic type found. The client is 
@@ -545,23 +481,7 @@
     if (lhs->isIntegerType())
       return rhs;
 
-    // the following code handles three different combinations:
-    // complex/complex, complex/float, float/complex. When both operands 
-    // are complex, the shorter operand is converted to the type of the longer,
-    // and that is the type of the result. This corresponds to what is done
-    // when combining two real floating-point operands. The fun begins when 
-    // size promotion occur across type domains. GetFloatingRank &
-    // ConvertFloatingRankToComplexType handle this without enumerating all
-    // permutations. It also allows us to add new types without breakage.
-    int lhsRank = GetFloatingRank(lhs);
-    int rhsRank = GetFloatingRank(rhs);
-    
-    // From H&S 6.3.4: When one operand is complex and the other is a real
-    // floating-point type, the less precise type is converted, within it's 
-    // real or complex domain, to the precision of the other type. For example,
-    // when combining a "long double" with a "double _Complex", the 
-    // "double _Complex" is promoted to "long double _Complex".
-    return ConvertFloatingRankToComplexType(std::max(lhsRank,rhsRank), Context);
+    return Context.maxComplexType(lhs, rhs);
   }
   // Now handle "real" floating types (i.e. float, double, long double).
   if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
@@ -572,23 +492,9 @@
       return rhs;
 
     // we have two real floating types, float/complex combos were handled above.
-    return GetFloatingRank(lhs) >= GetFloatingRank(rhs) ? lhs : rhs;
+    return Context.maxFloatingType(lhs, rhs);
   }
-  // Lastly, handle two integers (C99 6.3.1.8p1)
-  bool t1Unsigned = lhs->isUnsignedIntegerType();
-  bool t2Unsigned = rhs->isUnsignedIntegerType();
-  
-  if ((t1Unsigned && t2Unsigned) || (!t1Unsigned && !t2Unsigned))
-    return GetIntegerRank(lhs) >= GetIntegerRank(rhs) ? lhs : rhs; 
-  
-  // We have two integer types with differing signs
-  QualType unsignedType = t1Unsigned ? lhs : rhs;
-  QualType signedType = t1Unsigned ? rhs : lhs;
-  
-  if (GetIntegerRank(unsignedType) >= GetIntegerRank(signedType))
-    return unsignedType;
-  else 
-    return ConvertSignedWithGreaterRankThanUnsigned(signedType, unsignedType); 
+  return Context.maxIntegerType(lhs, rhs);
 }
 
 Action::ExprResult Sema::CheckMultiplicativeOperands(
@@ -596,21 +502,37 @@
 {
   QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
   
-  if ((BinaryOperator::Opcode)code == BinaryOperator::Rem) {
+  if ((BOP)code == BinaryOperator::Rem) {
     if (!resType->isIntegerType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
   } else { // *, /
     if (!resType->isArithmeticType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
   }
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+  return new BinaryOperator(lex, rex, (BOP)code, resType);
 }
 
 Action::ExprResult Sema::CheckAdditiveOperands( // C99 6.5.6
   Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
-  // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  // handle the common case first (both operands are arithmetic).
+  if (resType->isArithmeticType())
+    return new BinaryOperator(lex, rex, (BOP)code, resType);
+  else {
+    if ((BOP)code == BinaryOperator::Add) {
+      if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+          (lhsType->isIntegerType() && rhsType->isPointerType()))
+        return new BinaryOperator(lex, rex, (BOP)code, resType);
+    } else { // -
+      if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+          (lhsType->isPointerType() && rhsType->isPointerType()))
+        return new BinaryOperator(lex, rex, (BOP)code, resType);
+    }
+  }
+  return Diag(loc, diag::err_typecheck_invalid_operands);
 }
 
 Action::ExprResult Sema::CheckShiftOperands( // C99 6.5.7
@@ -621,7 +543,7 @@
   if (!resType->isIntegerType())
     return Diag(loc, diag::err_typecheck_invalid_operands);
 
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+  return new BinaryOperator(lex, rex, (BOP)code, resType);
 }
 
 Action::ExprResult Sema::CheckRelationalOperands( // C99 6.5.8
@@ -630,17 +552,14 @@
   QualType lType = lex->getType(), rType = rex->getType();
   
   if (lType->isRealType() && rType->isRealType())
-    ;
-  else if (lType->isPointerType() &&  rType->isPointerType())
-    ;
-  else {
-    // The following test is for GCC compatibility.
-    if (lType->isIntegerType() || rType->isIntegerType())
-      return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
-    return Diag(loc, diag::err_typecheck_invalid_operands);
-  }
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, 
-                            Context.IntTy);
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+  
+  if (lType->isPointerType() &&  rType->isPointerType())
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+  if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+    return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+  return Diag(loc, diag::err_typecheck_invalid_operands);
 }
 
 Action::ExprResult Sema::CheckEqualityOperands( // C99 6.5.9
@@ -649,17 +568,14 @@
   QualType lType = lex->getType(), rType = rex->getType();
   
   if (lType->isArithmeticType() && rType->isArithmeticType())
-    ;
-  else if (lType->isPointerType() &&  rType->isPointerType())
-    ;
-  else {
-    // The following test is for GCC compatibility.
-    if (lType->isIntegerType() || rType->isIntegerType())
-      return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
-    return Diag(loc, diag::err_typecheck_invalid_operands);
-  }
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, 
-                            Context.IntTy);
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+  
+  if (lType->isPointerType() &&  rType->isPointerType())
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+  if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+    return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+  return Diag(loc, diag::err_typecheck_invalid_operands);
 }
 
 Action::ExprResult Sema::CheckBitwiseOperands(
@@ -670,28 +586,33 @@
   if (!resType->isIntegerType())
     return Diag(loc, diag::err_typecheck_invalid_operands);
 
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+  return new BinaryOperator(lex, rex, (BOP)code, resType);
 }
 
 Action::ExprResult Sema::CheckLogicalOperands( // C99 6.5.[13,14]
   Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
-  // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+  QualType lhsType = UsualUnaryConversion(lex->getType());
+  QualType rhsType = UsualUnaryConversion(rex->getType());
+  
+  if (!lhsType->isScalarType() || !rhsType->isScalarType())
+    return Diag(loc, diag::err_typecheck_invalid_operands);
+    
+  return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
 }
 
 Action::ExprResult Sema::CheckAssignmentOperands( // C99 6.5.16
   Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
   // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+  return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
 }
 
 Action::ExprResult Sema::CheckCommaOperands( // C99 6.5.17
   Expr *lex, Expr *rex, SourceLocation loc) 
 {
-  // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, BinaryOperator::Comma, Context.IntTy);
+  QualType rhsType = UsualUnaryConversion(rex->getType());
+  return new BinaryOperator(lex, rex, BinaryOperator::Comma, rhsType);
 }
 
 Action::ExprResult
@@ -717,7 +638,7 @@
   if (!canonType.isModifiableLvalue())
     return Diag(OpLoc, diag::err_typecheck_not_modifiable, qType);
 
-  return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
+  return new UnaryOperator(op, (UOP)OpCode, qType);
 }
 
 /// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
@@ -806,5 +727,5 @@
       return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
     break;
   }
-  return new UnaryOperator(op, (UnaryOperator::Opcode)Opc, resultType);
+  return new UnaryOperator(op, (UOP)Opc, resultType);
 }

Modified: cfe/cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/clang.cpp?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/Driver/clang.cpp (original)
+++ cfe/cfe/trunk/Driver/clang.cpp Wed Jul 11 11:44:08 2007
@@ -299,7 +299,7 @@
 WarningsAsErrors("Werror", cl::desc("Treat all warnings as errors"));
 
 static cl::opt<bool>
-WarnOnExtensions("pedantic",
+WarnOnExtensions("pedantic", cl::init(true),
                  cl::desc("Issue a warning on uses of GCC extensions"));
 
 static cl::opt<bool>

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:08 2007
@@ -25,6 +25,12 @@
 using namespace llvm;
 using namespace clang;
 
+// Sema.h avoids including Expr.h. As a result, all the Check* functions take 
+// an unsigned which is really an enum. These typedefs provide a short hand
+// notiation for casting (to keep the lines within 80 columns:-)
+typedef BinaryOperator::Opcode BOP;
+typedef UnaryOperator::Opcode UOP;
+
 /// ParseStringLiteral - The specified tokens were lexed as pasted string
 /// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
 /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
@@ -88,8 +94,7 @@
   switch (Kind) {
   default:
     assert(0 && "Unknown simple primary expr!");
-  case tok::char_constant:     // constant: character-constant
-    // TODO: MOVE this to be some other callback.
+  // TODO: MOVE this to be some other callback.
   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
   case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU]
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
@@ -411,7 +416,7 @@
     return CheckAssignmentOperands(lhs, rhs, TokLoc, Opc);
   else if (Opc == BinaryOperator::Comma)
     return CheckCommaOperands(lhs, rhs, TokLoc);
-    
+
   assert(0 && "ParseBinOp(): illegal binary op");
 }
 
@@ -427,7 +432,7 @@
   assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
   assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
 
-  QualType canonType = rhs.getCanonicalType(); // TEMPORARY
+  QualType canonType = rhs.getCanonicalType(); // FIXME
   return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, canonType);
 }
 
@@ -448,75 +453,6 @@
   return t;
 }
 
-/// GetIntegerRank - Helper function for UsualArithmeticConversions().
-static inline int GetIntegerRank(QualType t) {
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
-    switch (BT->getKind()) {
-    case BuiltinType::SChar:
-    case BuiltinType::UChar:
-      return 1;
-    case BuiltinType::Short:
-    case BuiltinType::UShort:
-      return 2;
-    case BuiltinType::Int:
-    case BuiltinType::UInt:
-      return 3;
-    case BuiltinType::Long:
-    case BuiltinType::ULong:
-      return 4;
-    case BuiltinType::LongLong:
-    case BuiltinType::ULongLong:
-      return 5;
-    default:
-      assert(0 && "getFloatingPointRank(): not a floating type");
-    }
-  }
-  return 0;
-}
-
-static inline QualType ConvertSignedWithGreaterRankThanUnsigned(
-  QualType signedType, QualType unsignedType) {
-  // FIXME: Need to check if the signed type can represent all values of the 
-  // unsigned type. If it can, then the result is the signed type. If it can't, 
-  // then the result is the unsigned version of the signed type.
-  return signedType; 
-}
-
-/// GetFloatingRank - Helper function for UsualArithmeticConversions().
-static inline int GetFloatingRank(QualType t) {
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
-    switch (BT->getKind()) {
-    case BuiltinType::Float:
-    case BuiltinType::FloatComplex:
-      return 1;
-    case BuiltinType::Double:
-    case BuiltinType::DoubleComplex:
-      return 2;
-    case BuiltinType::LongDouble:
-    case BuiltinType::LongDoubleComplex:
-      return 3;
-    default:
-      assert(0 && "getFloatingPointRank(): not a floating type");
-    }
-  }
-  return 0;
-}
-
-/// ConvertFloatingRankToComplexType - Another helper for converting floats.
-static inline QualType ConvertFloatingRankToComplexType(int rank, 
-                                                        ASTContext &C) {
-  switch (rank) {
-  case 1:
-    return C.FloatComplexTy;
-  case 2:
-    return C.DoubleComplexTy;
-  case 3:
-    return C.LongDoubleComplexTy;
-  default:
-    assert(0 && "convertRankToComplex(): illegal value for rank");
-  }
-}
-
 /// UsualArithmeticConversions - Performs various conversions that are common to 
 /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
 /// routine returns the first non-arithmetic type found. The client is 
@@ -545,23 +481,7 @@
     if (lhs->isIntegerType())
       return rhs;
 
-    // the following code handles three different combinations:
-    // complex/complex, complex/float, float/complex. When both operands 
-    // are complex, the shorter operand is converted to the type of the longer,
-    // and that is the type of the result. This corresponds to what is done
-    // when combining two real floating-point operands. The fun begins when 
-    // size promotion occur across type domains. GetFloatingRank &
-    // ConvertFloatingRankToComplexType handle this without enumerating all
-    // permutations. It also allows us to add new types without breakage.
-    int lhsRank = GetFloatingRank(lhs);
-    int rhsRank = GetFloatingRank(rhs);
-    
-    // From H&S 6.3.4: When one operand is complex and the other is a real
-    // floating-point type, the less precise type is converted, within it's 
-    // real or complex domain, to the precision of the other type. For example,
-    // when combining a "long double" with a "double _Complex", the 
-    // "double _Complex" is promoted to "long double _Complex".
-    return ConvertFloatingRankToComplexType(std::max(lhsRank,rhsRank), Context);
+    return Context.maxComplexType(lhs, rhs);
   }
   // Now handle "real" floating types (i.e. float, double, long double).
   if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
@@ -572,23 +492,9 @@
       return rhs;
 
     // we have two real floating types, float/complex combos were handled above.
-    return GetFloatingRank(lhs) >= GetFloatingRank(rhs) ? lhs : rhs;
+    return Context.maxFloatingType(lhs, rhs);
   }
-  // Lastly, handle two integers (C99 6.3.1.8p1)
-  bool t1Unsigned = lhs->isUnsignedIntegerType();
-  bool t2Unsigned = rhs->isUnsignedIntegerType();
-  
-  if ((t1Unsigned && t2Unsigned) || (!t1Unsigned && !t2Unsigned))
-    return GetIntegerRank(lhs) >= GetIntegerRank(rhs) ? lhs : rhs; 
-  
-  // We have two integer types with differing signs
-  QualType unsignedType = t1Unsigned ? lhs : rhs;
-  QualType signedType = t1Unsigned ? rhs : lhs;
-  
-  if (GetIntegerRank(unsignedType) >= GetIntegerRank(signedType))
-    return unsignedType;
-  else 
-    return ConvertSignedWithGreaterRankThanUnsigned(signedType, unsignedType); 
+  return Context.maxIntegerType(lhs, rhs);
 }
 
 Action::ExprResult Sema::CheckMultiplicativeOperands(
@@ -596,21 +502,37 @@
 {
   QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
   
-  if ((BinaryOperator::Opcode)code == BinaryOperator::Rem) {
+  if ((BOP)code == BinaryOperator::Rem) {
     if (!resType->isIntegerType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
   } else { // *, /
     if (!resType->isArithmeticType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
   }
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+  return new BinaryOperator(lex, rex, (BOP)code, resType);
 }
 
 Action::ExprResult Sema::CheckAdditiveOperands( // C99 6.5.6
   Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
-  // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  // handle the common case first (both operands are arithmetic).
+  if (resType->isArithmeticType())
+    return new BinaryOperator(lex, rex, (BOP)code, resType);
+  else {
+    if ((BOP)code == BinaryOperator::Add) {
+      if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+          (lhsType->isIntegerType() && rhsType->isPointerType()))
+        return new BinaryOperator(lex, rex, (BOP)code, resType);
+    } else { // -
+      if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+          (lhsType->isPointerType() && rhsType->isPointerType()))
+        return new BinaryOperator(lex, rex, (BOP)code, resType);
+    }
+  }
+  return Diag(loc, diag::err_typecheck_invalid_operands);
 }
 
 Action::ExprResult Sema::CheckShiftOperands( // C99 6.5.7
@@ -621,7 +543,7 @@
   if (!resType->isIntegerType())
     return Diag(loc, diag::err_typecheck_invalid_operands);
 
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+  return new BinaryOperator(lex, rex, (BOP)code, resType);
 }
 
 Action::ExprResult Sema::CheckRelationalOperands( // C99 6.5.8
@@ -630,17 +552,14 @@
   QualType lType = lex->getType(), rType = rex->getType();
   
   if (lType->isRealType() && rType->isRealType())
-    ;
-  else if (lType->isPointerType() &&  rType->isPointerType())
-    ;
-  else {
-    // The following test is for GCC compatibility.
-    if (lType->isIntegerType() || rType->isIntegerType())
-      return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
-    return Diag(loc, diag::err_typecheck_invalid_operands);
-  }
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, 
-                            Context.IntTy);
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+  
+  if (lType->isPointerType() &&  rType->isPointerType())
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+  if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+    return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+  return Diag(loc, diag::err_typecheck_invalid_operands);
 }
 
 Action::ExprResult Sema::CheckEqualityOperands( // C99 6.5.9
@@ -649,17 +568,14 @@
   QualType lType = lex->getType(), rType = rex->getType();
   
   if (lType->isArithmeticType() && rType->isArithmeticType())
-    ;
-  else if (lType->isPointerType() &&  rType->isPointerType())
-    ;
-  else {
-    // The following test is for GCC compatibility.
-    if (lType->isIntegerType() || rType->isIntegerType())
-      return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
-    return Diag(loc, diag::err_typecheck_invalid_operands);
-  }
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, 
-                            Context.IntTy);
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+  
+  if (lType->isPointerType() &&  rType->isPointerType())
+    return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+  if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+    return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+  return Diag(loc, diag::err_typecheck_invalid_operands);
 }
 
 Action::ExprResult Sema::CheckBitwiseOperands(
@@ -670,28 +586,33 @@
   if (!resType->isIntegerType())
     return Diag(loc, diag::err_typecheck_invalid_operands);
 
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+  return new BinaryOperator(lex, rex, (BOP)code, resType);
 }
 
 Action::ExprResult Sema::CheckLogicalOperands( // C99 6.5.[13,14]
   Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
-  // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+  QualType lhsType = UsualUnaryConversion(lex->getType());
+  QualType rhsType = UsualUnaryConversion(rex->getType());
+  
+  if (!lhsType->isScalarType() || !rhsType->isScalarType())
+    return Diag(loc, diag::err_typecheck_invalid_operands);
+    
+  return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
 }
 
 Action::ExprResult Sema::CheckAssignmentOperands( // C99 6.5.16
   Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
   // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+  return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
 }
 
 Action::ExprResult Sema::CheckCommaOperands( // C99 6.5.17
   Expr *lex, Expr *rex, SourceLocation loc) 
 {
-  // FIXME: add type checking and fix result type
-  return new BinaryOperator(lex, rex, BinaryOperator::Comma, Context.IntTy);
+  QualType rhsType = UsualUnaryConversion(rex->getType());
+  return new BinaryOperator(lex, rex, BinaryOperator::Comma, rhsType);
 }
 
 Action::ExprResult
@@ -717,7 +638,7 @@
   if (!canonType.isModifiableLvalue())
     return Diag(OpLoc, diag::err_typecheck_not_modifiable, qType);
 
-  return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
+  return new UnaryOperator(op, (UOP)OpCode, qType);
 }
 
 /// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
@@ -806,5 +727,5 @@
       return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
     break;
   }
-  return new UnaryOperator(op, (UnaryOperator::Opcode)Opc, resultType);
+  return new UnaryOperator(op, (UOP)Opc, resultType);
 }

Modified: cfe/cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/ASTContext.h?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/cfe/trunk/include/clang/AST/ASTContext.h Wed Jul 11 11:44:08 2007
@@ -82,12 +82,39 @@
   /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
   /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
   QualType getSizeType() const;
+
+  // maxIntegerType - Returns the highest ranked integer type. Handles 3
+  // different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
+  QualType maxIntegerType(QualType lhs, QualType rhs);
+  
+  // maxFloatingType - Returns the highest ranked float type. Both input 
+  // types are required to be floats.
+  QualType maxFloatingType(QualType lt, QualType rt);
+
+  // maxComplexType - Returns the highest ranked complex type. Handles 3
+  // different type combos: complex/complex, complex/float, float/complex. 
+  QualType maxComplexType(QualType lt, QualType rt);
+  
 private:
   ASTContext(const ASTContext&); // DO NOT IMPLEMENT
   void operator=(const ASTContext&); // DO NOT IMPLEMENT
   
   void InitBuiltinTypes();
   void InitBuiltinType(QualType &R, BuiltinType::Kind K);
+
+  /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1).
+  /// This routine will assert if passed a built-in type that isn't an integer.
+  int getIntegerRank(QualType t);
+  
+  /// getFloatingRank - Return a relative rank for floating point types.
+  /// This routine will assert if passed a built-in type that isn't a float.
+  int getFloatingRank(QualType t);
+  
+  /// FIXME: comment
+  QualType convertSignedWithGreaterRankThanUnsigned(QualType signedT, 
+                                                    QualType unsignedT);
+  /// FIXME: comment                                                    
+  QualType convertFloatingRankToComplexType(int rank);
 };
   
 }  // end namespace clang

Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:08 2007
@@ -368,7 +368,7 @@
   static bool isEqualityOp(Opcode Op) { return Op == EQ || Op == NE; }
   static bool isBitwiseOp(Opcode Op) { return Op >= And && Op <= Or; }
   static bool isLogicalOp(Opcode Op) { return Op == LAnd || Op == LOr; }
-  static bool isAssignmentOp(Opcode Op) { return Op >= Assign || Op<=OrAssign; }
+  static bool isAssignmentOp(Opcode Op) { return Op >= Assign && Op<=OrAssign; }
   
   Opcode getOpcode() const { return Opc; }
   Expr *getLHS() { return LHS; }

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39418&r1=39417&r2=39418&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:44:08 2007
@@ -537,7 +537,7 @@
      "invalid argument type to unary expression '%s'")
 DIAG(err_typecheck_invalid_operands, ERROR,
      "invalid operands to binary expression")
-DIAG(err_typecheck_comparison_of_pointer_integer, WARNING,
+DIAG(ext_typecheck_comparison_of_pointer_integer, EXTENSION,
      "comparison between pointer and integer")
 
 // Statements.





More information about the cfe-commits mailing list