Bug #:
Submitted by: Reviewed by: Start work on typechecking constant expressions. - Added isIntegerConstantExpr() predicate to all exprs. - Use the predicate to implement checking for enum constant initializers. - Added diagnostic. - Added Init slot to EnumConstantDecl class/constructor. llvm-svn: 39436
This commit is contained in:
parent
35d8515be7
commit
6396921550
|
@ -728,9 +728,13 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 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());
|
||||
return 0;
|
||||
}
|
||||
QualType Ty = Context.getTagDeclType(TheEnumDecl);
|
||||
EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty);
|
||||
EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty, (Expr *)Val);
|
||||
|
||||
// Register this decl in the current scope stack.
|
||||
New->setNext(Id->getFETokenInfo<Decl>());
|
||||
|
|
|
@ -728,9 +728,13 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 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());
|
||||
return 0;
|
||||
}
|
||||
QualType Ty = Context.getTagDeclType(TheEnumDecl);
|
||||
EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty);
|
||||
EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty, (Expr *)Val);
|
||||
|
||||
// Register this decl in the current scope stack.
|
||||
New->setNext(Id->getFETokenInfo<Decl>());
|
||||
|
|
|
@ -248,10 +248,10 @@ public:
|
|||
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
|
||||
/// TagType for the X EnumDecl.
|
||||
class EnumConstantDecl : public ValueDecl {
|
||||
Expr *Init; // an integer constant expression
|
||||
public:
|
||||
// FIXME: Capture value info.
|
||||
EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
|
||||
: ValueDecl(EnumConstant, L, Id, T) {}
|
||||
EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E)
|
||||
: ValueDecl(EnumConstant, L, Id, T), Init(E) {}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
|
||||
bool isNullPointerConstant() const;
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return false; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() >= firstExprConstant &&
|
||||
|
@ -68,6 +70,9 @@ public:
|
|||
DeclRefExpr(Decl *d, QualType t) : Expr(DeclRefExprClass, t), D(d) {}
|
||||
|
||||
Decl *getDecl() const { return D; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const {
|
||||
return isa<EnumConstantDecl>(D); }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -86,6 +91,8 @@ public:
|
|||
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
|
||||
}
|
||||
intmax_t getValue() const { return Value; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return true; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -102,6 +109,8 @@ public:
|
|||
: Expr(CharacterLiteralClass, type), Value(value) {
|
||||
}
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return true; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CharacterLiteralClass;
|
||||
|
@ -115,6 +124,8 @@ public:
|
|||
FloatingLiteral(float value, QualType type) :
|
||||
Expr(FloatingLiteralClass, type), Value(value) {}
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return false; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == FloatingLiteralClass;
|
||||
|
@ -133,6 +144,8 @@ public:
|
|||
const char *getStrData() const { return StrData; }
|
||||
unsigned getByteLength() const { return ByteLength; }
|
||||
bool isWide() const { return IsWide; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return false; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -152,6 +165,9 @@ public:
|
|||
|
||||
Expr *getSubExpr() const { return Val; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const {
|
||||
return Val->isIntegerConstantExpr(); }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == ParenExprClass;
|
||||
|
@ -199,6 +215,9 @@ public:
|
|||
/// the following complex expression "s.zz[2].bb.vv".
|
||||
static bool isAddressable(Expr *e);
|
||||
|
||||
virtual bool isIntegerConstantExpr() const {
|
||||
return Val->isIntegerConstantExpr(); }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == UnaryOperatorClass;
|
||||
|
@ -223,6 +242,8 @@ public:
|
|||
bool isSizeOf() const { return isSizeof; }
|
||||
QualType getArgumentType() const { return Ty; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return true; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == SizeOfAlignOfTypeExprClass;
|
||||
|
@ -244,6 +265,8 @@ public:
|
|||
|
||||
Expr *getBase() const { return Base; }
|
||||
Expr *getIdx() { return Idx; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return false; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -281,6 +304,8 @@ public:
|
|||
/// this function call.
|
||||
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return false; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CallExprClass;
|
||||
|
@ -302,6 +327,8 @@ public:
|
|||
Expr *getBase() const { return Base; }
|
||||
FieldDecl *getMemberDecl() const { return MemberDecl; }
|
||||
bool isArrow() const { return IsArrow; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const { return false; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -325,6 +352,9 @@ public:
|
|||
|
||||
Expr *getSubExpr() { return Op; }
|
||||
|
||||
virtual bool isIntegerConstantExpr() const {
|
||||
return Op->isIntegerConstantExpr(); }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CastExprClass;
|
||||
|
@ -376,7 +406,10 @@ public:
|
|||
Opcode getOpcode() const { return Opc; }
|
||||
Expr *getLHS() { return LHS; }
|
||||
Expr *getRHS() { return RHS; }
|
||||
|
||||
|
||||
virtual bool isIntegerConstantExpr() const {
|
||||
return LHS->isIntegerConstantExpr() && RHS->isIntegerConstantExpr(); }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == BinaryOperatorClass;
|
||||
|
|
|
@ -461,6 +461,8 @@ DIAG(err_redefinition_of_enumerator, ERROR,
|
|||
"redefinition of enumerator '%s'")
|
||||
DIAG(err_duplicate_member, ERROR,
|
||||
"duplicate member '%s'")
|
||||
DIAG(err_enum_value_not_integer_constant_expr, ERROR,
|
||||
"enumerator value for '%s' is not an integer constant expression")
|
||||
|
||||
DIAG(warn_implicit_function_decl, WARNING,
|
||||
"implicit declaration of function '%s'")
|
||||
|
|
Loading…
Reference in New Issue