Skip to content

Commit 735915e

Browse files
committed
C++ front-end: various fixes and DEBUG
1 parent e504235 commit 735915e

File tree

5 files changed

+135
-70
lines changed

5 files changed

+135
-70
lines changed

src/ansi-c/scanner.l

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,10 +1244,10 @@ enable_or_disable ("enable"|"disable")
12441244
TOK_BIT_CAST);
12451245
}
12461246

1247-
"dynamic_cast" { return cpp98_keyword(TOK_DYNAMIC_CAST); }
1248-
"static_cast" { return cpp98_keyword(TOK_STATIC_CAST); }
1249-
"reinterpret_cast" { return cpp98_keyword(TOK_REINTERPRET_CAST); }
1250-
"const_cast" { return cpp98_keyword(TOK_CONST_CAST); }
1247+
"dynamic_cast" { return conditional_keyword(PARSER.cpp98, TOK_DYNAMIC_CAST); }
1248+
"static_cast" { return conditional_keyword(PARSER.cpp98, TOK_STATIC_CAST); }
1249+
"reinterpret_cast" { return conditional_keyword(PARSER.cpp98, TOK_REINTERPRET_CAST); }
1250+
"const_cast" { return conditional_keyword(PARSER.cpp98, TOK_CONST_CAST); }
12511251

12521252
{CPROVER_PREFIX}"atomic" { loc(); return TOK_CPROVER_ATOMIC; }
12531253
{CPROVER_PREFIX}"forall" { loc(); return TOK_FORALL; }
@@ -1363,7 +1363,7 @@ enable_or_disable ("enable"|"disable")
13631363
/* This is a C11 keyword */
13641364

