[cfe-commits] r39454 - in /cfe/cfe/trunk: AST/Expr.cpp AST/SemaDecl.cpp AST/SemaStmt.cpp AST/Type.cpp Sema/SemaDecl.cpp Sema/SemaStmt.cpp include/clang/AST/Expr.h include/clang/AST/Type.h

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


Author: snaroff
Date: Wed Jul 11 11:44:36 2007
New Revision: 39454

URL: http://llvm.org/viewvc/llvm-project?rev=39454&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
Extended Expr's constant expression predicates to return a source location
if the predicate returns false. This enables us to position the cursor
exactly were the error occurred (simple pleasures:-).

constant.c:9:9: error: enumerator value for 'E2' is not an integer constant
  E2 = (aconst + 1), // illegal
        ^
constant.c:10:8: error: enumerator value for 'E3' is not an integer constant
  E3 = "abc",
       ^
constant.c:12:12: error: enumerator value for 'E5' is not an integer constant
  E5 = 0?7:printf("xx"), // illegal
           ^
constant.c:13:12: error: enumerator value for 'E6' is not an integer constant
  E6 = 1?7:printf("xx"), // legal
           ^
constant.c:16:14: error: enumerator value for 'E9' is not an integer constant
  E9 = E0 || a, // illegal
             ^
constant.c:21:6: error: array has incomplete element type 'void'
void ary[7];
     ^
constant.c:22:28: error: variable length array declared outside of any function
struct { int a; } ary2[1?7:printf("xx")],
                           ^
constant.c:23:34: error: variable length array declared outside of any function
                  aryIllegal[0?7:printf("yy")];
                                 ^
constant.c:25:10: error: variable length array declared outside of any function
int ary3[a]; // illegal
         ^
constant.c:26:17: error: size of array has non-integer type 'float'
typedef int vla[2.0]; // illegal
                ^
constant.c:30:22: error: size of array has non-integer type 'float'
int nonIntegerArray2[1+2.0];
                     ^

Modified:
    cfe/cfe/trunk/AST/Expr.cpp
    cfe/cfe/trunk/AST/SemaDecl.cpp
    cfe/cfe/trunk/AST/SemaStmt.cpp
    cfe/cfe/trunk/AST/Type.cpp
    cfe/cfe/trunk/Sema/SemaDecl.cpp
    cfe/cfe/trunk/Sema/SemaStmt.cpp
    cfe/cfe/trunk/include/clang/AST/Expr.h
    cfe/cfe/trunk/include/clang/AST/Type.h

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

==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:44:36 2007
@@ -192,60 +192,76 @@
 /// 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 {
+bool Expr::isConstantExpr(bool isIntConst, SourceLocation &loc) const {
   switch (getStmtClass()) {
   case IntegerLiteralClass:
   case CharacterLiteralClass:
     return true;
   case FloatingLiteralClass:
   case StringLiteralClass:
-    return isIntConst ? false : true;
+    if (!isIntConst)
+      return true;
+    loc = getLocStart();
+    return false;
   case DeclRefExprClass:
-    return isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl());
+    if (isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl()))
+      return true;
+    loc = getLocStart();
+    return false;
   case UnaryOperatorClass:
     const UnaryOperator *uop = cast<UnaryOperator>(this);
-    if (uop->isIncrementDecrementOp()) // C99 6.6p3
+    if (uop->isIncrementDecrementOp()) { // C99 6.6p3
+      loc = getLocStart();
       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 uop->getSubExpr()->getType()->isConstantSizeType();
-    return uop->getSubExpr()->isConstantExpr(isIntConst);
+      return uop->getSubExpr()->getType()->isConstantSizeType(loc);
+    return uop->getSubExpr()->isConstantExpr(isIntConst, loc);
   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)
+    if (bop->isAssignmentOp() || bop->getOpcode() == BinaryOperator::Comma) {
+      loc = getLocStart();
       return false;
-    return bop->getLHS()->isConstantExpr(isIntConst) &&
-           bop->getRHS()->isConstantExpr(isIntConst);
+    }
+    return bop->getLHS()->isConstantExpr(isIntConst, loc) &&
+           bop->getRHS()->isConstantExpr(isIntConst, loc);
   case ParenExprClass:
-    return cast<ParenExpr>(this)->getSubExpr()->isConstantExpr();
+    return cast<ParenExpr>(this)->getSubExpr()->isConstantExpr(isIntConst, loc);
   case CastExprClass: 
     const CastExpr *castExpr = cast<CastExpr>(this);    
     // C99 6.6p6: shall only convert arithmetic types to integer types.
