diff --git a/interpreter.h b/interpreter.h index 8fe6d7c..bca3458 100644 --- a/interpreter.h +++ b/interpreter.h @@ -515,6 +515,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic); struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates); struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser, const char *StructName, int Size); +int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ); /* heap.c */ void HeapInit(Picoc *pc, int StackSize); diff --git a/tests/56_cross_structure.c b/tests/56_cross_structure.c new file mode 100644 index 0000000..f8f333d --- /dev/null +++ b/tests/56_cross_structure.c @@ -0,0 +1,18 @@ +#include + +struct s1; + +struct s2 +{ + struct s1 *s; +}; + +struct s1 +{ + struct s2 *s; +}; + +void main() +{ + printf("ok\n"); +} diff --git a/tests/56_cross_structure.expect b/tests/56_cross_structure.expect new file mode 100644 index 0000000..9766475 --- /dev/null +++ b/tests/56_cross_structure.expect @@ -0,0 +1 @@ +ok diff --git a/tests/Makefile b/tests/Makefile index a73199a..a160023 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -49,7 +49,8 @@ TESTS= 00_assignment.test \ 51_static.test \ 52_unnamed_enum.test \ 54_goto.test \ - 55_array_initialiser.test + 55_array_initialiser.test \ + 56_cross_structure.test %.test: %.expect %.c @echo Test: $*... diff --git a/type.c b/type.c index f7c8cb8..18fad9a 100644 --- a/type.c +++ b/type.c @@ -198,15 +198,18 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt StructIdentifier = PlatformMakeTempName(pc, TempNameBuf); } - *Typ = TypeGetMatching(pc, Parser, &Parser->pc->UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, Token != TokenLeftBrace); + *Typ = TypeGetMatching(pc, Parser, &Parser->pc->UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, TRUE); + if (Token == TokenLeftBrace && (*Typ)->Members != NULL) + ProgramFail(Parser, "data type '%t' is already defined", *Typ); Token = LexGetToken(Parser, NULL, FALSE); if (Token != TokenLeftBrace) { /* use the already defined structure */ +#if 0 if ((*Typ)->Members == NULL) ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier); - +#endif return; } @@ -527,3 +530,14 @@ void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identif TypeParseIdentPart(Parser, BasicType, Typ, Identifier); } +/* check if a type has been fully defined - otherwise it's just a forward declaration */ +int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ) +{ + if (Typ->Base == TypeArray) + return TypeIsForwardDeclared(Parser, Typ->FromType); + + if ( (Typ->Base == TypeStruct || Typ->Base == TypeUnion) && Typ->Members == NULL) + return TRUE; + + return FALSE; +} diff --git a/variable.c b/variable.c index 08659ed..d9de066 100644 --- a/variable.c +++ b/variable.c @@ -185,6 +185,10 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char * int DeclLine; int DeclColumn; + /* is the type a forward declaration? */ + if (TypeIsForwardDeclared(Parser, Typ)) + ProgramFail(Parser, "type '%t' isn't defined", Typ); + if (IsStatic) { char MangledName[LINEBUFFER_MAX];