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

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


Author: snaroff
Date: Wed Jul 11 11:44:30 2007
New Revision: 39446

URL: http://llvm.org/viewvc/llvm-project?rev=39446&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
- Unified isConstantExpr/isIntegerConstantExpr by creating a private function
named isConstantExpr (that takes a bool to indicate the flavor). isConstantExpr
and isIntegerConstantExpr are now inline wrapper/helper functions.
- Fixed bug in expression based sizeof (it needed to make sure the type is constant).
- Added Sema::CheckConditionalOperands() stub. Will add contraints in my next commit.

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

Modified: cfe/cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Expr.cpp?rev=39446&r1=39445&r2=39446&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:44:30 2007
@@ -175,13 +175,26 @@
   return true;    
 }
 
-bool Expr::isConstantExpr() const {
+/// isConstantExpr - this recursive routine will test if an expression is
+/// either a constant expression (isIntConst == false) or an integer constant
+/// expression (isIntConst == true). Note: With the introduction of VLA's in
+/// C99 the result of the sizeof operator is no longer always a constant
+/// expression. The generalization of the wording to include any subexpression
+/// that is not evaluated (C99 6.6p3) means that nonconstant subexpressions
+/// can appear as operands to other operators (e.g. &&, ||, ?:). For instance,
+/// "0 || f()" can be treated as a constant expression. In C90 this expression,
+/// occurring in a context requiring a constant, would have been a constraint
+/// violation. FIXME: This routine currently implements C90 semantics.
+/// To properly implement C99 semantics this routine will need to evaluate
+/// expressions involving operators previously mentioned.
+bool Expr::isConstantExpr(bool isIntConst) const {
   switch (getStmtClass()) {
   case IntegerLiteralClass:
-  case FloatingLiteralClass:
   case CharacterLiteralClass:
-  case StringLiteralClass:
     return true;
+  case FloatingLiteralClass:
+  case StringLiteralClass:
+    return isIntConst ? false : true;
   case DeclRefExprClass:
     return isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl());
   case UnaryOperatorClass:
@@ -192,8 +205,8 @@
     // is an integer constant. This effective ignores any subexpression that
     // isn't actually a constant expression (what an odd language:-)
     if (uop->isSizeOfAlignOfOp())
-      return true;
-    return uop->getSubExpr()->isConstantExpr();
+      return uop->getSubExpr()->getType()->isConstantSizeType();
+    return uop->getSubExpr()->isConstantExpr(isIntConst);
   case BinaryOperatorClass:
     const BinaryOperator *bop = cast<BinaryOperator>(this);
     // C99 6.6p3: shall not contain assignment, increment/decrement,
@@ -201,7 +214,8 @@
     // within a subexpression that is not evaluated. 
     if (bop->isAssignmentOp() || bop->getOpcode() == BinaryOperator::Comma)
       return false;
-    return bop->getLHS()->isConstantExpr() && bop->getRHS()->isConstantExpr();
+    return bop->getLHS()->isConstantExpr(isIntConst) &&
+           bop->getRHS()->isConstantExpr(isIntConst);
   case ParenExprClass:
     return cast<ParenExpr>(this)->getSubExpr()->isConstantExpr();
   case CastExprClass: 
@@ -222,73 +236,10 @@
       return sizeExpr->getArgumentType()->isConstantSizeType();
     return true; // alignof will always evaluate to a constant
   case ConditionalOperatorClass:
-    // GCC currently ignores any subexpression that isn't evaluated.
-    // GCC currently considers the following legal: "1 ? 7 : printf("xx")"
-    // EDG still flags this as an error (which is great, since this predicate
-    // can do it's job *without* evaluating the expression).
-    const ConditionalOperator *condExpr = cast<ConditionalOperator>(this);
-    return condExpr->getCond()->isConstantExpr() &&
-           condExpr->getLHS()->isConstantExpr() &&
-           condExpr->getRHS()->isConstantExpr();
-  default: 
-    return false;
-  }
-}
-
-bool Expr::isIntegerConstantExpr() const {
-  switch (getStmtClass()) {
-  case IntegerLiteralClass:
-  case CharacterLiteralClass:
-    return true;
-  case DeclRefExprClass:
-    return isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl());
-  case UnaryOperatorClass:
-    const UnaryOperator *uop = cast<UnaryOperator>(this);
-    if (uop->isIncrementDecrementOp()) // C99 6.6p3
-      return false;
-    // C99 6.5.3.4p2: otherwise, the operand is *not* evaluated and the result
-    // is an integer constant. This effective ignores any subexpression that
-    // isn't actually a constant expression (what an odd language:-)
-    if (uop->isSizeOfAlignOfOp())
-      return true;
-    return uop->getSubExpr()->isIntegerConstantExpr();
-  case BinaryOperatorClass:
-    const BinaryOperator *bop = cast<BinaryOperator>(this);
-    // C99 6.6p3: shall not contain assignment, increment/decrement,
-    // function call, or comma operators, *except* when they are contained
-    // within a subexpression that is not evaluated. 
-    if (bop->isAssignmentOp() || bop->getOpcode() == BinaryOperator::Comma)
-      return false;
-    return bop->getLHS()->isIntegerConstantExpr() &&
-           bop->getRHS()->isIntegerConstantExpr();
-  case ParenExprClass:
-    return cast<ParenExpr>(this)->getSubExpr()->isIntegerConstantExpr();
-  case CastExprClass: 
-    const CastExpr *castExpr = cast<CastExpr>(this);    
-    // C99 6.6p6: shall only convert arithmetic types to integer types.
-    if (!castExpr->getSubExpr()->getType()->isArithmeticType())
-      return false;
-    if (!castExpr->getDestType()->isIntegerType())
-      return false;      
-    // allow floating constants that are the immediate operands of casts.
-    if (castExpr->getSubExpr()->isIntegerConstantExpr() ||
-        isa<FloatingLiteral>(castExpr->getSubExpr()))
-      return true;
-    return false;
-  case SizeOfAlignOfTypeExprClass:
-    const SizeOfAlignOfTypeExpr *sizeExpr = cast<SizeOfAlignOfTypeExpr>(this);
-    if (sizeExpr->isSizeOf())
-      return sizeExpr->getArgumentType()->isConstantSizeType();
-    return true; // alignof will always evaluate to a constant
-  case ConditionalOperatorClass:
-    // GCC currently ignores any subexpression that isn't evaluated.
-    // GCC currently considers the following legal: "1 ? 7 : printf("xx")"
-    // EDG still flags this as an error (which is great, since this predicate
-    // can do it's job *without* evaluating the expression).
     const ConditionalOperator *condExpr = cast<ConditionalOperator>(this);
-    return condExpr->getCond()->isIntegerConstantExpr() &&
-           condExpr->getLHS()->isIntegerConstantExpr() &&
-           condExpr->getRHS()->isIntegerConstantExpr();
+    return condExpr->getCond()->isConstantExpr(isIntConst) &&
+           condExpr->getLHS()->isConstantExpr(isIntConst) &&
+           condExpr->getRHS()->isConstantExpr(isIntConst);
   default: 
     return false;
   }

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