13651365
"_Alignof" { return conditional_keyword(
1366-
!PARSER.cpp98 &&
1366+
(!PARSER.cpp98 || PARSER.cpp11) &&
13671367
(PARSER.mode==configt::ansi_ct::flavourt::GCC ||
13681368
PARSER.mode==configt::ansi_ct::flavourt::CLANG ||
13691369
PARSER.mode==configt::ansi_ct::flavourt::ARM ||
@@ -1384,7 +1384,7 @@ enable_or_disable ("enable"|"disable")
13841384
yyless(7);
13851385

13861386
return conditional_keyword(
1387-
!PARSER.cpp98 &&
1387+
(!PARSER.cpp98 || PARSER.cpp11) &&
13881388
(PARSER.mode==configt::ansi_ct::flavourt::GCC ||
13891389
PARSER.mode==configt::ansi_ct::flavourt::CLANG ||
13901390
PARSER.mode==configt::ansi_ct::flavourt::ARM),

src/cbmc/cbmc_parse_options.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,14 @@ int cbmc_parse_optionst::doit()
542542
register_languages();
543543

544544
// configure gcc, if required
545-
if(config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::GCC)
545+
if(config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::GCC ||
546+
config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::CLANG)
546547
{
547548
gcc_versiont gcc_version;
548549
gcc_version.get("gcc");
549550
configure_gcc(gcc_version);
551+
config.ansi_c.c_standard = gcc_version.default_c_standard;
552+
config.cpp.cpp_standard = gcc_version.default_cxx_standard;
550553
}
551554

552555
if(cmdline.isset("test-preprocessor"))

src/cpp/cpp_declaration.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ class cpp_declarationt:public exprt
5454

5555
bool is_class_template() const
5656
{
57+
const typet * t = &type();
58+
while(t->id() == ID_merged_type)
59+
t = &to_type_with_subtypes(*t).subtypes().back();
5760
return is_template() &&
58-
type().id()==ID_struct &&
61+
t->id()==ID_struct &&
5962
declarators().empty();
6063
}
6164

src/cpp/cpp_typecheck_template.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -987,23 +987,6 @@ void cpp_typecheckt::convert_template_declaration(
987987

988988
if(declaration.is_class_template())
989989
{
990-
// there should not be declarators
991-
if(!declaration.declarators().empty())
992-
{
993-
error().source_location=declaration.source_location();
994-
error() << "class template not expected to have declarators"
995-
<< eom;
996-
throw 0;
997-
}
998-
999-
// it needs to be a class template
1000-
if(type.id()!=ID_struct)
1001-
{
1002-
error().source_location=declaration.source_location();
1003-
error() << "expected class template" << eom;
1004-
throw 0;
1005-
}
1006-
1007990
// Is it class template specialization?
1008991
// We can tell if there are template arguments in the class name,
1009992
// like template<...> class tag<stuff> ...

src/cpp/parse.cpp

Lines changed: 121 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Author: Daniel Kroening, [email protected]
2323
#include "cpp_member_spec.h"
2424
#include "cpp_enum_type.h"
2525

26-
// #define DEBUG
26+
#define DEBUG
2727
#ifdef DEBUG
2828
#include <iostream>
2929

@@ -346,7 +346,6 @@ class Parser // NOLINT(readability/identifiers)
346346
bool rPostfixExpr(exprt &);
347347
bool rPrimaryExpr(exprt &);
348348
bool rVarName(exprt &);
349-
bool rVarNameCore(exprt &);
350349
bool maybeTemplateArgs();
351350

352351
bool rFunctionBody(cpp_declaratort &);
@@ -778,7 +777,7 @@ bool Parser::isTypeSpecifier()
778777
t == TOK_CPROVER_BOOL || t == TOK_CLASS || t == TOK_STRUCT ||
779778
t == TOK_UNION || t == TOK_ENUM || t == TOK_INTERFACE ||
780779
t == TOK_TYPENAME || t == TOK_TYPEOF || t == TOK_DECLTYPE ||
781-
t == TOK_UNDERLYING_TYPE;
780+
t == TOK_UNDERLYING_TYPE || t == TOK_ATOMIC_TYPE_SPECIFIER;
782781
}
783782

784783
/*
@@ -1336,31 +1335,61 @@ bool Parser::rTempArgDeclaration(cpp_declarationt &declaration)
13361335
if(!rTemplateDecl2(template_type, kind))
13371336
return false;
13381337

1339-
// TODO
1340-
1341-
cpp_tokent tk1, tk2;
1338+
cpp_tokent tk1;
13421339

13431340
if(lex.get_token(tk1) != TOK_CLASS)
13441341
return false;
13451342

1346-
if(lex.LookAhead(0) == ',')
1343+
declaration=cpp_declarationt();
1344+
set_location(declaration, tk1);
1345+
1346+
declaration.set(ID_is_type, true);
1347+
declaration.type()=template_type;
1348+
1349+
declaration.declarators().resize(1);
1350+
cpp_declaratort &declarator=declaration.declarators().front();
1351+
1352+
declarator=cpp_declaratort();
1353+
declarator.name().make_nil();
1354+
declarator.type().make_nil();
1355+
set_location(declarator, tk1);
1356+
1357+
if(lex.LookAhead(0) == ',' || lex.LookAhead(0) == '>')
13471358
return true;
13481359

1349-
if(!is_identifier(lex.get_token(tk2)))
1360+
if(lex.LookAhead(0)==TOK_ELLIPSIS)
1361+
{
1362+
cpp_tokent tk2;
1363+
lex.get_token(tk2);
1364+
declarator.set_has_ellipsis();
1365+
}
1366+
1367+
if(is_identifier(lex.LookAhead(0)))
1368+
{
1369+
cpp_tokent tk2;
1370+
lex.get_token(tk2);
1371+
1372+
declarator.name() = cpp_namet(tk2.data.get(ID_C_base_name));
1373+
set_location(declarator.name(), tk2);
1374+
1375+
add_id(declarator.name(), new_scopet::kindt::TYPE_TEMPLATE_PARAMETER);
1376+
}
1377+
else
13501378
return false;
1351-
// Ptree cspec=new PtreeClassSpec(new LeafReserved(tk1),
1352-
// Ptree::Cons(new Leaf(tk2),nil),
1353-
// nil);
1354-
// decl=Ptree::Snoc(decl, cspec);
1379+
13551380
if(lex.LookAhead(0)=='=')
13561381
{
1382+
if(declarator.get_has_ellipsis())
1383+
return false;
1384+
13571385
typet default_type;
1386+
13581387
lex.get_token(tk1);
13591388
if(!rTypeName(default_type))
1360-
return false;
1389+
return false;
13611390

1362-
// decl=Ptree::Nconc(decl, Ptree::List(new Leaf(tk1),
1363-
// default_type));
1391+
declarator.value()=exprt(ID_type);
1392+
declarator.value().type().swap(default_type);
13641393
}
13651394
}
13661395
else
@@ -1487,6 +1516,10 @@ bool Parser::rDeclaration(cpp_declarationt &declaration)
14871516
cpp_member_spect member_spec;
14881517
if(!optMemberSpec(member_spec))
14891518
return false;
1519+
if(!optAttribute(declaration.type()))
1520+
return false;
1521+
if(!optMemberSpec(member_spec))
1522+
return false;
14901523

14911524
#ifdef DEBUG
14921525
std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 0.2\n";
@@ -2051,8 +2084,6 @@ bool Parser::isPtrToMember(int i)
20512084
*/
20522085
bool Parser::optMemberSpec(cpp_member_spect &member_spec)
20532086
{
2054-
member_spec.clear();
2055-
20562087
int t=lex.LookAhead(0);
20572088

20582089
while(
@@ -2502,6 +2533,17 @@ bool Parser::optAttribute(typet &t)
25022533
break;
25032534
}
25042535

2536+
case TOK_GCC_IDENTIFIER:
2537+
if(tk.text == "clang" && lex.LookAhead(0) == TOK_SCOPE)
2538+
{
2539+
exprt discarded;
2540+
if(!rExpression(discarded, false))
2541+
return false;
2542+
}
2543+
else
2544+
return false;
2545+
break;
2546+
25052547
default:
25062548
// TODO: way may wish to change this: GCC, Clang, Visual Studio merely
25072549
// warn when they see an attribute that they don't recognize
@@ -2737,8 +2779,34 @@ bool Parser::optIntegralTypeOrClassSpec(typet &p)
27372779

27382780
return true;
27392781
}
2782+
else if(t == TOK_ATOMIC_TYPE_SPECIFIER)
2783+
{
2784+
#ifdef DEBUG
2785+
std::cout << std::string(__indent, ' ')
2786+
<< "Parser::optIntegralTypeOrClassSpec 9\n";
2787+
#endif // DEBUG
2788+
cpp_tokent atomic_tk;
2789+
lex.get_token(atomic_tk);
2790+
2791+
cpp_tokent tk;
2792+
if(lex.get_token(tk)!='(')
2793+
return false;
2794+
2795+
// the argument is always a type
2796+
if(!rTypeSpecifier(p, false))
2797+
return false;
2798+
2799+
if(lex.get_token(tk)!=')')
2800+
return false;
2801+
2802+
return true;
2803+
}
27402804
else
27412805
{
2806+
#ifdef DEBUG
2807+
std::cout << std::string(__indent, ' ')
2808+
<< "Parser::optIntegralTypeOrClassSpec 10\n";
2809+
#endif // DEBUG
27422810
p.make_nil();
27432811
return true;
27442812
}
@@ -3774,7 +3842,7 @@ bool Parser::rName(irept &name)
37743842
components.back().add(ID_expr_arg).swap(expr);
37753843

37763844
if(lex.LookAhead(0) != TOK_SCOPE)
3777-
return false;
3845+
return true;
37783846
}
37793847
break;
37803848

@@ -4549,6 +4617,9 @@ bool Parser::rEnumSpec(typet &spec)
45494617
spec.set(ID_C_class, true);
45504618
}
45514619

4620+
if(!optAttribute(spec))
4621+
return false;
4622+
45524623
if(lex.LookAhead(0)!='{' &&
45534624
lex.LookAhead(0)!=':')
45544625
{
@@ -4715,7 +4786,7 @@ bool Parser::rClassSpec(typet &spec)
47154786
if(!optAttribute(spec))
47164787
return false;
47174788

4718-
if(lex.LookAhead(0)=='{')
4789+
if(lex.LookAhead(0)=='{' || lex.LookAhead(0) == ':')
47194790
{
47204791
// no tag
47214792
#ifdef DEBUG
@@ -4734,21 +4805,21 @@ bool Parser::rClassSpec(typet &spec)
47344805
#ifdef DEBUG
47354806
std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 5\n";
47364807
#endif
4808+
}
47374809

4738-
t=lex.LookAhead(0);
4810+
t=lex.LookAhead(0);
47394811

4740-
if(t==':')
4741-
{
4742-
if(!rBaseSpecifiers(spec.add(ID_bases)))
4743-
return false;
4744-
}
4745-
else if(t=='{')
4746-
{
4747-
}
4748-
else
4749-
{
4750-
return true;
4751-
}
4812+
if(t==':')
4813+
{
4814+
if(!rBaseSpecifiers(spec.add(ID_bases)))
4815+
return false;
4816+
}
4817+
else if(t=='{')
4818+
{
4819+
}
4820+
else
4821+
{
4822+
return true;
47524823
}
47534824

47544825
#ifdef DEBUG
@@ -6721,7 +6792,10 @@ bool Parser::rPostfixExpr(exprt &exp)
67216792
}
67226793

67236794
#ifdef DEBUG
6724-
std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 1\n";
6795+
std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 1 "
6796+
<< lex.LookAhead(0)
6797+
<< ' ' << lex.peek().text
6798+
<< '\n';
67256799
#endif
67266800

67276801
exprt e;
@@ -7276,16 +7350,7 @@ bool Parser::rVarName(exprt &name)
72767350
<< '\n';
72777351
#endif
72787352

7279-
if(rVarNameCore(name))
7280-
return true;
7281-
else
7282-
return false;
7283-
}
7284-
7285-
bool Parser::rVarNameCore(exprt &name)
7286-
{
72877353
#ifdef DEBUG
7288-
indenter _i;
72897354
std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 0\n";
72907355
#endif
72917356

@@ -7458,7 +7523,7 @@ bool Parser::moreVarName()
74587523
/*
74597524
template.args : '<' any* '>'
74607525
7461-
template.args must be followed by '(' or '::'
7526+
template.args must be followed by '(', '::', or ';'
74627527
*/
74637528
bool Parser::maybeTemplateArgs()
74647529
{
@@ -7480,7 +7545,8 @@ bool Parser::maybeTemplateArgs()
74807545
return false;
74817546
else if((u=='>' || u==TOK_SHIFTRIGHT) &&
74827547
(lex.LookAhead(i)==TOK_SCOPE || lex.LookAhead(i)=='(' ||
7483-
lex.LookAhead(i)==')'))
7548+
lex.LookAhead(i)==')' || lex.LookAhead(i) == '}' ||
7549+
lex.LookAhead(i) == ',' || lex.LookAhead(i) == ';'))
74847550
return true;
74857551
}
74867552
#else
@@ -7903,7 +7969,9 @@ std::optional<codet> Parser::rStatement()
79037969
if(!rUsing(cpp_using))
79047970
return {};
79057971

7906-
UNIMPLEMENTED;
7972+
codet statement(ID_cpp_using);
7973+
// UNIMPLEMENTED;
7974+
return std::move(statement);
79077975
}
79087976

79097977
case TOK_STATIC_ASSERT:
@@ -7920,6 +7988,14 @@ std::optional<codet> Parser::rStatement()
79207988
return std::move(statement);
79217989
}
79227990

7991+
case '[':
7992+
{
7993+
typet discard;
7994+
if(!optAttribute(discard))
7995+
return {};
7996+
return code_blockt{};
7997+
}
7998+
79237999
default:
79248000
return rExprStatement();
79258001
}

0 commit comments

Comments
 (0)