Skip to content

Commit 401abcc

Browse files
committed
C++ front-end: support [[__nodiscard__]] and [[nodiscard]]
Required to parse cassert (which in turn includes stdlib.h) on macOS in C++11 mode.
1 parent f18b509 commit 401abcc

File tree

9 files changed

+67
-2
lines changed

9 files changed

+67
-2
lines changed

regression/cpp/nodiscard1/main.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[[nodiscard]] int foo(void)
2+
{
3+
return 1;
4+
}
5+
6+
#ifdef _MSC_VER
7+
#error try in compiler explorer
8+
#else
9+
[[__nodiscard__]] int bar(void)
10+
{
11+
return 2;
12+
}
13+
#endif
14+
15+
int main()
16+
{
17+
return foo() + bar();
18+
}

regression/cpp/nodiscard1/test.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.cpp
3+
-std=c++11
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$

src/ansi-c/ansi_c_convert_type.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ void ansi_c_convert_typet::read_rec(const typet &type)
216216
}
217217
}
218218
}
219+
else if(type.id()==ID_nodiscard)
220+
c_qualifiers.is_nodiscard=true;
219221
else if(type.id()==ID_noreturn)
220222
c_qualifiers.is_noreturn=true;
221223
else if(type.id()==ID_constructor)

src/ansi-c/c_qualifiers.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ c_qualifierst &c_qualifierst::operator=(const c_qualifierst &other)
1616
is_volatile = other.is_volatile;
1717
is_restricted = other.is_restricted;
1818
is_atomic = other.is_atomic;
19+
is_nodiscard = other.is_nodiscard;
1920
is_noreturn = other.is_noreturn;
2021
is_ptr32 = other.is_ptr32;
2122
is_ptr64 = other.is_ptr64;
@@ -52,6 +53,9 @@ std::string c_qualifierst::as_string() const
5253
if(is_ptr64)
5354
qualifiers+="__ptr64 ";
5455

56+
if(is_nodiscard)
57+
qualifiers+="[[nodiscard]] ";
58+
5559
if(is_noreturn)
5660
qualifiers+="_Noreturn ";
5761

@@ -81,6 +85,9 @@ void c_qualifierst::read(const typet &src)
8185
if(src.get_bool(ID_C_transparent_union))
8286
is_transparent_union=true;
8387

88+
if(src.get_bool(ID_C_nodiscard))
89+
is_nodiscard=true;
90+
8491
if(src.get_bool(ID_C_noreturn))
8592
is_noreturn=true;
8693
}
@@ -122,6 +129,11 @@ void c_qualifierst::write(typet &dest) const
122129
else
123130
dest.remove(ID_C_transparent_union);
124131

132+
if(is_nodiscard)
133+
dest.set(ID_C_nodiscard, true);
134+
else
135+
dest.remove(ID_C_nodiscard);
136+
125137
if(is_noreturn)
126138
dest.set(ID_C_noreturn, true);
127139
else
@@ -136,6 +148,7 @@ void c_qualifierst::clear(typet &dest)
136148
dest.remove(ID_C_ptr32);
137149
dest.remove(ID_C_ptr64);
138150
dest.remove(ID_C_transparent_union);
151+
dest.remove(ID_C_nodiscard);
139152
dest.remove(ID_C_noreturn);
140153
}
141154

src/ansi-c/c_qualifiers.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,12 @@ class c_qualifierst : public qualifierst
8585
is_atomic=false;
8686
is_ptr32=is_ptr64=false;
8787
is_transparent_union=false;
88+
is_nodiscard=false;
8889
is_noreturn=false;
8990
}
9091

9192
// standard ones
92-
bool is_constant, is_volatile, is_restricted, is_atomic, is_noreturn;
93+
bool is_constant, is_volatile, is_restricted, is_atomic, is_noreturn, is_nodiscard;
9394

9495
// MS Visual Studio extension
9596
bool is_ptr32, is_ptr64;
@@ -115,6 +116,7 @@ class c_qualifierst : public qualifierst
115116
(!is_atomic || cq->is_atomic) &&
116117
(!is_ptr32 || cq->is_ptr32) &&
117118
(!is_ptr64 || cq->is_ptr64) &&
119+
(!is_nodiscard || cq->is_nodiscard) &&
118120
(!is_noreturn || cq->is_noreturn);
119121

