Skip to content

Commit 4903c34

Browse files
committed
C++ front-end: various fixes and DEBUG
1 parent b9b2814 commit 4903c34

File tree

5 files changed

+109
-37
lines changed

5 files changed

+109
-37
lines changed

src/ansi-c/scanner.l

+2-2
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,7 @@ __decltype { if(PARSER.cpp98 &&
14361436

14371437
/* This is a C11 keyword */
14381438

1439-
"_Alignof" { if(!PARSER.cpp98 &&
1439+
"_Alignof" { if((!PARSER.cpp98 || PARSER.cpp11) &&
14401440
(PARSER.mode==configt::ansi_ct::flavourt::GCC ||
14411441
PARSER.mode==configt::ansi_ct::flavourt::CLANG ||
14421442
PARSER.mode==configt::ansi_ct::flavourt::ARM ||
@@ -1458,7 +1458,7 @@ __decltype { if(PARSER.cpp98 &&
14581458
"_Atomic"{ws}"(" { // put back all but _Atomic
14591459
yyless(7);
14601460

1461-
if(!PARSER.cpp98 &&
1461+
if((!PARSER.cpp98 || PARSER.cpp11) &&
14621462
(PARSER.mode==configt::ansi_ct::flavourt::GCC ||
14631463
PARSER.mode==configt::ansi_ct::flavourt::CLANG ||
14641464
PARSER.mode==configt::ansi_ct::flavourt::ARM))

src/cbmc/cbmc_parse_options.cpp

+4-1
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

+4-1
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

-17
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

+99-16
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ bool Parser::isTypeSpecifier()
778778
t == TOK_CPROVER_BOOL || t == TOK_CLASS || t == TOK_STRUCT ||
779779
t == TOK_UNION || t == TOK_ENUM || t == TOK_INTERFACE ||
780780
t == TOK_TYPENAME || t == TOK_TYPEOF || t == TOK_DECLTYPE ||
781-
t == TOK_UNDERLYING_TYPE;
781+
t == TOK_UNDERLYING_TYPE || t == TOK_ATOMIC_TYPE_SPECIFIER;
782782
}
783783

784784
/*
@@ -1336,31 +1336,61 @@ bool Parser::rTempArgDeclaration(cpp_declarationt &declaration)
13361336
if(!rTemplateDecl2(template_type, kind))
13371337
return false;
13381338

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

13431341
if(lex.get_token(tk1) != TOK_CLASS)
13441342
return false;
13451343

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

1349-
if(!is_identifier(lex.get_token(tk2)))
1361+
if(lex.LookAhead(0)==TOK_ELLIPSIS)
1362+
{
1363+
cpp_tokent tk2;
1364+
lex.get_token(tk2);
1365+
declarator.set_has_ellipsis();
1366+
}
1367+
1368+
if(is_identifier(lex.LookAhead(0)))
1369+
{
1370+
cpp_tokent tk2;
1371+
lex.get_token(tk2);
1372+
1373+
declarator.name() = cpp_namet(tk2.data.get(ID_C_base_name));
1374+
set_location(declarator.name(), tk2);
1375+
1376+
add_id(declarator.name(), new_scopet::kindt::TYPE_TEMPLATE_PARAMETER);
1377+
}
1378+
else
13501379
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);
1380+
13551381
if(lex.LookAhead(0)=='=')
13561382
{
1383+
if(declarator.get_has_ellipsis())
1384+
return false;
1385+
13571386
typet default_type;
1387+
13581388
lex.get_token(tk1);
13591389
if(!rTypeName(default_type))
1360-
return false;
1390+
return false;
13611391

1362-
// decl=Ptree::Nconc(decl, Ptree::List(new Leaf(tk1),
1363-
// default_type));
1392+
declarator.value()=exprt(ID_type);
1393+
declarator.value().type().swap(default_type);
13641394
}
13651395
}
13661396
else
@@ -2502,6 +2532,17 @@ bool Parser::optAttribute(typet &t)
25022532
break;
25032533
}
25042534

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

27382779
return true;
27392780
}
2781+
else if(t == TOK_ATOMIC_TYPE_SPECIFIER)
2782+
{
2783+
#ifdef DEBUG
2784+
std::cout << std::string(__indent, ' ')
2785+
<< "Parser::optIntegralTypeOrClassSpec 9\n";
2786+
#endif // DEBUG
2787+
cpp_tokent atomic_tk;
2788+
lex.get_token(atomic_tk);
2789+
2790+
cpp_tokent tk;
2791+
if(lex.get_token(tk)!='(')
2792+
return false;
2793+
2794+
// the argument is always a type
2795+
if(!rTypeSpecifier(p, false))
2796+
return false;
2797+
2798+
if(lex.get_token(tk)!=')')
2799+
return false;
2800+
2801+
return true;
2802+
}
27402803
else
27412804
{
2805+
#ifdef DEBUG
2806+
std::cout << std::string(__indent, ' ')
2807+
<< "Parser::optIntegralTypeOrClassSpec 10\n";
2808+
#endif // DEBUG
27422809
p.make_nil();
27432810
return true;
27442811
}
@@ -3774,7 +3841,7 @@ bool Parser::rName(irept &name)
37743841
components.back().add(ID_expr_arg).swap(expr);
37753842

37763843
if(lex.LookAhead(0) != TOK_SCOPE)
3777-
return false;
3844+
return true;
37783845
}
37793846
break;
37803847

@@ -4549,6 +4616,9 @@ bool Parser::rEnumSpec(typet &spec)
45494616
spec.set(ID_C_class, true);
45504617
}
45514618

4619+
if(!optAttribute(spec))
4620+
return false;
4621+
45524622
if(lex.LookAhead(0)!='{' &&
45534623
lex.LookAhead(0)!=':')
45544624
{
@@ -6721,7 +6791,10 @@ bool Parser::rPostfixExpr(exprt &exp)
67216791
}
67226792

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

67276800
exprt e;
@@ -7903,7 +7976,9 @@ std::optional<codet> Parser::rStatement()
79037976
if(!rUsing(cpp_using))
79047977
return {};
79057978

7906-
UNIMPLEMENTED;
7979+
codet statement(ID_cpp_using);
7980+
// UNIMPLEMENTED;
7981+
return std::move(statement);
79077982
}
79087983

79097984
case TOK_STATIC_ASSERT:
@@ -7920,6 +7995,14 @@ std::optional<codet> Parser::rStatement()
79207995
return std::move(statement);
79217996
}
79227997

7998+
case '[':
7999+
{
8000+
typet discard;
8001+
if(!optAttribute(discard))
8002+
return {};
8003+
return code_blockt{};
8004+
}
8005+
79238006
default:
79248007
return rExprStatement();
79258008
}

0 commit comments

Comments
 (0)