==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:44:30 2007
@@ -274,6 +274,8 @@
     Expr *lex, Expr *rex, SourceLocation OpLoc, QualType convertedType);
   inline QualType CheckCommaOperands( // C99 6.5.17
     Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckConditionalOperands( // C99 6.5.15
+    Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc);
   
   /// type checking unary operators (subroutines of ParseUnaryOp).
   QualType CheckIncrementDecrementOperand( // C99 6.5.3.1 

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

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:30 2007
@@ -384,20 +384,31 @@
   return new CastExpr(QualType::getFromOpaquePtr(Ty), (Expr*)Op);
 }
 
+inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
+  Expr *Cond, Expr *LHS, Expr *RHS, SourceLocation questionLoc) {
+  QualType cond = Cond->getType().getCanonicalType();
+  QualType lhs = LHS->getType().getCanonicalType();
+  QualType rhs = RHS->getType().getCanonicalType();
+
+  assert(!cond.isNull() && "ParseConditionalOp(): no conditional type");
+  assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
+  assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
+
+  // C99 6.5.15p2,3
+  return rhs;
+}
+
 /// ParseConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
 /// in the case of a the GNU conditional expr extension.
 Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc, 
                                             SourceLocation ColonLoc,
                                             ExprTy *Cond, ExprTy *LHS,
                                             ExprTy *RHS) {
-  QualType lhs = ((Expr *)LHS)->getType();
-  QualType rhs = ((Expr *)RHS)->getType();
-
-  assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
-  assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
-
-  QualType canonType = rhs.getCanonicalType(); // FIXME
-  return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, canonType);
+  QualType result = CheckConditionalOperands((Expr *)Cond, (Expr *)LHS, 
+                                             (Expr *)RHS, QuestionLoc);
+  if (result.isNull())
+    return true;
+  return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
 }
 
 /// UsualUnaryConversion - Performs various conversions that are common to most

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

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:44:30 2007
@@ -274,6 +274,8 @@
     Expr *lex, Expr *rex, SourceLocation OpLoc, QualType convertedType);
   inline QualType CheckCommaOperands( // C99 6.5.17
     Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckConditionalOperands( // C99 6.5.15
+    Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc);
   
   /// type checking unary operators (subroutines of ParseUnaryOp).
   QualType CheckIncrementDecrementOperand( // C99 6.5.3.1 

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:30 2007
@@ -384,20 +384,31 @@
   return new CastExpr(QualType::getFromOpaquePtr(Ty), (Expr*)Op);
 }
 
+inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
+  Expr *Cond, Expr *LHS, Expr *RHS, SourceLocation questionLoc) {
+  QualType cond = Cond->getType().getCanonicalType();
+  QualType lhs = LHS->getType().getCanonicalType();
+  QualType rhs = RHS->getType().getCanonicalType();
+
+  assert(!cond.isNull() && "ParseConditionalOp(): no conditional type");
+  assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
+  assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
+
+  // C99 6.5.15p2,3
+  return rhs;
+}
+
 /// ParseConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
 /// in the case of a the GNU conditional expr extension.
 Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc, 
                                             SourceLocation ColonLoc,
                                             ExprTy *Cond, ExprTy *LHS,
                                             ExprTy *RHS) {
-  QualType lhs = ((Expr *)LHS)->getType();
-  QualType rhs = ((Expr *)RHS)->getType();
-
-  assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
-  assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
-
-  QualType canonType = rhs.getCanonicalType(); // FIXME
-  return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, canonType);
+  QualType result = CheckConditionalOperands((Expr *)Cond, (Expr *)LHS, 
+                                             (Expr *)RHS, QuestionLoc);
+  if (result.isNull())
+    return true;
+  return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
 }
 
 /// UsualUnaryConversion - Performs various conversions that are common to most

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=39446&r1=39445&r2=39446&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:30 2007
@@ -56,8 +56,8 @@
   
   bool isNullPointerConstant() const;
 
-  bool isConstantExpr() const;
-  bool isIntegerConstantExpr() const;
+  bool isConstantExpr() const { return isConstantExpr(false); }
+  bool isIntegerConstantExpr() const { return isConstantExpr(true); }
   
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 
@@ -65,6 +65,8 @@
            T->getStmtClass() <= lastExprConstant; 
   }
   static bool classof(const Expr *) { return true; }
+private:
+  bool isConstantExpr(bool isIntegerConstant) const;
 };
 
 //===----------------------------------------------------------------------===//





More information about the cfe-commits mailing list