[cfe-commits] r39840 - in /cfe/trunk: AST/StmtPrinter.cpp Sema/Sema.h Sema/SemaExpr.cpp Sema/SemaStmt.cpp include/clang/AST/Expr.h

Steve Naroff snaroff at apple.com
Fri Jul 13 16:32:43 PDT 2007


Author: snaroff
Date: Fri Jul 13 18:32:42 2007
New Revision: 39840

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

More changes related to implementing ImplicitCastExpr.

- Fixed a recent regression discovered by Keith Bauer (thanks!). 
The fix involved adding (back) two arguments to UsualArithmeticConversions.
Without the reference arguments, no unary conversions were being passed back
to the caller. This had the effect of turning off the UsualUnaryConversions.
- Refactored CheckAssignmentConstraints into 3 functions. CheckAssignmentConstraints,
CheckSingleAssignmentConstraints, and CheckCompoundAssignmentConstraints. 
- Changed the argument type of DefaultFunctionArrayConversion from QualType->Expr*&.
- Removed a bunch of casts in routines I was working on (cleanup).
- Fixed the visitor for ImplicitCastExpr (oops).

Modified:
    cfe/trunk/AST/StmtPrinter.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/Sema/SemaStmt.cpp
    cfe/trunk/include/clang/AST/Expr.h

Modified: cfe/trunk/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/StmtPrinter.cpp?rev=39840&r1=39839&r2=39840&view=diff

==============================================================================
--- cfe/trunk/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/AST/StmtPrinter.cpp Fri Jul 13 18:32:42 2007
@@ -387,7 +387,8 @@
   PrintExpr(Node->getSubExpr());
 }
 void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
-  // No need to print anything.
+  // No need to print anything, simply forward to the sub expression.
+  PrintExpr(Node->getSubExpr());
 }
 void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
   PrintExpr(Node->getLHS());

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

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Jul 13 18:32:42 2007
@@ -271,16 +271,19 @@
   // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
   // functions and arrays to their respective pointers (C99 6.3.2.1)
   QualType UsualUnaryConversions(Expr *&expr); 
+  
   // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
   // operands and then handles 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 UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr);
+  QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
+                                      QualType &lhs, QualType &rhs);
+                                      
   // DefaultFunctionArrayConversion - converts functions and arrays
   // to their respective pointers (C99 6.3.2.1). If the type isn't a function
   // or array, this routine simply returns the input type (unmodified).
-  QualType DefaultFunctionArrayConversion(QualType t);
+  QualType DefaultFunctionArrayConversion(Expr *&expr);
   
   enum AssignmentCheckResult {
     Compatible,
@@ -290,10 +293,22 @@
     IncompatiblePointer,
     CompatiblePointerDiscardsQualifiers
   };
-  // CheckAssignmentConstraints - conversions for assignment, argument passing, 
-  // variable initialization, and function return values. Currently used by 
-  // CheckAssignmentOperands, ParseCallExpr, and ParseReturnStmt.  C99 6.5.16.
+  // CheckAssignmentConstraints - Perform type checking for assignment, 
+  // argument passing, variable initialization, and function return values. 
+  // This routine is only used by the following two methods. C99 6.5.16.
   AssignmentCheckResult CheckAssignmentConstraints(QualType lhs, QualType rhs);
