compiler: fix stuck parsing of 'enum{}' + handle such bugs

pull/3533/head
Delyan Angelov 2020-01-21 19:47:52 +02:00 committed by Alexander Medvednikov
parent ae3d84df6b
commit f4834bd85d
3 changed files with 38 additions and 4 deletions

View File

@ -8,7 +8,7 @@ import (
strings
filepath
//compiler.x64
// time
time
)
struct Parser {
@ -25,6 +25,7 @@ mut:
scanner &Scanner
tokens []Token
token_idx int
prev_stuck_token_idx int
tok TokenKind
prev_tok TokenKind
prev_tok2 TokenKind // TODO remove these once the tokens are cached
@ -462,8 +463,17 @@ fn (p mut Parser) parse(pass Pass) {
}
return
}
parsing_start_ticks := time.ticks()
compile_cycles_stuck_mask := u64( 0x1FFFFFFF ) // 2^29-1 cycles
mut parsing_cycle := u64(1)
p.prev_stuck_token_idx = p.token_idx
// Go through every top level token or throw a compilation error if a non-top level token is met
for {
parsing_cycle++
if compile_cycles_stuck_mask == (parsing_cycle & compile_cycles_stuck_mask) {
p.check_if_parser_is_stuck(parsing_cycle, parsing_start_ticks)
}
match p.tok {
.key_import {
p.imports()
@ -480,6 +490,8 @@ fn (p mut Parser) parse(pass Pass) {
// (for example, by DOOM). such fields are
// basically int consts
p.enum_decl(true)
} else {
p.error('Nameless enums are not allowed.')
}
}
.key_pub {
@ -3162,3 +3174,22 @@ fn todo_remove() {
//x64.new_gen('f')
}
fn (p mut Parser) check_if_parser_is_stuck(parsing_cycle u64, parsing_start_ticks i64){
if p.prev_stuck_token_idx == p.token_idx {
// many many cycles have passed with no progress :-( ...
eprintln('Parsing is [probably] stuck. Cycle: ${parsing_cycle:12ld} .')
eprintln(' parsing file: ${p.file_path} | pass: ${p.pass} | mod: ${p.mod} | fn: ${p.cur_fn.name}')
p.print_current_tokens(' source')
if time.ticks() > parsing_start_ticks + 10*1000{
p.warn('V compiling is too slow.')
}
if time.ticks() > parsing_start_ticks + 30*1000{
p.error('
V took more than 30 seconds to compile this file.
Please create a GitHub issue: https://github.com/vlang/v/issues/new/choose .
')
}
}
p.prev_stuck_token_idx = p.token_idx
}

View File

@ -106,13 +106,16 @@ int typ;
} $enum_name;
'
}
// Skip empty enums
// Skip nameless enums
else if !no_name && !p.first_pass() {
p.cgen.typedefs << 'typedef int $enum_name;'
}
}
p.check(.rcbr)
p.fgen_nl()
p.fgen_nl()
if !no_name && fields.len == 0 {
p.error('Empty enums are not allowed.')
}
}
fn (p mut Parser) check_enum_member_access() {

View File

@ -9,7 +9,7 @@ module gl
#flag @VROOT/thirdparty/glad/glad.o
// joe-c: fix & remove
pub enum TmpGlImportHack{}
pub enum TmpGlImportHack{ non_empty }
pub fn init_glad() {
ok := C.gladLoadGL()