Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cobj/cobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1779,6 +1779,14 @@ static int process_translate(struct filename *fn) {
if (ret) {
return ret;
}

/* Validate duplicate labels in the same section */
for (q = current_program; q; q = q->next_program) {
if (cb_validate_labels(q)) {
return -1;
}
}

if (cb_flag_syntax_only || current_program->entry_list == NULL) {
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions cobj/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,7 @@ extern void cb_validate_program_environment(struct cb_program *prog);
extern void cb_validate_program_data(struct cb_program *prog);
extern void cb_validate_program_body(struct cb_program *prog);
extern void cb_validate_indexed_file_key(const struct cb_file *f);
extern int cb_validate_labels(struct cb_program *prog);

extern cb_tree cb_build_expr(cb_tree list);
extern cb_tree cb_build_cond(cb_tree x);
Expand Down
45 changes: 45 additions & 0 deletions cobj/typeck.c
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,51 @@ void cb_validate_program_body(struct cb_program *prog) {
}
}

int cb_validate_labels(struct cb_program *prog) {
cb_tree l1, l2;
int duplicate_count = 0;

for (l1 = prog->exec_list; l1; l1 = CB_CHAIN(l1)) {
cb_tree x1 = CB_VALUE(l1);
if (!CB_LABEL_P(x1)) {
continue;
}
struct cb_label *label1 = CB_LABEL(x1);
if (label1->is_section) {
continue;
}

for (l2 = CB_CHAIN(l1); l2; l2 = CB_CHAIN(l2)) {
cb_tree x2 = CB_VALUE(l2);
if (!CB_LABEL_P(x2)) {
continue;
}
struct cb_label *label2 = CB_LABEL(x2);
if (label2->is_section) {
break;
}

if (label1->section != label2->section) {
break;
}

if (strcmp((const char *)label1->name, (const char *)label2->name) == 0) {
if (!label2->section || !label2->section->name ||
strcmp((char *)label2->section->name, "MAIN SECTION") == 0) {
cb_error_x(x2, _("Duplicate paragraph '%s' in the default section"),
label2->name);
} else {
cb_error_x(x2, _("Duplicate paragraph '%s' in section '%s'"),
label2->name, label2->section->name);
}
cb_error_x(x1, _("'%s' previously defined here"), label1->name);
duplicate_count++;
}
}
}
return duplicate_count;
}

/*
* Expressions
*/
Expand Down
83 changes: 72 additions & 11 deletions tests/syntax.src/definition.at
Original file line number Diff line number Diff line change
Expand Up @@ -501,24 +501,85 @@ AT_CLEANUP

AT_SETUP([Redefinition of paragraph names])

AT_DATA([prog.cob], [
AT_DATA([prog1.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
PROGRAM-ID. prog1.
PROCEDURE DIVISION.
*No Label
L.
*No Label
L.
STOP RUN.
])

AT_CHECK([${COMPILE_ONLY} prog.cob], [0], ,
[])

## Change when we DON'T allow this
## AT_CHECK([${COMPILE_ONLY} prog.cob], [1], ,
## [prog.cob: In paragraph 'L':
## prog.cob:6: Error: redefinition of 'L'
## prog.cob:5: Error: 'L' previously defined here
## ])
AT_DATA([prog2.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog2.
PROCEDURE DIVISION.
SECTION-A SECTION.
L.
*No Label
L.
STOP RUN.
])

AT_DATA([prog3.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog3.
PROCEDURE DIVISION.
SECTION-A SECTION.
L.
SECTION-B SECTION.
L.
STOP RUN.
])

AT_CHECK([${COMPILE} -fsyntax-only prog1.cob], [1], ,
[prog1.cob:8: Error: Duplicate paragraph 'L' in the default section
prog1.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} -fsyntax-only prog2.cob], [1], ,
[prog2.cob:8: Error: Duplicate paragraph 'L' in section 'SECTION-A'
prog2.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} -fsyntax-only prog3.cob])

AT_CHECK([${COMPILE} prog1.cob], [1], ,
[prog1.cob:8: Error: Duplicate paragraph 'L' in the default section
prog1.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} prog2.cob], [1], ,
[prog2.cob:8: Error: Duplicate paragraph 'L' in section 'SECTION-A'
prog2.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} prog3.cob])

AT_CHECK([${COMPILE} prog1.cob prog3.cob], [1], ,
[prog1.cob:8: Error: Duplicate paragraph 'L' in the default section
prog1.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} prog2.cob prog3.cob], [1], ,
[prog2.cob:8: Error: Duplicate paragraph 'L' in section 'SECTION-A'
prog2.cob:6: Error: 'L' previously defined here
])

AT_CHECK([${COMPILE} prog3.cob prog1.cob], [1], ,
[prog1.cob:8: Error: Duplicate paragraph 'L' in the default section
prog1.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} prog3.cob prog2.cob], [1], ,
[prog2.cob:8: Error: Duplicate paragraph 'L' in section 'SECTION-A'
prog2.cob:6: Error: 'L' previously defined here
])

AT_CHECK([${COMPILE} prog1.cob prog2.cob], [1], ,
[prog1.cob:8: Error: Duplicate paragraph 'L' in the default section
prog1.cob:6: Error: 'L' previously defined here
])
AT_CHECK([${COMPILE} prog2.cob prog1.cob], [1], ,
[prog2.cob:8: Error: Duplicate paragraph 'L' in section 'SECTION-A'
prog2.cob:6: Error: 'L' previously defined here
])

AT_CLEANUP

Expand Down