-    if (!castExpr->getSubExpr()->getType()->isArithmeticType())
+    if (!castExpr->getSubExpr()->getType()->isArithmeticType()) {
+      loc = castExpr->getSubExpr()->getLocStart();
+      return false;
+    }
+    if (!castExpr->getDestType()->isIntegerType()) {
+      loc = getLocStart();
       return false;
-    if (!castExpr->getDestType()->isIntegerType())
-      return false;      
+    }
     // allow floating constants that are the immediate operands of casts.
-    if (castExpr->getSubExpr()->isConstantExpr() ||
+    if (castExpr->getSubExpr()->isConstantExpr(isIntConst, loc) ||
         isa<FloatingLiteral>(castExpr->getSubExpr()))
       return true;
+    loc = getLocStart();
     return false;
   case SizeOfAlignOfTypeExprClass:
     const SizeOfAlignOfTypeExpr *sizeExpr = cast<SizeOfAlignOfTypeExpr>(this);
     if (sizeExpr->isSizeOf())
-      return sizeExpr->getArgumentType()->isConstantSizeType();
+      return sizeExpr->getArgumentType()->isConstantSizeType(loc);
     return true; // alignof will always evaluate to a constant
   case ConditionalOperatorClass:
     const ConditionalOperator *condExpr = cast<ConditionalOperator>(this);
-    return condExpr->getCond()->isConstantExpr(isIntConst) &&
-           condExpr->getLHS()->isConstantExpr(isIntConst) &&
-           condExpr->getRHS()->isConstantExpr(isIntConst);
-  default: 
+    return condExpr->getCond()->isConstantExpr(isIntConst, loc) &&
+           condExpr->getLHS()->isConstantExpr(isIntConst, loc) &&
+           condExpr->getRHS()->isConstantExpr(isIntConst, loc);
+  default:
+    loc = getLocStart();
     return false;
   }
 }

