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

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


Author: snaroff
Date: Wed Jul 11 11:44:04 2007
New Revision: 39411

URL: http://llvm.org/viewvc/llvm-project?rev=39411&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
Lot's of changes related to type checking binary expressions.
- Changed the name/proto of ImplicitConversion. It is now named UsualUnaryConversion - it takes a
type and returns a type. This allowed me to remove the explicit node creation for array/function->pointer conversions.
- Added function UsualArithmeticConversions().
- Changed all the "Check" functions for binary ops. They use the new "Usual" functions above.
- new predicates on Type, isSignedIntegerType()/isUnsignedIntegerType().
- moved getDecl() out of the Sema class. It is now a static helper function in SemaExpr.cpp. It was also renamed getPrimaryDeclaration().
- Added CheckArithmeticOperand() for consistency with the other unary "Check" functions.

Should finish up the binary expressions tomorrow...with a small number of "FIXME's"

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

Modified: cfe/cfe/trunk/AST/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Sema.h?rev=39411&r1=39410&r2=39411&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:44:04 2007
@@ -222,30 +222,39 @@
   virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
                                          tok::TokenKind Kind);
 private:
-  Expr *ImplicitConversion(Expr *E); // C99 6.3
-
+  QualType UsualUnaryConversion(QualType t); // C99 6.3
+  QualType UsualArithmeticConversions(QualType t1, QualType t2); // C99 6.3.1.8
+  
   /// the following "Check" methods will either return a well formed AST node
   /// or will return true if the expressions didn't type check properly.
   
   /// type checking binary operators (subroutines of ParseBinOp).
-  ExprResult CheckMultiplicativeOperands(Expr *op1, Expr *op2,
-          SourceLocation OpLoc, 
-          unsigned /*BinaryOperator::Opcode*/OpCode); // C99 6.5.5
-  ExprResult CheckAdditiveOperands(Expr *op1, Expr *op2);       // C99 6.5.6
-  ExprResult CheckShiftOperands(Expr *op1, Expr *op2);          // C99 6.5.7
-  ExprResult CheckRelationalOperands(Expr *op1, Expr *op2);     // C99 6.5.8
-  ExprResult CheckEqualityOperands(Expr *op1, Expr *op2);       // C99 6.5.9
-  ExprResult CheckBitwiseOperands(Expr *op1, Expr *op2);   // C99 6.5.[10...12]
-  ExprResult CheckLogicalOperands(Expr *op1, Expr *op2);   // C99 6.5.[13,14]
+  /// The unsigned arguments are really enums (BinaryOperator::Opcode)
+  ExprResult CheckMultiplicativeOperands( // C99 6.5.5
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode); 
+  ExprResult CheckAdditiveOperands( // C99 6.5.6
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
+  ExprResult CheckShiftOperands( // C99 6.5.7
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
+  ExprResult CheckRelationalOperands( // C99 6.5.8
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
+  ExprResult CheckEqualityOperands( // C99 6.5.9
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode); 
+  ExprResult CheckBitwiseOperands( // C99 6.5.[10...12]
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode); 
+  ExprResult CheckLogicalOperands( // C99 6.5.[13,14]
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
   
   /// type checking unary operators (subroutines of ParseUnaryOp).
-  /// C99 6.5.3.2
-  ExprResult CheckAddressOfOperand(Expr *op, SourceLocation loc, unsigned c);
-  Decl *getDecl(Expr *e);
-  ExprResult CheckIndirectionOperand(Expr *op, SourceLocation loc, unsigned c);
-  
-  ExprResult CheckIncrementDecrementOperand(Expr *op, SourceLocation loc,
-                                            unsigned /*UnaryOperator::Opcode*/c);
+  /// The unsigned arguments are really enums (UnaryOperator::Opcode)
+  ExprResult CheckIncrementDecrementOperand( // C99 6.5.3.1 
+    Expr *op, SourceLocation loc, unsigned c);
+  ExprResult CheckAddressOfOperand( // C99 6.5.3.2
+    Expr *op, SourceLocation loc, unsigned c);
+  ExprResult CheckIndirectionOperand( // C99 6.5.3.2
+    Expr *op, SourceLocation loc, unsigned c);
+  ExprResult CheckArithmeticOperand( // C99 6.5.3.3
+    Expr *op, SourceLocation OpLoc, unsigned Opc);
 };
 
 

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

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:04 2007
@@ -180,43 +180,11 @@
     return CheckAddressOfOperand((Expr *)Input, OpLoc, Opc);
   else if (Opc == UnaryOperator::Deref) 
     return CheckIndirectionOperand((Expr *)Input, OpLoc, Opc);
-  else { 
-    // handle the arithmetic unary operators (C99 6.5.3.3)
-    Expr *operand = ImplicitConversion((Expr *)Input);
-    QualType opType = operand->getType();
-    assert(!opType.isNull() && "no type for arithmetic unary expression");
-    QualType resultType = opType;
-    
-    switch (Opc) {
-    case UnaryOperator::Plus:
-    case UnaryOperator::Minus:
-      if (!opType->isArithmeticType()) // C99 6.5.3.3p1
-        return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
-
-      if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
-        resultType = Context.IntTy;
-      break;
-    case UnaryOperator::Not: // bitwise complement
-      if (!opType->isIntegralType()) // C99 6.5.3.3p1
-        return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
-
-      if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
-        resultType = Context.IntTy;
-      break;
-    case UnaryOperator::LNot: // logical negation
-      if (!opType->isScalarType()) // C99 6.5.3.3p1
-        return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
-
-      if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
-        resultType = Context.IntTy;
-      break;
-    case UnaryOperator::SizeOf: // C99 6.5.3.4 TODO
-      break;
-    default: 
-      break;
-    }
-    return new UnaryOperator(operand, Opc, resultType);
-  }
+  else if (UnaryOperator::isArithmeticOp(Opc))
+    return CheckArithmeticOperand((Expr *)Input, OpLoc, Opc);
+  
+  // will go away when all cases are handled...
+  return new UnaryOperator((Expr *)Input, Opc, QualType());
 }
 
 Action::ExprResult Sema::
@@ -287,7 +255,7 @@
     return Diag(LLoc, diag::err_typecheck_subscript_value);
 
   // C99 6.5.2.1p1
-  if (!indexType->isIntegralType())
+  if (!indexType->isIntegerType())
     return Diag(LLoc, diag::err_typecheck_subscript);
 
   // FIXME: need to deal with const...
@@ -395,26 +363,24 @@
   case tok::comma:                Opc = BinaryOperator::Comma; break;
   }
 
-  // perform implicit conversions (C99 6.3)
-  Expr *lhs = ImplicitConversion((Expr*)LHS);
-  Expr *rhs = ImplicitConversion((Expr*)RHS);
+  Expr *lhs = (Expr *)LHS, *rhs = (Expr*)RHS;
   
   if (BinaryOperator::isMultiplicativeOp(Opc)) 
     return CheckMultiplicativeOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isAdditiveOp(Opc))
