Skip to content

Commit a6902e0

Browse files
author
Remi Delmas
committed
mutliple enable/disable now cause a hard PARSING_ERROR in the C frontend.
1 parent 8fd4926 commit a6902e0

File tree

6 files changed

+28
-19
lines changed

6 files changed

+28
-19
lines changed

doc/cprover-manual/properties.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ CPROVER pragmas are handled using a stack:
142142
- `#pragma CPROVER check disable "<name_of_check>"` adds a disable pragma at the top of the stack
143143
- `#pragma CPROVER check enable "<name_of_check>"` adds a enable pragma at the top of the stack
144144
- an `enable` or `disable` pragma for a given check present at the top level of the stack shadows other pragmas for the same in lower levels of the stack
145-
- adding both `enable` and `disable` pragmas for a same check in a same level of the stack creates a warning, the most recent pragma takes precedence
145+
- adding both `enable` and `disable` pragmas for a same check in a same level of the stack creates a PARSING_ERROR.
146146
- `#pragma CPROVER check pop` pops a level in the stack and restores the state of pragmas at the sub level
147147
148148
For example, for unsigned overflow checks, use
@@ -183,12 +183,12 @@ unsigned foo(unsigned x)
183183
#pragma CPROVER check push
184184
#pragma CPROVER check disable "unsigned-overflow"
185185
#pragma CPROVER check enable "unsigned-overflow"
186-
// warning: both enable and disable for unsigned-overflow (last one takes precedence)
187-
x = x + 2; // unsigned and signed overflow check apply here
186+
// PARSING_ERROR ... Found enable and disable pragmas for unsigned-overflow-check
187+
x = x + 2;
188188
#pragma CPROVER check pop
189-
x = x + 3; // unsigned and signed overflow check apply here
189+
x = x + 3;
190190
#pragma CPROVER check pop
191-
x = x + 2; // unsigned overflow checks do not apply here
191+
x = x + 2;
192192
```
193193
194194

regression/cbmc/pragma_cprover_enable_disable_multiple/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ CORE
22
main.c
33

44
^file main.c line \d+ function main: Found enable and disable pragmas for pointer-primitive-check
5-
^VERIFICATION SUCCESSFUL$
6-
^EXIT=0$
5+
^PARSING ERROR$
6+
^EXIT=6$
77
^SIGNAL=0$
88
--
99
^file main.c line \d+ function main: Found enable and disable pragmas for pointer-overflow-check

src/analyses/goto_check.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ Author: Daniel Kroening, [email protected]
1010
/// GOTO Programs
1111

1212
#include "goto_check.h"
13-
#include<iostream>
1413

1514
#include <algorithm>
1615

src/ansi-c/ansi_c_parser.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,14 @@ void ansi_c_parsert::pragma_cprover_add_check(irep_idt name, bool enabled)
197197
if(pragma_cprover_stack.empty())
198198
pragma_cprover_push();
199199

200+
pragma_cprover_stack.back()[name] = enabled;
201+
}
202+
203+
bool ansi_c_parsert::pragma_cprover_clash(irep_idt name, bool enabled)
204+
{
200205
auto top = pragma_cprover_stack.back();
201206
auto found = top.find(name);
202-
if(found != top.end() && found->second!=enabled)
203-
yyansi_cerror("Found enable and disable pragmas for " + id2string(name));
204-
205-
pragma_cprover_stack.back()[name] = enabled;
207+
return found != top.end() && found->second != enabled;
206208
}
207209

208210
void ansi_c_parsert::set_pragma_cprover()

src/ansi-c/ansi_c_parser.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Author: Daniel Kroening, [email protected]
1515

1616
#include <util/parser.h>
1717
#include <util/config.h>
18-
#include <iostream>
18+
1919
#include "ansi_c_parse_tree.h"
2020
#include "ansi_c_scope.h"
2121

@@ -154,12 +154,12 @@ class ansi_c_parsert:public parsert
154154
void pragma_cprover_pop();
155155

156156
/// \brief Adds a check to the CPROVER pragma stack
157-
///
158-
/// Reports a yyansi_cerror if
159-
/// the same check with different polarity
160-
/// is already present in at top of the stack
161157
void pragma_cprover_add_check(irep_idt name, bool enabled);
162158

159+
/// Returns true the same check with different polarity
160+
/// is already present at top of the stack
161+
bool pragma_cprover_clash(irep_idt name, bool enabled);
162+
163163
/// \brief Tags \ref source_location with
164164
/// the current CPROVER pragma stack
165165
void set_pragma_cprover();

src/ansi-c/scanner.l

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,18 @@ void ansi_c_scanner_init()
416416
std::string tmp(yytext);
417417
bool enable = tmp.find("enable")!=std::string::npos;
418418
std::string::size_type p = tmp.find('"') + 1;
419-
std::string value =
419+
std::string check_name =
420420
std::string(tmp, p, tmp.size() - p - 1) +
421421
std::string("-check");
422-
PARSER.pragma_cprover_add_check(value, enable);
422+
bool clash = PARSER.pragma_cprover_clash(check_name, enable);
423+
if(clash)
424+
{
425+
yyansi_cerror(
426+
"Found enable and disable pragmas for " +
427+
id2string(check_name));
428+
return TOK_SCANNER_ERROR;
429+
}
430+
PARSER.pragma_cprover_add_check(check_name, enable);
423431
PARSER.set_pragma_cprover();
424432
}
425433
<CPROVER_PRAGMA>. {

0 commit comments

Comments
 (0)