Modified: cfe/cfe/trunk/AST/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaDecl.cpp?rev=39454&r1=39453&r2=39454&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:44:36 2007
@@ -31,12 +31,14 @@
 // a constant expression of type int with a value greater than zero.
 bool Sema::isConstantArrayType(ArrayType *ary, SourceLocation loc) { 
   if (Expr *size = ary->getSize()) {
-    if (!size->isConstantExpr()) {
-      Diag(loc, diag::err_typecheck_illegal_vla);
+    SourceLocation expLoc;
+    if (!size->isConstantExpr(expLoc)) {
+      Diag(expLoc, diag::err_typecheck_illegal_vla);
       return false;
     }
     if (!size->getType()->isIntegerType()) {
-      Diag(loc, diag::err_array_size_non_int, size->getType().getAsString());
+      Diag(size->getLocStart(), diag::err_array_size_non_int, 
+           size->getType().getAsString());
       return false;
     }
     // We have a constant expression with an integer type, now make sure 
@@ -778,9 +780,10 @@
       return 0;
     }
   }
+  SourceLocation expLoc;
   // C99 6.7.2.2p2: Make sure we have an integer constant expression.
-  if (Val && !((Expr *)Val)->isIntegerConstantExpr()) {
-    Diag(IdLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
+  if (Val && !((Expr *)Val)->isIntegerConstantExpr(expLoc)) {
+    Diag(expLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
     return 0;
   }
   QualType Ty = Context.getTagDeclType(TheEnumDecl);

Modified: cfe/cfe/trunk/AST/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaStmt.cpp?rev=39454&r1=39453&r2=39454&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaStmt.cpp (original)
+++ cfe/cfe/trunk/AST/SemaStmt.cpp Wed Jul 11 11:44:36 2007
@@ -37,8 +37,9 @@
                     SourceLocation ColonLoc, StmtTy *SubStmt) {
   assert((LHSVal != 0) && "missing expression in case statement");
     
+  SourceLocation expLoc;
   // C99 6.8.4.2p3: The expression shall be an integer constant.
-  if (!((Expr *)LHSVal)->isIntegerConstantExpr())
+  if (!((Expr *)LHSVal)->isIntegerConstantExpr(expLoc))
     return Diag(CaseLoc, diag::err_case_label_not_integer_constant_expr);
 
   return new CaseStmt((Expr*)LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt);

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

==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:44:36 2007
@@ -278,10 +278,10 @@
 // The only variable size types are auto arrays within a function. Structures 
 // cannot contain a VLA member. They can have a flexible array member, however
 // the structure is still constant size (C99 6.7.2.1p16).
-bool Type::isConstantSizeType() const {
+bool Type::isConstantSizeType(SourceLocation &loc) const {
   if (const ArrayType *ary = dyn_cast<ArrayType>(CanonicalType)) {
     if (Expr *size = ary->getSize()) {
-      if (!size->isConstantExpr())
+      if (!size->isConstantExpr(loc))
         return false; // Variable Length Array
     }
   }

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39454&r1=39453&r2=39454&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:44:36 2007
@@ -31,12 +31,14 @@
 // a constant expression of type int with a value greater than zero.
 bool Sema::isConstantArrayType(ArrayType *ary, SourceLocation loc) { 
   if (Expr *size = ary->getSize()) {
-    if (!size->isConstantExpr()) {
-      Diag(loc, diag::err_typecheck_illegal_vla);
+    SourceLocation expLoc;
+    if (!size->isConstantExpr(expLoc)) {
+      Diag(expLoc, diag::err_typecheck_illegal_vla);
       return false;
     }
     if (!size->getType()->isIntegerType()) {
-      Diag(loc, diag::err_array_size_non_int, size->getType().getAsString());
+      Diag(size->getLocStart(), diag::err_array_size_non_int, 
+           size->getType().getAsString());
       return false;
     }
     // We have a constant expression with an integer type, now make sure 
@@ -778,9 +780,10 @@
       return 0;
     }
   }
+  SourceLocation expLoc;
   // C99 6.7.2.2p2: Make sure we have an integer constant expression.
-  if (Val && !((Expr *)Val)->isIntegerConstantExpr()) {
-    Diag(IdLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
+  if (Val && !((Expr *)Val)->isIntegerConstantExpr(expLoc)) {
+    Diag(expLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
     return 0;
   }
   QualType Ty = Context.getTagDeclType(TheEnumDecl);

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaStmt.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaStmt.cpp Wed Jul 11 11:44:36 2007
@@ -37,8 +37,9 @@
                     SourceLocation ColonLoc, StmtTy *SubStmt) {
   assert((LHSVal != 0) && "missing expression in case statement");
     
+  SourceLocation expLoc;
   // C99 6.8.4.2p3: The expression shall be an integer constant.
-  if (!((Expr *)LHSVal)->isIntegerConstantExpr())
+  if (!((Expr *)LHSVal)->isIntegerConstantExpr(expLoc))
     return Diag(CaseLoc, diag::err_case_label_not_integer_constant_expr);
 
   return new CaseStmt((Expr*)LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt);

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=39454&r1=39453&r2=39454&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:36 2007
@@ -63,8 +63,10 @@
   
   bool isNullPointerConstant() const;
 
-  bool isConstantExpr() const { return isConstantExpr(false); }
-  bool isIntegerConstantExpr() const { return isConstantExpr(true); }
+  bool isConstantExpr(SourceLocation &loc) const 
+    { return isConstantExpr(false, loc); }
+  bool isIntegerConstantExpr(SourceLocation &loc) const 
+    { return isConstantExpr(true, loc); }
   
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 
@@ -73,7 +75,7 @@
   }
   static bool classof(const Expr *) { return true; }
 private:
-  bool isConstantExpr(bool isIntegerConstant) const;
+  bool isConstantExpr(bool isIntegerConstant, SourceLocation &loc) const;
 };
 
 //===----------------------------------------------------------------------===//
@@ -232,9 +234,9 @@
   Expr *getSubExpr() const { return Val; }
   virtual SourceRange getSourceRange() const {
     if (isPostfix())
-      return SourceRange(getSubExpr()->getLocStart(), Loc);
+      return SourceRange(Val->getLocStart(), Loc);
     else
-      return SourceRange(Loc, getSubExpr()->getLocEnd());
+      return SourceRange(Loc, Val->getLocEnd());
   }
   bool isPostfix() const { return isPostfix(Opc); }
   bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }

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=39454&r1=39453&r2=39454&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:44:36 2007
@@ -26,6 +26,7 @@
   class RecordDecl;
   class EnumDecl;
   class Expr;
+  class SourceLocation;
   
 /// QualType - For efficiency, we don't store CVR-qualified types as nodes on
 /// their own: instead each reference to a type stores the qualifiers.  This
@@ -233,7 +234,7 @@
   bool isSignedIntegerType() const;     // C99 6.2.5p4
   bool isUnsignedIntegerType() const;   // C99 6.2.5p6
   
-  bool isConstantSizeType() const; // C99 6.7.5p3: VLA if false
+  bool isConstantSizeType(SourceLocation &) const; // C99 6.7.5p3: VLA if false
 
   /// Compatibility predicates used to check assignment expressions.
   static bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1





More information about the cfe-commits mailing list