[cfe-commits] r41364 - in /cfe/trunk: Sema/Sema.h Sema/SemaExpr.cpp include/clang/AST/StmtNodes.def

Steve Naroff snaroff at apple.com
Fri Aug 24 12:07:16 PDT 2007


Author: snaroff
Date: Fri Aug 24 14:07:16 2007
New Revision: 41364

URL: http://llvm.org/viewvc/llvm-project?rev=41364&view=rev
Log:

Surpress ImplicitCastExprs for compound assignment expressions. For compound assignments,
it is o.k. for the LHS and RHS to have different types. Converting the type can cause
errors like the one Chris noticed (below).

This change required a fair number of diffs (since there is a lot of shared code
between single and compound assignments). This makes the API's look a bit uglier,
however I couldn't think of a better way to do it (without duplicating code).

Fix the following (incorrect) error:

int A;
long long B;

void foo() {
  A /= B;
}

$ clang ~/scalar.c -emit-llvm
/Users/sabre/scalar.c:6:5: error: expression is not assignable
  A /= B;
  ~ ^

Now it works properly...

[dylan:~/llvm/tools/clang] admin% cat compound.c
int A;
long long B;

void foo() {
  A /= B;
}
[dylan:~/llvm/tools/clang] admin% ../../Debug/bin/clang compound.c -parse-ast-dump
Read top-level variable decl: 'A'
Read top-level variable decl: 'B'

void foo()
(CompoundStmt 0x2605c40
  (BinaryOperator 0x2605c20 'int' '/=' ComputeTy='long long'
    (DeclRefExpr 0x2605be0 'int' Decl='A' 0x2605a80)
    (DeclRefExpr 0x2605c00 'long long' Decl='B' 0x2605ab0)))



Modified:
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/AST/StmtNodes.def

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

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Aug 24 14:07:16 2007
@@ -349,8 +349,8 @@
   // 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.
-  void UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr);
-                                     
+  QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
+                                      bool isCompAssign = false);
   enum AssignmentCheckResult {
     Compatible,
     Incompatible,
@@ -386,21 +386,21 @@
   inline void InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
   inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
   inline QualType CheckMultiplyDivideOperands( // C99 6.5.5
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc); 
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); 
   inline QualType CheckRemainderOperands( // C99 6.5.5
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc); 
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); 
   inline QualType CheckAdditionOperands( // C99 6.5.6
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc);
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckSubtractionOperands( // C99 6.5.6
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc);
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckShiftOperands( // C99 6.5.7
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc);
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckRelationalOperands( // C99 6.5.8
     Expr *&lex, Expr *&rex, SourceLocation OpLoc);
   inline QualType CheckEqualityOperands( // C99 6.5.9
     Expr *&lex, Expr *&rex, SourceLocation OpLoc); 
   inline QualType CheckBitwiseOperands( // C99 6.5.[10...12]
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc); 
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); 
   inline QualType CheckLogicalOperands( // C99 6.5.[13,14]
     Expr *&lex, Expr *&rex, SourceLocation OpLoc);
   // CheckAssignmentOperands is used for both simple and compound assignment.

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

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Fri Aug 24 14:07:16 2007
@@ -752,7 +752,8 @@
 /// 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.
-void Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr) {
+QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
+                                          bool isCompAssign) {
   UsualUnaryConversions(lhsExpr);
   UsualUnaryConversions(rhsExpr);
   
@@ -761,12 +762,12 @@
   
   // If both types are identical, no conversion is needed.
   if (lhs == rhs) 
-    return;
+    return lhs;
   
   // If either side is a non-arithmetic type (e.g. a pointer), we are done.
   // The caller can deal with this (e.g. pointer + int).
   if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
-    return;
+    return lhs;
     
   // At this point, we have two different arithmetic types. 
   
@@ -774,48 +775,48 @@
   if (lhs->isComplexType() || rhs->isComplexType()) {
     // if we have an integer operand, the result is the complex type.
     if (rhs->isIntegerType()) { // convert the rhs to the lhs complex type.
-      promoteExprToType(rhsExpr, lhs);
-      return;
+      if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
+      return lhs;
     }
     if (lhs->isIntegerType()) { // convert the lhs to the rhs complex type.
-      promoteExprToType(lhsExpr, rhs);
-      return;
+      if (!isCompAssign) promoteExprToType(lhsExpr, rhs);
+      return rhs;
     }
     // Two complex types. Convert the smaller operand to the bigger result.
     if (Context.maxComplexType(lhs, rhs) == lhs) { // convert the rhs
-      promoteExprToType(rhsExpr, lhs);
-      return;
+      if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
+      return lhs;
     }
-    promoteExprToType(lhsExpr, rhs); // convert the lhs
-    return;
+    if (!isCompAssign) promoteExprToType(lhsExpr, rhs); // convert the lhs
+    return rhs;
   }
   // 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()) { // convert rhs to the lhs floating point type.
-      promoteExprToType(rhsExpr, lhs);
-      return;
+      if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
+      return lhs;
     }
     if (lhs->isIntegerType()) { // convert lhs to the rhs floating point type.
-      promoteExprToType(lhsExpr, rhs);
-      return;
+      if (!isCompAssign) promoteExprToType(lhsExpr, rhs);
+      return 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
-      promoteExprToType(rhsExpr, lhs);
-      return;
+      if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
+      return lhs;
     }
