F diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignorecmake_install.cmakeMakefilebuild+ tagsF diff --git a/.term.swp b/.term.swp new file mode 100644B Binary files /dev/null and b/.term.swp differF diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txtsemantics/scope.csemantics/semantics.csemantics/gcc_error.c+ semantics/linkage.ccode_generation/js/transpile_to_js.c)F diff --git a/code_generation/js/transpile_to_js.c b/code_generation/js/transpile_to_js.c --- a/code_generation/js/transpile_to_js.c +++ b/code_generation/js/transpile_to_js.c{fprintf(out,"\n/*EXTERNS START*/\n");Map_Map_Extended(- &((struct Normal_Scope*)program->externs)->ordinary+ &program->external_linkage->ids,_to_js_print_externs,command_arguments);fprintf(out,"\n/*EXTERNS END*/\n");{Map_Map_Extended(- &((struct Normal_Scope*)translation_unit->scope)->ordinary+ &((struct Normal_Scope*)translation_unit->file_scope)->ordinary,_to_js_print_statics,command_arguments);}break;case ST_OBJECT_DECLARATION:to_js_print_object_declaration_tree(out,((struct AST_Object_Declaration*)tree),program);- if(((struct AST_Object_Declaration*)tree)->initializer!=NULL)+ if(((struct AST_Object_Declaration*)tree)->object->initializer!=NULL){fprintf(out,"=");- to_js_print_ast(out,((struct AST_Object_Declaration*)tree)->initializer,program);+ to_js_print_ast(out,((struct AST_Object_Declaration*)tree)->object->initializer,program);}break;case ST_FUNCTION_DECLARATION:}void to_js_print_object_declaration_tree(FILE* out,struct AST_Object_Declaration *object_declaration,struct Program *program){- if(object_declaration->object->object->storage_class!=SC_EXTERN)+ if(object_declaration->object->object->storage_class!=SCS_EXTERN){fprintf(out,"let ");print_token(out,object_declaration->object->id);cache_type=(struct Type_Function*)function_definition->function->type;- if((struct Type_Function*)function_definition->function->storage_class==SC_EXTERN)+ if((struct Type_Function*)function_definition->function->linkage==LINKAGE_EXTERNAL){// fprintf(out,"var ");print_token(out,function_definition->function->id);F diff --git a/lex/preprocessing.c b/lex/preprocessing.c --- a/lex/preprocessing.c +++ b/lex/preprocessing.cstruct token *hold_token;int result;- null_scope=get_normal_scope(NULL,EXTERN_SCOPE);+ null_scope=get_normal_scope(NULL,FILE_SCOPE);tokens=lex_line(src,translation_data,1);F diff --git a/misc/map.c b/misc/map.c --- a/misc/map.c +++ b/misc/map.ctree->is_final=1;return NULL;}+ /*requires that the map has no loops. does not free the root node*/+ /*TODO*/+ void Map_Delete_Map(struct Map *tree)+ {++ }#endif //#ifndef GMAPF diff --git a/misc/map.h b/misc/map.h --- a/misc/map.h +++ b/misc/map.hvoid Map_Remove(Map *tree, void *str,size_t size);void Map_Map(Map *tree,void (*map)(void*));void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data);+void Map_Destroy(Map *tree);+ void Map_Delete_Map(struct Map *tree);struct Condensed_Map* Map_Condense(Map* tree);struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id);F diff --git a/misc/print.c b/misc/print.c --- a/misc/print.c +++ b/misc/print.c}ret=0;- hold_translation_data=get_translation_data(NULL);+ hold_translation_data=get_translation_data(NULL,get_linkage(),get_linkage());do{base_file=get_source_file(*base_source_names,this_directory);case DT_Label:fprintf(out,"label ");return;case DT_Object:- switch(((struct Denoted_Object*)denoted)->object->storage_class)+ switch(((struct Denoted_Object*)denoted)->linkage){- case SC_EXTERN:- fprintf(out,"extern ");+ case LINKAGE_INTERNAL:+ fprintf(out,"internally linked ");+ break;+ case LINKAGE_EXTERNAL:+ fprintf(out,"externally linked ");break;- case SC_STATIC:- fprintf(out,"static ");+ case LINKAGE_NONE:break;+ default:+ assert(0);}fprintf(out,"denoted object ");print_token(out,((struct Denoted_Object*)denoted)->id);+ switch(((struct Denoted_Object*)denoted)->object->storage_class)+ {+ case SCS_NONE:+ fprintf(out," with automatic storage duration");+ break;+ case SCS_STATIC:+ fprintf(out," static storage duration");+ break;+ assert(0);+ }fprintf(out," is a ");print_type(out,((struct Denoted_Object*)denoted)->object->type,1);print_type(out,((struct Denoted_Typedef*)denoted)->type,0);return;case DT_Function:- switch(((struct Denoted_Function*)denoted)->storage_class)+ print_token(out,((struct Denoted_Function*)denoted)->id);+ fprintf(out," is ");+ switch(((struct Denoted_Function*)denoted)->linkage){- case SC_EXTERN:- fprintf(out,"extern ");+ case LINKAGE_EXTERNAL:+ fprintf(out," an externally linked ");break;- case SC_STATIC:- fprintf(out,"static ");+ case LINKAGE_INTERNAL:+ fprintf(out," an internally linked ");break;+ default:+ assert(0);}- print_token(out,((struct Denoted_Function*)denoted)->id);- fprintf(out," is ");print_type(out,((struct Denoted_Function*)denoted)->type,1);return;case DT_Enum:case ST_OBJECT_DECLARATION:print_denoted(out,(struct Denoted*)((struct AST_Object_Declaration*)tree)->object);fprintf(out,"=");- print_ast(out,((struct AST_Object_Declaration*)tree)->initializer);+ print_ast(out,((struct AST_Object_Declaration*)tree)->object->initializer);break;case ST_TYPE_DEFINITION:print_denoted(out,(struct Denoted*)((struct AST_Type_Definition*)tree)->definition);void print_function_definition(FILE *out,struct Denoted_Function *function){print_token(out,function->id);- fprintf(out," is a ");+ fprintf(out," is");+ switch(function->linkage)+ {+ case LINKAGE_EXTERNAL:+ fprintf(out," an externally linked ");+ break;+ case LINKAGE_INTERNAL:+ fprintf(out," an internally linked ");+ break;+ default:+ assert(0);+ }print_type(out,function->type,1);print_ast(out,(struct AST*)function->body);}F diff --git a/parse/parse_declaration.c b/parse/parse_declaration.c --- a/parse/parse_declaration.c +++ b/parse/parse_declaration.cstruct Denoted *hold;prototype=parse_declaration_specifiers(translation_data,scope);- while(1)+ while(!get_and_check(translation_data,KW_SEMI_COLUMN)){- if(get_and_check(translation_data,KW_SEMI_COLUMN))- goto finish;-hold=parse_declarator(translation_data,scope,prototype);--- if(hold->denotation==DT_Function && parse_function_definitions==1)+ if(hold->denotation==DT_Function){- if(get_and_check(translation_data,KW_OPEN_CURLY))+ /*check if this is a function definition*/+ if(parse_function_definitions && get_and_check(translation_data,KW_OPEN_CURLY)){- ((struct Denoted_Function*)hold)->body=(struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,scope);-+ ((struct Denoted_Function*)hold) ->body=+ (struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,scope);Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold));Scope_Push(scope,hold,translation_data);- goto finish;+ break;}-+ /*this is a function declaration*/Queue_Push(where_to_push,get_function_declaration_tree(scope,(struct Denoted_Function*)hold));}else if(hold->denotation==DT_Typedef){Queue_Push(where_to_push,get_type_definition_tree((struct Denoted_Typedef*)hold));}else if(hold->denotation==DT_Object){- struct AST_Object_Declaration *od;- od=get_object_declaration_tree((struct Denoted_Object*)hold,NULL);- Queue_Push(where_to_push,od);+ Queue_Push(where_to_push,get_object_declaration_tree((struct Denoted_Object*)hold));if(get_and_check(translation_data,KW_EQ))- {- od->initializer=parse_initializer(translation_data,scope,od->object);- }+ ((struct Denoted_Object*)hold)->initializer=parse_initializer(translation_data,scope,(struct Denoted_Object*)hold);}else{/*TODO error*/Queue_Push(where_to_push,get_declaration_error_tree(hold));push_translation_error("declaration expected",translation_data);+/*search for end of erronous declaration*/- while(!get_and_check(translation_data,KW_SEMI_COLUMN))- {- free(Queue_Pop(translation_data->tokens));- }- goto finish;+ break;}Scope_Push(scope,hold,translation_data);parse_function_definitions=0;- if(!get_and_check(translation_data,KW_COMMA))+ if(!get_and_check(translation_data,KW_COMMA) && !check(translation_data,KW_SEMI_COLUMN,0)){- if(get_and_check(translation_data,KW_SEMI_COLUMN))- {- goto finish;- }else- {- /*TODO error*/- Queue_Push(where_to_push,get_declaration_error_tree(NULL));- push_translation_error("semi column expected",translation_data);- goto finish;- }+ /*TODO error*/+ Queue_Push(where_to_push,get_declaration_error_tree(NULL));+ push_translation_error("semi column expected",translation_data);+ break;}}- finish:free(prototype);}if(!parse_storage_class)goto exit;chomp(translation_data);- if(ret->storage_class!=SC_NONE)+ if(ret->storage_class!=SCS_NONE){switch(ret->storage_class){- case SC_EXTERN:+ case SCS_EXTERN:push_translation_error("only one extern allowed >:|",translation_data);break;- case SC_TYPEDEF:- case SC_STATIC:+ case SCS_TYPEDEF:+ case SCS_STATIC:push_translation_error("only one storage class allowed >:|",translation_data);break;default:return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);}- ret->storage_class=SC_EXTERN;+ ret->storage_class=SCS_EXTERN;break;case KW_STATIC:if(!parse_storage_class)goto exit;chomp(translation_data);- if(ret->storage_class!=SC_NONE)+ if(ret->storage_class!=SCS_NONE){switch(ret->storage_class){- case SC_STATIC:+ case SCS_STATIC:push_translation_error("only one static allowed >:|",translation_data);break;- case SC_EXTERN:- case SC_TYPEDEF:+ case SCS_EXTERN:+ case SCS_TYPEDEF:push_translation_error("only one storage class allowed >:|",translation_data);break;default:}return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);}- ret->storage_class=SC_STATIC;+ ret->storage_class=SCS_STATIC;break;case KW_TYPEDEF:if(!parse_storage_class)goto exit;chomp(translation_data);- if(ret->storage_class!=SC_NONE)+ if(ret->storage_class!=SCS_NONE){switch(ret->storage_class){- case SC_STATIC:- case SC_EXTERN:- case SC_TYPEDEF:+ case SCS_STATIC:+ case SCS_EXTERN:+ case SCS_TYPEDEF:push_translation_error("only one storage class allowed >:|",translation_data);break;default:}return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);}- ret->storage_class=SC_TYPEDEF;+ ret->storage_class=SCS_TYPEDEF;break;case KW_STRUCT:ret->specifier=TS_STRUCT;{base->is_finished=1;while(parse_struct_declaration(translation_data,(struct Scope*)base->inner_namespace,base->members))- {-if(get_and_check(translation_data,KW_CLOSE_CURLY))- {return ;- }- }-/*TODO error*/push_translation_error("expected closing curly bracket from struct declaration",translation_data);- return ;--- }else- {- /*if this isnt a struct definition return an incomplete struct-union*/- return ;-+ return;}-}/*struct-declaration:struct Denotation_Prototype *prototype;struct Denoted *hold;prototype=parse_specifier_qualifier_list(translation_data,struct_scope);- while(1)+ while(!get_and_check(translation_data,KW_SEMI_COLUMN)){hold=parse_struct_declarator(translation_data,struct_scope,prototype);if(hold!=NULL && hold->denotation!=DT_Error)}else{free(prototype);- /*todo error*/push_translation_error("there is a problem with the declarator",translation_data);return 0;}- if(!get_and_check(translation_data,KW_COMMA))++ if(!get_and_check(translation_data,KW_COMMA) && !check(translation_data,KW_SEMI_COLUMN,0)){- if(get_and_check(translation_data,KW_SEMI_COLUMN))- {- break;- }else- {- free(prototype);- push_translation_error("semi column expected in struct declaration",translation_data);- /*todo error*/- return 0;- }+ free(prototype);+ push_translation_error("semi column expected in struct declaration",translation_data);+ return 0;}}free(prototype);if(get_and_check(translation_data,KW_COLUMN)){/*unnamed bitfields are possible*/- hold=get_denoted_object(NULL,SC_NONE,prototype->type);+ hold=get_denoted_object(NULL,SCS_NONE,prototype->type,NULL);}else{hold=parse_declarator(translation_data,scope,prototype);if(get_and_check(translation_data,KW_COLUMN)){- /*TODO move error detection in get_type_bitfield*/+ /*TODO move error detection in get_type_bitfield*/((struct Denoted_Object*)hold)->object->type=(struct Type*)get_type_bitfield(prototype->type,parse_expression(translation_data,scope));}}*/struct AST* parse_initializer(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Object *base){+ /*TODO add compound initialiser*/return parse_assignment_expression(translation_data,scope);}F diff --git a/parse/parse_declaration.h b/parse/parse_declaration.h --- a/parse/parse_declaration.h +++ b/parse/parse_declaration.h#include <map.h>#include <lexer.h>#include <assert.h>+ #include <linkage.h>F diff --git a/parse/parse_statement.c b/parse/parse_statement.c --- a/parse/parse_statement.c +++ b/parse/parse_statement.c{struct AST_Compound_Statement *hold;hold=get_compound_statement_tree(scope);- while(!get_and_check(translation_data,KW_CLOSE_CURLY))+ while(!get_and_check(translation_data,KW_CLOSE_CURLY) && !has_no_tokens(translation_data)){if(is_type(translation_data,hold->scope)){void chase_next_semicolumn(struct Translation_Data *translation_data){/*chase ; and start parsing next declaration*/- while(!get_and_check(translation_data,KW_SEMI_COLUMN) &&+ while(!get_and_check(translation_data,KW_SEMI_COLUMN) && !check(translation_data,KW_CLOSE_CURLY,0) &&translation_data->tokens->size>0){chomp(translation_data);F diff --git a/parse/parse_translation_unit.c b/parse/parse_translation_unit.c --- a/parse/parse_translation_unit.c +++ b/parse/parse_translation_unit.cdeclaration [ translation-unit ]function-definition [ translation-unit ]*/- struct AST* parse_translation_unit(struct Translation_Data *translation_data,struct Scope *externs)+ struct AST* parse_translation_unit(struct Translation_Data *translation_data){+ size_t loop_preventer;struct AST_Translation_Unit *hold;- hold=get_translation_unit_tree(externs);- while(translation_data->tokens->size>0)+ hold=get_translation_unit_tree();++ loop_preventer=0;+ while(translation_data->tokens->size>0 && loop_preventer!=translation_data->tokens->size){- if(is_type(translation_data,hold->scope) || kw_get(translation_data)==KW_ID)+ loop_preventer=translation_data->tokens->size;++ if(is_type(translation_data,hold->file_scope) || kw_get(translation_data)==KW_ID){- parse_declaration(translation_data,hold->scope,&hold->components,1);+ parse_declaration(translation_data,hold->file_scope,&hold->components,1);if(has_new_errors(translation_data)){chase_next_semicolumn(translation_data);F diff --git a/parse/parse_translation_unit.h b/parse/parse_translation_unit.h --- a/parse/parse_translation_unit.h +++ b/parse/parse_translation_unit.h#include <parse_statement.h>#include <error.h>- struct AST* parse_translation_unit(struct Translation_Data *translation_data,struct Scope *externs);+ struct AST* parse_translation_unit(struct Translation_Data *translation_data);#endifF diff --git a/semantics/ast.c b/semantics/ast.c --- a/semantics/ast.c +++ b/semantics/ast.creturn ret;}- struct AST_Object_Declaration* get_object_declaration_tree(struct Denoted_Object *object,struct AST *initializer)+ struct AST_Object_Declaration* get_object_declaration_tree(struct Denoted_Object *object){struct AST_Object_Declaration *ret;ret=malloc(sizeof(struct AST_Object_Declaration));ret->type=ST_OBJECT_DECLARATION;ret->object=object;- ret->initializer=initializer;-return ret;}ret->function=function;return ret;}- struct AST_Translation_Unit* get_translation_unit_tree(struct Scope* parent_scope)+ struct AST_Translation_Unit* get_translation_unit_tree(){struct AST_Translation_Unit *ret;ret=malloc(sizeof(struct AST_Translation_Unit));- ret->type=TRANSLATION_UNIT;++ ret->internal_linkage=get_linkage();+ ret->file_scope=get_normal_scope(NULL,FILE_SCOPE);+++Queue_Init(&ret->components);- ret->scope=get_normal_scope(parent_scope,FILE_SCOPE);+ Queue_Init(&ret->static_objects);+ ret->type=TRANSLATION_UNIT;+return ret;}}void delete_ast_object_declaration(struct AST_Object_Declaration *object_declaration){- if(object_declaration->initializer!=NULL)- delete_ast(object_declaration->initializer);free(object_declaration);}{while(translation_unit->components.size>0)delete_ast((struct AST*)Queue_Pop(&translation_unit->components));- if(translation_unit->scope!=NULL)- delete_scope(translation_unit->scope);+ if(translation_unit->file_scope!=NULL)+ delete_scope(translation_unit->file_scope);+ delete_linkage(translation_unit->internal_linkage);free(translation_unit);}F diff --git a/semantics/ast.h b/semantics/ast.h --- a/semantics/ast.h +++ b/semantics/ast.h#include <scope.h>#include <parse_declaration.h>#include <denoted.h>+ #include <linkage.h>{enum AST_Type type;struct Denoted_Object *object;- struct AST *initializer;};struct AST_Function_Definition{{enum AST_Type type;struct Queue components;- struct Scope *scope;++ struct Scope *file_scope;+ struct Linkage *internal_linkage;+ struct Queue static_objects;};struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope);struct AST* get_nop_tree();struct AST_Type_Definition* get_type_definition_tree(struct Denoted_Typedef *definition);- struct AST_Object_Declaration* get_object_declaration_tree(struct Denoted_Object *object,struct AST *initializer);+ struct AST_Object_Declaration* get_object_declaration_tree(struct Denoted_Object *object);struct AST_Function_Declaration* get_function_declaration_tree(struct Scope *scope,struct Denoted_Function *function);struct AST_Function_Definition* get_function_definition_tree(struct Scope *scope,struct Denoted_Function *function);- struct AST_Translation_Unit* get_translation_unit_tree(struct Scope* parent_scope);+ struct AST_Translation_Unit* get_translation_unit_tree();F diff --git a/semantics/denoted.c b/semantics/denoted.c --- a/semantics/denoted.c +++ b/semantics/denoted.cstruct Denoted_Function *ret;ret=malloc(sizeof(struct Denoted_Function));ret->denotation=DT_Function;+ ret->linkage=LINKAGE_NONE;ret->id=id;ret->type=return_type;ret->function_specifier=fs;ret->body=NULL;- ret->storage_class=SC_NONE;return (struct Denoted*)ret;}- struct Denoted* get_denoted_object(struct token *id, enum Storage_Class sc,struct Type *type)+ struct Denoted* get_denoted_object(struct token *id, enum Storage_Class_Specifier sc,struct Type *type,struct AST *initializer){struct Denoted_Object *ret;ret=malloc(sizeof(struct Denoted_Object));ret->denotation=DT_Object;+ ret->linkage=LINKAGE_NONE;ret->id=id;ret->object=malloc(sizeof(struct Object));ret->object->location=NULL;ret->object->storage_class=sc;+ ret->initializer=initializer;+return (struct Denoted*)ret;}ret->denotation=DT_Prototype;ret->type=NULL;ret->node=types;- ret->storage_class=SC_NONE;+ ret->storage_class=SCS_NONE;ret->specifier=TS_NONE;ret->constraint=TC_NONE;ret->sign=TSIGN_NONE;if(base->type->specifier==TS_FUNC){if(base->id==NULL && !allow_abstract)- {+ {return get_denoted_error(get_denoted_function(NULL,((struct Type_Function*)base->type)->return_type,prototype->function_specifier));}else{- return get_denoted_function(base->id,base->type,prototype->function_specifier);+ struct Denoted_Function *hold_denoted_function;+ hold_denoted_function=(struct Denoted_Function*)get_denoted_function(base->id,base->type,prototype->function_specifier);+ /*hack*/+ switch(prototype->storage_class)+ {+ case SCS_NONE:+ hold_denoted_function->linkage=LINKAGE_NONE;+ break;+ case SCS_EXTERN:+ hold_denoted_function->linkage=LINKAGE_EXTERNAL;+ break;+ case SCS_STATIC:+ hold_denoted_function->linkage=LINKAGE_INTERNAL;+ break;++ }+ return (struct Denoted*)hold_denoted_function;}- }else if(prototype->storage_class==SC_TYPEDEF)+ }else if(prototype->storage_class==SCS_TYPEDEF){if(base->id==NULL && !allow_abstract){{if(base->id==NULL && !allow_abstract){- return get_denoted_error(get_denoted_object(base->id,prototype->storage_class,base->type));+ return get_denoted_error(get_denoted_object(base->id,prototype->storage_class,base->type,NULL));}else{- return get_denoted_object(base->id,prototype->storage_class,base->type);+ return get_denoted_object(base->id,prototype->storage_class,base->type,NULL);}}}free(object->id);if(object->object!=NULL)delete_object(object->object);+ if(object->initializer!=NULL)+ delete_ast(object->initializer);free(object);}void delete_denoted_typedef(struct Denoted_Typedef *typedefed){delete_denoted(denoted);}-+ void delete_denoted_with_no_linkage_wrapper(void *denoted)+ {+ if( ((struct Denoted*)denoted)->denotation == DT_Object )+ {+ if( AS_DENOTED_OBJECT_PTR(denoted)->linkage!=LINKAGE_NONE )+ return;+ }+ delete_denoted(denoted);+ }F diff --git a/semantics/denoted.h b/semantics/denoted.h --- a/semantics/denoted.h +++ b/semantics/denoted.h#include <type.h>#include <scope.h>#include <semantics.h>+ #include <linkage.h>enum Denotation_Type;enum Function_Specifier;- enum Storage_Class;+ enum Storage_Class_Specifier;struct Denotedstruct Denoted_Function{enum Denotation_Type denotation;+ enum Linkage_Type linkage;struct token *id;struct Type *type;enum Function_Specifier function_specifier;- enum Storage_Class storage_class;-struct AST_Compound_Statement *body;};struct Denoted_Object{enum Denotation_Type denotation;- struct token *id;+ enum Linkage_Type linkage;+ struct token *id;struct Object *object;+ struct AST *initializer;};struct Denoted_Typedef{struct Map *node;- enum Storage_Class storage_class;+ enum Storage_Class_Specifier storage_class;enum Type_Specifier specifier;enum Type_Constraint constraint;enum Type_Signedness sign;{struct Type *type;struct Location *location;- enum Storage_Class storage_class;+ enum Storage_Class_Specifier storage_class;};-+ struct Static_Object;+ struct Automatic_Object;struct Denoted_Base* get_denoted_base(struct Denotation_Prototype *prototype);struct Denoted* get_denoted_error(struct Denoted *error);struct Denoted* get_denoted_function(struct token *id,struct Type *return_type,enum Function_Specifier fs);- struct Denoted* get_denoted_object(struct token *id, enum Storage_Class sc,struct Type *type);+ struct Denoted* get_denoted_object(struct token *id, enum Storage_Class_Specifier sc,struct Type *type,struct AST *initializer);struct Denoted* get_denoted_typedef(struct Denoted_Base *base);struct Denoted* get_denoted_enum_const_expr(struct token *id,struct Enum *parent,struct AST* expression);struct Denoted* get_denoted_enum_const_num(struct token *id,struct Enum *parent,int value);void delete_denoted_wrapper(void *denoted);+ void delete_denoted_with_no_linkage_wrapper(void *denoted);void delete_denoted(struct Denoted *denoted);void delete_denoted_error(struct Denoted_Error *error);void delete_denoted_function(struct Denoted_Function *function);void delete_denoted_base(struct Denoted_Base *base);- enum Storage_Class get_denoted_function_storage_class(struct Denoted_Function *function);+ enum Storage_Class_Specifier get_denoted_function_storage_class(struct Denoted_Function *function);#endifF diff --git a/semantics/denoted.hh b/semantics/denoted.hh --- a/semantics/denoted.hh +++ b/semantics/denoted.hh#define GCC_DENOTED_HH GCC_DENOTED_HH#define AS_DENOTED_OBJECT_PTR(x) ((struct Denoted_Object*)x)- #define AS_DENOTED_FUNCTION(x) ((struct Denoted_Object*)x)- #define AS_DENOTED_TYPEDEF(x) ((struct Denoted_Object*)x)- #define AS_DENOTED_ENUM(x) ((struct Denoted_Object*)x)- #define AS_DENOTED_ENUM_CONST(x) ((struct Denoted_Object*)x)- #define AS_DENOTED_STRUCT_UNION(x) ((struct denoted_object*)x)+ #define AS_DENOTED_FUNCTION(x) ((struct Denoted_Function*)x)+ #define AS_DENOTED_TYPEDEF(x) ((struct Denoted_Typedef*)x)+ #define AS_DENOTED_ENUM(x) ((struct Denoted_Enum*)x)+ #define AS_DENOTED_ENUM_CONST(x) ((struct Denoted_Enum_Const*)x)+ #define AS_DENOTED_STRUCT_UNION(x) ((struct Denoted_Struct_Union*)x)enum Denotation_Type{FS_Inline,FS_None};- enum Storage_Class+ enum Storage_Class_Specifier{- SC_EXTERN,- SC_STATIC,- SC_TYPEDEF,- SC_NONE+ SCS_EXTERN,+ SCS_STATIC,+ SCS_TYPEDEF,+ SCS_REGISTER,+ SCS_NONE+};struct Denoted;F diff --git a/semantics/linkage.c b/semantics/linkage.c new file mode 100644 --- /dev/null +++ b/semantics/linkage.c+ #ifndef GCC_LINKAGE_C+ #define GCC_LINKAGE_C GCC_LINKAGE_C+ #include<linkage.h>++++++ struct Linkage* get_linkage()+ {+ struct Linkage *ret;+ ret=malloc(sizeof(struct Linkage));+ Map_Init(&ret->ids);++ return ret;+ }++ /*denoted things are deleted here and left alone when deleting scopes*/+ void delete_linkage(struct Linkage *linkage)+ {+ Map_Map(&linkage->ids,delete_denoted_wrapper);+ Map_Destroy(&linkage->ids);+ free(linkage);+ }+++ /*TODO optimise when you know what should happen here*/++ void account_for_upper_linkage_on_object(struct Scope *scope,struct Translation_Data *translation_data,struct Denoted_Object *denoted_object)+ {+ struct Denoted_Object *hold_object;+ hold_object=check_ordinary(scope,denoted_object->id);+ if(hold_object!=NULL && hold_object->denotation==DT_Object && types_are_identical(denoted_object->object->type,hold_object->object->type))+ {+ if(hold_object->linkage!=LINKAGE_NONE)+ {+ denoted_object->linkage=hold_object->linkage;+ denoted_object->object->storage_class=SCS_STATIC;+ }else+ {+ denoted_object->linkage=LINKAGE_EXTERNAL;+ denoted_object->object->storage_class=SCS_STATIC;+ }+ }else+ {+ denoted_object->linkage=LINKAGE_EXTERNAL;+ denoted_object->object->storage_class=SCS_STATIC;+ }+ }+ void account_for_upper_linkage_on_function(struct Scope *scope,struct Translation_Data *translation_data,struct Denoted_Function *denoted_function)+ {+ struct Denoted_Function *hold_function;+ hold_function=check_ordinary(scope,denoted_function->id);+ if(hold_function!=NULL)+ {+ if(hold_function->denotation==DT_Function && types_are_identical(denoted_function->type,hold_function->type))+ {+ denoted_function->linkage=( (hold_function->linkage==LINKAGE_NONE) ? LINKAGE_EXTERNAL : hold_function->linkage);+ }else+ {+ push_translation_error("linking mismatching things",translation_data);+ return;+ }+ }else+ {+ denoted_function->linkage=LINKAGE_EXTERNAL;+ }+ }+ void resolve_object_linkage(struct Scope *scope,struct Translation_Data *translation_data,struct Denoted_Object *denoted_object)+ {+ if(scope->type==FILE_SCOPE)+ {+ if(denoted_object->object->storage_class==SCS_NONE || denoted_object->object->storage_class==SCS_EXTERN)+ {+ denoted_object->linkage=LINKAGE_EXTERNAL;+ denoted_object->object->storage_class=SCS_STATIC;+ account_for_upper_linkage_on_object(scope,translation_data,denoted_object);++ }else if(denoted_object->object->storage_class==SCS_STATIC)+ {+ denoted_object->linkage=LINKAGE_INTERNAL;+ denoted_object->object->storage_class=SCS_STATIC;+ }else+ {+ assert(0);+ }+ }else if(scope->type==FUNCTION_PROTOTYPE_SCOPE)+ {+ denoted_object->linkage=LINKAGE_NONE;+ denoted_object->object->storage_class=SCS_NONE;+ if(denoted_object->object->storage_class!=SCS_NONE && denoted_object->object->storage_class!=SCS_REGISTER)+ {+ push_translation_error("storage class specifier other than register in function prototype scope",translation_data);+ return ;+ }+ }else if(scope->type==BLOCK_SCOPE)+ {+ denoted_object->linkage=LINKAGE_NONE;+ /*here comes the spooky part*/+ if(denoted_object->object->storage_class==SCS_EXTERN)+ account_for_upper_linkage_on_object(scope,translation_data,denoted_object);+ }else+ {+ assert(0);+ }++ /*check if id is linked oppositely*/+ if(denoted_object->linkage==LINKAGE_EXTERNAL &&+ Map_Check(&translation_data->internal_linkage->ids,denoted_object->id->data,denoted_object->id->data_size)!=NULL)+ {+ push_translation_error("linking id both internally and externally",translation_data);+ }else if(denoted_object->linkage==LINKAGE_INTERNAL &&+ Map_Check(&translation_data->external_linkage->ids,denoted_object->id->data,denoted_object->id->data_size)!=NULL)+ {+ push_translation_error("linking id both internally and externally",translation_data);+ }+ }+ void resolve_function_linkage(struct Scope *scope,struct Translation_Data *translation_data,struct Denoted_Function *denoted_function)+ {+ if(scope->type==BLOCK_SCOPE)+ {+ if(denoted_function->linkage==LINKAGE_INTERNAL)+ {+ push_translation_error("static storage class specifier on function declaration in block scope",translation_data);+ return;+ }else+ {+ denoted_function->linkage=LINKAGE_EXTERNAL;+ account_for_upper_linkage_on_function(scope,translation_data,denoted_function);++ }+ }else if(scope->type==FILE_SCOPE)+ {+ if(denoted_function->linkage==LINKAGE_NONE)+ denoted_function->linkage=LINKAGE_EXTERNAL;+ /*falltrough*/++ if(denoted_function->linkage==LINKAGE_EXTERNAL)+ account_for_upper_linkage_on_function(scope,translation_data,denoted_function);++ }else+ {+ assert(0);+ }++ /*check if id is linked oppositely*/+ if(denoted_function->linkage==LINKAGE_EXTERNAL &&+ Map_Check(&translation_data->internal_linkage->ids,denoted_function->id->data,denoted_function->id->data_size)!=NULL)+ {+ push_translation_error("linking id both internally and externally",translation_data);+ }else if(denoted_function->linkage==LINKAGE_INTERNAL &&+ Map_Check(&translation_data->external_linkage->ids,denoted_function->id->data,denoted_function->id->data_size)!=NULL)+ {+ push_translation_error("linking id both internally and externally",translation_data);+ }++ }++ #endifF diff --git a/semantics/linkage.h b/semantics/linkage.h new file mode 100644 --- /dev/null +++ b/semantics/linkage.h+ #ifndef GCC_LINKAGE_H+ #define GCC_LINKAGE_H GCC_LINKAGE_H+ #include <linkage.hh>+ #include <map.h>+ #include <denoted.h>++ enum Linkage_Type;++ /*this can be external or internal depending on which structure it is located*/+ struct Linkage+ {+ struct Map ids;+ };+++ struct Linkage* get_linkage();+ void delete_linkage();++ /*these don't push the object into the linkage map*/+ void resolve_object_linkage(struct Scope *scope,struct Translation_Data *translation_data,struct Denoted_Object *denoted_object);+ void resolve_function_linkage(struct Scope *scope,struct Translation_Data *translation_data,struct Denoted_Function *denoted_function);+ #endifF diff --git a/semantics/linkage.hh b/semantics/linkage.hh new file mode 100644 --- /dev/null +++ b/semantics/linkage.hh+ #ifndef GCC_LINKAGE_HH+ #define GCC_LINKAGE_HH GCC_LINKAGE_HH+++ enum Linkage_Type+ {+ LINKAGE_EXTERNAL,+ LINKAGE_INTERNAL,+ LINKAGE_NONE+ };++ struct Linkage;++++ #endifF diff --git a/semantics/program.c b/semantics/program.c --- a/semantics/program.c +++ b/semantics/program.cret->source_files=malloc(sizeof(struct Queue));ret->errors=malloc(sizeof(struct Queue));ret->types=malloc(sizeof(struct Map));+ ret->external_linkage=malloc(sizeof(struct Linkage));Queue_Init(ret->translation_units);Queue_Init(ret->source_files);Queue_Init(ret->errors);- /*this isn't really a scope,- TODO rework*/- ret->externs=get_normal_scope(NULL,EXTERN_SCOPE);++Map_Init(ret->types);fclose(in);return src;}- struct Translation_Data* get_translation_data(struct Map *types)+ struct Translation_Data* get_translation_data(struct Map *types,struct Linkage *internal_linkage,struct Linkage *external_linkage){struct Translation_Data *ret;ret=malloc(sizeof(struct Translation_Data));ret->number_of_errors_when_last_checked=0;+ ret->external_linkage=external_linkage;+ ret->internal_linkage=internal_linkage;+return ret;}struct Source_Name* get_source_name(char *filename,char *base)}program=get_program();- hold_translation_data=get_translation_data(program->types);+ hold_translation_data=get_translation_data(program->types,get_linkage(),program->external_linkage);do{base_file=get_source_file(*base_source_names,this_directory);lex(base_file,hold_translation_data);if(!has_new_errors(hold_translation_data)){- Queue_Push(program->translation_units,parse_translation_unit(hold_translation_data,program->externs));+ Queue_Push(program->translation_units,parse_translation_unit(hold_translation_data));}else{flush_tokens(hold_translation_data->tokens);free(program->errors);- delete_scope(program->externs);+ delete_linkage(program->external_linkage);/*BEWARE*/Map_Map(program->types,delete_type);}+ char has_no_tokens(struct Translation_Data *translation_data)+ {+ return (translation_data->tokens->size)==0;+ }#endifF diff --git a/semantics/program.h b/semantics/program.h --- a/semantics/program.h +++ b/semantics/program.hstruct Queue *translation_units;struct Queue *source_files;struct Queue *errors;- struct Scope *externs;/*we the type node structures fromall the translation units are stored here*/struct Map *types;++ struct Linkage *external_linkage;};struct Translation_Data{/*passed from program struct*/struct Map *types;+ struct Linkage *external_linkage;+ struct Linkage *internal_linkage;+ /*end of passed from program struct*/};struct Program* get_program();struct Source_File* get_source_file(char *filename,char **where_to_search);void normalise_source_name(struct Source_Name *name);- struct Translation_Data* get_translation_data(struct Map *types);+ struct Translation_Data* get_translation_data(struct Map *types,struct Linkage *internal_linkage,struct Linkage *external_linkage);struct Program* parse_program(char **base_source_names);char has_new_errors(struct Translation_Data *translation_data);+ char has_no_tokens(struct Translation_Data *translation_data);void delete_program(struct Program *program);void delete_translation_data(struct Translation_Data *translation_data);F diff --git a/semantics/scope.c b/semantics/scope.c --- a/semantics/scope.c +++ b/semantics/scope.cstruct Scope* get_normal_scope(struct Scope *parent,enum Scope_Type type){struct Normal_Scope *ret;- assert(type==BLOCK_SCOPE || type==EXTERN_SCOPE || type==FILE_SCOPE || type==FUNCTION_PROTOTYPE_SCOPE);+ assert(type==BLOCK_SCOPE || type==FILE_SCOPE || type==FUNCTION_PROTOTYPE_SCOPE);ret=malloc(sizeof(struct Normal_Scope));ret->type=type;- assert((type!=EXTERN_SCOPE) || parent==NULL);- assert((type!=FILE_SCOPE) || parent->type==EXTERN_SCOPE);+ assert((type!=FILE_SCOPE) || parent==NULL);ret->parent=parent;Map_Init(&ret->tags);{Map_Map(&scope->tags,delete_denoted_wrapper);Map_Destroy(&scope->tags);- Map_Map(&scope->ordinary,delete_denoted_wrapper);+ Map_Map(&scope->ordinary,delete_denoted_with_no_linkage_wrapper);Map_Destroy(&scope->ordinary);free(scope);}{case BLOCK_SCOPE:case FILE_SCOPE:- case EXTERN_SCOPE:case FUNCTION_PROTOTYPE_SCOPE:delete_normal_scope((struct Normal_Scope*)scope);break;void Scope_Push(struct Scope *scope,struct Denoted *declarator,struct Translation_Data *translation_data){- /*TODO remove this macro */- #define CHECK_IF_ID_IS_TAKEN_THEN_PUSH(type,namespace) \- if(check_##namespace(scope,((type*)declarator)->id))\- { push_translation_error("redeclaration of id",translation_data);delete_denoted(declarator); return;}\- else { push_##namespace(scope,((type*)declarator)->id,declarator); }-switch(declarator->denotation){/*perhaps lables should be denoted*/assert(0);case DT_Function:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Function,ordinary);+ push_function(scope,translation_data,AS_DENOTED_FUNCTION(declarator));break;case DT_Object:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Object,ordinary);+ push_object(scope,translation_data,AS_DENOTED_OBJECT_PTR(declarator));break;case DT_Typedef:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Typedef,ordinary);+ push_typedef(scope,translation_data,AS_DENOTED_TYPEDEF(declarator));break;case DT_Enum_Constant:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Enum_Const,ordinary);+ push_denoted_enum_constant(scope,translation_data,AS_DENOTED_ENUM_CONST(declarator));break;case DT_Struct_Union_Member:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Object,ordinary);+ assert(0);break;case DT_Enum:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Enum,tag);+ push_denoted_enum_tag(scope,translation_data,AS_DENOTED_ENUM(declarator));break;case DT_Struct_Union_Tag:- CHECK_IF_ID_IS_TAKEN_THEN_PUSH(struct Denoted_Struct_Union,tag);+ push_denoted_struct_union_tag(scope,translation_data,AS_DENOTED_STRUCT_UNION(declarator));break;}- #undef CHECK_IF_ID_IS_TAKEN_THEN_PUSH}char check_if_typedefed(struct Scope* scope,struct token *id){return 1;}- void push_tag(struct Scope *current,struct token *id,struct Denoted *denot)+ #define CHECK_AND_PUSH(thing,scope) Map_Check_And_Push(scope,thing->id->data,thing->id->data_size,thing)++ void push_object(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Object *denoted_object)+ {+ #define PO_ERROR(msg) delete_denoted_object(denoted_object);push_translation_error(msg,translation_data);return;++ struct Denoted_Object *hold_object;+ struct Linkage *linkage;+ resolve_object_linkage(current,translation_data,denoted_object);+ if(has_new_errors(translation_data))+ {PO_ERROR("in declaration");}++ hold_object=CHECK_AND_PUSH(denoted_object,&AS_NORMAL_SCOPE(current)->ordinary);+ if(hold_object!=NULL && hold_object->linkage==LINKAGE_NONE)+ {PO_ERROR("redeclaration of identifier");}++ if(denoted_object->linkage==LINKAGE_NONE)+ {+ if(hold_object!=NULL)+ {PO_ERROR("redeclaration of identifier");}+ }else if(denoted_object->linkage==LINKAGE_EXTERNAL || denoted_object->linkage==LINKAGE_INTERNAL)+ {+ linkage=(denoted_object->linkage==LINKAGE_EXTERNAL?translation_data->external_linkage:translation_data->internal_linkage);+ hold_object=CHECK_AND_PUSH(denoted_object,&linkage->ids);+ if(hold_object!=NULL)+ {+ if(hold_object->denotation!=DT_Object)+ {PO_ERROR("linking an object to a function");}+ if(!types_are_identical(hold_object->object->type,denoted_object->object->type))+ {PO_ERROR("linking an objects with mismatching types");}+ if(denoted_object->initializer!=NULL)+ {+ if(hold_object->initializer==NULL)+ hold_object->initializer=denoted_object->initializer;+ else+ {PO_ERROR("two initialisers for static storage duration object");}+ //delete_denoted_object(denoted_object);+ }+ }+ }else+ {+ assert(0);+ }++ #undef PO_ERROR+ }+ void push_function(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Function *denoted_function)+ {+ #define PF_ERROR(msg) delete_denoted_function(denoted_function);push_translation_error(msg,translation_data);return;++ struct Denoted_Function *hold_function;+ struct Linkage *linkage;+ resolve_function_linkage(current,translation_data,denoted_function);+ if(has_new_errors(translation_data))+ {PF_ERROR("in declaration");}++ if(denoted_function->linkage==LINKAGE_NONE)+ {+ hold_function=CHECK_AND_PUSH(denoted_function,&AS_NORMAL_SCOPE(current)->ordinary);+ if(hold_function!=NULL)+ {PF_ERROR("id with function type without linkage");}+ }else if(denoted_function->linkage==LINKAGE_EXTERNAL || denoted_function->linkage==LINKAGE_INTERNAL)+ {+ linkage=(denoted_function->linkage==LINKAGE_EXTERNAL?translation_data->external_linkage:translation_data->internal_linkage);+ hold_function=CHECK_AND_PUSH(denoted_function,&linkage->ids);+ if(hold_function!=NULL)+ {+ if(hold_function->denotation!=DT_Function)+ {PF_ERROR("linking an function to a object");}+ if(!types_are_identical(hold_function->type,denoted_function->type))+ {PF_ERROR("linking functions with mismatching types");}+ if(hold_function->body!=NULL && denoted_function->body!=NULL)+ {PF_ERROR("redefinition of a function");}+ if(denoted_function->body!=NULL)+ {+ hold_function->body=denoted_function->body;+ denoted_function->body=NULL;+ // delete_denoted_function(denoted_function);+ }+ }+ }else+ {+ assert(0);+ }++ #undef PF_ERROR+ }+ void push_typedef(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Typedef *denoted_typedef){- /*TODO fix this shit*/- assert(current->type!=FUNCTION_SCOPE);- assert(denot!=NULL);- Map_Push(&((struct Normal_Scope*)current)->tags,id->data,id->data_size,denot);+ struct Denoted *hold_denotated;+ hold_denotated=CHECK_AND_PUSH(denoted_typedef,&AS_NORMAL_SCOPE(current)->ordinary);+ if(hold_denotated)+ {+ delete_denoted_typedef(denoted_typedef);+ push_translation_error("redefinition of identifier",translation_data);+ }}- void push_ordinary(struct Scope *current,struct token *id,struct Denoted *denot)+ void push_denoted_enum_tag(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Enum *denoted_enum){- assert(current->type!=FUNCTION_SCOPE);- assert(denot!=NULL);- Map_Push(&((struct Normal_Scope*)current)->ordinary,id->data,id->data_size,denot);+ struct Denoted *hold_denotated;+ hold_denotated=CHECK_AND_PUSH(denoted_enum,&AS_NORMAL_SCOPE(current)->tags);+ if(hold_denotated)+ {+ delete_denoted_enum(denoted_enum);+ push_translation_error("redefinition of tag",translation_data);+ }+ }+ void push_denoted_enum_constant(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Enum_Const *denoted_enum_constant)+ {+ struct Denoted *hold_denotated;+ hold_denotated=CHECK_AND_PUSH(denoted_enum_constant,&AS_NORMAL_SCOPE(current)->ordinary);+ if(hold_denotated)+ {+ delete_denoted_enum_constant(denoted_enum_constant);+ push_translation_error("redefinition of identifier",translation_data);+ }+ }+ void push_denoted_struct_union_tag(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Struct_Union *denoted_struct_union)+ {+ struct Denoted *hold_denotated;+ hold_denotated=CHECK_AND_PUSH(denoted_struct_union,&AS_NORMAL_SCOPE(current)->tags);+ if(hold_denotated)+ {+ delete_denoted_struct_union(denoted_struct_union);+ push_translation_error("redefinition of tag",translation_data);+ }}+ #undef CHECK_AND_PUSH#endifF diff --git a/semantics/scope.h b/semantics/scope.h --- a/semantics/scope.h +++ b/semantics/scope.hstruct Scope* get_function_scope(struct Scope *parent);void* check_label(struct Scope *current,struct token *id);- void push_label(struct Scope *current,struct token *id);/*TODO*/-struct Denoted* check_tag(struct Scope *current,struct token *id);- void push_tag(struct Scope *current,struct token *id,struct Denoted *denot);-void* check_ordinary(struct Scope *current,struct token *id);- void push_ordinary(struct Scope *current,struct token *id,struct Denoted *denot);-- void Scope_Push(struct Scope *scope,struct Denoted *declarator,struct Translation_Data *translation_data);-- char check_if_typedefed(struct Scope* scope,struct token *id);+ void push_label(struct Scope *current,struct token *id);/*TODO*/+ void push_object(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Object *denoted_object);+ void push_function(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Function *denoted_function);+ void push_typedef(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Typedef *denoted_typedef);+ void push_denoted_enum_tag(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Enum *denoted_enum);+ void push_denoted_enum_constant(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Enum_Const *denoted_enum_constant);+ void push_denoted_struct_union_tag(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Struct_Union *denoted_struct_union);+ void Scope_Push(struct Scope *scope,struct Denoted *declarator,struct Translation_Data *translation_data);void delete_scope(struct Scope *scope);void delete_normal_scope(struct Normal_Scope *scope);void delete_function_scope(struct Function_Scope *scope);+++++ char check_if_typedefed(struct Scope* scope,struct token *id);#endifF diff --git a/semantics/scope.hh b/semantics/scope.hh --- a/semantics/scope.hh +++ b/semantics/scope.hh#ifndef GCC_SCOPE_HH#define GCC_SCOPE_HH GCC_SCOPE_HH+ #define AS_NORMAL_SCOPE(x) ((struct Normal_Scope*)x)+ #define AS_FUNCTION_SCOPE(x) ((struct Function_Scope*)x)enum Scope_Type{- EXTERN_SCOPE,FILE_SCOPE,BLOCK_SCOPE,FUNCTION_PROTOTYPE_SCOPE,F diff --git a/semantics/type.c b/semantics/type.c --- a/semantics/type.c +++ b/semantics/type.cfree(type);}}+ char types_are_identical(struct Type *a,struct Type *b)+ {+ return 1;+ }#endifF diff --git a/semantics/type.h b/semantics/type.h --- a/semantics/type.h +++ b/semantics/type.hchar is_type(struct Translation_Data *translation_data,struct Scope *scope);size_t get_type_size(struct Type *type);+ char types_are_identical(struct Type *a,struct Type *b);F diff --git a/tests/test2.c b/tests/test2.c --- a/tests/test2.c +++ b/tests/test2.c+ extern int err;struct A{int x;int y;int kak:1;- };+ }zeh;int main(){- int a;- struct A b;+ int * const * volatile a[3][2][1];+ struct A kek;return 0;}F diff --git a/tests/test4.c b/tests/test4.c --- a/tests/test4.c +++ b/tests/test4.c-- #include <limits.h>--+ extern int a=10;+ extern int a;int main(){- printf("asdf\n");- return 0;+ {+ extern int a;+ }}F diff --git a/tests/test5.c b/tests/test5.c new file mode 100644 --- /dev/null +++ b/tests/test5.c+ extern int a;