diff --git a/expr.cpp b/expr.cpp index 4a1a16db..8fa64f91 100644 --- a/expr.cpp +++ b/expr.cpp @@ -5143,9 +5143,18 @@ MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos, exprType->GetString().c_str()); return NULL; } - - if (CastType(exprType) != NULL) + if (CastType(exprType) != NULL) { + const StructType *st = CastType(exprType); + if (st->IsDefined()) { return new StructMemberExpr(e, id, p, idpos, derefLValue); + } + else { + Error(p, "Member operator \"%s\" can't be applied to declared " + "struct \"%s\" containing an undefined struct type.", derefLValue ? "->" : ".", + exprType->GetString().c_str()); + return NULL; + } + } else if (CastType(exprType) != NULL) return new VectorMemberExpr(e, id, p, idpos, derefLValue); else if (CastType(exprType)) { @@ -8708,6 +8717,12 @@ NewExpr::TypeCheck() { "but not defined type \"%s\".", allocType->GetString().c_str()); return NULL; } + const StructType *st = CastType(allocType); + if (st != NULL && !st->IsDefined()) { + Error(pos, "Can't dynamically allocate storage for declared " + "type \"%s\" containing undefined member type.", allocType->GetString().c_str()); + return NULL; + } // Otherwise we only need to make sure that if we have an expression // giving a number of elements to allocate that it can be converted to diff --git a/type.cpp b/type.cpp index 082f8910..9e8ef131 100644 --- a/type.cpp +++ b/type.cpp @@ -1956,6 +1956,25 @@ StructType::IsConstType() const { } +bool +StructType::IsDefined() const { + for (int i = 0; i < GetElementCount(); i++) { + const Type *t = GetElementType(i); + const UndefinedStructType *ust = CastType(t); + if (ust != NULL) { + return false; + } + const StructType *st = CastType(t); + if (st != NULL) { + if (!st->IsDefined()) { + return false; + } + } + } + return true; +} + + const Type * StructType::GetBaseType() const { return this; diff --git a/type.h b/type.h index 9093af59..94648eb1 100644 --- a/type.h +++ b/type.h @@ -81,15 +81,15 @@ struct Variability { /** Enumerant that records each of the types that inherit from the Type baseclass. */ enum TypeId { - ATOMIC_TYPE, - ENUM_TYPE, - POINTER_TYPE, - ARRAY_TYPE, - VECTOR_TYPE, - STRUCT_TYPE, - UNDEFINED_STRUCT_TYPE, - REFERENCE_TYPE, - FUNCTION_TYPE + ATOMIC_TYPE, // 0 + ENUM_TYPE, // 1 + POINTER_TYPE, // 2 + ARRAY_TYPE, // 3 + VECTOR_TYPE, // 4 + STRUCT_TYPE, // 5 + UNDEFINED_STRUCT_TYPE, // 6 + REFERENCE_TYPE, // 7 + FUNCTION_TYPE // 8 }; @@ -675,6 +675,7 @@ public: bool IsIntType() const; bool IsUnsignedType() const; bool IsConstType() const; + bool IsDefined() const; const Type *GetBaseType() const; const StructType *GetAsVaryingType() const;