-    promoteExprToType(lhsExpr, rhs); // convert the lhs
-    return;
+    if (!isCompAssign) promoteExprToType(lhsExpr, rhs); // convert the lhs
+    return rhs;
   }
   // Finally, we have two differing integer types.
   if (Context.maxIntegerType(lhs, rhs) == lhs) { // convert the rhs
-    promoteExprToType(rhsExpr, lhs);
-    return;
+    if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
+    return lhs;
   }
-  promoteExprToType(lhsExpr, rhs); // convert the lhs
-  return;
+  if (!isCompAssign) promoteExprToType(lhsExpr, rhs); // convert the lhs
+  return rhs;
 }
 
 // CheckPointerTypesForAssignment - This is a very tricky routine (despite
@@ -949,47 +950,45 @@
 }    
 
 inline QualType Sema::CheckMultiplyDivideOperands(
-  Expr *&lex, Expr *&rex, SourceLocation loc) 
+  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
 {
   QualType lhsType = lex->getType(), rhsType = rex->getType();
 
   if (lhsType->isVectorType() || rhsType->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
     
-  UsualArithmeticConversions(lex, rex);
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
   
-  // handle the common case first (both operands are arithmetic).
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
-    return lex->getType();
+    return compType;
   InvalidOperands(loc, lex, rex);
   return QualType();
 }
 
 inline QualType Sema::CheckRemainderOperands(
-  Expr *&lex, Expr *&rex, SourceLocation loc) 
+  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
 {
   QualType lhsType = lex->getType(), rhsType = rex->getType();
 
-  UsualArithmeticConversions(lex, rex);
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
   
-  // handle the common case first (both operands are arithmetic).
   if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
-    return lex->getType();
+    return compType;
   InvalidOperands(loc, lex, rex);
   return QualType();
 }
 
 inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
-  Expr *&lex, Expr *&rex, SourceLocation loc) 
+  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
 {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
 
-  UsualArithmeticConversions(lex, rex);
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
   
   // handle the common case first (both operands are arithmetic).
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
-    return lex->getType();
+    return compType;
 
   if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
     return lex->getType();
@@ -1000,19 +999,19 @@
 }
 
 inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
-  Expr *&lex, Expr *&rex, SourceLocation loc) 
+  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
 {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
     
-  UsualArithmeticConversions(lex, rex);
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
   
   // handle the common case first (both operands are arithmetic).
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
-    return lex->getType();
+    return compType;
     
   if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
-    return lex->getType();
+    return compType;
   if (lex->getType()->isPointerType() && rex->getType()->isPointerType())
     return Context.getPointerDiffType();
   InvalidOperands(loc, lex, rex);
@@ -1020,15 +1019,15 @@
 }
 
 inline QualType Sema::CheckShiftOperands( // C99 6.5.7
-  Expr *&lex, Expr *&rex, SourceLocation loc)
+  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
 {
   // FIXME: Shifts don't perform usual arithmetic conversions.  This is wrong
   // for int << longlong -> the result type should be int, not long long.
-  UsualArithmeticConversions(lex, rex);
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
   
   // handle the common case first (both operands are arithmetic).
   if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
-    return lex->getType();
+    return compType;
   InvalidOperands(loc, lex, rex);
   return QualType();
 }
@@ -1132,15 +1131,15 @@
 }
 
 inline QualType Sema::CheckBitwiseOperands(
-  Expr *&lex, Expr *&rex, SourceLocation loc) 
+  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
 {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
 
-  UsualArithmeticConversions(lex, rex);
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
   
   if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
-    return lex->getType();
+    return compType;
   InvalidOperands(loc, lex, rex);
   return QualType();
 }
@@ -1486,35 +1485,35 @@
     break;
   case BinaryOperator::MulAssign:
   case BinaryOperator::DivAssign:
-    CompTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc);
+    CompTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc, true);
     if (!CompTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
     break;
   case BinaryOperator::RemAssign:
-    CompTy = CheckRemainderOperands(lhs, rhs, TokLoc);
+    CompTy = CheckRemainderOperands(lhs, rhs, TokLoc, true);
     if (!CompTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
     break;
   case BinaryOperator::AddAssign:
-    CompTy = CheckAdditionOperands(lhs, rhs, TokLoc);
+    CompTy = CheckAdditionOperands(lhs, rhs, TokLoc, true);
     if (!CompTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
     break;
   case BinaryOperator::SubAssign:
-    CompTy = CheckSubtractionOperands(lhs, rhs, TokLoc);
+    CompTy = CheckSubtractionOperands(lhs, rhs, TokLoc, true);
     if (!CompTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
     break;
   case BinaryOperator::ShlAssign:
   case BinaryOperator::ShrAssign:
-    CompTy = CheckShiftOperands(lhs, rhs, TokLoc);
+    CompTy = CheckShiftOperands(lhs, rhs, TokLoc, true);
     if (!CompTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
     break;
   case BinaryOperator::AndAssign:
   case BinaryOperator::XorAssign:
   case BinaryOperator::OrAssign:
-    CompTy = CheckBitwiseOperands(lhs, rhs, TokLoc);
+    CompTy = CheckBitwiseOperands(lhs, rhs, TokLoc, true);
     if (!CompTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
     break;

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=41364&r1=41363&r2=41364&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Fri Aug 24 14:07:16 2007
@@ -78,7 +78,7 @@
 STMT(56, ObjCStringLiteral    , Expr)
 STMT(57, ObjCEncodeExpr       , Expr)
 
-LAST_EXPR(56)
+LAST_EXPR(57)
 
 #undef STMT
 #undef FIRST_STMT





More information about the cfe-commits mailing list