Skip to content

Commit 3e5bf81

Browse files
authored
Merge pull request #8287 from tautschnig/bugfixes/c++-nodiscard
C++ front-end: support [[__nodiscard__]] and [[nodiscard]]
2 parents 9b805cd + 4bd13f2 commit 3e5bf81

File tree

9 files changed

+81
-20
lines changed

9 files changed

+81
-20
lines changed

regression/cpp/nodiscard1/main.cpp

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

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: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ 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,
94+
is_nodiscard;
9395

9496
// MS Visual Studio extension
9597
bool is_ptr32, is_ptr64;
@@ -108,30 +110,24 @@ class c_qualifierst : public qualifierst
108110
virtual bool is_subset_of(const qualifierst &other) const override
109111
{
110112
const c_qualifierst *cq = dynamic_cast<const c_qualifierst *>(&other);
111-
return
112-
(!is_constant || cq->is_constant) &&
113-
(!is_volatile || cq->is_volatile) &&
114-
(!is_restricted || cq->is_restricted) &&
115-
(!is_atomic || cq->is_atomic) &&
116-
(!is_ptr32 || cq->is_ptr32) &&
117-
(!is_ptr64 || cq->is_ptr64) &&
118-
(!is_noreturn || cq->is_noreturn);
113+
return (!is_constant || cq->is_constant) &&
114+
(!is_volatile || cq->is_volatile) &&
115+
(!is_restricted || cq->is_restricted) &&
116+
(!is_atomic || cq->is_atomic) && (!is_ptr32 || cq->is_ptr32) &&
117+
(!is_ptr64 || cq->is_ptr64) && (!is_nodiscard || cq->is_nodiscard) &&
118+
(!is_noreturn || cq->is_noreturn);
119119

120120
// is_transparent_union isn't checked
121121
}
122122

123123
virtual bool operator==(const qualifierst &other) const override
124124
{
125125
const c_qualifierst *cq = dynamic_cast<const c_qualifierst *>(&other);
126-
return
127-
is_constant == cq->is_constant &&
128-
is_volatile == cq->is_volatile &&
129-
is_restricted == cq->is_restricted &&
130-
is_atomic == cq->is_atomic &&
131-
is_ptr32 == cq->is_ptr32 &&
132-
is_ptr64 == cq->is_ptr64 &&
133-
is_transparent_union == cq->is_transparent_union &&
134-
is_noreturn == cq->is_noreturn;
126+
return is_constant == cq->is_constant && is_volatile == cq->is_volatile &&
127+
is_restricted == cq->is_restricted && is_atomic == cq->is_atomic &&
128+
is_ptr32 == cq->is_ptr32 && is_ptr64 == cq->is_ptr64 &&
129+
is_transparent_union == cq->is_transparent_union &&
130+
is_nodiscard == cq->is_nodiscard && is_noreturn == cq->is_noreturn;
135131
}
136132

137133
virtual qualifierst &operator+=(const qualifierst &other) override
@@ -144,14 +140,15 @@ class c_qualifierst : public qualifierst
144140
is_ptr32 |= cq->is_ptr32;
145141
is_ptr64 |= cq->is_ptr64;
146142
is_transparent_union |= cq->is_transparent_union;
143+
is_nodiscard |= cq->is_nodiscard;
147144
is_noreturn |= cq->is_noreturn;
148145
return *this;
149146
}
150147

151148
virtual std::size_t count() const override
152149
{
153-
return is_constant+is_volatile+is_restricted+is_atomic+
154-
is_ptr32+is_ptr64+is_noreturn;
150+
return is_constant + is_volatile + is_restricted + is_atomic + is_ptr32 +
151+
is_ptr64 + is_nodiscard + is_noreturn;
155152
}
156153
};
157154

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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,8 @@ bool Parser::optAttribute(typet &t)
24202420
switch(tk.kind)
24212421
{
24222422
case ']':
2423+
if(lex.LookAhead(0) != ']')
2424+
return false;
24232425
lex.get_token();
24242426
return true;
24252427

@@ -2431,7 +2433,17 @@ bool Parser::optAttribute(typet &t)
24312433
break;
24322434
}
24332435

2436+
case TOK_NODISCARD:
2437+
{
2438+
typet attr(ID_nodiscard);
2439+
set_location(attr, tk);
2440+
merge_types(attr, t);
2441+
break;
2442+
}
2443+
24342444
default:
2445+
// TODO: way may wish to change this: GCC, Clang, Visual Studio merely
2446+
// warn when they see an attribute that they don't recognize
24352447
return false;
24362448
}
24372449
}

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)