-    CheckAdditiveOperands(lhs, rhs);
+    return CheckAdditiveOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isShiftOp(Opc))
-    CheckShiftOperands(lhs, rhs);
+    return CheckShiftOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isRelationalOp(Opc))
-    CheckRelationalOperands(lhs, rhs);
+    return CheckRelationalOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isEqualityOp(Opc))
-    CheckEqualityOperands(lhs, rhs);
+    return CheckEqualityOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isBitwiseOp(Opc))
-    CheckBitwiseOperands(lhs, rhs);
+    return CheckBitwiseOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isLogicalOp(Opc))
-    CheckLogicalOperands(lhs, rhs);
-  
-  return new BinaryOperator(lhs, rhs, Opc);
+    return CheckLogicalOperands(lhs, rhs, TokLoc, Opc);
+    
+  assert(0 && "ParseBinOp() not handling all binary ops properly");
 }
 
 /// ParseConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
@@ -426,66 +392,145 @@
   return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
 }
 
-/// ImplicitConversion - Performs various conversions that are common to most
-/// operators. At present, this routine only handles conversions that require
-/// synthesizing an expression/type. Arithmetic type promotions are done locally,
-/// since they don't require a new expression.
-Expr *Sema::ImplicitConversion(Expr *E) {
-  QualType t = E->getType();
-  assert(!t.isNull() && "no type for implicit conversion");
-  
-  if (t->isFunctionType()) // C99 6.3.2.1p4
-    return new UnaryOperator(E, UnaryOperator::AddrOf, Context.getPointerType(t));
-  else if (t->isArrayType()) { // C99 6.3.2.1p3
-    QualType elt = cast<ArrayType>(t)->getElementType();
-    QualType convertedType = Context.getPointerType(elt);
-    return new UnaryOperator(E, UnaryOperator::AddrOf, convertedType);
-  }
-  return E;
+/// UsualUnaryConversion - Performs various conversions that are common to most
+/// operators (C99 6.3). The conversions of array and function types are 
+/// sometimes surpressed. For example, the array->pointer conversion doesn't
+/// apply if the array is an argument to the sizeof or address (&) operators.
+/// In these instances, this routine should *not* be called.
+QualType Sema::UsualUnaryConversion(QualType t) {
+  assert(!t.isNull() && "UsualUnaryConversion - missing type");
+  
+  if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
+    return Context.IntTy;
+  else if (t->isFunctionType()) // C99 6.3.2.1p4
+    return Context.getPointerType(t);
+  else if (t->isArrayType()) // C99 6.3.2.1p3
+    return Context.getPointerType(cast<ArrayType>(t)->getElementType());
+  return t;
+}
+
+/// 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 
+/// responsible for emitting appropriate error diagnostics.
+QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
+  t1 = UsualUnaryConversion(t1);
+  t2 = UsualUnaryConversion(t2);
+  
+  // if either operand is not of arithmetic type, no conversion is possible.
+  if (!t1->isArithmeticType())
+    return t1;
+  else if (!t2->isArithmeticType())
+    return t2;
+    
+  // if both operands have the same type, no conversion is needed.
+  if (t1 == t2) 
+    return t1;
+  
+  // at this point, we have two different arithmetic types. Handle the
+  // real floating types first (C99 6.3.1.8p1). If either operand is float,
+  // double, or long double, the result is float, double, or long double.
+  if (t1->isRealFloatingType()) 
+    return t1;
+  else if (t2->isRealFloatingType())
+    return t2;
+    
+  bool t1Unsigned = t1->isUnsignedIntegerType();
+  bool t2Unsigned = t2->isUnsignedIntegerType();
+  
+  if (t1Unsigned && t2Unsigned)
+    return t1; // FIXME: return the unsigned type with the greatest rank
+  else if (!t1Unsigned && !t2Unsigned)
+    return t1; // FIXME: return the signed type with the greatest rank
+  else 
+    return t1; // FIXME: we have a mixture...
 }
 
 Action::ExprResult Sema::CheckMultiplicativeOperands(
-  Expr *lexpr, Expr *rexpr, SourceLocation loc, unsigned code) 
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
-  lexpr = ImplicitConversion((Expr *)lexpr);
-  rexpr = ImplicitConversion((Expr *)rexpr);
-  QualType ltype = lexpr->getType();
-  QualType rtype = rexpr->getType();
-  assert(!ltype.isNull() && "no left type for CheckMultiplicativeOperands()");
-  assert(!rtype.isNull() && "no right type for CheckMultiplicativeOperands()");
+  QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
   
   if ((BinaryOperator::Opcode)code == BinaryOperator::Rem) {
-    if (!ltype->isIntegralType() || !rtype->isIntegralType())
+    if (!resType->isIntegerType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
-  } else {
-    if (!ltype->isArithmeticType() || !rtype->isArithmeticType())
+  } else { // *, /
+    if (!resType->isArithmeticType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
   }
-  return new BinaryOperator(lexpr, rexpr, (BinaryOperator::Opcode)code);
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
 }
 
-Action::ExprResult Sema::CheckAdditiveOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckAdditiveOperands( // C99 6.5.6
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
+{
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
 }
 
-Action::ExprResult Sema::CheckShiftOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckShiftOperands( // C99 6.5.7
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
+{
+  QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
+  
+  if (!resType->isIntegerType())
+    return Diag(loc, diag::err_typecheck_invalid_operands);
+
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
 }
 
-Action::ExprResult Sema::CheckRelationalOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckRelationalOperands( // C99 6.5.8
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
+{
+  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);
 }
 
-Action::ExprResult Sema::CheckEqualityOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckEqualityOperands( // C99 6.5.9
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
+{
+  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);
 }
 
-Action::ExprResult Sema::CheckBitwiseOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckBitwiseOperands(
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
+{
+  QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
+  
+  if (!resType->isIntegerType())
+    return Diag(loc, diag::err_typecheck_invalid_operands);
+
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
 }
 
-Action::ExprResult Sema::CheckLogicalOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
+{
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code);
 }
 
 Action::ExprResult
@@ -514,24 +559,24 @@
   return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
 }
 
-/// getDecl - This is currently a helper function for CheckAddressOfOperand().
+/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
 /// This routine allows us to typecheck complex/recursive expressions
 /// where the declaration is needed for type checking. Here are some
 /// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2].
-Decl *Sema::getDecl(Expr *e) {
+static Decl *getPrimaryDeclaration(Expr *e) {
   switch (e->getStmtClass()) {
   case Stmt::DeclRefExprClass:
     return cast<DeclRefExpr>(e)->getDecl();
   case Stmt::MemberExprClass:
-    return getDecl(cast<MemberExpr>(e)->getBase());
+    return getPrimaryDeclaration(cast<MemberExpr>(e)->getBase());
   case Stmt::ArraySubscriptExprClass:
-    return getDecl(cast<ArraySubscriptExpr>(e)->getBase());
+    return getPrimaryDeclaration(cast<ArraySubscriptExpr>(e)->getBase());
   case Stmt::CallExprClass:
-    return getDecl(cast<CallExpr>(e)->getCallee());
+    return getPrimaryDeclaration(cast<CallExpr>(e)->getCallee());
   case Stmt::UnaryOperatorClass:
-    return getDecl(cast<UnaryOperator>(e)->getSubExpr());
+    return getPrimaryDeclaration(cast<UnaryOperator>(e)->getSubExpr());
   case Stmt::ParenExprClass:
-    return getDecl(cast<ParenExpr>(e)->getSubExpr());
+    return getPrimaryDeclaration(cast<ParenExpr>(e)->getSubExpr());
   default:
     return 0;
   }
@@ -544,7 +589,7 @@
 /// operator, and its result is never an lvalue.
 Action::ExprResult
 Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc, unsigned OpCode) {
-  Decl *dcl = getDecl(op);
+  Decl *dcl = getPrimaryDeclaration(op);
   
   if (!op->isLvalue()) {
     if (dcl && isa<FunctionDecl>(dcl))
@@ -575,3 +620,26 @@
   
   return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, QualType());
 }
+
+/// CheckArithmeticOperand - Check the arithmetic unary operators (C99 6.5.3.3).
+Action::ExprResult
+Sema::CheckArithmeticOperand(Expr *op, SourceLocation OpLoc, unsigned Opc) {
+  QualType resultType = UsualUnaryConversion(op->getType());
+  
+  switch (Opc) {
+  case UnaryOperator::Plus:
+  case UnaryOperator::Minus:
+    if (!resultType->isArithmeticType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
+    break;
+  case UnaryOperator::Not: // bitwise complement
+    if (!resultType->isIntegerType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
+    break;
+  case UnaryOperator::LNot: // logical negation
+    if (!resultType->isScalarType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
+    break;
+  }
+  return new UnaryOperator(op, (UnaryOperator::Opcode)Opc, resultType);
+}

Modified: cfe/cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Type.cpp?rev=39411&r1=39410&r2=39411&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:44:04 2007
@@ -71,7 +71,7 @@
   return false;
 }
 
-bool Type::isIntegralType() const {
+bool Type::isIntegerType() const {
   switch (CanonicalType->getTypeClass()) {
   default: return false;
   case Builtin:
@@ -86,6 +86,26 @@
   }
 }
 
+bool Type::isSignedIntegerType() const {
+  switch (CanonicalType->getTypeClass()) {
+  default: return false;
+  case Builtin:
+    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+    return BT->getKind() >= BuiltinType::SChar &&
+           BT->getKind() <= BuiltinType::LongLong;
+  }
+}
+
+bool Type::isUnsignedIntegerType() const {
+  switch (CanonicalType->getTypeClass()) {
+  default: return false;
+  case Builtin:
+    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+    return BT->getKind() >= BuiltinType::UChar &&
+           BT->getKind() <= BuiltinType::ULongLong;
+  }
+}
+
 bool Type::isFloatingType() const {
   switch (CanonicalType->getTypeClass()) {
   default: return false;
@@ -107,7 +127,7 @@
 }
 
 bool Type::isRealType() const {
-  // this is equivalent to (isIntegralType() || isRealFloatingType()).
+  // this is equivalent to (isIntegerType() || isRealFloatingType()).
   switch (CanonicalType->getTypeClass()) { // inlined for performance
   default: return false;
   case Builtin:

Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39411&r1=39410&r2=39411&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:44:04 2007
@@ -222,30 +222,39 @@
   virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
                                          tok::TokenKind Kind);
 private:
-  Expr *ImplicitConversion(Expr *E); // C99 6.3
-
+  QualType UsualUnaryConversion(QualType t); // C99 6.3
+  QualType UsualArithmeticConversions(QualType t1, QualType t2); // C99 6.3.1.8
+  
   /// the following "Check" methods will either return a well formed AST node
   /// or will return true if the expressions didn't type check properly.
   
   /// type checking binary operators (subroutines of ParseBinOp).
-  ExprResult CheckMultiplicativeOperands(Expr *op1, Expr *op2,
-          SourceLocation OpLoc, 
-          unsigned /*BinaryOperator::Opcode*/OpCode); // C99 6.5.5
-  ExprResult CheckAdditiveOperands(Expr *op1, Expr *op2);       // C99 6.5.6
-  ExprResult CheckShiftOperands(Expr *op1, Expr *op2);          // C99 6.5.7
-  ExprResult CheckRelationalOperands(Expr *op1, Expr *op2);     // C99 6.5.8
-  ExprResult CheckEqualityOperands(Expr *op1, Expr *op2);       // C99 6.5.9
-  ExprResult CheckBitwiseOperands(Expr *op1, Expr *op2);   // C99 6.5.[10...12]
-  ExprResult CheckLogicalOperands(Expr *op1, Expr *op2);   // C99 6.5.[13,14]
+  /// The unsigned arguments are really enums (BinaryOperator::Opcode)
+  ExprResult CheckMultiplicativeOperands( // C99 6.5.5
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode); 
+  ExprResult CheckAdditiveOperands( // C99 6.5.6
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
+  ExprResult CheckShiftOperands( // C99 6.5.7
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
+  ExprResult CheckRelationalOperands( // C99 6.5.8
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
+  ExprResult CheckEqualityOperands( // C99 6.5.9
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode); 
+  ExprResult CheckBitwiseOperands( // C99 6.5.[10...12]
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode); 
+  ExprResult CheckLogicalOperands( // C99 6.5.[13,14]
+    Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
   
   /// type checking unary operators (subroutines of ParseUnaryOp).
-  /// C99 6.5.3.2
-  ExprResult CheckAddressOfOperand(Expr *op, SourceLocation loc, unsigned c);
-  Decl *getDecl(Expr *e);
-  ExprResult CheckIndirectionOperand(Expr *op, SourceLocation loc, unsigned c);
-  
-  ExprResult CheckIncrementDecrementOperand(Expr *op, SourceLocation loc,
-                                            unsigned /*UnaryOperator::Opcode*/c);
+  /// The unsigned arguments are really enums (UnaryOperator::Opcode)
+  ExprResult CheckIncrementDecrementOperand( // C99 6.5.3.1 
+    Expr *op, SourceLocation loc, unsigned c);
+  ExprResult CheckAddressOfOperand( // C99 6.5.3.2
+    Expr *op, SourceLocation loc, unsigned c);
+  ExprResult CheckIndirectionOperand( // C99 6.5.3.2
+    Expr *op, SourceLocation loc, unsigned c);
+  ExprResult CheckArithmeticOperand( // C99 6.5.3.3
+    Expr *op, SourceLocation OpLoc, unsigned Opc);
 };
 
 

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:04 2007
@@ -180,43 +180,11 @@
     return CheckAddressOfOperand((Expr *)Input, OpLoc, Opc);
   else if (Opc == UnaryOperator::Deref) 
     return CheckIndirectionOperand((Expr *)Input, OpLoc, Opc);
-  else { 
-    // handle the arithmetic unary operators (C99 6.5.3.3)
-    Expr *operand = ImplicitConversion((Expr *)Input);
-    QualType opType = operand->getType();
-    assert(!opType.isNull() && "no type for arithmetic unary expression");
-    QualType resultType = opType;
-    
-    switch (Opc) {
-    case UnaryOperator::Plus:
-    case UnaryOperator::Minus:
-      if (!opType->isArithmeticType()) // C99 6.5.3.3p1
-        return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
-
-      if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
-        resultType = Context.IntTy;
-      break;
-    case UnaryOperator::Not: // bitwise complement
-      if (!opType->isIntegralType()) // C99 6.5.3.3p1
-        return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
-
-      if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
-        resultType = Context.IntTy;
-      break;
-    case UnaryOperator::LNot: // logical negation
-      if (!opType->isScalarType()) // C99 6.5.3.3p1
-        return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
-
-      if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
-        resultType = Context.IntTy;
-      break;
-    case UnaryOperator::SizeOf: // C99 6.5.3.4 TODO
-      break;
-    default: 
-      break;
-    }
-    return new UnaryOperator(operand, Opc, resultType);
-  }
+  else if (UnaryOperator::isArithmeticOp(Opc))
+    return CheckArithmeticOperand((Expr *)Input, OpLoc, Opc);
+  
+  // will go away when all cases are handled...
+  return new UnaryOperator((Expr *)Input, Opc, QualType());
 }
 
 Action::ExprResult Sema::
@@ -287,7 +255,7 @@
     return Diag(LLoc, diag::err_typecheck_subscript_value);
 
   // C99 6.5.2.1p1
-  if (!indexType->isIntegralType())
+  if (!indexType->isIntegerType())
     return Diag(LLoc, diag::err_typecheck_subscript);
 
   // FIXME: need to deal with const...
@@ -395,26 +363,24 @@
   case tok::comma:                Opc = BinaryOperator::Comma; break;
   }
 
-  // perform implicit conversions (C99 6.3)
-  Expr *lhs = ImplicitConversion((Expr*)LHS);
-  Expr *rhs = ImplicitConversion((Expr*)RHS);
+  Expr *lhs = (Expr *)LHS, *rhs = (Expr*)RHS;
   
   if (BinaryOperator::isMultiplicativeOp(Opc)) 
     return CheckMultiplicativeOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isAdditiveOp(Opc))
-    CheckAdditiveOperands(lhs, rhs);
+    return CheckAdditiveOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isShiftOp(Opc))
-    CheckShiftOperands(lhs, rhs);
+    return CheckShiftOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isRelationalOp(Opc))
-    CheckRelationalOperands(lhs, rhs);
+    return CheckRelationalOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isEqualityOp(Opc))
-    CheckEqualityOperands(lhs, rhs);
+    return CheckEqualityOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isBitwiseOp(Opc))
-    CheckBitwiseOperands(lhs, rhs);
+    return CheckBitwiseOperands(lhs, rhs, TokLoc, Opc);
   else if (BinaryOperator::isLogicalOp(Opc))
-    CheckLogicalOperands(lhs, rhs);
-  
-  return new BinaryOperator(lhs, rhs, Opc);
+    return CheckLogicalOperands(lhs, rhs, TokLoc, Opc);
+    
+  assert(0 && "ParseBinOp() not handling all binary ops properly");
 }
 
 /// ParseConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
@@ -426,66 +392,145 @@
   return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
 }
 
-/// ImplicitConversion - Performs various conversions that are common to most
-/// operators. At present, this routine only handles conversions that require
-/// synthesizing an expression/type. Arithmetic type promotions are done locally,
-/// since they don't require a new expression.
-Expr *Sema::ImplicitConversion(Expr *E) {
-  QualType t = E->getType();
-  assert(!t.isNull() && "no type for implicit conversion");
-  
-  if (t->isFunctionType()) // C99 6.3.2.1p4
-    return new UnaryOperator(E, UnaryOperator::AddrOf, Context.getPointerType(t));
-  else if (t->isArrayType()) { // C99 6.3.2.1p3
-    QualType elt = cast<ArrayType>(t)->getElementType();
-    QualType convertedType = Context.getPointerType(elt);
-    return new UnaryOperator(E, UnaryOperator::AddrOf, convertedType);
-  }
-  return E;
+/// UsualUnaryConversion - Performs various conversions that are common to most
+/// operators (C99 6.3). The conversions of array and function types are 
+/// sometimes surpressed. For example, the array->pointer conversion doesn't
+/// apply if the array is an argument to the sizeof or address (&) operators.
+/// In these instances, this routine should *not* be called.
+QualType Sema::UsualUnaryConversion(QualType t) {
+  assert(!t.isNull() && "UsualUnaryConversion - missing type");
+  
+  if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
+    return Context.IntTy;
+  else if (t->isFunctionType()) // C99 6.3.2.1p4
+    return Context.getPointerType(t);
+  else if (t->isArrayType()) // C99 6.3.2.1p3
+    return Context.getPointerType(cast<ArrayType>(t)->getElementType());
+  return t;
+}
+
+/// 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 
+/// responsible for emitting appropriate error diagnostics.
+QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
+  t1 = UsualUnaryConversion(t1);
+  t2 = UsualUnaryConversion(t2);
+  
+  // if either operand is not of arithmetic type, no conversion is possible.
+  if (!t1->isArithmeticType())
+    return t1;
+  else if (!t2->isArithmeticType())
+    return t2;
+    
+  // if both operands have the same type, no conversion is needed.
+  if (t1 == t2) 
+    return t1;
+  
+  // at this point, we have two different arithmetic types. Handle the
+  // real floating types first (C99 6.3.1.8p1). If either operand is float,
+  // double, or long double, the result is float, double, or long double.
+  if (t1->isRealFloatingType()) 
+    return t1;
+  else if (t2->isRealFloatingType())
+    return t2;
+    
+  bool t1Unsigned = t1->isUnsignedIntegerType();
+  bool t2Unsigned = t2->isUnsignedIntegerType();
+  
+  if (t1Unsigned && t2Unsigned)
+    return t1; // FIXME: return the unsigned type with the greatest rank
+  else if (!t1Unsigned && !t2Unsigned)
+    return t1; // FIXME: return the signed type with the greatest rank
+  else 
+    return t1; // FIXME: we have a mixture...
 }
 
 Action::ExprResult Sema::CheckMultiplicativeOperands(
-  Expr *lexpr, Expr *rexpr, SourceLocation loc, unsigned code) 
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
 {
-  lexpr = ImplicitConversion((Expr *)lexpr);
-  rexpr = ImplicitConversion((Expr *)rexpr);
-  QualType ltype = lexpr->getType();
-  QualType rtype = rexpr->getType();
-  assert(!ltype.isNull() && "no left type for CheckMultiplicativeOperands()");
-  assert(!rtype.isNull() && "no right type for CheckMultiplicativeOperands()");
+  QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
   
   if ((BinaryOperator::Opcode)code == BinaryOperator::Rem) {
-    if (!ltype->isIntegralType() || !rtype->isIntegralType())
+    if (!resType->isIntegerType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
-  } else {
-    if (!ltype->isArithmeticType() || !rtype->isArithmeticType())
+  } else { // *, /
+    if (!resType->isArithmeticType())
       return Diag(loc, diag::err_typecheck_invalid_operands);
   }
-  return new BinaryOperator(lexpr, rexpr, (BinaryOperator::Opcode)code);
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
 }
 
-Action::ExprResult Sema::CheckAdditiveOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckAdditiveOperands( // C99 6.5.6
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
+{
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
 }
 
-Action::ExprResult Sema::CheckShiftOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckShiftOperands( // C99 6.5.7
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
+{
+  QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
+  
+  if (!resType->isIntegerType())
+    return Diag(loc, diag::err_typecheck_invalid_operands);
+
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
 }
 
-Action::ExprResult Sema::CheckRelationalOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckRelationalOperands( // C99 6.5.8
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
+{
+  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);
 }
 
-Action::ExprResult Sema::CheckEqualityOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckEqualityOperands( // C99 6.5.9
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
+{
+  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);
 }
 
-Action::ExprResult Sema::CheckBitwiseOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckBitwiseOperands(
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
+{
+  QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
+  
+  if (!resType->isIntegerType())
+    return Diag(loc, diag::err_typecheck_invalid_operands);
+
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
 }
 
-Action::ExprResult Sema::CheckLogicalOperands(Expr *op1, Expr *op2) {
-  return false;
+Action::ExprResult Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+  Expr *lex, Expr *rex, SourceLocation loc, unsigned code) 
+{
+  return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code);
 }
 
 Action::ExprResult
@@ -514,24 +559,24 @@
   return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
 }
 
-/// getDecl - This is currently a helper function for CheckAddressOfOperand().
+/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
 /// This routine allows us to typecheck complex/recursive expressions
 /// where the declaration is needed for type checking. Here are some
 /// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2].
-Decl *Sema::getDecl(Expr *e) {
+static Decl *getPrimaryDeclaration(Expr *e) {
   switch (e->getStmtClass()) {
   case Stmt::DeclRefExprClass:
     return cast<DeclRefExpr>(e)->getDecl();
   case Stmt::MemberExprClass:
-    return getDecl(cast<MemberExpr>(e)->getBase());
+    return getPrimaryDeclaration(cast<MemberExpr>(e)->getBase());
   case Stmt::ArraySubscriptExprClass:
-    return getDecl(cast<ArraySubscriptExpr>(e)->getBase());
+    return getPrimaryDeclaration(cast<ArraySubscriptExpr>(e)->getBase());
   case Stmt::CallExprClass:
-    return getDecl(cast<CallExpr>(e)->getCallee());
+    return getPrimaryDeclaration(cast<CallExpr>(e)->getCallee());
   case Stmt::UnaryOperatorClass:
-    return getDecl(cast<UnaryOperator>(e)->getSubExpr());
+    return getPrimaryDeclaration(cast<UnaryOperator>(e)->getSubExpr());
   case Stmt::ParenExprClass:
-    return getDecl(cast<ParenExpr>(e)->getSubExpr());
+    return getPrimaryDeclaration(cast<ParenExpr>(e)->getSubExpr());
   default:
     return 0;
   }
@@ -544,7 +589,7 @@
 /// operator, and its result is never an lvalue.
 Action::ExprResult
 Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc, unsigned OpCode) {
-  Decl *dcl = getDecl(op);
+  Decl *dcl = getPrimaryDeclaration(op);
   
   if (!op->isLvalue()) {
     if (dcl && isa<FunctionDecl>(dcl))
@@ -575,3 +620,26 @@
   
   return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, QualType());
 }
+
+/// CheckArithmeticOperand - Check the arithmetic unary operators (C99 6.5.3.3).
+Action::ExprResult
+Sema::CheckArithmeticOperand(Expr *op, SourceLocation OpLoc, unsigned Opc) {
+  QualType resultType = UsualUnaryConversion(op->getType());
+  
+  switch (Opc) {
+  case UnaryOperator::Plus:
+  case UnaryOperator::Minus:
+    if (!resultType->isArithmeticType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
+    break;
+  case UnaryOperator::Not: // bitwise complement
+    if (!resultType->isIntegerType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
+    break;
+  case UnaryOperator::LNot: // logical negation
+    if (!resultType->isScalarType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
+    break;
+  }
+  return new UnaryOperator(op, (UnaryOperator::Opcode)Opc, resultType);
+}

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=39411&r1=39410&r2=39411&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:04 2007
@@ -81,7 +81,7 @@
   // or UnsignedLongLongTy
   IntegerLiteral(intmax_t value, QualType type)
     : Expr(IntegerLiteralClass, type), Value(value) {
-    assert(type->isIntegralType() && "Illegal type in IntegerLiteral");
+    assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
   }
 
   virtual void visit(StmtVisitor &Visitor);
@@ -169,6 +169,8 @@
   /// isPostfix - Return true if this is a postfix operation, like x++.
   static bool isPostfix(Opcode Op);
 
+  static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
+
   Opcode getOpcode() const { return Opc; }
   Expr *getSubExpr() const { return Val; }
   
@@ -336,8 +338,8 @@
     Comma             // [C99 6.5.17] Comma operator.
   };
   
-  BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc)
-    : Expr(BinaryOperatorClass, QualType()), LHS(lhs), RHS(rhs), Opc(opc) {}
+  BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType t=QualType())
+    : Expr(BinaryOperatorClass, t), LHS(lhs), RHS(rhs), Opc(opc) {}
 
   /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
   /// corresponds to, e.g. "<<=".

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

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:44:04 2007
@@ -207,7 +207,7 @@
   
   /// Helper methods to distinguish type categories. All type predicates
   /// operate on the canonical type, ignoring typedefs.
-  bool isIntegralType() const;     // C99 6.2.5p17 (int, char, bool, enum)
+  bool isIntegerType() const;     // C99 6.2.5p17 (int, char, bool, enum)
   bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
   bool isComplexType() const;      // C99 6.2.5p11 (complex)
   bool isFloatingType() const;     // C99 6.2.5p11 (real floating + complex)
@@ -227,8 +227,10 @@
   
   bool isLvalue() const;         // C99 6.3.2.1
   
-  /// Type Conversions/Promotions
+  /// More type predicates useful for type checking/promotion
   bool isPromotableIntegerType() const; // C99 6.3.1.1p2
+  bool isSignedIntegerType() const;     // C99 6.2.5p4
+  bool isUnsignedIntegerType() const;   // C99 6.2.5p6
 private:
   // this forces clients to use isModifiableLvalue on QualType, the class that 
   // knows if the type is const. This predicate is a helper to QualType. 

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=39411&r1=39410&r2=39411&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:44:04 2007
@@ -537,6 +537,8 @@
      "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,
+     "comparison between pointer and integer")
 
 // Statements.
 DIAG(err_continue_not_in_loop, ERROR,





More information about the cfe-commits mailing list