+  
+  // CheckSingleAssignmentConstraints - Currently used by ParseCallExpr,
+  // CheckAssignmentOperands, and ParseReturnStmt. Prior to type checking, 
+  // this routine performs the default function/array converions.
+  AssignmentCheckResult CheckSingleAssignmentConstraints(QualType lhs, 
+                                                         Expr *&rExpr);
+  // CheckCompoundAssignmentConstraints - Type check without performing any 
+  // conversions. For compound assignments, the "Check...Operands" methods 
+  // perform the necessary conversions. 
+  AssignmentCheckResult CheckCompoundAssignmentConstraints(QualType lhs, 
+                                                           QualType rhs);
+  
   // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
   AssignmentCheckResult CheckPointerTypesForAssignment(QualType lhsType, 
                                                        QualType rhsType);

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

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Fri Jul 13 18:32:42 2007
@@ -278,14 +278,16 @@
 Action::ExprResult Sema::
 ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
                         ExprTy *Idx, SourceLocation RLoc) {
-  QualType t1 = ((Expr *)Base)->getType();
-  QualType t2 = ((Expr *)Idx)->getType();
+  Expr *lex = (Expr *)Base;
+  Expr *rex = (Expr *)Idx;
+  QualType t1 = lex->getType();
+  QualType t2 = rex->getType();
 
   assert(!t1.isNull() && "no type for array base expression");
   assert(!t2.isNull() && "no type for array index expression");
 
-  QualType canonT1 = DefaultFunctionArrayConversion(t1).getCanonicalType();
-  QualType canonT2 = DefaultFunctionArrayConversion(t2).getCanonicalType();
+  QualType canonT1 = DefaultFunctionArrayConversion(lex).getCanonicalType();
+  QualType canonT2 = DefaultFunctionArrayConversion(rex).getCanonicalType();
   
   // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
   // to the expression *((e1)+(e2)). This means the array "Base" may actually be 
@@ -297,17 +299,16 @@
   if (isa<PointerType>(canonT1) || isa<VectorType>(canonT1)) {
     baseType = canonT1;
     indexType = canonT2;
-    baseExpr = static_cast<Expr *>(Base);
-    indexExpr = static_cast<Expr *>(Idx);
+    baseExpr = lex;
+    indexExpr = rex;
   } else if (isa<PointerType>(canonT2)) { // uncommon
     baseType = canonT2;
     indexType = canonT1;
-    baseExpr = static_cast<Expr *>(Idx);
-    indexExpr = static_cast<Expr *>(Base);
+    baseExpr = rex;
+    indexExpr = lex;
   } else {
-    return Diag(static_cast<Expr *>(Base)->getLocStart(), 
-                diag::err_typecheck_subscript_value, 
-                static_cast<Expr *>(Base)->getSourceRange());
+    return Diag(lex->getLocStart(), diag::err_typecheck_subscript_value, 
+                rex->getSourceRange());
   }              
   // C99 6.5.2.1p1
   if (!indexType->isIntegerType()) {
@@ -427,8 +428,8 @@
       if (lhsType == rhsType) // common case, fast path...
         continue;
         
-      AssignmentCheckResult result = CheckAssignmentConstraints(lhsType,
-                                                                rhsType);
+      AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
+                                                                      argExpr);
       SourceLocation l = argExpr->getLocStart();
 
       // decode the result (notice that AST's are still created for extensions).
@@ -495,7 +496,7 @@
   }
   // now check the two expressions.
   if (lexT->isArithmeticType() && rexT->isArithmeticType()) // C99 6.5.15p3,5
-    return UsualArithmeticConversions(lex, rex);
+    return UsualArithmeticConversions(lex, rex, lexT, rexT);
     
   if ((lexT->isStructureType() && rexT->isStructureType()) || // C99 6.5.15p3
       (lexT->isUnionType() && rexT->isUnionType())) {
@@ -565,7 +566,10 @@
   return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
 }
 
