[cfe-commits] r39445 - 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:29 PDT 2007
Author: snaroff
Date: Wed Jul 11 11:44:29 2007
New Revision: 39445
URL: http://llvm.org/viewvc/llvm-project?rev=39445&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
- Completed Expr::isConstantExpr() and Expr::isIntegerConstantExpr().
- Completed Sema::ParseUnaryOp(), it lacked support for sizeof/alignof.
- Added Sema::CheckSizeOfAlignOfOperand(), used by ParseUnaryOp/ParseSizeOfAlignOfTypeExpr.
- Fixed a couple bugs in CheckRelationalOperands/CheckEqualityOperands (make sure extensions aren't treated as errors).
- Changed a bunch of predicates (in BinaryOperator/UnaryOperator) to member functions (the static members weren't being used).
- Added UnaryOperator::isIncrementDecrementOp/isSizeOfAlignOfOp.
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=39445&r1=39444&r2=39445&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:44:29 2007
@@ -185,17 +185,51 @@
case DeclRefExprClass:
return isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl());
case UnaryOperatorClass:
- return cast<UnaryOperator>(this)->getSubExpr()->isConstantExpr();
+ 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()->isConstantExpr();
case BinaryOperatorClass:
- return cast<BinaryOperator>(this)->getLHS()->isConstantExpr() &&
- cast<BinaryOperator>(this)->getRHS()->isConstantExpr();
+ 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()->isConstantExpr() && bop->getRHS()->isConstantExpr();
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->isConstantExpr();
- case CastExprClass:
- return cast<CastExpr>(this)->getSubExpr()->isConstantExpr();
+ 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()->isConstantExpr() ||
+ isa<FloatingLiteral>(castExpr->getSubExpr()))
+ return true;
+ return false;
case SizeOfAlignOfTypeExprClass:
- return cast<SizeOfAlignOfTypeExpr>(this)->getArgumentType()
- ->isConstantSizeType();
+ 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()->isConstantExpr() &&
+ condExpr->getLHS()->isConstantExpr() &&
+ condExpr->getRHS()->isConstantExpr();
default:
return false;
}
@@ -209,17 +243,52 @@
case DeclRefExprClass:
return isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl());
case UnaryOperatorClass:
- return cast<UnaryOperator>(this)->getSubExpr()->isIntegerConstantExpr();
+ 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:
- return cast<BinaryOperator>(this)->getLHS()->isIntegerConstantExpr() &&
- cast<BinaryOperator>(this)->getRHS()->isIntegerConstantExpr();
+ 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:
- return cast<CastExpr>(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:
- return cast<SizeOfAlignOfTypeExpr>(this)->getArgumentType()
- ->isConstantSizeType();
+ 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();
default:
return false;
}
Modified: cfe/cfe/trunk/AST/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Sema.h?rev=39445&r1=39444&r2=39445&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:44:29 2007
@@ -282,6 +282,8 @@
Expr *op, SourceLocation loc);
QualType CheckIndirectionOperand( // C99 6.5.3.2
Expr *op, SourceLocation loc);
+ QualType CheckSizeOfAlignOfOperand( // C99 6.5.3.4
+ QualType type, SourceLocation loc, bool isSizeof);
// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
// a constant expression of type int with a value greater than zero.
Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39445&r1=39444&r2=39445&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:29 2007
@@ -170,6 +170,25 @@
return e;
}
+QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType,
+ SourceLocation OpLoc, bool isSizeof) {
+ // C99 6.5.3.4p1:
+ if (isa<FunctionType>(exprType) && isSizeof)
+ // alignof(function) is allowed.
+ Diag(OpLoc, diag::ext_sizeof_function_type);
+ else if (exprType->isVoidType())
+ Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
+ else if (exprType->isIncompleteType()) {
+ std::string TypeName;
+ exprType->getAsString(TypeName);
+ Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
+ diag::err_alignof_incomplete_type, TypeName);
+ return QualType(); // error
+ }
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Context.getSizeType();
+}
+
Action::ExprResult Sema::
ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LParenLoc, TypeTy *Ty,
@@ -180,21 +199,11 @@
// Verify that this is a valid expression.
QualType ArgTy = QualType::getFromOpaquePtr(Ty);
- if (isa<FunctionType>(ArgTy) && isSizeof) {
- // alignof(function) is allowed.
- Diag(OpLoc, diag::ext_sizeof_function_type);
- return new IntegerLiteral(1, Context.IntTy);
- } else if (ArgTy->isVoidType()) {
- Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
- } else if (ArgTy->isIncompleteType()) {
- std::string TypeName;
- ArgTy->getAsString(TypeName);
- Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
- diag::err_alignof_incomplete_type, TypeName);
- return new IntegerLiteral(0, Context.IntTy);
- }
- // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, Context.getSizeType());
+ QualType resultType = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, isSizeof);
+
+ if (resultType.isNull())
+ return true;
+ return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType);
}
@@ -624,10 +633,11 @@
if (lType->isPointerType() && rType->isPointerType())
return Context.IntTy;
- if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ if (lType->isIntegerType() || rType->isIntegerType()) { // GCC extension.
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
- else
- Diag(loc, diag::err_typecheck_invalid_operands);
+ return Context.IntTy;
+ }
+ Diag(loc, diag::err_typecheck_invalid_operands);
return QualType();
}
@@ -641,10 +651,11 @@
if (lType->isPointerType() && rType->isPointerType())
return Context.IntTy;
- if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ if (lType->isIntegerType() || rType->isIntegerType()) { // GCC extension.
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
- else
- Diag(loc, diag::err_typecheck_invalid_operands);
+ return Context.IntTy;
+ }
+ Diag(loc, diag::err_typecheck_invalid_operands);
return QualType();
}
@@ -1014,8 +1025,13 @@
return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
break;
case UnaryOperator::SizeOf:
+ resultType = CheckSizeOfAlignOfOperand(((Expr *)Input)->getType(), OpLoc,
+ true);
+ break;
case UnaryOperator::AlignOf:
- assert(0 && "need to implement type checking for sizeof/alignof");
+ resultType = CheckSizeOfAlignOfOperand(((Expr *)Input)->getType(), OpLoc,
+ false);
+ break;
}
if (resultType.isNull())
return true;
Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39445&r1=39444&r2=39445&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:44:29 2007
@@ -282,6 +282,8 @@
Expr *op, SourceLocation loc);
QualType CheckIndirectionOperand( // C99 6.5.3.2
Expr *op, SourceLocation loc);
+ QualType CheckSizeOfAlignOfOperand( // C99 6.5.3.4
+ QualType type, SourceLocation loc, bool isSizeof);
// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
// a constant expression of type int with a value greater than zero.
Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39445&r1=39444&r2=39445&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:29 2007
@@ -170,6 +170,25 @@
return e;
}
+QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType,
+ SourceLocation OpLoc, bool isSizeof) {
+ // C99 6.5.3.4p1:
+ if (isa<FunctionType>(exprType) && isSizeof)
+ // alignof(function) is allowed.
+ Diag(OpLoc, diag::ext_sizeof_function_type);
+ else if (exprType->isVoidType())
+ Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
+ else if (exprType->isIncompleteType()) {
+ std::string TypeName;
+ exprType->getAsString(TypeName);
+ Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
+ diag::err_alignof_incomplete_type, TypeName);
+ return QualType(); // error
+ }
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Context.getSizeType();
+}
+
Action::ExprResult Sema::
ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LParenLoc, TypeTy *Ty,
@@ -180,21 +199,11 @@
// Verify that this is a valid expression.
QualType ArgTy = QualType::getFromOpaquePtr(Ty);
- if (isa<FunctionType>(ArgTy) && isSizeof) {
- // alignof(function) is allowed.
- Diag(OpLoc, diag::ext_sizeof_function_type);
- return new IntegerLiteral(1, Context.IntTy);
- } else if (ArgTy->isVoidType()) {
- Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
- } else if (ArgTy->isIncompleteType()) {
- std::string TypeName;
- ArgTy->getAsString(TypeName);
- Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
- diag::err_alignof_incomplete_type, TypeName);
- return new IntegerLiteral(0, Context.IntTy);
- }
- // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, Context.getSizeType());
+ QualType resultType = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, isSizeof);
+
+ if (resultType.isNull())
+ return true;
+ return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType);
}
@@ -624,10 +633,11 @@
if (lType->isPointerType() && rType->isPointerType())
return Context.IntTy;
- if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ if (lType->isIntegerType() || rType->isIntegerType()) { // GCC extension.
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
- else
- Diag(loc, diag::err_typecheck_invalid_operands);
+ return Context.IntTy;
+ }
+ Diag(loc, diag::err_typecheck_invalid_operands);
return QualType();
}
@@ -641,10 +651,11 @@
if (lType->isPointerType() && rType->isPointerType())
return Context.IntTy;
- if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ if (lType->isIntegerType() || rType->isIntegerType()) { // GCC extension.
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
- else
- Diag(loc, diag::err_typecheck_invalid_operands);
+ return Context.IntTy;
+ }
+ Diag(loc, diag::err_typecheck_invalid_operands);
return QualType();
}
@@ -1014,8 +1025,13 @@
return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
break;
case UnaryOperator::SizeOf:
+ resultType = CheckSizeOfAlignOfOperand(((Expr *)Input)->getType(), OpLoc,
+ true);
+ break;
case UnaryOperator::AlignOf:
- assert(0 && "need to implement type checking for sizeof/alignof");
+ resultType = CheckSizeOfAlignOfOperand(((Expr *)Input)->getType(), OpLoc,
+ false);
+ break;
}
if (resultType.isNull())
return true;
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=39445&r1=39444&r2=39445&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:29 2007
@@ -203,6 +203,8 @@
Expr *getSubExpr() const { return Val; }
bool isPostfix() const { return isPostfix(Opc); }
+ bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
+ bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; }
/// getDecl - a recursive routine that derives the base decl for an
/// expression. For example, it will return the declaration for "s" from
@@ -374,14 +376,14 @@
static const char *getOpcodeStr(Opcode Op);
/// predicates to categorize the respective opcodes.
- static bool isMultiplicativeOp(Opcode Op) { return Op >= Mul && Op <= Rem; }
- static bool isAdditiveOp(Opcode Op) { return Op == Add || Op == Sub; }
- static bool isShiftOp(Opcode Op) { return Op == Shl || Op == Shr; }
- static bool isBitwiseOp(Opcode Op) { return Op >= And && Op <= Or; }
- static bool isRelationalOp(Opcode Op) { return Op >= LT && Op <= GE; }
- static bool isEqualityOp(Opcode Op) { return Op == EQ || Op == NE; }
- static bool isLogicalOp(Opcode Op) { return Op == LAnd || Op == LOr; }
- static bool isAssignmentOp(Opcode Op) { return Op >= Assign && Op<=OrAssign; }
+ bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; }
+ bool isAdditiveOp() const { return Opc == Add || Opc == Sub; }
+ bool isShiftOp() const { return Opc == Shl || Opc == Shr; }
+ bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }
+ bool isRelationalOp() const { return Opc >= LT && Opc <= GE; }
+ bool isEqualityOp() const { return Opc == EQ || Opc == NE; }
+ bool isLogicalOp() const { return Opc == LAnd || Opc == LOr; }
+ bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; }
Opcode getOpcode() const { return Opc; }
Expr *getLHS() const { return LHS; }
@@ -406,9 +408,9 @@
ConditionalOperator(Expr *cond, Expr *lhs, Expr *rhs, QualType t)
: Expr(ConditionalOperatorClass, t), Cond(cond), LHS(lhs), RHS(rhs) {}
- Expr *getCond() { return Cond; }
- Expr *getLHS() { return LHS; }
- Expr *getRHS() { return RHS; }
+ Expr *getCond() const { return Cond; }
+ Expr *getLHS() const { return LHS; }
+ Expr *getRHS() const { return RHS; }
virtual void visit(StmtVisitor &Visitor);
static bool classof(const Stmt *T) {
More information about the cfe-commits
mailing list