120122
// is_transparent_union isn't checked
@@ -131,6 +133,7 @@ class c_qualifierst : public qualifierst
131133
is_ptr32 == cq->is_ptr32 &&
132134
is_ptr64 == cq->is_ptr64 &&
133135
is_transparent_union == cq->is_transparent_union &&
136+
is_nodiscard == cq->is_nodiscard &&
134137
is_noreturn == cq->is_noreturn;
135138
}
136139

@@ -144,14 +147,15 @@ class c_qualifierst : public qualifierst
144147
is_ptr32 |= cq->is_ptr32;
145148
is_ptr64 |= cq->is_ptr64;
146149
is_transparent_union |= cq->is_transparent_union;
150+
is_nodiscard |= cq->is_nodiscard;
147151
is_noreturn |= cq->is_noreturn;
148152
return *this;
149153
}
150154

151155
virtual std::size_t count() const override
152156
{
153157
return is_constant+is_volatile+is_restricted+is_atomic+
154-
is_ptr32+is_ptr64+is_noreturn;
158+
is_ptr32+is_ptr64+is_nodiscard+is_noreturn;
155159
}
156160
};
157161

src/ansi-c/parser.y

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ int yyansi_cerror(const std::string &error);
255255
%token TOK_MUTABLE "mutable"
256256
%token TOK_NAMESPACE "namespace"
257257
%token TOK_NEW "new"
258+
%token TOK_NODISCARD "nodiscard"
258259
%token TOK_NOEXCEPT "noexcept"
259260
%token TOK_OPERATOR "operator"
260261
%token TOK_PRIVATE "private"

src/ansi-c/scanner.l

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,7 @@ friend { return cpp98_keyword(TOK_FRIEND); }
864864
mutable { return cpp98_keyword(TOK_MUTABLE); }
865865
namespace { return cpp98_keyword(TOK_NAMESPACE); }
866866
new { return cpp98_keyword(TOK_NEW); }
867+
nodiscard { return cpp11_keyword(TOK_NODISCARD); } // C++11
867868
noexcept { return cpp11_keyword(TOK_NOEXCEPT); } // C++11
868869
noreturn { return cpp11_keyword(TOK_NORETURN); } // C++11
869870
not { return cpp98_keyword('!'); }
@@ -1291,6 +1292,14 @@ __decltype { if(PARSER.cpp98 &&
12911292
return make_identifier();
12921293
}
12931294

1295+
"__nodiscard__" { if(PARSER.mode==configt::ansi_ct::flavourt::GCC ||
1296+
PARSER.mode==configt::ansi_ct::flavourt::CLANG ||
1297+
PARSER.mode==configt::ansi_ct::flavourt::ARM)
1298+
{ loc(); return TOK_NODISCARD; }
1299+
else
1300+
return make_identifier();
1301+
}
1302+
12941303
{CPROVER_PREFIX}"atomic" { loc(); return TOK_CPROVER_ATOMIC; }
12951304
{CPROVER_PREFIX}"forall" { loc(); return TOK_FORALL; }
12961305
{CPROVER_PREFIX}"exists" { loc(); return TOK_EXISTS; }

src/cpp/parse.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,6 +2402,14 @@ bool Parser::optAttribute(typet &t)
24022402
break;
24032403
}
24042404

2405+
case TOK_NODISCARD:
2406+
{
2407+
typet attr(ID_nodiscard);
2408+
set_location(attr, tk);
2409+
merge_types(attr, t);
2410+
break;
2411+
}
2412+
24052413
default:
24062414
return false;
24072415
}

src/util/irep_ids.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@ IREP_ID_ONE(onehot)
574574
IREP_ID_ONE(onehot0)
575575
IREP_ID_ONE(popcount)
576576
IREP_ID_ONE(function_type)
577+
IREP_ID_ONE(nodiscard)
578+
IREP_ID_TWO(C_nodiscard, #nodiscard)
577579
IREP_ID_ONE(noreturn)
578580
IREP_ID_TWO(C_noreturn, #noreturn)
579581
IREP_ID_ONE(weak)

0 commit comments

Comments
 (0)