-QualType Sema::DefaultFunctionArrayConversion(QualType t) {
+QualType Sema::DefaultFunctionArrayConversion(Expr *&expr) {
+  QualType t = expr->getType();
+  assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
+  
   if (t->isFunctionType()) // C99 6.3.2.1p4
     return Context.getPointerType(t);
   if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
@@ -582,18 +586,21 @@
   QualType t = expr->getType();
   assert(!t.isNull() && "UsualUnaryConversions - missing type");
   
-  if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
+  if (t->isPromotableIntegerType()) { // C99 6.3.1.1p2
+    // expr = new ImplicitCastExpr(Context.IntTy, expr);
     return Context.IntTy;
-  return DefaultFunctionArrayConversion(t);
+  }
+  return DefaultFunctionArrayConversion(expr);
 }
 
 /// 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(Expr *&lhsExpr, Expr *&rhsExpr) {
-  QualType lhs = UsualUnaryConversions(lhsExpr);
-  QualType rhs = UsualUnaryConversions(rhsExpr);
+QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
+                                          QualType &lhs, QualType &rhs) {
+  lhs = UsualUnaryConversions(lhsExpr);
+  rhs = UsualUnaryConversions(rhsExpr);
   
   // If both types are identical, no conversion is needed.
   if (lhs == rhs) 
@@ -695,12 +702,6 @@
 ///
 Sema::AssignmentCheckResult
 Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
-  // This check seems unnatural, however it is necessary to insure the proper
-  // conversion of functions/arrays. If the conversion were done for all
-  // DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
-  // expressions that surpress this implicit conversion (&, sizeof).
-  rhsType = DefaultFunctionArrayConversion(rhsType);
-    
   if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) {
     if (lhsType->isVectorType() || rhsType->isVectorType()) {
       if (lhsType.getCanonicalType() != rhsType.getCanonicalType())
@@ -730,6 +731,22 @@
   return Incompatible;
 }
 
+Sema::AssignmentCheckResult
+Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
+  // This check seems unnatural, however it is necessary to insure the proper
+  // conversion of functions/arrays. If the conversion were done for all
+  // DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
+  // expressions that surpress this implicit conversion (&, sizeof).
+  QualType rhsType = DefaultFunctionArrayConversion(rExpr);
+  
+  return CheckAssignmentConstraints(lhsType, rhsType);
+}
+
+Sema::AssignmentCheckResult
+Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
+  return CheckAssignmentConstraints(lhsType, rhsType);
+}
+
 inline void Sema::InvalidOperands(SourceLocation loc, Expr *&lex, Expr *&rex) {
   Diag(loc, diag::err_typecheck_invalid_operands, 
        lex->getType().getAsString(), rex->getType().getAsString(),
@@ -753,10 +770,12 @@
 inline QualType Sema::CheckMultiplyDivideOperands(
   Expr *&lex, Expr *&rex, SourceLocation loc) 
 {
-  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+  if (lhsType->isVectorType() || rhsType->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
     
-  QualType resType = UsualArithmeticConversions(lex, rex);
+  QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
   
   if (resType->isArithmeticType())
     return resType;
@@ -767,7 +786,9 @@
 inline QualType Sema::CheckRemainderOperands(
   Expr *&lex, Expr *&rex, SourceLocation loc) 
 {
-  QualType resType = UsualArithmeticConversions(lex, rex);
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+  QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
   
   if (resType->isIntegerType())
     return resType;
@@ -783,7 +804,7 @@
   if (lhsType->isVectorType() || rhsType->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
 
-  QualType resType = UsualArithmeticConversions(lex, rex);
+  QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
 
   // handle the common case first (both operands are arithmetic).
   if (resType->isArithmeticType())
@@ -803,7 +824,8 @@
 
   if (lhsType->isVectorType() || rhsType->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
-  QualType resType = UsualArithmeticConversions(lex, rex);
+    
+  QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
   
   // handle the common case first (both operands are arithmetic).
   if (resType->isArithmeticType())
@@ -822,7 +844,7 @@
   // FIXME: Shifts don't perform usual arithmetic conversions.  This is wrong
   // for int << longlong -> the result type should be int, not long long.
   QualType lhsType = lex->getType(), rhsType = rex->getType();
-  QualType resType = UsualArithmeticConversions(lex, rex);
+  QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
   
   if (resType->isIntegerType())
     return resType;
@@ -897,7 +919,8 @@
   
   if (lhsType->isVectorType() || rhsType->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
-  QualType resType = UsualArithmeticConversions(lex, rex);
+
+  QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
   
   if (resType->isIntegerType())
     return resType;
@@ -953,8 +976,13 @@
   if (lhsType == rhsType) // common case, fast path...
     return lhsType;
   
-  AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
-
+  AssignmentCheckResult result;
+  
+  if (compoundType.isNull())
+    result = CheckSingleAssignmentConstraints(lhsType, rex);
+  else
+    result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
+    
   // decode the result (notice that extensions still return a type).
   switch (result) {
   case Compatible:
@@ -1313,7 +1341,7 @@
     break;
   case UnaryOperator::LNot: // logical negation
     // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
-    resultType = DefaultFunctionArrayConversion(Input->getType());
+    resultType = DefaultFunctionArrayConversion(Input);
     if (!resultType->isScalarType()) // C99 6.5.3.3p1
       return Diag(OpLoc, diag::err_typecheck_unary_expr,
                   resultType.getAsString());

Modified: cfe/trunk/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaStmt.cpp?rev=39840&r1=39839&r2=39840&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/Sema/SemaStmt.cpp Fri Jul 13 18:32:42 2007
@@ -107,7 +107,7 @@
   Expr *condExpr = (Expr *)CondVal;
   assert(condExpr && "ParseIfStmt(): missing expression");
   
-  QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
+  QualType condType = DefaultFunctionArrayConversion(condExpr);
   assert(!condType.isNull() && "ParseIfStmt(): missing expression type");
   
   if (!condType->isScalarType()) // C99 6.8.4.1p1
@@ -127,7 +127,7 @@
   Expr *condExpr = (Expr *)Cond;
   assert(condExpr && "ParseWhileStmt(): missing expression");
   
-  QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
+  QualType condType = DefaultFunctionArrayConversion(condExpr);
   assert(!condType.isNull() && "ParseWhileStmt(): missing expression type");
   
   if (!condType->isScalarType()) // C99 6.8.5p2
@@ -143,7 +143,7 @@
   Expr *condExpr = (Expr *)Cond;
   assert(condExpr && "ParseDoStmt(): missing expression");
   
-  QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
+  QualType condType = DefaultFunctionArrayConversion(condExpr);
   assert(!condType.isNull() && "ParseDoStmt(): missing expression type");
   
   if (!condType->isScalarType()) // C99 6.8.5p2
@@ -164,7 +164,7 @@
   }
   if (Second) {
     Expr *testExpr = (Expr *)Second;
-    QualType testType = DefaultFunctionArrayConversion(testExpr->getType());
+    QualType testType = DefaultFunctionArrayConversion(testExpr);
     assert(!testType.isNull() && "ParseForStmt(): missing test expression type");
     
     if (!testType->isScalarType()) // C99 6.8.5p2
@@ -224,15 +224,16 @@
 
 
 Action::StmtResult
-Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) {
+Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
+  Expr *RetValExp = static_cast<Expr *>(rex);
   QualType lhsType = CurFunctionDecl->getResultType();
 
   if (lhsType->isVoidType()) {
     if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
       Diag(ReturnLoc, diag::ext_return_has_expr, 
            CurFunctionDecl->getIdentifier()->getName(),
-           ((Expr *)RetValExp)->getSourceRange());
-    return new ReturnStmt((Expr*)RetValExp);
+           RetValExp->getSourceRange());
+    return new ReturnStmt(RetValExp);
   } else {
     if (!RetValExp) {
       const char *funcName = CurFunctionDecl->getIdentifier()->getName();
@@ -244,15 +245,16 @@
     }
   }
   // we have a non-void function with an expression, continue checking
-  QualType rhsType = ((Expr *)RetValExp)->getType();
+  QualType rhsType = RetValExp->getType();
 
   if (lhsType == rhsType) // common case, fast path...
-    return new ReturnStmt((Expr*)RetValExp);
+    return new ReturnStmt(RetValExp);
 
   // C99 6.8.6.4p3(136): The return statement is not an assignment. The 
   // overlap restriction of subclause 6.5.16.1 does not apply to the case of 
   // function return.  
-  AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
+  AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType, 
+                                                                  RetValExp);
   bool hadError = false;
   
   // decode the result (notice that extensions still return a type).
@@ -262,31 +264,31 @@
   case Incompatible:
     Diag(ReturnLoc, diag::err_typecheck_return_incompatible, 
          lhsType.getAsString(), rhsType.getAsString(),
-         ((Expr *)RetValExp)->getSourceRange());
+         RetValExp->getSourceRange());
     hadError = true;
     break;
   case PointerFromInt:
     // check for null pointer constant (C99 6.3.2.3p3)
-    if (!((Expr *)RetValExp)->isNullPointerConstant()) {
+    if (!RetValExp->isNullPointerConstant()) {
       Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
            lhsType.getAsString(), rhsType.getAsString(),
-           ((Expr *)RetValExp)->getSourceRange());
+           RetValExp->getSourceRange());
     }
     break;
   case IntFromPointer:
     Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
          lhsType.getAsString(), rhsType.getAsString(),
-         ((Expr *)RetValExp)->getSourceRange());
+         RetValExp->getSourceRange());
     break;
   case IncompatiblePointer:
     Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer,
          lhsType.getAsString(), rhsType.getAsString(),
-         ((Expr *)RetValExp)->getSourceRange());
+         RetValExp->getSourceRange());
     break;
   case CompatiblePointerDiscardsQualifiers:
     Diag(ReturnLoc, diag::ext_typecheck_return_discards_qualifiers,
          lhsType.getAsString(), rhsType.getAsString(),
-         ((Expr *)RetValExp)->getSourceRange());
+         RetValExp->getSourceRange());
     break;
   }
   return new ReturnStmt((Expr*)RetValExp);

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

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Jul 13 18:32:42 2007
@@ -438,7 +438,9 @@
     
   Expr *getSubExpr() { return Op; }
   const Expr *getSubExpr() const { return Op; }
-  
+
+  virtual SourceRange getSourceRange() const { return SourceRange(); }
+
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == ImplicitCastExprClass; 





More information about the cfe-commits mailing list