cprover
Loading...
Searching...
No Matches
parse.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: C++ Language Parsing
4
5Author: Daniel Kroening, kroening@cs.cmu.edu
6
7\*******************************************************************/
8
11
12#include "cpp_parser.h"
13
14#include <map>
15
16#include <util/c_types.h>
17#include <util/std_code.h>
18
19#include <ansi-c/ansi_c_y.tab.h>
20#include <ansi-c/merged_type.h>
21
22#include "cpp_token_buffer.h"
23#include "cpp_member_spec.h"
24#include "cpp_enum_type.h"
25
26#ifdef DEBUG
27#include <iostream>
28
29static unsigned __indent;
30
31struct indenter // NOLINT(readability/identifiers)
32{
33 indenter() { __indent+=2; }
34 ~indenter() { __indent-=2; }
35};
36
37#define TOK_TEXT \
38{ \
39 cpp_tokent _tk; \
40 lex.LookAhead(0, _tk); \
41 std::cout << std::string(__indent, ' ') << "Text [" << _tk.line_no << "]: " \
42 << _tk.text << '\n'; \
43}
44#endif
45
47{
48public:
52
71
74
82
89
90 bool is_named_scope() const
91 {
92 return kind==kindt::NAMESPACE ||
95 }
96
97 static const char *kind2string(kindt kind)
98 {
99 switch(kind)
100 {
101 case kindt::NONE:
102 return "?";
103 case kindt::TEMPLATE:
104 return "TEMPLATE";
105 case kindt::MEMBER:
106 return "MEMBER";
107 case kindt::FUNCTION:
108 return "FUNCTION";
109 case kindt::VARIABLE:
110 return "VARIABLE";
111 case kindt::TYPEDEF:
112 return "TYPEDEF";
113 case kindt::TAG:
114 return "TAG";
115 case kindt::NAMESPACE:
116 return "NAMESPACE";
118 return "CLASS_TEMPLATE";
120 return "MEMBER_TEMPLATE";
122 return "FUNCTION_TEMPLATE";
123 case kindt::BLOCK:
124 return "BLOCK";
126 return "NON_TYPE_TEMPLATE_PARAMETER";
128 return "TYPE_TEMPLATE_PARAMETER";
130 return "TEMPLATE_TEMPLATE_PARAMETER";
131 default:
132 return "";
133 }
134 }
135
136 typedef std::map<irep_idt, new_scopet> id_mapt;
138
139 std::size_t anon_count;
140
142
143 inline void print(std::ostream &out) const
144 {
145 print_rec(out, 0);
146 }
147
149 {
150 ++anon_count;
151 return "#anon"+std::to_string(anon_count);
152 }
153
154 std::string full_name() const
155 {
156 return (parent==nullptr?"":(parent->full_name()+"::"))+
157 id2string(id);
158 }
159
160protected:
161 void print_rec(std::ostream &, unsigned indent) const;
162};
163
165{
166public:
171
173 {
175 }
176
177protected:
180};
181
182void new_scopet::print_rec(std::ostream &out, unsigned indent) const
183{
184 for(id_mapt::const_iterator
185 it=id_map.begin();
186 it!=id_map.end();
187 it++)
188 {
189 out << std::string(indent, ' ') << it->first << ": "
190 << kind2string(it->second.kind) << '\n';
191 it->second.print_rec(out, indent+2);
192 }
193}
194
195class Parser // NOLINT(readability/identifiers)
196{
197public:
206
207 bool operator()();
208
209protected:
212
213 // scopes
218 void make_sub_scope(const irept &name, new_scopet::kindt);
220
224
225 // rules
226 bool rProgram(cpp_itemt &item);
227
228 bool SyntaxError();
229
230 bool rDefinition(cpp_itemt &);
235 bool rTypeSpecifier(typet &, bool);
236 bool isTypeSpecifier();
239 bool rUsing(cpp_usingt &);
244 bool rTempArgList(irept &);
247
253 typet &,
254 typet &);
260 typet &);
261 bool rCondition(exprt &);
263
264 bool isConstructorDecl();
265 bool isPtrToMember(int);
268 bool optCvQualify(typet &);
269 bool optAlignas(typet &);
270 bool rGCCAttribute(typet &);
271 bool optAttribute(typet &);
273 bool rConstructorDecl(
275 typet &,
277 bool optThrowDecl(irept &);
278
279 bool rDeclarators(cpp_declarationt::declaratorst &, bool, bool=false);
280 bool rDeclaratorWithInit(cpp_declaratort &, bool, bool);
281 bool rDeclarator(cpp_declaratort &, DeclKind, bool, bool);
283 bool optPtrOperator(typet &);
285 bool rMemberInit(exprt &);
286
287 bool rName(irept &);
288 bool rOperatorName(irept &);
289 bool rCastOperatorName(irept &);
290 bool rPtrToMember(irept &);
291 bool rTemplateArgs(irept &);
292
293 bool rArgDeclListOrInit(exprt &, bool&, bool);
294 bool rArgDeclList(irept &);
296
298 bool rInitializeExpr(exprt &);
299
300 bool rEnumSpec(typet &);
301 bool rEnumBody(irept &);
302 bool rClassSpec(typet &);
303 bool rBaseSpecifiers(irept &);
304 bool rClassBody(exprt &);
305 bool rClassMember(cpp_itemt &);
307
308 bool rCommaExpression(exprt &);
309
310 bool rExpression(exprt &, bool);
311 bool rConditionalExpr(exprt &, bool);
312 bool rLogicalOrExpr(exprt &, bool);
313 bool rLogicalAndExpr(exprt &, bool);
314 bool rInclusiveOrExpr(exprt &, bool);
315 bool rExclusiveOrExpr(exprt &, bool);
316 bool rAndExpr(exprt &, bool);
317 bool rEqualityExpr(exprt &, bool);
318 bool rRelationalExpr(exprt &, bool);
319 bool rShiftExpr(exprt &, bool);
320 bool rAdditiveExpr(exprt &);
321 bool rMultiplyExpr(exprt &);
322 bool rPmExpr(exprt &);
323 bool rCastExpr(exprt &);
324 bool rTypeName(typet &);
326 bool rUnaryExpr(exprt &);
327 bool rThrowExpr(exprt &);
328 bool rNoexceptExpr(exprt &);
329 bool rSizeofExpr(exprt &);
330 bool rTypeidExpr(exprt &);
331 bool rAlignofExpr(exprt &);
332 bool isAllocateExpr(int);
333 bool rAllocateExpr(exprt &);
334 bool rAllocateType(exprt &, typet &, exprt &);
335 bool rNewDeclarator(typet &);
337 bool rPostfixExpr(exprt &);
338 bool rPrimaryExpr(exprt &);
339 bool rVarName(exprt &);
340 bool rVarNameCore(exprt &);
341 bool maybeTemplateArgs();
342
352
358
360 void SkipTo(int token);
361 bool moreVarName();
362
363 bool rString(cpp_tokent &tk);
364
365 // GCC extensions
367
368 // MSC extensions
373 bool rTypePredicate(exprt &);
374 bool rMSCuuidof(exprt &);
376
377 std::size_t number_of_errors;
379
380 void merge_types(const typet &src, typet &dest);
381
382 void set_location(irept &dest, const cpp_tokent &token)
383 {
384 source_locationt &source_location=
385 static_cast<source_locationt &>(dest.add(ID_C_source_location));
386 source_location.set_file(token.filename);
387 source_location.set_line(token.line_no);
389 source_location.set_function(current_function);
390 }
391
392 void make_subtype(const typet &src, typet &dest)
393 {
394 typet *p=&dest;
395
396 while(!p->id().empty() && p->is_not_nil())
397 {
398 if(p->id()==ID_merged_type)
399 {
400 auto &merged_type = to_merged_type(*p);
401 p = &merged_type.last_type();
402 }
403 else
404 p = &p->add_subtype();
405 }
406
407 *p=src;
408 }
409
410 unsigned int max_errors;
411};
412
413static bool is_identifier(int token)
414{
415 return token == TOK_GCC_IDENTIFIER || token == TOK_MSC_IDENTIFIER;
416}
417
419{
420 irep_idt id;
421
422 if(cpp_name.get_sub().size()==1 &&
423 cpp_name.get_sub().front().id()==ID_name)
424 id=cpp_name.get_sub().front().get(ID_identifier);
425 else
427
428 return add_id(id, kind);
429}
430
432{
434
435 s.kind=kind;
436 s.id=id;
438
439 return s;
440}
441
447
449{
450 new_scopet &s=add_id(id, kind);
451 current_scope=&s;
452}
453
455{
457 return false;
458
459 return true;
460}
461
462void Parser::merge_types(const typet &src, typet &dest)
463{
464 if(src.is_nil())
465 return;
466
467 if(dest.is_nil())
468 dest=src;
469 else
470 {
471 if(dest.id()!=ID_merged_type)
472 {
473 source_locationt location=dest.source_location();
475 tmp.move_to_subtypes(dest);
476 tmp.add_source_location()=location;
477 dest=tmp;
478 }
479
480 // the end of the subtypes container needs to stay the same,
481 // since several analysis functions traverse via the end for
482 // merged_types
483 auto &sub = to_type_with_subtypes(dest).subtypes();
484 sub.emplace(sub.begin(), src);
485 }
486}
487
489{
490#define ERROR_TOKENS 4
491
493
494 for(std::size_t i=0; i<ERROR_TOKENS; i++)
495 lex.LookAhead(i, t[i]);
496
497 if(t[0].kind!='\0')
498 {
499 source_locationt source_location;
500 source_location.set_file(t[0].filename);
501 source_location.set_line(std::to_string(t[0].line_no));
502
503 std::string message = "parse error before '";
504
505 for(std::size_t i=0; i<ERROR_TOKENS; i++)
506 if(t[i].kind!='\0')
507 {
508 if(i!=0)
509 message+=' ';
510 message+=t[i].text;
511 }
512
513 message+="'";
514
515 parser.log.error().source_location = source_location;
516 parser.log.error() << message << messaget::eom;
517 }
518
519 return ++number_of_errors < max_errors;
520}
521
523{
524 while(lex.LookAhead(0)!='\0')
525 if(rDefinition(item))
526 return true;
527 else
528 {
530
531 if(!SyntaxError())
532 return false; // too many errors
533
534 SkipTo(';');
535 lex.get_token(tk); // ignore ';'
536 }
537
538 return false;
539}
540
541/*
542 definition
543 : null.declaration
544 | typedef
545 | template.decl
546 | linkage.spec
547 | namespace.spec
548 | using.declaration
549 | extern.template.decl
550 | declaration
551*/
553{
554 int t=lex.LookAhead(0);
555
556#ifdef DEBUG
557 indenter _i;
558 std::cout << std::string(__indent, ' ') << "Parser::rDefinition 1 " << t
559 << '\n';
560#endif
561
562 if(t==';')
563 return rNullDeclaration(item.make_declaration());
564 else if(t==TOK_TYPEDEF)
565 return rTypedef(item.make_declaration());
566 else if(t==TOK_TEMPLATE)
567 return rTemplateDecl(item.make_declaration());
568 else if(t==TOK_EXTERN && lex.LookAhead(1)==TOK_STRING)
569 return rLinkageSpec(item.make_linkage_spec());
570 else if(t==TOK_EXTERN && lex.LookAhead(1)==TOK_TEMPLATE)
571 return rExternTemplateDecl(item.make_declaration());
572 else if(t==TOK_NAMESPACE)
573 return rNamespaceSpec(item.make_namespace_spec());
574 else if(t==TOK_INLINE && lex.LookAhead(1)==TOK_NAMESPACE)
575 return rNamespaceSpec(item.make_namespace_spec());
576 else if(
577 t == TOK_USING && is_identifier(lex.LookAhead(1)) &&
578 lex.LookAhead(2) == '=')
579 {
580 return rTypedefUsing(item.make_declaration());
581 }
582 else if(t==TOK_USING)
583 return rUsing(item.make_using());
584 else if(t==TOK_STATIC_ASSERT)
585 return rStaticAssert(item.make_static_assert());
586 else
587 return rDeclaration(item.make_declaration());
588}
589
591{
593
594 if(lex.get_token(tk)!=';')
595 return false;
596
597 set_location(decl, tk);
598
599 return true;
600}
601
602/*
603 typedef
604 : TYPEDEF type.specifier declarators ';'
605*/
607{
609
611 return false;
612
613#ifdef DEBUG
614 indenter _i;
615 std::cout << std::string(__indent, ' ') << "Parser::rTypedef 1\n";
616#endif
617
618 declaration=cpp_declarationt();
619 set_location(declaration, tk);
620 declaration.set_is_typedef();
621
622 if(!rTypeSpecifier(declaration.type(), true))
623 return false;
624
625 if(!rDeclarators(declaration.declarators(), true))
626 return false;
627
628 return true;
629}
630
631/*
632 USING Identifier '=' type.specifier ';'
633*/
635{
638
640 return false;
641
642#ifdef DEBUG
643 indenter _i;
644 std::cout << std::string(__indent, ' ') << "Parser::rTypedefUsing 1\n";
645#endif
646
647 declaration=cpp_declarationt();
648 set_location(declaration, tk);
649
650 declaration.type()=typet(ID_typedef);
651
653 return false;
654
655 cpp_declaratort name;
656 name.name()=cpp_namet(tk.data.get(ID_C_base_name));
657 name.type().make_nil();
658
659#ifdef DEBUG
660 std::cout << std::string(__indent, ' ') << "Parser::rTypedefUsing 2\n";
661#endif
662
663 if(lex.get_token(tk)!='=')
664 return false;
665
667 return false;
668
669 merge_types(type_name, declaration.type());
670
671 declaration.declarators().push_back(name);
672
673 if(lex.get_token(tk)!=';')
674 return false;
675
676#ifdef DEBUG
677 std::cout << std::string(__indent, ' ') << "Parser::rTypedefUsing 3\n";
678#endif
679
680 return true;
681}
682
684{
685 cpp_declarationt declaration;
686 if(!rTypedef(declaration))
687 return {};
688
689 return code_frontend_declt(
690 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
691}
692
693/*
694 type.specifier
695 : {cv.qualify} (integral.or.class.spec | name) {cv.qualify}
696*/
698{
699#ifdef DEBUG
700 indenter _i;
701 std::cout << std::string(__indent, ' ') << "Parser::rTypeSpecifier 0\n";
702#endif
703
704 typet cv_q;
705
706 cv_q.make_nil();
707
708 if(!optCvQualify(cv_q))
709 return false;
710
711#ifdef DEBUG
712 std::cout << std::string(__indent, ' ') << "Parser::rTypeSpecifier 0.1\n";
713#endif
714
716 return false;
717
718 if(tspec.is_nil())
719 {
721 lex.LookAhead(0, tk);
722
723#ifdef DEBUG
724 std::cout << std::string(__indent, ' ') << "Parser::rTypeSpecifier 1\n";
725#endif
726
727 if(check)
729 return false;
730
731#ifdef DEBUG
732 std::cout << std::string(__indent, ' ') << "Parser::rTypeSpecifier 2\n";
733#endif
734
735 if(!rName(tspec))
736 return false;
737 }
738
739#ifdef DEBUG
740 std::cout << std::string(__indent, ' ') << "Parser::rTypeSpecifier 3\n";
741#endif
742
743 if(!optCvQualify(cv_q))
744 return false;
745
747
748#ifdef DEBUG
749 std::cout << std::string(__indent, ' ') << "Parser::rTypeSpecifier 4\n";
750#endif
751
752 return true;
753}
754
755// isTypeSpecifier() returns true if the next is probably a type specifier.
756
758{
759 int t=lex.LookAhead(0);
760
761 return is_identifier(t) || t == TOK_SCOPE || t == TOK_CONSTEXPR ||
762 t == TOK_CONST || t == TOK_VOLATILE || t == TOK_RESTRICT ||
763 t == TOK_CHAR || t == TOK_INT || t == TOK_SHORT || t == TOK_LONG ||
764 t == TOK_CHAR16_T || t == TOK_CHAR32_T || t == TOK_WCHAR_T ||
765 t == TOK_COMPLEX // new !!!
766 || t == TOK_SIGNED || t == TOK_UNSIGNED || t == TOK_FLOAT ||
767 t == TOK_DOUBLE || t == TOK_INT8 || t == TOK_INT16 || t == TOK_INT32 ||
768 t == TOK_INT64 || t == TOK_GCC_INT128 || t == TOK_PTR32 ||
769 t == TOK_PTR64 || t == TOK_GCC_FLOAT80 || t == TOK_GCC_FLOAT128 ||
770 t == TOK_VOID || t == TOK_BOOL || t == TOK_CPROVER_BOOL ||
771 t == TOK_CLASS || t == TOK_STRUCT || t == TOK_UNION || t == TOK_ENUM ||
772 t == TOK_INTERFACE || t == TOK_TYPENAME || t == TOK_TYPEOF ||
774}
775
776/*
777 linkage.spec
778 : EXTERN String definition
779 | EXTERN String linkage.body
780*/
782{
784
786 return false;
787
788 if(!rString(tk2))
789 return false;
790
791 linkage_spec=cpp_linkage_spect();
792 set_location(linkage_spec, tk1);
793 linkage_spec.linkage().swap(tk2.data);
794 set_location(linkage_spec.linkage(), tk2);
795
796 if(lex.LookAhead(0)=='{')
797 {
798 if(!rLinkageBody(linkage_spec.items()))
799 return false;
800 }
801 else
802 {
804
805 if(!rDefinition(item))
806 return false;
807
808 linkage_spec.items().push_back(item);
809 }
810
811 return true;
812}
813
814/*
815 namespace.spec
816 : { INLINE } NAMESPACE Identifier definition
817 | { INLINE } NAMESPACE Identifier = name
818 | { INLINE } NAMESPACE { Identifier } linkage.body
819*/
820
822{
824 bool is_inline=false;
825
826 if(lex.LookAhead(0)==TOK_INLINE)
827 {
829 is_inline=true;
830 }
831
833 return false;
834
835 irep_idt name;
836
837 // namespace might be anonymous
838 if(lex.LookAhead(0) != '{')
839 {
841 name=tk2.data.get(ID_C_base_name);
842 else
843 return false;
844 }
845
848 namespace_spec.set_namespace(name);
849 namespace_spec.set_is_inline(is_inline);
850
851 // Tolerate constructs such as:
852 // inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
853 // which occurs in glibc. Obviously we need to better than just throw attribs
854 // away like this in the future.
857 return false;
858
859 switch(lex.LookAhead(0))
860 {
861 case '{':
862 return rLinkageBody(namespace_spec.items());
863
864 case '=': // namespace alias
865 lex.get_token(tk2); // eat =
866 return rName(namespace_spec.alias());
867
868 default:
869 namespace_spec.items().push_back(cpp_itemt());
870 return rDefinition(namespace_spec.items().back());
871 }
872}
873
874/*
875 using.declaration : USING { NAMESPACE } name ';'
876*/
878{
880
882 return false;
883
886
888 {
890 cpp_using.set_namespace(true);
891 }
892
893 if(!rName(cpp_using.name()))
894 return false;
895
896 if(lex.get_token(tk)!=';')
897 return false;
898
899 return true;
900}
901
902/*
903 static_assert.declaration : STATIC_ASSERT ( expression , expression ) ';'
904*/
906{
908
910 return false;
911
912 if(lex.get_token(tk)!='(')
913 return false;
914
915 exprt cond;
916
917 if(!rExpression(cond, false))
918 return false;
919
920 if(lex.get_token(tk)!=',')
921 return false;
922
923 exprt description;
924
925 if(!rExpression(description, false))
926 return false;
927
928 if(lex.get_token(tk)!=')')
929 return false;
930
931 if(lex.get_token(tk)!=';')
932 return false;
933
935 cpp_static_assertt(std::move(cond), std::move(description));
937
938 return true;
939}
940
941/*
942 linkage.body : '{' (definition)* '}'
943
944 Note: this is also used to construct namespace.spec
945*/
947{
948 cpp_tokent op, cp;
949
950 if(lex.get_token(op)!='{')
951 return false;
952
953 items.clear();
954 while(lex.LookAhead(0)!='}')
955 {
957
958 if(!rDefinition(item))
959 {
960 if(!SyntaxError())
961 return false; // too many errors
962
963 SkipTo('}');
965 items.push_back(item);
966 return true; // error recovery
967 }
968
969 items.push_back(item);
970 }
971
973 return true;
974}
975
976/*
977 template.decl
978 : TEMPLATE '<' temp.arg.list '>' declaration
979 | TEMPLATE declaration
980 | TEMPLATE '<' '>' declaration
981
982 The second case is an explicit template instantiation. declaration must
983 be a class declaration. For example,
984
985 template class Foo<int, char>;
986
987 explicitly instantiates the template Foo with int and char.
988
989 The third case is a specialization of a function template. declaration
990 must be a function template. For example,
991
992 template <> int count(String x) { return x.length; }
993*/
995{
997
999 current_scope->id_map.clear();
1000
1001 typet template_type;
1002 if(!rTemplateDecl2(template_type, kind))
1003 return false;
1004
1005 cpp_declarationt body;
1006 if(lex.LookAhead(0)==TOK_USING)
1007 {
1008 if(!rTypedefUsing(body))
1009 return false;
1010 }
1011 else if(!rDeclaration(body))
1012 return false;
1013
1014 // Repackage the decl and body depending upon what kind of template
1015 // declaration was observed.
1016 switch(kind)
1017 {
1018 case tdk_decl:
1019#ifdef DEBUG
1020 std::cout << std::string(__indent, ' ') << "BODY: "
1021 << body.pretty() << '\n';
1022 std::cout << std::string(__indent, ' ') << "TEMPLATE_TYPE: "
1023 << template_type.pretty() << '\n';
1024#endif
1025 body.add(ID_template_type).swap(template_type);
1026 body.set(ID_is_template, true);
1027 decl.swap(body);
1028 break;
1029
1030 case tdk_instantiation:
1031 // Repackage the decl
1032 decl=body;
1033 break;
1034
1035 case tdk_specialization:
1036 body.add(ID_template_type).swap(template_type);
1037 body.set(ID_is_template, true);
1038 decl.swap(body);
1039 break;
1040
1041 case num_tdks:
1042 case tdk_unknown:
1044 break;
1045 }
1046
1047 return true;
1048}
1049
1051{
1052 cpp_tokent tk;
1053
1055 return false;
1056
1057 decl=typet(ID_template);
1058 set_location(decl, tk);
1059
1060 if(lex.LookAhead(0)!='<')
1061 {
1062 // template instantiation
1063 kind=tdk_instantiation;
1064 return true; // ignore TEMPLATE
1065 }
1066
1067 if(lex.get_token(tk)!='<')
1068 return false;
1069
1070 irept &template_parameters=decl.add(ID_template_parameters);
1071
1072 if(!rTempArgList(template_parameters))
1073 return false;
1074
1075 if(lex.get_token(tk)!='>')
1076 return false;
1077
1078 // ignore nested TEMPLATE
1079 while(lex.LookAhead(0)==TOK_TEMPLATE)
1080 {
1081 lex.get_token(tk);
1082 if(lex.LookAhead(0)!='<')
1083 break;
1084
1085 lex.get_token(tk);
1088 return false;
1089
1090 if(lex.get_token(tk)!='>')
1091 return false;
1092 }
1093
1094 if(template_parameters.get_sub().empty())
1095 // template < > declaration
1096 kind=tdk_specialization;
1097 else
1098 // template < ... > declaration
1099 kind=tdk_decl;
1100
1101 return true;
1102}
1103
1104/*
1105 temp.arg.list
1106 : empty
1107 | temp.arg.declaration (',' temp.arg.declaration)*
1108*/
1110{
1111 if(lex.LookAhead(0)=='>')
1112 return true;
1113
1116 return false;
1117
1118 args.get_sub().push_back(get_nil_irep());
1119 args.get_sub().back().swap(a);
1120
1121 while(lex.LookAhead(0)==',')
1122 {
1123 cpp_tokent tk;
1124
1125 lex.get_token(tk);
1127 return false;
1128
1129 args.get_sub().push_back(get_nil_irep());
1130 args.get_sub().back().swap(a);
1131 }
1132
1133 return true;
1134}
1135
1136/*
1137 temp.arg.declaration
1138 : CLASS [Identifier] {'=' type.name}
1139 | CLASS Ellipsis [Identifier]
1140 | type.specifier arg.declarator {'=' conditional.expr}
1141 | template.decl2 CLASS Identifier {'=' type.name}
1142*/
1144{
1145#ifdef DEBUG
1146 indenter _i;
1147 std::cout << std::string(__indent, ' ') << "Parser::rTempArgDeclaration 0\n";
1148#endif
1149
1150 int t0=lex.LookAhead(0);
1151
1152 if((t0==TOK_CLASS || t0==TOK_TYPENAME))
1153 {
1155
1157 lex.get_token(tk1);
1158
1159 declaration=cpp_declarationt();
1160 set_location(declaration, tk1);
1161
1162 declaration.set(ID_is_type, true);
1163 declaration.type()=typet("cpp-template-type");
1164
1165 declaration.declarators().resize(1);
1166 cpp_declaratort &declarator=declaration.declarators().front();
1167
1168 declarator=cpp_declaratort();
1169 declarator.name().make_nil();
1170 declarator.type().make_nil();
1171 set_location(declarator, tk1);
1172
1173 bool has_ellipsis=false;
1174
1175 if(lex.LookAhead(0)==TOK_ELLIPSIS)
1176 {
1178 lex.get_token(tk2);
1179
1180 has_ellipsis=true;
1181 }
1182
1184 {
1186 lex.get_token(tk2);
1187
1188 declarator.name() = cpp_namet(tk2.data.get(ID_C_base_name));
1189 set_location(declarator.name(), tk2);
1190
1192
1193 if(has_ellipsis)
1194 {
1195 // TODO
1196 }
1197 }
1198
1199 if(lex.LookAhead(0)=='=')
1200 {
1201 if(has_ellipsis)
1202 return false;
1203
1205
1206 lex.get_token(tk1);
1208 return false;
1209
1210 declarator.value()=exprt(ID_type);
1211 declarator.value().type().swap(default_type);
1212 }
1213
1214 if(lex.LookAhead(0)==',' ||
1215 lex.LookAhead(0)=='>')
1216 return true;
1217
1218 lex.Restore(pos);
1219 }
1220
1221#ifdef DEBUG
1222 std::cout << std::string(__indent, ' ') << "Parser::rTempArgDeclaration 1\n";
1223#endif
1224
1225 if(t0==TOK_TEMPLATE)
1226 {
1227 TemplateDeclKind kind;
1228
1229 typet template_type;
1230
1231 if(!rTemplateDecl2(template_type, kind))
1232 return false;
1233
1234 // TODO
1235
1237
1239 return false;
1240
1241 // Ptree cspec=new PtreeClassSpec(new LeafReserved(tk1),
1242 // Ptree::Cons(new Leaf(tk2),nil),
1243 // nil);
1244 // decl=Ptree::Snoc(decl, cspec);
1245 if(lex.LookAhead(0)=='=')
1246 {
1248 lex.get_token(tk1);
1250 return false;
1251
1252 // decl=Ptree::Nconc(decl, Ptree::List(new Leaf(tk1),
1253 // default_type));
1254 }
1255 }
1256 else
1257 {
1258#ifdef DEBUG
1259 std::cout << std::string(__indent, ' ')
1260 << "Parser::rTempArgDeclaration 2\n";
1261#endif
1262
1263 declaration=cpp_declarationt();
1264 declaration.set(ID_is_type, false);
1265
1266 if(!rTypeSpecifier(declaration.type(), true))
1267 return false;
1268
1269#ifdef DEBUG
1270 std::cout << std::string(__indent, ' ')
1271 << "Parser::rTempArgDeclaration 3\n";
1272#endif
1273
1274 bool has_ellipsis=false;
1275
1276 if(lex.LookAhead(0)==TOK_ELLIPSIS)
1277 {
1279 lex.get_token(tk2);
1280
1281 has_ellipsis=true;
1282 }
1283
1284 declaration.declarators().resize(1);
1285 cpp_declaratort &declarator=declaration.declarators().front();
1286
1287 if(!rDeclarator(declarator, kArgDeclarator, true, false))
1288 return false;
1289
1290#ifdef DEBUG
1291 std::cout << std::string(__indent, ' ')
1292 << "Parser::rTempArgDeclaration 4\n";
1293#endif
1294
1296
1297 if(has_ellipsis)
1298 {
1299 // TODO
1300 }
1301
1302 exprt &value=declarator.value();
1303
1304 if(lex.LookAhead(0)=='=')
1305 {
1306 if(has_ellipsis)
1307 return false;
1308
1309 cpp_tokent tk;
1310
1311 lex.get_token(tk);
1312 if(!rConditionalExpr(value, true))
1313 return false;
1314 }
1315 else
1316 value.make_nil();
1317 }
1318
1319 return true;
1320}
1321
1322/*
1323 extern.template.decl
1324 : EXTERN TEMPLATE declaration
1325*/
1327{
1329
1331 return false;
1332
1334 return false;
1335
1336 if(!rDeclaration(decl))
1337 return false;
1338
1339 // decl=new PtreeExternTemplate(new Leaf(tk1),
1340 // Ptree::List(new Leaf(tk2), body));
1341 return true;
1342}
1343
1344/*
1345 declaration
1346 : integral.declaration
1347 | const.declaration
1348 | other.declaration
1349
1350 decl.head
1351 : {member.spec} {storage.spec} {member.spec} {cv.qualify}
1352
1353 integral.declaration
1354 : integral.decl.head declarators (';' | function.body)
1355 | integral.decl.head ';'
1356 | integral.decl.head ':' expression ';'
1357
1358 integral.decl.head
1359 : decl.head integral.or.class.spec {cv.qualify}
1360
1361 other.declaration
1362 : decl.head name {cv.qualify} declarators (';' | function.body)
1363 | decl.head name constructor.decl (';' | function.body)
1364 | FRIEND name ';'
1365
1366 const.declaration
1367 : cv.qualify {'*'} Identifier '=' expression {',' declarators} ';'
1368
1369 Note: if you modify this function, look at declaration.statement, too.
1370 Note: this regards a statement like "T (a);" as a constructor
1371 declaration. See isConstructorDecl().
1372*/
1373
1375{
1376#ifdef DEBUG
1377 indenter _i;
1378 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 0.1 token: "
1379 << lex.LookAhead(0) << '\n';
1380#endif
1381
1382 if(!optAttribute(declaration.type()))
1383 return false;
1384
1385 cpp_member_spect member_spec;
1386 if(!optMemberSpec(member_spec))
1387 return false;
1388
1389#ifdef DEBUG
1390 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 0.2\n";
1391#endif
1392
1393 cpp_storage_spect storage_spec;
1394 if(!optStorageSpec(storage_spec))
1395 return false;
1396
1397#ifdef DEBUG
1398 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 1\n";
1399#endif
1400
1401 if(member_spec.is_empty())
1402 if(!optMemberSpec(member_spec))
1403 return false;
1404
1405#ifdef DEBUG
1406 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 3\n";
1407#endif
1408
1410 cv_q.make_nil();
1411
1412 if(!optCvQualify(cv_q))
1413 return false;
1414
1415 if(member_spec.is_empty())
1416 if(!optMemberSpec(member_spec))
1417 return false;
1418
1419 // added these two to do "const static volatile int i=1;"
1420 if(!optStorageSpec(storage_spec))
1421 return false;
1422
1423 if(!optCvQualify(cv_q))
1424 return false;
1425
1426#ifdef DEBUG
1427 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 4\n";
1428#endif
1429
1431 return false;
1432
1433 // added this one to do "void inline foo();"
1434 if(member_spec.is_empty())
1435 if(!optMemberSpec(member_spec))
1436 return false;
1437
1438 if(integral.is_not_nil())
1439 {
1440#ifdef DEBUG
1441 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 5\n";
1442#endif
1443 return
1445 declaration, storage_spec, member_spec, integral, cv_q);
1446 }
1447 else
1448 {
1449 int t=lex.LookAhead(0);
1450
1451#ifdef DEBUG
1452 std::cout << std::string(__indent, ' ') << "Parser::rDeclaration 6 " << t
1453 << '\n';
1454#endif
1455
1456 if(
1457 cv_q.is_not_nil() &&
1458 ((is_identifier(t) && lex.LookAhead(1) == '=') || t == '*'))
1459 {
1460 return rConstDeclaration(declaration);
1461 }
1462 else
1463 return rOtherDeclaration(declaration, storage_spec, member_spec, cv_q);
1464 }
1465}
1466
1467/* single declaration, for use in a condition (controlling
1468 expression of switch/while/if) */
1470{
1472
1473 /* no member specification permitted here, and no
1474 storage specifier:
1475 type-specifier ::=
1476 simple-type-specifier
1477 class-specifier
1478 enum-specifier
1479 elaborated-type-specifier
1480 cv-qualifier */
1481
1482 cv_q.make_nil();
1483
1484 if(!optCvQualify(cv_q))
1485 return false;
1486
1488 return false;
1489
1490 if(integral.is_nil() &&
1491 !rName(integral))
1492 return false;
1493
1494 if(cv_q.is_not_nil() && integral.is_not_nil())
1496 else if(cv_q.is_not_nil() && integral.is_nil())
1497 integral.swap(cv_q);
1498
1499 /* no type-specifier so far -> can't be a declaration */
1500 if(integral.is_nil())
1501 return false;
1502
1504
1505 declaration.type().swap(integral);
1506
1507 cpp_declaratort declarator;
1508 if(!rDeclarator(declarator, kDeclarator, true, true))
1509 return false;
1510
1511 // there really _has_ to be an initializer!
1512
1513 if(lex.LookAhead(0)!='=')
1514 return false;
1515
1517 lex.get_token(eqs);
1518
1519 if(!rExpression(declarator.value(), false))
1520 return false;
1521
1522 declaration.declarators().push_back(declarator);
1523
1524 return true;
1525}
1526
1528 cpp_declarationt &declaration,
1529 cpp_storage_spect &storage_spec,
1530 cpp_member_spect &member_spec,
1531 typet &integral,
1532 typet &cv_q)
1533{
1534#ifdef DEBUG
1535 indenter _i;
1536 std::cout << std::string(__indent, ' ')
1537 << "Parser::rIntegralDeclaration 1 token: "
1538 << static_cast<char>(lex.LookAhead(0)) << '\n';
1539#endif
1540
1541 if(!optCvQualify(cv_q))
1542 return false;
1543
1544#ifdef DEBUG
1545 std::cout << std::string(__indent, ' ') << "Parser::rIntegralDeclaration 2\n";
1546#endif
1547
1549
1550#ifdef DEBUG
1551 std::cout << std::string(__indent, ' ') << "Parser::rIntegralDeclaration 3\n";
1552#endif
1553
1554 declaration.type().swap(integral);
1555 declaration.storage_spec().swap(storage_spec);
1556 declaration.member_spec().swap(member_spec);
1557
1558 cpp_tokent tk;
1559
1560 switch(lex.LookAhead(0))
1561 {
1562 case ';':
1563#ifdef DEBUG
1564 std::cout << std::string(__indent, ' ')
1565 << "Parser::rIntegralDeclaration 4\n";
1566#endif
1567
1568 lex.get_token(tk);
1569 return true;
1570
1571 case ':': // bit field
1572#ifdef DEBUG
1573 std::cout << std::string(__indent, ' ')
1574 << "Parser::rIntegralDeclaration 5\n";
1575#endif
1576
1577 lex.get_token(tk);
1578
1579 {
1580 exprt width;
1581
1582 if(!rExpression(width, false))
1583 return false;
1584
1585 if(lex.get_token(tk)!=';')
1586 return false;
1587
1588 // TODO
1589 }
1590 return true;
1591
1592 default:
1593#ifdef DEBUG
1594 std::cout << std::string(__indent, ' ') << "Parser::rIntegralDeclaration 6 "
1595 << lex.LookAhead(0) << '\n';
1596#endif
1597
1598 if(!rDeclarators(declaration.declarators(), true))
1599 return false;
1600
1601 // handle trailing return type
1602 if(
1603 declaration.type().id() == ID_auto &&
1604 declaration.declarators().size() == 1 &&
1605 declaration.declarators().front().type().id() == ID_function_type &&
1606 declaration.declarators().front().type().add_subtype().is_not_nil())
1607 {
1608 declaration.type() =
1609 to_type_with_subtype(declaration.declarators().front().type())
1610 .subtype();
1611 declaration.declarators().front().type().add_subtype().make_nil();
1612 }
1613
1614#ifdef DEBUG
1615 std::cout << std::string(__indent, ' ')
1616 << "Parser::rIntegralDeclaration 7\n";
1617#endif
1618
1619 if(lex.LookAhead(0)==';')
1620 {
1621#ifdef DEBUG
1622 std::cout << std::string(__indent, ' ')
1623 << "Parser::rIntegralDeclaration 8 "
1624 << declaration.pretty() << '\n';
1625#endif
1626 lex.get_token(tk);
1627 return true;
1628 }
1629 else
1630 {
1631#ifdef DEBUG
1632 std::cout << std::string(__indent, ' ')
1633 << "Parser::rIntegralDeclaration 9\n";
1634#endif
1635
1636 if(declaration.declarators().size()!=1)
1637 return false;
1638
1639 if(!rFunctionBody(declaration.declarators().front()))
1640 return false;
1641
1642#ifdef DEBUG
1643 std::cout << std::string(__indent, ' ')
1644 << "Parser::rIntegralDeclaration 10\n";
1645#endif
1646
1647 return true;
1648 }
1649 }
1650}
1651
1653{
1654#ifdef DEBUG
1655 indenter _i;
1656 std::cout << std::string(__indent, ' ') << "Parser::rConstDeclaration\n";
1657#endif
1658
1659 if(!rDeclarators(declaration.declarators(), false))
1660 return false;
1661
1662 if(lex.LookAhead(0)!=';')
1663 return false;
1664
1665 cpp_tokent tk;
1666 lex.get_token(tk);
1667
1668 return true;
1669}
1670
1672 cpp_declarationt &declaration,
1673 cpp_storage_spect &storage_spec,
1674 cpp_member_spect &member_spec,
1675 typet &cv_q)
1676{
1678
1679#ifdef DEBUG
1680 indenter _i;
1681 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 1\n";
1682#endif
1683
1684 if(!rName(type_name))
1685 return false;
1686
1688
1689#ifdef DEBUG
1690 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 2\n";
1691#endif
1692
1693 // added this one to do "typename inline foo();"
1694 if(member_spec.is_empty())
1695 if(!optMemberSpec(member_spec))
1696 return false;
1697
1698 // this allows "typename static foo();"
1699 if(storage_spec.is_empty())
1700 if(!optStorageSpec(storage_spec))
1701 return false;
1702
1703#ifdef DEBUG
1704 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 3\n";
1705#endif
1706
1708 bool is_operator = false;
1709
1710 if(is_constructor)
1711 {
1712#ifdef DEBUG
1713 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 4\n";
1714#endif
1715
1716 DATA_INVARIANT(!type_name.get_sub().empty(), "type name details expected");
1717
1718 for(std::size_t i=0; i < type_name.get_sub().size(); i++)
1719 {
1720 if(type_name.get_sub()[i].id() == ID_operator)
1721 {
1722 is_operator = true;
1723 break;
1724 }
1725 }
1726 }
1727
1729 {
1730#ifdef DEBUG
1731 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 5\n";
1732#endif
1733
1734 // it's a conversion operator
1735 typet type = type_name;
1736 type.get_sub().erase(type.get_sub().begin());
1737
1740 if(!rConstructorDecl(
1742 return false;
1743
1744 type_name=typet("cpp-cast-operator");
1745
1746 declaration.declarators().push_back(conv_operator_declarator);
1747 }
1748 else if(cv_q.is_nil() && is_constructor)
1749 {
1750#ifdef DEBUG
1751 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 6\n";
1752#endif
1753
1754 DATA_INVARIANT(!type_name.get_sub().empty(), "type name details expected");
1755
1756 bool is_destructor=false;
1757 for(const auto &irep : type_name.get_sub())
1758 {
1759 if(irep.id() == "~")
1760 {
1761 is_destructor=true;
1762 break;
1763 }
1764 }
1765
1768 if(!rConstructorDecl(
1770 return false;
1771
1772#ifdef DEBUG
1773 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 7\n";
1774#endif
1775
1776 // type_name above is the name declarator, not the return type
1777 if(storage_spec.is_auto())
1779 else
1781
1782 declaration.declarators().push_back(constructor_declarator);
1783 }
1784 else if(!member_spec.is_empty() && lex.LookAhead(0)==';')
1785 {
1786#ifdef DEBUG
1787 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 8\n";
1788#endif
1789
1790 // FRIEND name ';'
1791 // if(Ptree::Length(member_spec)==1 && member_spec->Car()->What()==FRIEND)
1792 {
1793 cpp_tokent tk;
1794 lex.get_token(tk);
1795 // statement=new PtreeDeclaration(head, Ptree::List(type_name,
1796 // new Leaf(tk)));
1797 return true;
1798 }
1799 // else
1800 // return false;
1801 }
1802 else
1803 {
1804#ifdef DEBUG
1805 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 9\n";
1806#endif
1807
1808 if(!optCvQualify(cv_q))
1809 return false;
1810
1812
1813 if(!rDeclarators(declaration.declarators(), false))
1814 return false;
1815 }
1816
1817 declaration.type().swap(type_name);
1818 declaration.storage_spec().swap(storage_spec);
1819 declaration.member_spec().swap(member_spec);
1820
1821#ifdef DEBUG
1822 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 10\n";
1823#endif
1824
1825 if(lex.LookAhead(0)==';')
1826 {
1827#ifdef DEBUG
1828 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 11\n";
1829#endif
1830
1831 cpp_tokent tk;
1832 lex.get_token(tk);
1833 }
1834 else
1835 {
1836#ifdef DEBUG
1837 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclaration 12\n";
1838#endif
1839
1840 if(declaration.declarators().size()!=1)
1841 return false;
1842
1843 if(!rFunctionBody(declaration.declarators().front()))
1844 return false;
1845 }
1846
1847 return true;
1848}
1849
1850/*
1851 This returns true for an declaration like:
1852 T (a);
1853 even if a is not a type name. This is a bug according to the ANSI
1854 specification, but I believe none says "T (a);" for a variable
1855 declaration.
1856*/
1858{
1859#ifdef DEBUG
1860 indenter _i;
1861 std::cout << std::string(__indent, ' ') << "Parser::isConstructorDecl "
1862 << lex.LookAhead(0) << " " << lex.LookAhead(1) << '\n';
1863#endif
1864
1865 if(lex.LookAhead(0)!='(')
1866 return false;
1867 else
1868 {
1869 int t=lex.LookAhead(1);
1870 if(t=='*' || t=='&' || t=='(')
1871 return false; // it's a declarator
1872 else if(t==TOK_STDCALL || t==TOK_FASTCALL || t==TOK_CLRCALL || t==TOK_CDECL)
1873 return false; // it's a declarator
1874 else if(isPtrToMember(1))
1875 return false; // declarator (::*)
1876 else if(is_identifier(t))
1877 {
1878 // Ambiguous. Do some more look-ahead.
1879 if(lex.LookAhead(2)==')' &&
1880 lex.LookAhead(3)=='(')
1881 return false; // must be declarator (decl)(...)
1882 }
1883
1884 // maybe constructor
1885 return true;
1886 }
1887}
1888
1889/*
1890 ptr.to.member
1891 : {'::'} (identifier {'<' any* '>'} '::')+ '*'
1892*/
1894{
1895 int t0=lex.LookAhead(i++);
1896
1897 if(t0==TOK_SCOPE)
1898 t0=lex.LookAhead(i++);
1899
1900 while(is_identifier(t0))
1901 {
1902 int t=lex.LookAhead(i++);
1903 if(t=='<')
1904 {
1905 int n=1;
1906 while(n > 0)
1907 {
1908 int u=lex.LookAhead(i++);
1909 if(u=='<')
1910 ++n;
1911 else if(u=='>')
1912 --n;
1913 else if(u=='(')
1914 {
1915 int m=1;
1916 while(m > 0)
1917 {
1918 int v=lex.LookAhead(i++);
1919 if(v=='(')
1920 ++m;
1921 else if(v==')')
1922 --m;
1923 else if(v=='\0' || v==';' || v=='}')
1924 return false;
1925 }
1926 }
1927 else if(u=='\0' || u==';' || u=='}')
1928 return false;
1929 }
1930
1931 t=lex.LookAhead(i++);
1932 }
1933
1934 if(t!=TOK_SCOPE)
1935 return false;
1936
1937 t0=lex.LookAhead(i++);
1938
1939 if(t0=='*')
1940 return true;
1941 }
1942
1943 return false;
1944}
1945
1946/*
1947 member.spec
1948 : (FRIEND | INLINE | VIRTUAL | EXPLICIT)+
1949*/
1951{
1952 member_spec.clear();
1953
1954 int t=lex.LookAhead(0);
1955
1956 while(
1957 t == TOK_FRIEND || t == TOK_INLINE || t == TOK_VIRTUAL ||
1958 t == TOK_EXPLICIT || t == TOK_MSC_FORCEINLINE)
1959 {
1960 cpp_tokent tk;
1961 lex.get_token(tk);
1962
1963 switch(t)
1964 {
1965 case TOK_INLINE:
1967 member_spec.set_inline(true);
1968 break;
1969 case TOK_VIRTUAL: member_spec.set_virtual(true); break;
1970 case TOK_FRIEND: member_spec.set_friend(true); break;
1971 case TOK_EXPLICIT: member_spec.set_explicit(true); break;
1972 default: UNREACHABLE;
1973 }
1974
1975 t=lex.LookAhead(0);
1976 }
1977
1978 return true;
1979}
1980
1981/*
1982 storage.spec : STATIC | EXTERN | AUTO | REGISTER | MUTABLE | ASM |
1983 THREAD_LOCAL
1984*/
1986{
1987 int t=lex.LookAhead(0);
1988
1989 if(t==TOK_STATIC ||
1990 t==TOK_EXTERN ||
1991 (t == TOK_AUTO && !ansi_c_parser.cpp11) ||
1992 t==TOK_REGISTER ||
1993 t==TOK_MUTABLE ||
1994 t==TOK_GCC_ASM ||
1996 {
1997 cpp_tokent tk;
1998 lex.get_token(tk);
1999
2000 switch(t)
2001 {
2002 case TOK_STATIC: storage_spec.set_static(); break;
2003 case TOK_EXTERN: storage_spec.set_extern(); break;
2004 case TOK_AUTO: storage_spec.set_auto(); break;
2005 case TOK_REGISTER: storage_spec.set_register(); break;
2006 case TOK_MUTABLE: storage_spec.set_mutable(); break;
2007 case TOK_GCC_ASM: storage_spec.set_asm(); break;
2008 case TOK_THREAD_LOCAL: storage_spec.set_thread_local(); break;
2009 default: UNREACHABLE;
2010 }
2011
2012 set_location(storage_spec, tk);
2013 }
2014
2015 return true;
2016}
2017
2018/*
2019 cv.qualify : (CONSTEXPR | CONST | VOLATILE | RESTRICT)+
2020*/
2022{
2023 for(;;)
2024 {
2025 int t=lex.LookAhead(0);
2026 if(t==TOK_CONSTEXPR ||
2027 t==TOK_CONST || t==TOK_VOLATILE || t==TOK_RESTRICT ||
2028 t==TOK_PTR32 || t==TOK_PTR64 ||
2030 {
2031 cpp_tokent tk;
2032 lex.get_token(tk);
2033 typet p;
2034
2035 switch(t)
2036 {
2037 case TOK_CONSTEXPR:
2039 set_location(p, tk);
2040 merge_types(p, cv);
2041 break;
2042
2043 case TOK_CONST:
2044 p=typet(ID_const);
2045 set_location(p, tk);
2046 merge_types(p, cv);
2047 break;
2048
2049 case TOK_VOLATILE:
2050 p=typet(ID_volatile);
2051 set_location(p, tk);
2052 merge_types(p, cv);
2053 break;
2054
2055 case TOK_RESTRICT:
2056 p=typet(ID_restrict);
2057 set_location(p, tk);
2058 merge_types(p, cv);
2059 break;
2060
2061 case TOK_PTR32:
2062 p=typet(ID_ptr32);
2063 set_location(p, tk);
2064 merge_types(p, cv);
2065 break;
2066
2067 case TOK_PTR64:
2068 p=typet(ID_ptr64);
2069 set_location(p, tk);
2070 merge_types(p, cv);
2071 break;
2072
2073 case TOK_GCC_ATTRIBUTE:
2074 if(!rGCCAttribute(cv))
2075 return false;
2076 break;
2077
2078 case TOK_GCC_ASM:
2079 // asm post-declarator
2080 // this is stuff like
2081 // int x __asm("asd")=1, y;
2082 if(lex.get_token(tk)!='(')
2083 return false;
2084 if(!rString(tk))
2085 return false;
2086 if(lex.get_token(tk)!=')')
2087 return false;
2088 break;
2089
2090 default:
2092 break;
2093 }
2094 }
2095 else
2096 break;
2097 }
2098
2099 return true;
2100}
2101
2102/*
2103 dcl.align
2104 : ALIGNAS unary.expr
2105 | ALIGNAS '(' type.name ')'
2106*/
2108{
2109 if(lex.LookAhead(0)!=TOK_ALIGNAS)
2110 return true;
2111
2112 cpp_tokent tk;
2113 lex.get_token(tk);
2114
2115 if(lex.LookAhead(0)!='(')
2116 return false;
2117
2118 typet tname;
2119 cpp_tokent op, cp;
2120
2122 lex.get_token(op);
2123
2124 if(rTypeName(tname))
2125 {
2126 if(lex.get_token(cp)==')')
2127 {
2128 exprt exp(ID_alignof);
2129 exp.add(ID_type_arg).swap(tname);
2130 set_location(exp, tk);
2131
2134 attr.add(ID_size, exp);
2135
2137
2138 return true;
2139 }
2140 }
2141
2142 lex.Restore(pos);
2143
2144 exprt exp;
2145
2146 if(!rCommaExpression(exp))
2147 return false;
2148
2149 if(lex.get_token(cp)==')')
2150 {
2153 attr.add(ID_size, exp);
2154
2156
2157 return true;
2158 }
2159
2160 return false;
2161}
2162
2164{
2165#ifdef DEBUG
2166 indenter _i;
2167 std::cout << std::string(__indent, ' ') << "Parser::rGCCAttribute "
2168 << lex.LookAhead(0);
2169#endif
2170 cpp_tokent tk;
2171 lex.get_token(tk);
2172
2173 switch(tk.kind)
2174 {
2175 case '(':
2176 if(lex.LookAhead(0)!=')')
2177 rGCCAttribute(t);
2178
2179 if(lex.LookAhead(0)!=')')
2180 return false;
2181 lex.get_token(tk);
2182 return true;
2183
2185 {
2188 merge_types(attr, t);
2189 break;
2190 }
2191
2193 {
2196 merge_types(attr, t);
2197 break;
2198 }
2199
2201 {
2203
2204 if(lex.get_token(tk2)!='(')
2205 return false;
2206
2207 exprt exp;
2208 if(!rCommaExpression(exp))
2209 return false;
2210
2211 if(lex.get_token(tk3)!=')')
2212 return false;
2213
2215 attr.set(ID_size, exp);
2216 attr.add_source_location()=exp.source_location();
2217 merge_types(attr, t);
2218 break;
2219 }
2220
2222 {
2225
2226 if(lex.LookAhead(0)=='(')
2227 {
2229
2230 if(lex.get_token(tk2)!='(')
2231 return false;
2232
2233 exprt exp;
2234 if(!rCommaExpression(exp))
2235 return false;
2236
2237 if(lex.get_token(tk3)!=')')
2238 return false;
2239
2240 attr.add(ID_size, exp);
2241 }
2242
2243 merge_types(attr, t);
2244 break;
2245 }
2246
2248 {
2250
2251 if(lex.get_token(tk2)!='(')
2252 return false;
2253
2254 irept name;
2255 if(!rName(name))
2256 return false;
2257
2258 if(lex.get_token(tk3)!=')')
2259 return false;
2260
2263 attr.set(ID_size, to_cpp_name(name).get_base_name());
2264 merge_types(attr, t);
2265 break;
2266 }
2267
2269 {
2272 merge_types(attr, t);
2273 break;
2274 }
2275
2277 {
2280 merge_types(attr, t);
2281 break;
2282 }
2283
2285 {
2287
2288 if(lex.get_token(tk2)!='(')
2289 return false;
2290
2291 if(!rString(tk3))
2292 return false;
2293
2294 if(lex.get_token(tk4)!=')')
2295 return false;
2296
2299 attr.move_to_sub(tk3.data);
2300 merge_types(attr, t);
2301 break;
2302 }
2303
2305 {
2307
2308 if(lex.get_token(tk2)!='(')
2309 return false;
2310
2311 if(!rString(tk3))
2312 return false;
2313
2314 if(lex.get_token(tk4)!=')')
2315 return false;
2316
2319 attr.move_to_sub(tk3.data);
2320 merge_types(attr, t);
2321 break;
2322 }
2323
2325 {
2328 merge_types(attr, t);
2329 break;
2330 }
2331
2333 {
2336 merge_types(attr, t);
2337 break;
2338 }
2339
2341 {
2344 merge_types(attr, t);
2345 break;
2346 }
2347
2348 case ',':
2349 if(lex.LookAhead(0)==')')
2350 // the scanner ignored an attribute
2351 return true;
2352 break;
2353
2354 default:
2355 return false;
2356 }
2357
2358 if(lex.LookAhead(0)==')')
2359 return true;
2360
2361 return rGCCAttribute(t);
2362}
2363
2365{
2367 {
2368 lex.get_token();
2369
2370 if(!rGCCAttribute(t))
2371 return false;
2372 }
2373
2374 if(lex.LookAhead(0)!='[' ||
2375 lex.LookAhead(1)!='[')
2376 return true;
2377
2378 lex.get_token();
2379 lex.get_token();
2380
2381 for(;;)
2382 {
2383 cpp_tokent tk;
2384 lex.get_token(tk);
2385
2386 switch(tk.kind)
2387 {
2388 case ']':
2389 lex.get_token();
2390 return true;
2391
2392 case TOK_NORETURN:
2393 {
2396 merge_types(attr, t);
2397 break;
2398 }
2399
2400 default:
2401 return false;
2402 }
2403 }
2404}
2405
2406/*
2407
2408 integral.or.class.spec
2409 : (CHAR | CHAR16_T | CHAR32_T | WCHAR_T
2410 | INT | SHORT | LONG | SIGNED | UNSIGNED | FLOAT | DOUBLE
2411 | VOID | BOOLEAN | COMPLEX)+
2412 | class.spec
2413 | enum.spec
2414
2415 Note: if editing this, see also isTypeSpecifier().
2416*/
2418{
2419#ifdef DEBUG
2420 indenter _i;
2421 std::cout << std::string(__indent, ' ')
2422 << "Parser::optIntegralTypeOrClassSpec 0\n";
2423#endif // DEBUG
2424
2425 // This makes no sense, but is used in Visual Studio header files.
2426 if(lex.LookAhead(0)==TOK_TYPENAME)
2427 {
2428 cpp_tokent tk;
2429 lex.get_token(tk);
2430 }
2431
2432 bool is_integral=false;
2433 p.make_nil();
2434
2435 int t;
2436
2437 for(;;)
2438 {
2439 t=lex.LookAhead(0);
2440
2441#ifdef DEBUG
2442 std::cout << std::string(__indent, ' ')
2443 << "Parser::optIntegralTypeOrClassSpec 1\n";
2444#endif // DEBUG
2445
2447
2448 switch(t)
2449 {
2450 case TOK_CHAR: type_id=ID_char; break;
2451 case TOK_CHAR16_T: type_id=ID_char16_t; break;
2452 case TOK_CHAR32_T: type_id=ID_char32_t; break;
2453 case TOK_INT: type_id=ID_int; break;
2454 case TOK_SHORT: type_id=ID_short; break;
2455 case TOK_LONG: type_id=ID_long; break;
2456 case TOK_SIGNED: type_id=ID_signed; break;
2457 case TOK_WCHAR_T: type_id=ID_wchar_t; break;
2458 case TOK_COMPLEX: type_id=ID_complex; break;
2459 case TOK_UNSIGNED: type_id=ID_unsigned; break;
2460 case TOK_FLOAT: type_id=ID_float; break;
2461 case TOK_DOUBLE: type_id=ID_double; break;
2462 case TOK_VOID: type_id=ID_void; break;
2463 case TOK_INT8: type_id=ID_int8; break;
2464 case TOK_INT16: type_id=ID_int16; break;
2465 case TOK_INT32: type_id=ID_int32; break;
2466 case TOK_INT64: type_id=ID_int64; break;
2470 case TOK_BOOL:
2472 break;
2474 case TOK_AUTO: type_id = ID_auto; break;
2475 default: type_id=irep_idt();
2476 }
2477
2478 if(!type_id.empty())
2479 {
2480 cpp_tokent tk;
2481 typet kw;
2482 lex.get_token(tk);
2483 kw=typet(type_id);
2484 set_location(kw, tk);
2485
2486 merge_types(kw, p);
2487
2488 is_integral=true;
2489 }
2490 else
2491 break;
2492 }
2493
2494#ifdef DEBUG
2495 std::cout << std::string(__indent, ' ')
2496 << "Parser::optIntegralTypeOrClassSpec 2\n";
2497#endif // DEBUG
2498
2499 if(is_integral)
2500 return true;
2501
2502#ifdef DEBUG
2503 std::cout << std::string(__indent, ' ')
2504 << "Parser::optIntegralTypeOrClassSpec 3\n";
2505#endif // DEBUG
2506
2507 if(t==TOK_CLASS || t==TOK_STRUCT || t==TOK_UNION || t==TOK_INTERFACE)
2508 return rClassSpec(p);
2509 else if(t==TOK_ENUM)
2510 return rEnumSpec(p);
2511 else if(t==TOK_TYPEOF)
2512 {
2513#ifdef DEBUG
2514 std::cout << std::string(__indent, ' ')
2515 << "Parser::optIntegralTypeOrClassSpec 4\n";
2516#endif // DEBUG
2517
2520
2521#ifdef DEBUG
2522 std::cout << std::string(__indent, ' ')
2523 << "Parser::optIntegralTypeOrClassSpec 5\n";
2524#endif // DEBUG
2525
2526 p=typet(ID_typeof);
2528
2529 cpp_tokent tk;
2530 if(lex.get_token(tk)!='(')
2531 return false;
2532
2533 // the argument can be a type or an expression
2534
2535 {
2536 typet tname;
2538
2539 if(rTypeName(tname))
2540 {
2541 if(lex.get_token(tk)==')')
2542 {
2544 return true;
2545 }
2546 }
2547
2548 lex.Restore(pos);
2549 }
2550
2551#ifdef DEBUG
2552 std::cout << std::string(__indent, ' ')
2553 << "Parser::optIntegralTypeOrClassSpec 6\n";
2554#endif // DEBUG
2555
2556 exprt expr;
2557 if(!rCommaExpression(expr))
2558 return false;
2559
2560#ifdef DEBUG
2561 std::cout << std::string(__indent, ' ')
2562 << "Parser::optIntegralTypeOrClassSpec 7\n";
2563#endif // DEBUG
2564
2565 if(lex.get_token(tk)!=')')
2566 return false;
2567
2568#ifdef DEBUG
2569 std::cout << std::string(__indent, ' ')
2570 << "Parser::optIntegralTypeOrClassSpec 8\n";
2571#endif // DEBUG
2572
2573 p.add(ID_expr_arg).swap(expr);
2574
2575 return true;
2576 }
2577 else if(t==TOK_DECLTYPE)
2578 {
2581
2582 p=typet(ID_decltype);
2584
2585 cpp_tokent tk;
2586 if(lex.get_token(tk)!='(')
2587 return false;
2588
2589 // the argument is always an expression
2590
2591 exprt expr;
2592 if(!rCommaExpression(expr))
2593 return false;
2594
2595 if(lex.get_token(tk)!=')')
2596 return false;
2597
2598 p.add(ID_expr_arg).swap(expr);
2599
2600 return true;
2601 }
2602 else if(t==TOK_UNDERLYING_TYPE)
2603 {
2604 // A Visual Studio extension that returns the underlying
2605 // type of an enum.
2608
2611
2612 cpp_tokent tk;
2613 if(lex.get_token(tk)!='(')
2614 return false;
2615
2616 // the argument is always a type
2617
2618 typet tname;
2619
2620 if(!rTypeName(tname))
2621 return false;
2622
2623 if(lex.get_token(tk)!=')')
2624 return false;
2625
2627
2628 return true;
2629 }
2630 else
2631 {
2632 p.make_nil();
2633 return true;
2634 }
2635}
2636
2637/*
2638 constructor.decl
2639 : '(' {arg.decl.list} ')' {cv.qualify} {throw.decl}
2640 {member.initializers} {'=' Constant}
2641*/
2643 cpp_declaratort &constructor,
2646{
2647#ifdef DEBUG
2648 indenter _i;
2649 std::cout << std::string(__indent, ' ') << "Parser::rConstructorDecl 0\n";
2650#endif
2651
2652 trailing_return_type.make_nil();
2653
2655 constructor.type().add_subtype().make_nil();
2656 constructor.name().swap(type_name);
2657
2658 cpp_tokent op;
2659 if(lex.get_token(op)!='(')
2660 return false;
2661
2662#ifdef DEBUG
2663 std::cout << std::string(__indent, ' ') << "Parser::rConstructorDecl 1\n";
2664#endif
2665
2666 irept &parameters=constructor.type().add(ID_parameters);
2667
2668 if(lex.LookAhead(0)!=')')
2669 if(!rArgDeclList(parameters))
2670 return false;
2671
2672 cpp_tokent cp;
2673 lex.get_token(cp);
2674
2675#ifdef DEBUG
2676 std::cout << std::string(__indent, ' ') << "Parser::rConstructorDecl 2\n";
2677#endif
2678
2679 typet &cv=static_cast<typet &>(constructor.add(ID_method_qualifier));
2680 cv.make_nil();
2682
2683 optThrowDecl(constructor.throw_decl());
2684
2685 if(lex.LookAhead(0)==TOK_ARROW)
2686 {
2687#ifdef DEBUG
2688 std::cout << std::string(__indent, ' ') << "Parser::rConstructorDecl 3\n";
2689#endif
2690
2691 // C++11 trailing return type
2694
2696 return false;
2697 }
2698
2699#ifdef DEBUG
2700 std::cout << std::string(__indent, ' ') << "Parser::rConstructorDecl 4\n";
2701#endif
2702
2703 if(lex.LookAhead(0)==':')
2704 {
2705 irept mi;
2706
2708 constructor.member_initializers().swap(mi);
2709 else
2710 return false;
2711 }
2712
2713#ifdef DEBUG
2714 std::cout << std::string(__indent, ' ') << "Parser::rConstructorDecl 5\n";
2715#endif
2716
2717 if(lex.LookAhead(0)=='=')
2718 {
2719 cpp_tokent eq, value;
2720 lex.get_token(eq);
2721
2722 switch(lex.get_token(value))
2723 {
2724 case TOK_INTEGER:
2725 {
2726 constructor.value()=codet("cpp-pure-virtual");
2727 set_location(constructor.value(), value);
2728 }
2729 break;
2730
2731 case TOK_DEFAULT: // C++0x
2732 {
2733 if(!ansi_c_parser.cpp11)
2734 {
2735 SyntaxError();
2736 return false;
2737 }
2738
2739 constructor.value()=codet(ID_default);
2740 set_location(constructor.value(), value);
2741 }
2742 break;
2743
2744 case TOK_DELETE: // C++0x
2745 {
2746 if(!ansi_c_parser.cpp11)
2747 {
2748 SyntaxError();
2749 return false;
2750 }
2751
2752 constructor.value()=codet(ID_cpp_delete);
2753 set_location(constructor.value(), value);
2754 }
2755 break;
2756
2757 default:
2758 return false;
2759 }
2760 }
2761 else
2762 constructor.add(ID_value).make_nil();
2763
2764 return true;
2765}
2766
2767/*
2768 throw.decl : THROW '(' (name {','})* {name} ')'
2769 | THROW '(' '...' ')'
2770 | NOEXCEPT
2771*/
2773{
2774 cpp_tokent tk;
2775 int t;
2776 irept p=get_nil_irep();
2777
2778 if(lex.LookAhead(0)==TOK_THROW)
2779 {
2780 lex.get_token(tk);
2781 // p=Ptree::Snoc(p, new LeafReserved(tk));
2782
2783 if(lex.get_token(tk)!='(')
2784 return false;
2785
2786 // p=Ptree::Snoc(p, new Leaf(tk));
2787
2788 for(;;)
2789 {
2790 irept q;
2791 t=lex.LookAhead(0);
2792 if(t=='\0')
2793 return false;
2794 else if(t==')')
2795 break;
2796 else if(t==TOK_ELLIPSIS)
2797 {
2798 lex.get_token(tk);
2799 }
2800 else if(rName(q))
2801 {
2802 // p=Ptree::Snoc(p, q);
2803 }
2804 else
2805 return false;
2806
2807 if(lex.LookAhead(0)==',')
2808 {
2809 lex.get_token(tk);
2810 // p=Ptree::Snoc(p, new Leaf(tk));
2811 }
2812 else
2813 break;
2814 }
2815
2816 if(lex.get_token(tk)!=')')
2817 return false;
2818
2819 // p=Ptree::Snoc(p, new Leaf(tk));
2820 }
2821 else if(lex.LookAhead(0)==TOK_NOEXCEPT)
2822 {
2823 exprt expr;
2824
2825 if(!rNoexceptExpr(expr))
2826 return false;
2827
2828 // TODO
2829 }
2830
2831 throw_decl=p;
2832 return true;
2833}
2834
2835/*
2836 declarators : declarator.with.init (',' declarator.with.init)*
2837
2838 is_statement changes the behavior of rArgDeclListOrInit().
2839*/
2841 cpp_declarationt::declaratorst &declarators,
2843 bool is_statement)
2844{
2845 cpp_tokent tk;
2846
2847 for(;;)
2848 {
2849 cpp_declaratort declarator;
2851 return false;
2852
2853 declarators.push_back(declarator);
2854
2855 if(lex.LookAhead(0)==',')
2856 lex.get_token(tk);
2857 else
2858 return true;
2859 }
2860}
2861
2862/*
2863 declarator.with.init
2864 : ':' expression
2865 | declarator
2866 {'=' initialize.expr |
2867 ':' expression}
2868*/
2872 bool is_statement)
2873{
2874 if(lex.LookAhead(0)==':')
2875 {
2876 // This is an anonymous bit field.
2877 cpp_tokent tk;
2878 lex.get_token(tk); // get :
2879
2880 exprt e;
2881 if(!rExpression(e, false))
2882 return false;
2883
2885 bit_field_type.set(ID_size, e);
2886 bit_field_type.add_subtype().make_nil();
2888
2889 dw.type() = std::move(bit_field_type);
2890
2891 return true;
2892 }
2893 else
2894 {
2895 cpp_declaratort declarator;
2896
2897 if(!rDeclarator(
2899 return false;
2900
2901 int t=lex.LookAhead(0);
2902 if(t=='=')
2903 {
2904 // initializer
2905 cpp_tokent tk;
2906 lex.get_token(tk);
2907
2908 if(lex.LookAhead(0)==TOK_DEFAULT) // C++0x
2909 {
2910 if(!ansi_c_parser.cpp11)
2911 {
2912 SyntaxError();
2913 return false;
2914 }
2915
2916 lex.get_token(tk);
2917 declarator.value()=codet(ID_default);
2918 set_location(declarator.value(), tk);
2919 }
2920 else if(lex.LookAhead(0)==TOK_DELETE) // C++0x
2921 {
2922 if(!ansi_c_parser.cpp11)
2923 {
2924 SyntaxError();
2925 return false;
2926 }
2927
2928 lex.get_token(tk);
2929 declarator.value()=codet(ID_cpp_delete);
2930 set_location(declarator.value(), tk);
2931 }
2932 else
2933 {
2934 if(!rInitializeExpr(declarator.value()))
2935 return false;
2936 }
2937 }
2938 else if(t=='{')
2939 {
2940 // Possibly a C++11 list initializer;
2941 // or a function body.
2942
2943 if(declarator.type().id()!=ID_function_type)
2944 {
2945 if(!rInitializeExpr(declarator.value()))
2946 return false;
2947 }
2948 }
2949 else if(t==':')
2950 {
2951 // bit field
2952 cpp_tokent tk;
2953 lex.get_token(tk); // get :
2954
2955 exprt e;
2956 if(!rExpression(e, false))
2957 return false;
2958
2960 bit_field_type.set(ID_size, e);
2961 bit_field_type.add_subtype().make_nil();
2963
2964 merge_types(bit_field_type, declarator.type());
2965 }
2966
2967 dw.swap(declarator);
2968 return true;
2969 }
2970}
2971
2972/* __stdcall, __fastcall, __clrcall, __cdecl
2973
2974 These are Visual-Studio specific.
2975
2976*/
2977
2979{
2980 int t=lex.LookAhead(0);
2981
2982 // we just eat these
2983
2984 while(t==TOK_STDCALL || t==TOK_FASTCALL || t==TOK_CLRCALL || t==TOK_CDECL)
2985 {
2986 cpp_tokent op;
2987 lex.get_token(op);
2988 t=lex.LookAhead(0);
2989 }
2990
2991 return true;
2992}
2993
2994/*
2995 declarator
2996 : (ptr.operator)* (name | '(' declarator ')')
2997 ('[' comma.expression ']')* {func.args.or.init}
2998
2999 func.args.or.init
3000 : '(' arg.decl.list.or.init ')' {cv.qualify} {throw.decl}
3001 {member.initializers}
3002
3003 Note: We assume that '(' declarator ')' is followed by '(' or '['.
3004 This is to avoid accepting a function call F(x) as a pair of
3005 a type F and a declarator x. This assumption is ignored
3006 if should_be_declarator is true.
3007
3008 Note: is_statement changes the behavior of rArgDeclListOrInit().
3009*/
3010
3012 cpp_declaratort &declarator,
3013 DeclKind kind,
3015 bool is_statement)
3016{
3017 int t;
3018
3019#ifdef DEBUG
3020 indenter _i;
3021 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 1\n";
3022#endif
3023
3024 // we can have one or more declarator qualifiers
3026 return false;
3027
3029 irept name;
3030
3031 name.make_nil();
3032 d_outer.make_nil();
3033 d_inner.make_nil();
3034
3036 return false;
3037
3038 // we can have another sequence of declarator qualifiers
3040 return false;
3041
3042#ifdef DEBUG
3043 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 2\n";
3044#endif
3045
3046 t=lex.LookAhead(0);
3047
3048 if(t=='(')
3049 {
3050#ifdef DEBUG
3051 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 3\n";
3052#endif
3053
3054 cpp_tokent op;
3055 lex.get_token(op);
3056
3058 if(!rDeclarator(declarator2, kind, true, false))
3059 return false;
3060
3061#ifdef DEBUG
3062 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 4\n";
3063#endif
3064
3065 cpp_tokent cp;
3066
3067 if(lex.get_token(cp)!=')')
3068 return false;
3069
3071 {
3072 if((kind==kDeclarator || kind==kCastDeclarator) && d_outer.is_nil())
3073 {
3074 t=lex.LookAhead(0);
3075 if(t!='[' && t!='(')
3076 return false;
3077 }
3078 }
3079
3080#ifdef DEBUG
3081 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 5\n";
3082#endif
3083
3084 d_inner.swap(declarator2.type());
3085 name.swap(declarator2.name());
3086 }
3087 else if(
3088 kind != kCastDeclarator &&
3089 (kind == kDeclarator || is_identifier(t) || t == TOK_SCOPE))
3090 {
3091#ifdef DEBUG
3092 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 6\n";
3093#endif
3094
3095 // if this is an argument declarator, "int (*)()" is valid.
3096 if(!rName(name))
3097 return false;
3098 }
3099
3100#ifdef DEBUG
3101 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 7\n";
3102#endif
3103
3104 exprt init_args(static_cast<const exprt &>(get_nil_irep()));
3105 // const...
3106 typet method_qualifier(static_cast<const typet &>(get_nil_irep()));
3107
3108 for(;;)
3109 {
3110 t=lex.LookAhead(0);
3111 if(t=='(') // function
3112 {
3113#ifdef DEBUG
3114 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 8\n";
3115#endif
3116
3117 cpp_tokent op, cp;
3118 exprt args;
3119 bool is_args=true;
3120
3121 lex.get_token(op);
3122
3123 if(lex.LookAhead(0)==')')
3124 args.clear();
3125 else
3127 return false;
3128
3129 if(lex.get_token(cp)!=')')
3130 return false;
3131
3132 if(is_args)
3133 {
3134 typet function_type(ID_function_type);
3135 function_type.add_subtype().swap(d_outer);
3136 function_type.add(ID_parameters).swap(args);
3137
3138 // make this subtype of d_inner
3139 make_subtype(function_type, d_inner);
3140 d_outer.swap(d_inner);
3141
3142 optCvQualify(method_qualifier);
3143 }
3144 else
3145 {
3146 init_args.swap(args);
3147 // loop should end here
3148 }
3149
3150#ifdef DEBUG
3151 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 9\n";
3152#endif
3153
3154 irept throw_decl;
3155 optThrowDecl(throw_decl); // ignore in this version
3156
3157 if(lex.LookAhead(0)==TOK_ARROW)
3158 {
3159#ifdef DEBUG
3160 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 10\n";
3161#endif
3162
3163 // C++11 trailing return type, but we already have
3164 // a return type. We should report this as an error.
3167
3168 typet return_type;
3169 if(!rTypeSpecifier(return_type, false))
3170 return false;
3171
3172 if(d_outer.add_subtype().is_not_nil())
3173 return false;
3174
3175 d_outer.add_subtype().swap(return_type);
3176 }
3177
3178 if(lex.LookAhead(0)==':')
3179 {
3180#ifdef DEBUG
3181 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 11\n";
3182#endif
3183
3184 irept mi;
3186 {
3187 // TODO: these are only meant to show up in a
3188 // constructor!
3189 }
3190 else
3191 return false;
3192 }
3193
3194 break; // "T f(int)(char)" is invalid.
3195 }
3196 else if(t=='[') // array
3197 {
3198#ifdef DEBUG
3199 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 12\n";
3200#endif
3201
3202 cpp_tokent ob, cb;
3203 exprt expr;
3204 lex.get_token(ob);
3205 if(lex.LookAhead(0)==']')
3206 expr.make_nil();
3207 else
3208 if(!rCommaExpression(expr))
3209 return false;
3210
3211 if(lex.get_token(cb)!=']')
3212 return false;
3213
3214 std::list<typet> tl;
3215 tl.push_back(d_outer);
3216 while(tl.back().id() == ID_array)
3217 {
3218 tl.push_back(tl.back().add_subtype());
3219 }
3220
3221 array_typet array_type(tl.back(), expr);
3222 tl.pop_back();
3223 d_outer.swap(array_type);
3224 while(!tl.empty())
3225 {
3226 tl.back().add_subtype().swap(d_outer);
3227 d_outer.swap(tl.back());
3228 tl.pop_back();
3229 }
3230 }
3231 else
3232 break;
3233 }
3234
3236 if(d_outer.is_not_nil() && !d_outer.has_subtypes())
3237 {
3239 merged_type.move_to_subtypes(d_outer);
3240 typet nil;
3241 nil.make_nil();
3242 merged_type.move_to_sub(nil);
3243 d_outer.swap(merged_type);
3244 }
3245
3246#ifdef DEBUG
3247 std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 13\n";
3248#endif
3249
3250 declarator=cpp_declaratort();
3251
3252 declarator.name().swap(name);
3253
3254 if(init_args.is_not_nil())
3255 declarator.init_args().swap(init_args);
3256
3257 if(method_qualifier.is_not_nil())
3258 declarator.method_qualifier().swap(method_qualifier);
3259
3260 declarator.type().swap(d_outer);
3261
3262 return true;
3263}
3264
3265/*
3266 ptr.operator
3267 : (('*' | ptr.to.member)['&'] {cv.qualify})+
3268*/
3270{
3271#ifdef DEBUG
3272 indenter _i;
3273 std::cout << std::string(__indent, ' ') << "Parser::optPtrOperator 1\n";
3274#endif // DEBUG
3275
3276 std::list<typet> t_list;
3277
3278 for(;;)
3279 {
3280 int t=lex.LookAhead(0);
3281
3282#ifdef DEBUG
3283 std::cout << std::string(__indent, ' ') << "Parser::optPtrOperator 2 " << t
3284 << '\n';
3285#endif
3286
3287 if(t=='*')
3288 {
3289 typet op(ID_frontend_pointer); // width gets set during conversion
3290 cpp_tokent tk;
3291 lex.get_token(tk);
3292 set_location(op, tk);
3293
3294 typet cv;
3295 cv.make_nil();
3296 optCvQualify(cv); // the qualifier is for the pointer
3297 if(cv.is_not_nil())
3298 merge_types(cv, op);
3299
3300 t_list.push_back(op);
3301 }
3302 else if(t=='^')
3303 {
3304 // this is an Apple extension called 'block pointer' or 'closure pointer'
3306 cpp_tokent tk;
3307 lex.get_token(tk);
3308 set_location(op, tk);
3309
3310 typet cv;
3311 cv.make_nil();
3312 optCvQualify(cv); // the qualifier is for the pointer
3313 if(cv.is_not_nil())
3314 merge_types(cv, op);
3315
3316 t_list.push_back(op);
3317 }
3318 else if(isPtrToMember(0))
3319 {
3320 typet op;
3321 if(!rPtrToMember(op))
3322 return false;
3323
3324 typet cv;
3325 cv.make_nil();
3326 optCvQualify(cv); // the qualifier is for the pointer
3327 if(cv.is_not_nil())
3328 {
3329 merge_types(op, cv);
3330 t_list.push_back(cv);
3331 }
3332 else
3333 t_list.push_back(op);
3334 }
3335 else
3336 break;
3337 }
3338
3339 {
3340 int t=lex.LookAhead(0);
3341
3342 if(t=='&')
3343 {
3344 cpp_tokent tk;
3345 lex.get_token(tk);
3346 typet op(ID_frontend_pointer); // width gets set during conversion
3347 op.set(ID_C_reference, true);
3348 set_location(op, tk);
3349 t_list.push_front(op);
3350 }
3351 else if(t==TOK_ANDAND) // &&, these are C++0x rvalue refs
3352 {
3353 cpp_tokent tk;
3354 lex.get_token(tk);
3355 typet op(ID_frontend_pointer); // width gets set during conversion
3356 op.set(ID_C_rvalue_reference, true);
3357 set_location(op, tk);
3358 t_list.push_front(op);
3359 }
3360 }
3361
3362 for(std::list<typet>::reverse_iterator
3363 it=t_list.rbegin();
3364 it!=t_list.rend();
3365 it++)
3366 {
3367 if(it->id()==ID_merged_type)
3368 {
3369 auto &merged_type = to_merged_type(*it);
3370 merged_type.last_type().add_subtype().swap(ptrs);
3371 }
3372 else
3373 {
3374 DATA_INVARIANT(it->is_not_nil(), "must not be nil");
3375 it->add_subtype().swap(ptrs);
3376 }
3377
3378 ptrs.swap(*it);
3379 }
3380
3381 return true;
3382}
3383
3384/*
3385 member.initializers
3386 : ':' member.init (',' member.init)*
3387*/
3389{
3390 cpp_tokent tk;
3391
3392 if(lex.get_token(tk)!=':')
3393 return false;
3394
3396 set_location(init, tk);
3397
3398 exprt m;
3399 if(!rMemberInit(m))
3400 return false;
3401
3402 init.move_to_sub(m);
3403
3404 while(lex.LookAhead(0)==',')
3405 {
3406 lex.get_token(tk);
3407 if(!rMemberInit(m))
3408 return false;
3409
3410 init.move_to_sub(m);
3411 }
3412
3413 return true;
3414}
3415
3416/*
3417 member.init
3418 : name '(' function.arguments ')'
3419 : name '(' '{' initialize.expr ... '}' ')'
3420*/
3422{
3423#ifdef DEBUG
3424 indenter _i;
3425 std::cout << std::string(__indent, ' ') << "Parser::rMemberInit 1\n";
3426#endif
3427
3428 irept name;
3429
3430 if(!rName(name))
3431 return false;
3432
3433#ifdef DEBUG
3434 std::cout << std::string(__indent, ' ') << "Parser::rMemberInit 2\n";
3435#endif
3436
3438 init.add(ID_member).swap(name);
3439
3441 lex.get_token(tk1);
3442 set_location(init, tk1);
3443
3444 if(tk1.kind=='{' ||
3445 (tk1.kind=='(' && lex.LookAhead(0)=='{'))
3446 {
3447#ifdef DEBUG
3448 std::cout << std::string(__indent, ' ') << "Parser::rMemberInit 3\n";
3449#endif
3450 exprt exp;
3451 if(!rInitializeExpr(exp))
3452 return false;
3453
3454 init.operands().push_back(exp);
3455
3456 // read closing parenthesis
3457 lex.get_token(tk2);
3458 if(tk2.kind!='}' && tk2.kind!=')')
3459 return false;
3460 }
3461 else
3462 {
3463 if(tk1.kind!='(')
3464 return false;
3465
3466#ifdef DEBUG
3467 std::cout << std::string(__indent, ' ') << "Parser::rMemberInit 4\n";
3468#endif
3469
3470 exprt args;
3471
3472 if(!rFunctionArguments(args))
3473 return false;
3474
3475 init.operands().swap(args.operands());
3476
3477 // read closing parenthesis
3478 if(lex.get_token(tk2)!=')')
3479 return false;
3480 }
3481
3482 if(lex.LookAhead(0)==TOK_ELLIPSIS)
3483 {
3484 lex.get_token();
3485
3486 // TODO
3487 }
3488
3489 return true;
3490}
3491
3492/*
3493 name : {'::'} name2 ('::' name2)*
3494
3495 name2
3496 : Identifier {template.args}
3497 | '~' Identifier
3498 | OPERATOR operator.name {template.args}
3499
3500 Don't use this function for parsing an expression
3501 It always regards '<' as the beginning of template arguments.
3502*/
3504{
3505#ifdef DEBUG
3506 indenter _i;
3507 std::cout << std::string(__indent, ' ') << "Parser::rName 0\n";
3508#endif
3509
3510 name=cpp_namet();
3511 irept::subt &components=name.get_sub();
3512
3513 if(lex.LookAhead(0)==TOK_TYPENAME)
3514 {
3515 cpp_tokent tk;
3516 lex.get_token(tk);
3517 name.set(ID_typename, true);
3518 }
3519
3520 {
3521 cpp_tokent tk;
3522 lex.LookAhead(0, tk);
3523 set_location(name, tk);
3524 }
3525
3526#ifdef DEBUG
3527 std::cout << std::string(__indent, ' ') << "Parser::rName 1\n";
3528#endif
3529
3530 for(;;)
3531 {
3532 cpp_tokent tk;
3533
3534#ifdef DEBUG
3535 std::cout << std::string(__indent, ' ') << "Parser::rName 2 "
3536 << lex.LookAhead(0) << '\n';
3537#endif
3538
3539 switch(lex.LookAhead(0))
3540 {
3541 case TOK_TEMPLATE:
3542#ifdef DEBUG
3543 std::cout << std::string(__indent, ' ') << "Parser::rName 3\n";
3544#endif
3545 lex.get_token(tk);
3546 // Skip template token, next will be identifier
3547 if(!is_identifier(lex.LookAhead(0)))
3548 return false;
3549 break;
3550
3551 case '<':
3552#ifdef DEBUG
3553 std::cout << std::string(__indent, ' ') << "Parser::rName 4\n";
3554#endif
3555 {
3556 irept args;
3557 if(!rTemplateArgs(args))
3558 return false;
3559
3560 components.push_back(irept(ID_template_args));
3561 components.back().add(ID_arguments).swap(args);
3562
3563 // done unless scope is next
3564 if(lex.LookAhead(0)!=TOK_SCOPE)
3565 return true;
3566 }
3567 break;
3568
3569 case TOK_GCC_IDENTIFIER:
3570 case TOK_MSC_IDENTIFIER:
3571#ifdef DEBUG
3572 std::cout << std::string(__indent, ' ') << "Parser::rName 5\n";
3573#endif
3574 lex.get_token(tk);
3575 components.push_back(cpp_namet::namet(tk.data.get(ID_C_base_name)));
3576 set_location(components.back(), tk);
3577
3578 {
3579 int t=lex.LookAhead(0);
3580 // done unless scope or template args is next
3581 if(t!=TOK_SCOPE && t!='<')
3582 return true;
3583 }
3584 break;
3585
3586 case TOK_SCOPE:
3587#ifdef DEBUG
3588 std::cout << std::string(__indent, ' ') << "Parser::rName 6\n";
3589#endif
3590 lex.get_token(tk);
3591 components.push_back(irept("::"));
3592 set_location(components.back(), tk);
3593 break;
3594
3595 case '~':
3596#ifdef DEBUG
3597 std::cout << std::string(__indent, ' ') << "Parser::rName 7\n";
3598#endif
3599 lex.get_token(tk);
3600
3601 // identifier must be next
3602 if(!is_identifier(lex.LookAhead(0)))
3603 return false;
3604
3605 components.push_back(irept("~"));
3606 set_location(components.back(), tk);
3607 break;
3608
3609 case TOK_OPERATOR:
3610#ifdef DEBUG
3611 std::cout << std::string(__indent, ' ') << "Parser::rName 8\n";
3612#endif
3613 lex.get_token(tk);
3614 {
3615 components.push_back(irept(ID_operator));
3616 set_location(components.back(), tk);
3617
3618 components.push_back(irept());
3619
3620 if(!rOperatorName(components.back()))
3621 return false;
3622 }
3623
3624 // done unless template args are next
3625 if(lex.LookAhead(0)!='<')
3626 return true;
3627 break;
3628
3629 default:
3630 return false;
3631 }
3632 }
3633}
3634
3635/*
3636 operator.name
3637 : '+' | '-' | '*' | '/' | '%' | '^' | '&' | '|' | '~'
3638 | '!' | '=' | '<' | '>' | AssignOp | ShiftOp | EqualOp
3639 | RelOp | LogAndOp | LogOrOp | IncOp | ',' | DOTPM | ARROWPM | ArrowOp
3640 | NEW {'[' ']'}
3641 | DELETE {'[' ']'}
3642 | '(' ')'
3643 | '[' ']'
3644 | cast.operator.name
3645*/
3646
3648{
3649 cpp_tokent tk;
3650
3651 int t=lex.LookAhead(0);
3652
3654
3655 switch(t)
3656 {
3657 case '+':
3658 case '-':
3659 case '*':
3660 case '/':
3661 case '%':
3662 case '^':
3663 case '&':
3664 case '|':
3665 case '~':
3666 case '!':
3667 case '=':
3668 case '<':
3669 case '>':
3670 case ',':
3671 operator_id = std::string(1, static_cast<char>(t));
3672 break;
3673
3674 case TOK_MULTASSIGN: operator_id="*="; break;
3675 case TOK_DIVASSIGN: operator_id="/="; break;
3676 case TOK_MODASSIGN: operator_id="%="; break;
3677 case TOK_PLUSASSIGN: operator_id="+="; break;
3678 case TOK_MINUSASSIGN: operator_id="-="; break;
3679 case TOK_SHLASSIGN: operator_id="<<="; break;
3680 case TOK_SHRASSIGN: operator_id=">>="; break;
3681 case TOK_ANDASSIGN: operator_id="&="; break;
3682 case TOK_XORASSIGN: operator_id="^="; break;
3683 case TOK_ORASSIGN: operator_id="|="; break;
3684 case TOK_SHIFTLEFT: operator_id="<<"; break;
3685 case TOK_SHIFTRIGHT: operator_id=">>"; break;
3686 case TOK_EQ: operator_id="=="; break;
3687 case TOK_NE: operator_id="!="; break;
3688 case TOK_LE: operator_id="<="; break;
3689 case TOK_GE: operator_id=">="; break;
3690 case TOK_ANDAND: operator_id="&&"; break;
3691 case TOK_OROR: operator_id="||"; break;
3692 case TOK_INCR: operator_id="++"; break;
3693 case TOK_DECR: operator_id="--"; break;
3694 case TOK_DOTPM: operator_id=".*"; break;
3695 case TOK_ARROWPM: operator_id="->*"; break;
3696 case TOK_ARROW: operator_id="->"; break;
3697
3698 case TOK_NEW:
3699 case TOK_DELETE:
3700 {
3701 lex.get_token(tk);
3702
3703 if(lex.LookAhead(0)!='[')
3704 {
3706 set_location(name, tk);
3707 }
3708 else
3709 {
3711 set_location(name, tk);
3712
3713 lex.get_token(tk);
3714
3715 if(lex.get_token(tk)!=']')
3716 return false;
3717 }
3718 }
3719 return true;
3720
3721 case '(':
3722 lex.get_token(tk);
3723 name=irept("()");
3724 set_location(name, tk);
3725 return lex.get_token(tk)==')';
3726
3727 case '[':
3728 lex.get_token(tk);
3729 name=irept("[]");
3730 set_location(name, tk);
3731 return lex.get_token(tk)==']';
3732
3733 default:
3734 return rCastOperatorName(name);
3735 }
3736
3737 DATA_INVARIANT(!operator_id.empty(), "operator id missing");
3738 lex.get_token(tk);
3739 name=irept(operator_id);
3740 set_location(name, tk);
3741
3742 return true;
3743}
3744
3745/*
3746 cast.operator.name
3747 : {cv.qualify} (integral.or.class.spec | name) {cv.qualify}
3748 {(ptr.operator)*}
3749*/
3750
3752{
3753 typet cv1, cv2, type_name, ptr;
3754
3755 cv1.make_nil();
3756 cv2.make_nil();
3757 type_name.make_nil();
3758 ptr.make_nil();
3759
3760 if(!optCvQualify(cv1))
3761 return false;
3762
3764 return false;
3765
3766 if(type_name.is_nil())
3767 {
3768 if(!rName(type_name))
3769 return false;
3770 }
3771
3773
3774 if(!optCvQualify(cv2))
3775 return false;
3776
3777 if(!optPtrOperator(ptr))
3778 return false;
3779
3780 make_subtype(type_name, ptr);
3781 merge_types(cv2, ptr);
3782 name = ptr;
3783
3784 return true;
3785}
3786
3787/*
3788 ptr.to.member
3789 : {'::'} (identifier {template.args} '::')+ '*'
3790*/
3792{
3793#ifdef DEBUG
3794 indenter _i;
3795 std::cout << std::string(__indent, ' ') << "Parser::rPtrToMember 0\n";
3796#endif
3797
3798 typet ptm(ID_frontend_pointer); // width gets set during conversion
3799 irept &name = ptm.add(ID_to_member);
3800 name=cpp_namet();
3801 irept::subt &components=name.get_sub();
3802
3803 {
3804 cpp_tokent tk;
3805 lex.LookAhead(0, tk);
3806 set_location(name, tk);
3807 }
3808
3809 bool loop_cond = true;
3810 while(loop_cond)
3811 {
3812 cpp_tokent tk;
3813
3814 switch(lex.LookAhead(0))
3815 {
3816 case TOK_TEMPLATE:
3817 lex.get_token(tk);
3818 // Skip template token, next will be identifier
3819 if(!is_identifier(lex.LookAhead(0)))
3820 return false;
3821 break;
3822
3823 case '<':
3824 {
3825 irept args;
3826 if(!rTemplateArgs(args))
3827 return false;
3828
3829 components.push_back(irept(ID_template_args));
3830 components.back().add(ID_arguments).swap(args);
3831
3832 if(lex.LookAhead(0) != TOK_SCOPE)
3833 return false;
3834
3835 break;
3836 }
3837
3838 case TOK_GCC_IDENTIFIER:
3839 case TOK_MSC_IDENTIFIER:
3840 {
3841 lex.get_token(tk);
3842 components.push_back(cpp_namet::namet(tk.data.get(ID_C_base_name)));
3843 set_location(components.back(), tk);
3844
3845 int t = lex.LookAhead(0);
3846 if(t != TOK_SCOPE && t != '<')
3847 return false;
3848
3849 break;
3850 }
3851
3852 case TOK_SCOPE:
3853 lex.get_token(tk);
3854 components.push_back(irept("::"));
3855 set_location(components.back(), tk);
3856
3857 // done if next token is '*'
3858 if(lex.LookAhead(0) == '*')
3859 {
3860 lex.get_token(tk);
3861 ptr_to_mem.swap(ptm);
3862
3863#ifdef DEBUG
3864 std::cout << std::string(__indent, ' ') << "Parser::rPtrToMember 1\n";
3865#endif
3866
3867 return true;
3868 }
3869
3870 if(!is_identifier(lex.LookAhead(0)))
3871 return false;
3872
3873 break;
3874
3875 default:
3876 return false;
3877 }
3878 }
3879 return false;
3880}
3881
3882/*
3883 template.args
3884 : '<' '>'
3885 | '<' template.argument {',' template.argument} '>'
3886
3887 template.argument
3888 : type.name
3889 | logical.or.expr
3890*/
3892{
3893#ifdef DEBUG
3894 indenter _i;
3895 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 0\n";
3896#endif
3897
3899
3900 if(lex.get_token(tk1)!='<')
3901 return false;
3902
3904
3905#ifdef DEBUG
3906 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 1\n";
3907#endif
3908
3909 // in case of Foo<>
3910 if(lex.LookAhead(0)=='>')
3911 {
3913 lex.get_token(tk2);
3914 return true;
3915 }
3916
3917#ifdef DEBUG
3918 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 2\n";
3919#endif
3920
3921 for(;;)
3922 {
3923 exprt exp;
3925
3926#ifdef DEBUG
3927 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 3\n";
3928#endif
3929
3930 typet a;
3931
3932 // try type name first
3934 ((lex.LookAhead(0) == '>' || lex.LookAhead(0) == ',' ||
3936 (lex.LookAhead(0)==TOK_ELLIPSIS &&
3937 (lex.LookAhead(1) == '>' ||
3939 )
3940 {
3941#ifdef DEBUG
3942 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 4\n";
3943#endif
3944
3945 // ok
3946 exp=exprt(ID_type);
3947 exp.add_source_location()=a.source_location();
3948 exp.type().swap(a);
3949
3950 // but could also be an expr
3951 lex.Restore(pos);
3952 exprt tmp;
3953 if(rConditionalExpr(tmp, true))
3954 exp.id(ID_ambiguous);
3955#ifdef DEBUG
3956 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 4.1\n";
3957#endif
3958 lex.Restore(pos);
3960
3961 if(lex.LookAhead(0)==TOK_ELLIPSIS)
3962 {
3963 lex.get_token(tk1);
3964
3965 // TODO
3966 }
3967#ifdef DEBUG
3968 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 4.2\n";
3969#endif
3970 }
3971 else
3972 {
3973 // parsing failed, try expression
3974#ifdef DEBUG
3975 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 5\n";
3976#endif
3977
3978 lex.Restore(pos);
3979
3980
3981 if(!rConditionalExpr(exp, true))
3982 return false;
3983
3984 if(lex.LookAhead(0)==TOK_ELLIPSIS)
3985 {
3986 lex.get_token(tk1);
3987
3988 // TODO
3989 }
3990 }
3991
3992#ifdef DEBUG
3993 std::cout << std::string(__indent, ' ') << "Parser::rTemplateArgs 6\n";
3994#endif
3995
3996 template_args.get_sub().push_back(irept(irep_idt()));
3997 template_args.get_sub().back().swap(exp);
3998
3999 pos=lex.Save();
4001 switch(lex.get_token(tk2))
4002 {
4003 case '>':
4004 return true;
4005
4006 case ',':
4007 break;
4008
4009 case TOK_SHIFTRIGHT: // turn >> into > >
4010 lex.Restore(pos);
4011 tk2.kind='>';
4012 tk2.text='>';
4013 lex.Replace(tk2);
4014 lex.Insert(tk2);
4015 DATA_INVARIANT(lex.LookAhead(0) == '>', "should be >");
4016 DATA_INVARIANT(lex.LookAhead(1) == '>', "should be >");
4017 return true;
4018
4019 default:
4020 return false;
4021 }
4022 }
4023}
4024
4025/*
4026 arg.decl.list.or.init
4027 : arg.decl.list
4028 | function.arguments
4029
4030 This rule accepts function.arguments to parse declarations like:
4031 Point p(1, 3);
4032 "(1, 3)" is arg.decl.list.or.init.
4033
4034 If maybe_init is true, we first examine whether tokens construct
4035 function.arguments. This ordering is significant if tokens are
4036 Point p(s, t);
4037 s and t can be type names or variable names.
4038*/
4040 exprt &arglist,
4041 bool &is_args,
4042 bool maybe_init)
4043{
4045 if(maybe_init)
4046 {
4048 if(lex.LookAhead(0)==')')
4049 {
4050 is_args=false;
4051 // encode.Clear();
4052 return true;
4053 }
4054
4055 lex.Restore(pos);
4056 return(is_args=rArgDeclList(arglist));
4057 }
4058 else
4059 {
4061
4062 if(is_args)
4063 return true;
4064 else
4065 {
4066 lex.Restore(pos);
4067 // encode.Clear();
4069 }
4070 }
4071}
4072
4073/*
4074 arg.decl.list
4075 : empty
4076 | arg.declaration ( ',' arg.declaration )* {{ ',' } Ellipses}
4077*/
4079{
4080 irept list;
4081
4082 list.clear();
4083 for(;;)
4084 {
4085 cpp_declarationt declaration;
4086
4087 int t=lex.LookAhead(0);
4088 if(t==')')
4089 break;
4090 else if(t==TOK_ELLIPSIS)
4091 {
4092 cpp_tokent tk;
4093 lex.get_token(tk);
4094 list.get_sub().push_back(irept(ID_ellipsis));
4095 break;
4096 }
4097 else if(rArgDeclaration(declaration))
4098 {
4099 cpp_tokent tk;
4100
4101 list.get_sub().push_back(irept(irep_idt()));
4102 list.get_sub().back().swap(declaration);
4103 t=lex.LookAhead(0);
4104 if(t==',')
4105 lex.get_token(tk);
4106 else if(t==TOK_ELLIPSIS)
4107 {
4108 lex.get_token(tk);
4109 list.get_sub().push_back(irept(ID_ellipsis));
4110 }
4111 else if(t!=')' && t!=TOK_ELLIPSIS)
4112 return false;
4113 }
4114 else
4115 {
4116 arglist.clear();
4117 return false;
4118 }
4119 }
4120
4121 arglist.swap(list);
4122
4123 return true;
4124}
4125
4126/*
4127 arg.declaration
4128 : {userdef.keyword | REGISTER} type.specifier arg.declarator
4129 {'=' expression}
4130*/
4132{
4133 typet header;
4134 cpp_tokent tk;
4135
4136 switch(lex.LookAhead(0))
4137 {
4138 case TOK_REGISTER:
4139 lex.get_token(tk);
4141 break;
4142
4143 default:
4144 header.make_nil();
4145 break;
4146 }
4147
4148 if(!rTypeSpecifier(declaration.type(), true))
4149 return false;
4150
4152
4153 if(!rDeclarator(arg_declarator, kArgDeclarator, true, false))
4154 return false;
4155
4156 arg_declarator.set_is_parameter(true);
4157
4158 declaration.declarators().push_back(arg_declarator);
4159
4160 int t=lex.LookAhead(0);
4161 if(t=='=')
4162 {
4163 lex.get_token(tk);
4164 if(!rInitializeExpr(declaration.declarators().back().value()))
4165 return false;
4166 }
4167
4168 return true;
4169}
4170
4171/*
4172 initialize.expr
4173 : expression
4174 | '{' initialize.expr (',' initialize.expr)* {','} '}'
4175*/
4177{
4178 if(lex.LookAhead(0)!='{')
4179 return rExpression(expr, false);
4180
4181 // we want { initialize_expr, ... }
4182
4183 cpp_tokent tk;
4184 lex.get_token(tk);
4185
4186 exprt e;
4187
4188 expr.id(ID_initializer_list);
4189 set_location(expr, tk);
4190
4191 int t=lex.LookAhead(0);
4192
4193 while(t!='}')
4194 {
4195 exprt tmp;
4196
4197 if(t==TOK_MSC_IF_EXISTS ||
4199 {
4200 // TODO
4201 exprt name;
4202 lex.get_token(tk);
4203 if(lex.get_token(tk)!='(')
4204 return false;
4205 if(!rVarName(name))
4206 return false;
4207 if(lex.get_token(tk)!=')')
4208 return false;
4209 if(lex.get_token(tk)!='{')
4210 return false;
4211 if(!rInitializeExpr(name))
4212 return false;
4213 if(lex.LookAhead(0)==',')
4214 lex.get_token(tk);
4215 if(lex.get_token(tk)!='}')
4216 return false;
4217 }
4218
4219 if(!rInitializeExpr(tmp))
4220 {
4221 if(!SyntaxError())
4222 return false; // too many errors
4223
4224 SkipTo('}');
4225 lex.get_token(tk);
4226 return true; // error recovery
4227 }
4228
4229 expr.add_to_operands(std::move(tmp));
4230
4231 t=lex.LookAhead(0);
4232 if(t=='}')
4233 {
4234 // done!
4235 }
4236 else if(t==',')
4237 {
4238 lex.get_token(tk);
4239 t=lex.LookAhead(0);
4240 }
4241 else
4242 {
4243 if(!SyntaxError())
4244 return false; // too many errors
4245
4246 SkipTo('}');
4247 lex.get_token(tk);
4248 return true; // error recovery
4249 }
4250 }
4251
4252 lex.get_token(tk);
4253
4254 return true;
4255}
4256
4257/*
4258 function.arguments
4259 : empty
4260 | expression (',' expression)*
4261
4262 This assumes that the next token following function.arguments is ')'.
4263*/
4265{
4266 exprt exp;
4267 cpp_tokent tk;
4268
4269 args=exprt(irep_idt());
4270 if(lex.LookAhead(0)==')')
4271 return true;
4272
4273 for(;;)
4274 {
4275 if(!rExpression(exp, false))
4276 return false;
4277
4278 args.add_to_operands(std::move(exp));
4279
4280 if(lex.LookAhead(0)==TOK_ELLIPSIS &&
4281 (lex.LookAhead(1)==')' || lex.LookAhead(1)==','))
4282 {
4283 lex.get_token(tk);
4284 // TODO
4285
4286 if(lex.LookAhead(0)==')')
4287 return true;
4288 lex.get_token();
4289 }
4290 else if(lex.LookAhead(0)!=',')
4291 return true;
4292 else
4293 lex.get_token(tk);
4294 }
4295}
4296
4297/*
4298 enum.spec
4299 : ENUM Identifier
4300 | ENUM {Identifier} '{' {enum.body} '}'
4301 | ENUM CLASS Identifier '{' {enum.body} '}'
4302 | ENUM CLASS Identifier ':' Type '{' {enum.body} '}'
4303*/
4305{
4306#ifdef DEBUG
4307 indenter _i;
4308 std::cout << std::string(__indent, ' ') << "Parser::rEnumSpec 1\n";
4309#endif
4310
4311 cpp_tokent tk;
4312
4313 if(lex.get_token(tk)!=TOK_ENUM)
4314 return false;
4315
4316 spec=cpp_enum_typet();
4317 set_location(spec, tk);
4318
4319 spec.add_subtype().make_nil();
4320
4321 // C++11 enum classes
4322 if(lex.LookAhead(0)==TOK_CLASS)
4323 {
4324 lex.get_token(tk);
4325 spec.set(ID_C_class, true);
4326 }
4327
4328 if(lex.LookAhead(0)!='{' &&
4329 lex.LookAhead(0)!=':')
4330 {
4331 // Visual Studio allows full names for the tag,
4332 // not just an identifier
4333 irept name;
4334
4335 if(!rName(name))
4336 return false;
4337
4338 spec.add(ID_tag).swap(name);
4339 }
4340
4341#ifdef DEBUG
4342 std::cout << std::string(__indent, ' ') << "Parser::rEnumSpec 2\n";
4343#endif
4344
4345 // C++11 enums have an optional underlying type
4346 if(lex.LookAhead(0)==':')
4347 {
4348 lex.get_token(tk); // read the colon
4349 if(!rTypeName(spec.add_subtype()))
4350 return false;
4351 }
4352
4353#ifdef DEBUG
4354 std::cout << std::string(__indent, ' ') << "Parser::rEnumSpec 3\n";
4355#endif
4356
4357 if(lex.LookAhead(0)!='{')
4358 return true; // ok, no body
4359
4360 lex.get_token(tk);
4361
4362 if(lex.LookAhead(0)=='}')
4363 {
4364 // there is still a body, just an empty one!
4365 spec.add(ID_body);
4366 }
4367 else
4368 if(!rEnumBody(spec.add(ID_body)))
4369 return false;
4370
4371 // there must be closing '}'
4372
4373 if(lex.get_token(tk)!='}')
4374 return false;
4375
4376#ifdef DEBUG
4377 std::cout << std::string(__indent, ' ') << "Parser::rEnumSpec 4\n";
4378#endif
4379
4380 return true;
4381}
4382
4383/*
4384 enum.body
4385 : Identifier {'=' expression} (',' Identifier {'=' expression})* {','}
4386*/
4388{
4389 body.clear();
4390
4391 for(;;)
4392 {
4393 cpp_tokent tk, tk2;
4394
4395 if(lex.LookAhead(0)=='}')
4396 return true;
4397
4399 return false;
4400
4401 body.get_sub().push_back(irept());
4402 irept &n=body.get_sub().back();
4403 set_location(n, tk);
4404 n.set(ID_name, tk.data.get(ID_C_base_name));
4405
4406 if(lex.LookAhead(0, tk2)=='=') // set the constant
4407 {
4408 lex.get_token(tk2); // read the '='
4409
4410 exprt exp;
4411
4412 if(!rExpression(exp, false))
4413 {
4414 if(!SyntaxError())
4415 return false; // too many errors
4416
4417 SkipTo('}');
4418 body.clear(); // empty
4419 return true; // error recovery
4420 }
4421
4422 n.add(ID_value).swap(exp);
4423 }
4424 else
4425 n.add(ID_value).make_nil();
4426
4427 if(lex.LookAhead(0)!=',')
4428 return true;
4429
4430 lex.get_token(tk);
4431 }
4432}
4433
4434/*
4435 class.spec
4436 : {userdef.keyword} class.key class.body
4437 | {userdef.keyword} class.key name {class.body}
4438 | {userdef.keyword} class.key name ':' base.specifiers class.body
4439
4440 class.key
4441 : CLASS | STRUCT | UNION | INTERFACE
4442*/
4444{
4445 cpp_tokent tk;
4446
4447#ifdef DEBUG
4448 indenter _i;
4449 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 1\n";
4450#endif
4451
4452 int t=lex.get_token(tk);
4453 if(t!=TOK_CLASS && t!=TOK_STRUCT &&
4454 t!=TOK_UNION && t!=TOK_INTERFACE)
4455 return false;
4456
4457#ifdef DEBUG
4458 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 2\n";
4459#endif
4460
4461 if(t==TOK_CLASS)
4462 {
4463 spec=typet(ID_struct);
4464 spec.set(ID_C_class, true);
4465 }
4466 else if(t==TOK_INTERFACE) // MS-specific
4467 {
4468 spec=typet(ID_struct);
4469 spec.set(ID_C_interface, true);
4470 }
4471 else if(t==TOK_STRUCT)
4472 spec=typet(ID_struct);
4473 else if(t==TOK_UNION)
4474 spec=typet(ID_union);
4475 else
4477
4478 set_location(spec, tk);
4479
4480#ifdef DEBUG
4481 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 3\n";
4482#endif
4483
4484 if(lex.LookAhead(0)=='{')
4485 {
4486 // no tag
4487#ifdef DEBUG
4488 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 4\n";
4489#endif
4490 }
4491 else
4492 {
4493 if(!optAlignas(spec))
4494 return false;
4495
4496 if(!optAttribute(spec))
4497 return false;
4498
4499 irept name;
4500
4501 if(!rName(name))
4502 return false;
4503
4504 spec.add(ID_tag).swap(name);
4505
4506#ifdef DEBUG
4507 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 5\n";
4508#endif
4509
4510 t=lex.LookAhead(0);
4511
4512 if(t==':')
4513 {
4514 if(!rBaseSpecifiers(spec.add(ID_bases)))
4515 return false;
4516 }
4517 else if(t=='{')
4518 {
4519 }
4520 else
4521 {
4522 return true;
4523 }
4524 }
4525
4526#ifdef DEBUG
4527 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 6\n";
4528#endif
4529
4530 save_scopet saved_scope(current_scope);
4532
4533 exprt body;
4534
4535 if(!rClassBody(body))
4536 return false;
4537
4538#ifdef DEBUG
4539 std::cout << std::string(__indent, ' ') << "Parser::rClassSpec 7\n";
4540#endif
4541
4542 ((exprt&)spec.add(ID_body)).operands().swap(body.operands());
4543 return true;
4544}
4545
4546/*
4547 base.specifiers
4548 : ':' base.specifier (',' base.specifier)*
4549
4550 base.specifier
4551 : {{VIRTUAL} (PUBLIC | PROTECTED | PRIVATE) {VIRTUAL}} name
4552*/
4554{
4555 cpp_tokent tk;
4556
4557 if(lex.get_token(tk)!=':')
4558 return false;
4559
4560 for(;;)
4561 {
4562 int t=lex.LookAhead(0);
4563 irept base(ID_base);
4564
4565 if(t==TOK_VIRTUAL)
4566 {
4567 lex.get_token(tk);
4568 base.set(ID_virtual, true);
4569 t=lex.LookAhead(0);
4570 }
4571
4572 if(t==TOK_PUBLIC || t==TOK_PROTECTED || t==TOK_PRIVATE)
4573 {
4574 switch(lex.get_token(tk))
4575 {
4576 case TOK_PUBLIC:
4578 break;
4579
4580 case TOK_PROTECTED:
4582 break;
4583
4584 case TOK_PRIVATE:
4586 break;
4587
4588 default:
4590 }
4591
4592 t=lex.LookAhead(0);
4593 }
4594
4595 if(t==TOK_VIRTUAL)
4596 {
4597 lex.get_token(tk);
4598 base.set(ID_virtual, true);
4599 }
4600
4601 if(!rName(base.add(ID_name)))
4602 return false;
4603
4604 if(lex.LookAhead(0)==TOK_ELLIPSIS)
4605 {
4606 lex.get_token();
4607
4608 // TODO
4609 }
4610
4611 bases.get_sub().push_back(irept());
4612 bases.get_sub().back().swap(base);
4613
4614 if(lex.LookAhead(0)!=',')
4615 return true;
4616 else
4617 lex.get_token(tk);
4618 }
4619}
4620
4621/*
4622 class.body : '{' (class.members)* '}'
4623*/
4625{
4626 cpp_tokent tk;
4627
4628#ifdef DEBUG
4629 indenter _i;
4630 std::cout << std::string(__indent, ' ') << "Parser::rClassBody 0\n";
4631#endif
4632
4633 if(lex.get_token(tk)!='{')
4634 return false;
4635
4636 exprt members=exprt("cpp-class-body");
4637
4638 set_location(members, tk);
4639
4640 while(lex.LookAhead(0)!='}')
4641 {
4642 cpp_itemt member;
4643
4644 if(!rClassMember(member))
4645 {
4646 if(!SyntaxError())
4647 return false; // too many errors
4648
4649 SkipTo('}');
4650 lex.get_token(tk);
4651 // body=Ptree::List(ob, nil, new Leaf(tk));
4652 return true; // error recovery
4653 }
4654#ifdef DEBUG
4655 std::cout << std::string(__indent, ' ') << "Parser::rClassBody "
4656 << member.pretty() << '\n';
4657#endif
4658
4659 members.add_to_operands(
4660 std::move(static_cast<exprt &>(static_cast<irept &>(member))));
4661 }
4662
4663 lex.get_token(tk);
4664 body.swap(members);
4665 return true;
4666}
4667
4668/*
4669 class.member
4670 : (PUBLIC | PROTECTED | PRIVATE) ':'
4671 | user.access.spec
4672 | ';'
4673 | type.def
4674 | template.decl
4675 | using.declaration
4676 | metaclass.decl
4677 | declaration
4678 | access.decl
4679 | static_assert
4680
4681 Note: if you modify this function, see ClassWalker::TranslateClassSpec()
4682 as well.
4683*/
4685{
4687
4688 int t=lex.LookAhead(0);
4689
4690#ifdef DEBUG
4691 indenter _i;
4692 std::cout << std::string(__indent, ' ') << "Parser::rClassMember 0 " << t
4693 << '\n';
4694#endif // DEBUG
4695
4696 if(t==TOK_PUBLIC || t==TOK_PROTECTED || t==TOK_PRIVATE)
4697 {
4698 switch(lex.get_token(tk1))
4699 {
4700 case TOK_PUBLIC:
4701 member.id("cpp-public");
4702 break;
4703
4704 case TOK_PROTECTED:
4705 member.id("cpp-protected");
4706 break;
4707
4708 case TOK_PRIVATE:
4709 member.id("cpp-private");
4710 break;
4711
4712 default:
4714 }
4715
4716 set_location(member, tk1);
4717
4718 if(lex.get_token(tk2)!=':')
4719 return false;
4720
4721 return true;
4722 }
4723 else if(t==';')
4724 return rNullDeclaration(member.make_declaration());
4725 else if(t==TOK_TYPEDEF)
4726 return rTypedef(member.make_declaration());
4727 else if(t==TOK_TEMPLATE)
4728 return rTemplateDecl(member.make_declaration());
4729 else if(
4730 t == TOK_USING && is_identifier(lex.LookAhead(1)) &&
4731 lex.LookAhead(2) == '=')
4732 {
4733 return rTypedefUsing(member.make_declaration());
4734 }
4735 else if(t==TOK_USING)
4736 return rUsing(member.make_using());
4737 else if(t==TOK_STATIC_ASSERT)
4738 return rStaticAssert(member.make_static_assert());
4739 else
4740 {
4742 if(rDeclaration(member.make_declaration()))
4743 return true;
4744
4745 lex.Restore(pos);
4746 return rAccessDecl(member.make_declaration());
4747 }
4748}
4749
4750/*
4751 access.decl
4752 : name ';' e.g. <qualified class>::<member name>;
4753*/
4755{
4756 cpp_namet name;
4757 cpp_tokent tk;
4758
4759 if(!rName(name))
4760 return false;
4761
4762 if(lex.get_token(tk)!=';')
4763 return false;
4764
4766 name_decl.name() = name;
4767 mem.declarators().push_back(name_decl);
4768
4769 // mem=new PtreeAccessDecl(new PtreeName(name, encode),
4770 // Ptree::List(new Leaf(tk)));
4771 return true;
4772}
4773
4774/*
4775 comma.expression
4776 : expression
4777 | comma.expression ',' expression (left-to-right)
4778*/
4780{
4781#ifdef DEBUG
4782 indenter _i;
4783 std::cout << std::string(__indent, ' ') << "Parser::rCommaExpression 0\n";
4784#endif
4785
4786 if(!rExpression(exp, false))
4787 return false;
4788
4789#ifdef DEBUG
4790 std::cout << std::string(__indent, ' ') << "Parser::rCommaExpression 1\n";
4791#endif
4792
4793 while(lex.LookAhead(0)==',')
4794 {
4795 cpp_tokent tk;
4796
4797 lex.get_token(tk);
4798
4799 exprt right;
4800 if(!rExpression(right, false))
4801 return false;
4802
4803 exprt left;
4804 left.swap(exp);
4805
4806 exp=exprt(ID_comma);
4807 exp.add_to_operands(std::move(left), std::move(right));
4808 set_location(exp, tk);
4809 }
4810
4811#ifdef DEBUG
4812 std::cout << std::string(__indent, ' ') << "Parser::rCommaExpression 2\n";
4813#endif
4814
4815 return true;
4816}
4817
4818/*
4819 expression
4820 : conditional.expr {(AssignOp | '=') expression} right-to-left
4821*/
4823{
4824 cpp_tokent tk;
4825
4826#ifdef DEBUG
4827 indenter _i;
4828 std::cout << std::string(__indent, ' ') << "Parser::rExpression 0\n";
4829#endif
4830
4832 return false;
4833
4834#ifdef DEBUG
4835 std::cout << std::string(__indent, ' ') << "Parser::rExpression 1\n";
4836#endif
4837
4838 int t=lex.LookAhead(0);
4839
4840 if(t=='=' ||
4843 t==TOK_SHRASSIGN || t==TOK_ANDASSIGN ||
4844 t==TOK_XORASSIGN || t==TOK_ORASSIGN)
4845 {
4846 lex.get_token(tk);
4847
4848#ifdef DEBUG
4849 std::cout << std::string(__indent, ' ') << "Parser::rExpression 2\n";
4850#endif
4851
4852 exprt right;
4853 if(!rExpression(right, template_args))
4854 return false;
4855
4856#ifdef DEBUG
4857 std::cout << std::string(__indent, ' ') << "Parser::rExpression 3\n";
4858#endif
4859
4860 exprt left;
4861 left.swap(exp);
4862
4863 exp=exprt(ID_side_effect);
4864
4865 if(t=='=')
4867 else if(t==TOK_PLUSASSIGN)
4869 else if(t==TOK_MINUSASSIGN)
4871 else if(t==TOK_MULTASSIGN)
4873 else if(t==TOK_DIVASSIGN)
4875 else if(t==TOK_MODASSIGN)
4877 else if(t==TOK_SHLASSIGN)
4879 else if(t==TOK_SHRASSIGN)
4881 else if(t==TOK_ANDASSIGN)
4883 else if(t==TOK_XORASSIGN)
4885 else if(t==TOK_ORASSIGN)
4887
4888 exp.add_to_operands(std::move(left), std::move(right));
4889 set_location(exp, tk);
4890 }
4891
4892#ifdef DEBUG
4893 std::cout << std::string(__indent, ' ') << "Parser::rExpression 4\n";
4894#endif
4895
4896 return true;
4897}
4898
4899/*
4900 conditional.expr
4901 : logical.or.expr {'?' comma.expression ':' conditional.expr} right-to-left
4902*/
4904{
4905#ifdef DEBUG
4906 indenter _i;
4907 std::cout << std::string(__indent, ' ') << "Parser::rConditionalExpr 0\n";
4908#endif
4909
4910 if(!rLogicalOrExpr(exp, template_args))
4911 return false;
4912
4913#ifdef DEBUG
4914 std::cout << std::string(__indent, ' ') << "Parser::rConditionalExpr 1\n";
4915#endif
4916
4917 if(lex.LookAhead(0)=='?')
4918 {
4921
4922 lex.get_token(tk1);
4924 return false;
4925
4926#ifdef DEBUG
4927 std::cout << std::string(__indent, ' ') << "Parser::rConditionalExpr 2\n";
4928#endif
4929
4930 if(lex.get_token(tk2)!=':')
4931 return false;
4932
4934 return false;
4935
4936 exprt cond;
4937 cond.swap(exp);
4938
4939 exp =
4940 if_exprt(std::move(cond), std::move(then), std::move(otherwise), typet());
4941 set_location(exp, tk1);
4942 }
4943
4944 return true;
4945}
4946
4947/*
4948 logical.or.expr
4949 : logical.and.expr
4950 | logical.or.expr LogOrOp logical.and.expr left-to-right
4951*/
4953{
4954#ifdef DEBUG
4955 indenter _i;
4956 std::cout << std::string(__indent, ' ') << "Parser::rLogicalOrExpr 0\n";
4957#endif
4958
4960 return false;
4961
4962#ifdef DEBUG
4963 std::cout << std::string(__indent, ' ') << "Parser::rLogicalOrExpr 1\n";
4964#endif
4965
4966 while(lex.LookAhead(0)==TOK_OROR)
4967 {
4968 cpp_tokent tk;
4969 lex.get_token(tk);
4970
4971 exprt right;
4972 if(!rLogicalAndExpr(right, template_args))
4973 return false;
4974
4975 exprt left;
4976 left.swap(exp);
4977
4978 exp=exprt(ID_or);
4979 exp.add_to_operands(std::move(left), std::move(right));
4980 set_location(exp, tk);
4981 }
4982
4983 return true;
4984}
4985
4986/*
4987 logical.and.expr
4988 : inclusive.or.expr
4989 | logical.and.expr LogAndOp inclusive.or.expr
4990*/
4992{
4993#ifdef DEBUG
4994 indenter _i;
4995 std::cout << std::string(__indent, ' ') << "Parser::rLogicalAndExpr 1\n";
4996#endif
4997
4999 return false;
5000
5001#ifdef DEBUG
5002 std::cout << std::string(__indent, ' ') << "Parser::rLogicalAndExpr 1\n";
5003#endif
5004
5005 while(lex.LookAhead(0)==TOK_ANDAND)
5006 {
5007 cpp_tokent tk;
5008 lex.get_token(tk);
5009
5010 exprt right;
5011 if(!rInclusiveOrExpr(right, template_args))
5012 return false;
5013
5014 exprt left;
5015 left.swap(exp);
5016
5017 exp=exprt(ID_and);
5018 exp.add_to_operands(std::move(left), std::move(right));
5019 set_location(exp, tk);
5020 }
5021
5022 return true;
5023}
5024
5025/*
5026 inclusive.or.expr
5027 : exclusive.or.expr
5028 | inclusive.or.expr '|' exclusive.or.expr
5029*/
5031{
5032#ifdef DEBUG
5033 indenter _i;
5034 std::cout << std::string(__indent, ' ') << "Parser::rInclusiveOrExpr 0\n";
5035#endif
5036
5038 return false;
5039
5040#ifdef DEBUG
5041 std::cout << std::string(__indent, ' ') << "Parser::rInclusiveOrExpr 1\n";
5042#endif
5043
5044 while(lex.LookAhead(0)=='|')
5045 {
5046 cpp_tokent tk;
5047 lex.get_token(tk);
5048
5049 exprt right;
5050 if(!rExclusiveOrExpr(right, template_args))
5051 return false;
5052
5053 exprt left;
5054 left.swap(exp);
5055
5056 exp=exprt(ID_bitor);
5057 exp.add_to_operands(std::move(left), std::move(right));
5058 set_location(exp, tk);
5059 }
5060
5061 return true;
5062}
5063
5064/*
5065 exclusive.or.expr
5066 : and.expr
5067 | exclusive.or.expr '^' and.expr
5068*/
5070{
5071#ifdef DEBUG
5072 indenter _i;
5073 std::cout << std::string(__indent, ' ') << "Parser::rExclusiveOrExpr 0\n";
5074#endif
5075
5076 if(!rAndExpr(exp, template_args))
5077 return false;
5078
5079#ifdef DEBUG
5080 std::cout << std::string(__indent, ' ') << "Parser::rExclusiveOrExpr 1\n";
5081#endif
5082
5083 while(lex.LookAhead(0)=='^')
5084 {
5085 cpp_tokent tk;
5086 lex.get_token(tk);
5087
5088 exprt right;
5089 if(!rAndExpr(right, template_args))
5090 return false;
5091
5092 exprt left;
5093 left.swap(exp);
5094
5095 exp=exprt(ID_bitxor);
5096 exp.add_to_operands(std::move(left), std::move(right));
5097 set_location(exp, tk);
5098 }
5099
5100 return true;
5101}
5102
5103/*
5104 and.expr
5105 : equality.expr
5106 | and.expr '&' equality.expr
5107*/
5109{
5110#ifdef DEBUG
5111 indenter _i;
5112 std::cout << std::string(__indent, ' ') << "Parser::rAndExpr 0\n";
5113#endif
5114
5115 if(!rEqualityExpr(exp, template_args))
5116 return false;
5117
5118#ifdef DEBUG
5119 std::cout << std::string(__indent, ' ') << "Parser::rAndExpr 1\n";
5120#endif
5121
5122 while(lex.LookAhead(0)=='&')
5123 {
5124 cpp_tokent tk;
5125 lex.get_token(tk);
5126
5127 exprt right;
5128 if(!rEqualityExpr(right, template_args))
5129 return false;
5130
5131 exprt left;
5132 left.swap(exp);
5133
5134 exp=exprt(ID_bitand);
5135 exp.add_to_operands(std::move(left), std::move(right));
5136 set_location(exp, tk);
5137 }
5138
5139 return true;
5140}
5141
5142/*
5143 equality.expr
5144 : relational.expr
5145 | equality.expr EqualOp relational.expr
5146*/
5148{
5149#ifdef DEBUG
5150 indenter _i;
5151 std::cout << std::string(__indent, ' ') << "Parser::rEqualityExpr 0\n";
5152#endif
5153
5155 return false;
5156
5157#ifdef DEBUG
5158 std::cout << std::string(__indent, ' ') << "Parser::rEqualityExpr 1\n";
5159#endif
5160
5161 while(lex.LookAhead(0)==TOK_EQ ||
5162 lex.LookAhead(0)==TOK_NE)
5163 {
5164 cpp_tokent tk;
5165 lex.get_token(tk);
5166
5167 exprt right;
5168 if(!rRelationalExpr(right, template_args))
5169 return false;
5170
5171 exprt left;
5172 left.swap(exp);
5173
5174 exp=exprt(tk.kind==TOK_EQ?ID_equal:ID_notequal);
5175 exp.add_to_operands(std::move(left), std::move(right));
5176 set_location(exp, tk);
5177 }
5178
5179 return true;
5180}
5181
5182/*
5183 relational.expr
5184 : shift.expr
5185 | relational.expr (RelOp | '<' | '>') shift.expr
5186*/
5188{
5189#ifdef DEBUG
5190 indenter _i;
5191 std::cout << std::string(__indent, ' ') << "Parser::rRelationalExpr 0\n";
5192#endif
5193
5194 if(!rShiftExpr(exp, template_args))
5195 return false;
5196
5197#ifdef DEBUG
5198 std::cout << std::string(__indent, ' ') << "Parser::rRelationalExpr 1\n";
5199#endif
5200
5201 int t;
5202
5203 while(t=lex.LookAhead(0),
5204 (t==TOK_LE || t==TOK_GE || t=='<' || (t=='>' && !template_args)))
5205 {
5206 cpp_tokent tk;
5207 lex.get_token(tk);
5208
5209 exprt right;
5210 if(!rShiftExpr(right, template_args))
5211 return false;
5212
5213 exprt left;
5214 left.swap(exp);
5215
5216 irep_idt id;
5217
5218 switch(t)
5219 {
5220 case TOK_LE: id=ID_le; break;
5221 case TOK_GE: id=ID_ge; break;
5222 case '<': id=ID_lt; break;
5223 case '>': id=ID_gt; break;
5224 }
5225
5226 exp=exprt(id);
5227 exp.add_to_operands(std::move(left), std::move(right));
5228 set_location(exp, tk);
5229 }
5230
5231 return true;
5232}
5233
5234/*
5235 shift.expr
5236 : additive.expr
5237 | shift.expr ShiftOp additive.expr
5238*/
5240{
5241#ifdef DEBUG
5242 indenter _i;
5243 std::cout << std::string(__indent, ' ') << "Parser::rShiftExpr 0\n";
5244#endif
5245
5246 if(!rAdditiveExpr(exp))
5247 return false;
5248
5249#ifdef DEBUG
5250 std::cout << std::string(__indent, ' ') << "Parser::rShiftExpr 1\n";
5251#endif
5252
5253 while(lex.LookAhead(0)==TOK_SHIFTLEFT ||
5255 {
5256 cpp_tokent tk;
5257 lex.get_token(tk);
5258
5259 exprt right;
5260 if(!rAdditiveExpr(right))
5261 return false;
5262
5263 exprt left;
5264 left.swap(exp);
5265
5266 exp=exprt((tk.kind==TOK_SHIFTRIGHT)?ID_shr:ID_shl);
5267 exp.add_to_operands(std::move(left), std::move(right));
5268 set_location(exp, tk);
5269 }
5270
5271 return true;
5272}
5273
5274/*
5275 additive.expr
5276 : multiply.expr
5277 | additive.expr ('+' | '-') multiply.expr
5278*/
5280{
5281#ifdef DEBUG
5282 indenter _i;
5283 std::cout << std::string(__indent, ' ') << "Parser::rAdditiveExpr 0\n";
5284#endif
5285
5286 if(!rMultiplyExpr(exp))
5287 return false;
5288
5289#ifdef DEBUG
5290 std::cout << std::string(__indent, ' ') << "Parser::rAdditiveExpr 1\n";
5291#endif
5292
5293 int t;
5294 while(t=lex.LookAhead(0), (t=='+' || t=='-'))
5295 {
5296 cpp_tokent tk;
5297 lex.get_token(tk);
5298
5299 exprt right;
5300 if(!rMultiplyExpr(right))
5301 return false;
5302
5303 exprt left;
5304 left.swap(exp);
5305
5306 irep_idt id;
5307 switch(t)
5308 {
5309 case '+': id=ID_plus; break;
5310 case '-': id=ID_minus; break;
5311 }
5312
5313 exp=exprt(id);
5314 exp.add_to_operands(std::move(left), std::move(right));
5315 set_location(exp, tk);
5316 }
5317
5318 return true;
5319}
5320
5321/*
5322 multiply.expr
5323 : pm.expr
5324 | multiply.expr ('*' | '/' | '%') pm.expr
5325*/
5327{
5328#ifdef DEBUG
5329 indenter _i;
5330 std::cout << std::string(__indent, ' ') << "Parser::rMultiplyExpr 0\n";
5331#endif
5332
5333 if(!rPmExpr(exp))
5334 return false;
5335
5336#ifdef DEBUG
5337 std::cout << std::string(__indent, ' ') << "Parser::rMultiplyExpr 1\n";
5338#endif
5339
5340 int t;
5341 while(t=lex.LookAhead(0), (t=='*' || t=='/' || t=='%'))
5342 {
5343 cpp_tokent tk;
5344 lex.get_token(tk);
5345
5346 exprt right;
5347 if(!rPmExpr(right))
5348 return false;
5349
5350 exprt left;
5351 left.swap(exp);
5352
5353 irep_idt id;
5354 switch(t)
5355 {
5356 case '*': id=ID_mult; break;
5357 case '/': id=ID_div; break;
5358 case '%': id=ID_mod; break;
5359 }
5360
5361 exp=exprt(id);
5362 exp.add_to_operands(std::move(left), std::move(right));
5363 set_location(exp, tk);
5364 }
5365
5366#ifdef DEBUG
5367 std::cout << std::string(__indent, ' ') << "Parser::rMultiplyExpr 2\n";
5368#endif
5369
5370 return true;
5371}
5372
5373/*
5374 pm.expr (pointer to member .*, ->*)
5375 : cast.expr
5376 | pm.expr DOTPM cast.expr
5377 | pm.expr ARROWPM cast.expr
5378*/
5380{
5381#ifdef DEBUG
5382 indenter _i;
5383 std::cout << std::string(__indent, ' ') << "Parser::rPmExpr 0\n";
5384#endif
5385
5386 if(!rCastExpr(exp))
5387 return false;
5388
5389#ifdef DEBUG
5390 std::cout << std::string(__indent, ' ') << "Parser::rPmExpr 1\n";
5391#endif
5392
5393 while(lex.LookAhead(0)==TOK_DOTPM ||
5395 {
5396 cpp_tokent tk;
5397 lex.get_token(tk);
5398
5399 exprt right;
5400 if(!rCastExpr(right))
5401 return false;
5402
5403 exprt left;
5404 left.swap(exp);
5405
5407 exp.add_to_operands(std::move(left), std::move(right));
5408 set_location(exp, tk);
5409 }
5410
5411#ifdef DEBUG
5412 std::cout << std::string(__indent, ' ') << "Parser::rPmExpr 2\n";
5413#endif
5414
5415 return true;
5416}
5417
5418/*
5419 cast.expr
5420 : unary.expr
5421 | '(' type.name ')' cast.expr
5422*/
5424{
5425#ifdef DEBUG
5426 indenter _i;
5427 std::cout << std::string(__indent, ' ') << "Parser::rCastExpr 0\n";
5428#endif
5429
5430 if(lex.LookAhead(0)!='(')
5431 return rUnaryExpr(exp);
5432 else
5433 {
5434 // There is an ambiguity in the C++ grammar as follows:
5435 // (TYPENAME) + expr (typecast of unary plus) vs.
5436 // (expr) + expr (sum of two expressions)
5437 // Same issue with the operators & and - and *
5438
5440 typet tname;
5441
5442#ifdef DEBUG
5443 std::cout << std::string(__indent, ' ') << "Parser::rCastExpr 1\n";
5444#endif
5445
5447 lex.get_token(tk1);
5448
5449 if(rTypeName(tname))
5450 {
5451 if(lex.get_token(tk2)==')')
5452 {
5453 if(lex.LookAhead(0)=='&' &&
5455 {
5456 // we have (x) & 123
5457 // This is likely a binary bit-wise 'and'
5458 }
5459 else if(rCastExpr(exp))
5460 {
5461 exprt op;
5462 op.swap(exp);
5463
5464 exp=exprt("explicit-typecast");
5465 exp.type().swap(tname);
5466 exp.add_to_operands(std::move(op));
5467 set_location(exp, tk1);
5468
5469 return true;
5470 }
5471 }
5472 }
5473
5474 lex.Restore(pos);
5475 return rUnaryExpr(exp);
5476 }
5477}
5478
5479/*
5480 type.name
5481 : type.specifier cast.declarator
5482*/
5484{
5485#ifdef DEBUG
5486 indenter _i;
5487 std::cout << std::string(__indent, ' ') << "Parser::rTypeName 0\n";
5488#endif
5489
5491
5492 if(!rTypeSpecifier(type_name, true))
5493 return false;
5494
5495#ifdef DEBUG
5496 std::cout << std::string(__indent, ' ') << "Parser::rTypeName 1\n";
5497#endif
5498
5499 cpp_declaratort declarator;
5500
5501 if(!rDeclarator(declarator, kCastDeclarator, false, false))
5502 return false;
5503
5504 if(!declarator.method_qualifier().id().empty())
5505 {
5506 tname.swap(declarator.method_qualifier());
5507 merge_types(declarator.type(), tname);
5508 }
5509 else
5510 tname.swap(declarator.type());
5511
5512 // make type_name subtype of arg
5514
5515#ifdef DEBUG
5516 std::cout << std::string(__indent, ' ') << "Parser::rTypeName 2\n";
5517#endif
5518
5519 return true;
5520}
5521
5522/*
5523 type.name
5524 | type.specifier { '(' type.specifier ( ',' type.specifier )*
5525 { {,} Ellipsis } ')' } {cv.qualify} {(ptr.operator)*}
5526*/
5528{
5529#ifdef DEBUG
5530 indenter _i;
5531 std::cout << std::string(__indent, ' ')
5532 << "Parser::rTypeNameOrFunctionType 0\n";
5533#endif
5534
5536
5537 if(rTypeName(tname) && lex.LookAhead(0)!='(')
5538 {
5539#ifdef DEBUG
5540 std::cout << std::string(__indent, ' ')
5541 << "Parser::rTypeNameOrFunctionType 1\n";
5542#endif
5543
5544 if(!optPtrOperator(tname))
5545 return false;
5546
5547 return true;
5548 }
5549
5550 lex.Restore(pos);
5551
5552#ifdef DEBUG
5553 std::cout << std::string(__indent, ' ')
5554 << "Parser::rTypeNameOrFunctionType 2\n";
5555#endif
5556
5557 typet return_type;
5558 if(!rCastOperatorName(return_type))
5559 return false;
5560
5561#ifdef DEBUG
5562 std::cout << std::string(__indent, ' ')
5563 << "Parser::rTypeNameOrFunctionType 3\n";
5564#endif
5565
5566 if(lex.LookAhead(0)!='(')
5567 {
5568 tname.swap(return_type);
5569
5570 if(!optPtrOperator(tname))
5571 return false;
5572
5573 return true;
5574 }
5575
5576#ifdef DEBUG
5577 std::cout << std::string(__indent, ' ')
5578 << "Parser::rTypeNameOrFunctionType 4\n";
5579#endif
5580
5581 code_typet type({}, return_type);
5582 cpp_tokent op;
5583 lex.get_token(op);
5584
5585 // TODO -- cruel hack for Clang's type_traits:
5586 // struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...),
5587 // true, false>
5588 if(
5590 lex.LookAhead(2) == '*' && lex.LookAhead(3) == ')' &&
5591 lex.LookAhead(4) == '(')
5592 {
5593 lex.get_token();
5594 lex.get_token();
5595 lex.get_token();
5596 lex.get_token();
5597 lex.get_token();
5598 }
5599 else if(
5600 is_identifier(lex.LookAhead(0)) && lex.LookAhead(1) == ')' &&
5601 lex.LookAhead(2) == '(')
5602 {
5603 lex.get_token(op);
5604 type.set(ID_identifier, op.data.get(ID_C_base_name));
5605 lex.get_token();
5606 lex.get_token();
5607 }
5608 else if(
5609 lex.LookAhead(0) == '*' && is_identifier(lex.LookAhead(1)) &&
5610 lex.LookAhead(2) == ')' && lex.LookAhead(3) == '(')
5611 {
5612 lex.get_token(op);
5613 lex.get_token(op);
5614 type.set(ID_identifier, op.data.get(ID_C_base_name));
5615 lex.get_token();
5616 lex.get_token();
5617 }
5618
5619 for(;;)
5620 {
5621 // function type parameters
5622
5623#ifdef DEBUG
5624 std::cout << std::string(__indent, ' ')
5625 << "Parser::rTypeNameOrFunctionType 5\n";
5626#endif
5627
5628 int t=lex.LookAhead(0);
5629 if(t==')')
5630 break;
5631 else if(t==TOK_ELLIPSIS)
5632 {
5633 cpp_tokent tk;
5634 lex.get_token(tk);
5635 type.make_ellipsis();
5636 }
5637 else
5638 {
5641 return false;
5642
5645 type.parameters().push_back(parameter);
5646
5647 t=lex.LookAhead(0);
5648 if(t==',')
5649 {
5650 cpp_tokent tk;
5651 lex.get_token(tk);
5652 }
5653 else if(t==TOK_ELLIPSIS)
5654 {
5655 // TODO -- this is actually ambiguous as it could refer to a
5656 // template parameter pack or declare a variadic function
5657 cpp_tokent tk;
5658 lex.get_token(tk);
5659 type.make_ellipsis();
5660 }
5661 else if(t==')')
5662 break;
5663 }
5664 }
5665
5666#ifdef DEBUG
5667 std::cout << std::string(__indent, ' ')
5668 << "Parser::rTypeNameOrFunctionType 6\n";
5669#endif
5670
5671 cpp_tokent cp;
5672 lex.get_token(cp);
5673
5674 // not sure where this one belongs
5675 if(!optCvQualify(type))
5676 return false;
5677
5678#ifdef DEBUG
5679 std::cout << std::string(__indent, ' ')
5680 << "Parser::rTypeNameOrFunctionType 7\n";
5681#endif
5682
5683 // not sure where this one belongs
5684 if(!optPtrOperator(type))
5685 return false;
5686
5687 tname.swap(type);
5688
5689#ifdef DEBUG
5690 std::cout << std::string(__indent, ' ')
5691 << "Parser::rTypeNameOrFunctionType 8\n";
5692#endif
5693
5694 return true;
5695}
5696
5697/*
5698 unary.expr
5699 : postfix.expr
5700 | ('*' | '&' | '+' | '-' | '!' | '~' | IncOp) cast.expr
5701 | sizeof.expr
5702 | allocate.expr
5703 | throw.expression
5704 | noexcept.expr
5705*/
5706
5708{
5709 int t=lex.LookAhead(0);
5710
5711#ifdef DEBUG
5712 indenter _i;
5713 std::cout << std::string(__indent, ' ') << "Parser::rUnaryExpr 0\n";
5714#endif
5715
5716 if(t=='*' || t=='&' || t=='+' ||
5717 t=='-' || t=='!' || t=='~' ||
5718 t==TOK_INCR || t==TOK_DECR)
5719 {
5720 cpp_tokent tk;
5721 lex.get_token(tk);
5722
5723#ifdef DEBUG
5724 std::cout << std::string(__indent, ' ') << "Parser::rUnaryExpr 1\n";
5725#endif
5726
5727 exprt right;
5728 if(!rCastExpr(right))
5729 return false;
5730
5731#ifdef DEBUG
5732 std::cout << std::string(__indent, ' ') << "Parser::rUnaryExpr 2\n";
5733#endif
5734
5735 switch(t)
5736 {
5737 case '*':
5738 exp=exprt(ID_dereference);
5739 break;
5740
5741 case '&':
5742 exp=exprt(ID_address_of);
5743 break;
5744
5745 case '+':
5746 exp=exprt(ID_unary_plus);
5747 break;
5748
5749 case '-':
5750 exp=exprt(ID_unary_minus);
5751 break;
5752
5753 case '!':
5754 exp=exprt(ID_not);
5755 break;
5756
5757 case '~':
5758 exp=exprt(ID_bitnot);
5759 break;
5760
5761 case TOK_INCR:
5762 exp=exprt(ID_side_effect);
5764 break;
5765
5766 case TOK_DECR:
5767 exp=exprt(ID_side_effect);
5769 break;
5770
5771 default:
5773 }
5774
5775 exp.add_to_operands(std::move(right));
5776 set_location(exp, tk);
5777
5778 return true;
5779 }
5780 else if(t==TOK_SIZEOF)
5781 return rSizeofExpr(exp);
5782 else if(t==TOK_ALIGNOF)
5783 return rAlignofExpr(exp);
5784 else if(t==TOK_THROW)
5785 return rThrowExpr(exp);
5786 else if(t==TOK_NOEXCEPT)
5787 return rNoexceptExpr(exp);
5788 else if(t==TOK_REAL || t==TOK_IMAG)
5789 {
5790 // a GCC extension for complex floating-point arithmetic
5791 cpp_tokent tk;
5792 lex.get_token(tk);
5793
5794 exprt unary;
5795
5796 if(!rUnaryExpr(unary))
5797 return false;
5798
5800 exp.add_to_operands(std::move(unary));
5801 set_location(exp, tk);
5802 return true;
5803 }
5804 else if(isAllocateExpr(t))
5805 return rAllocateExpr(exp);
5806 else
5807 return rPostfixExpr(exp);
5808}
5809
5810/*
5811 throw.expression
5812 : THROW {expression}
5813*/
5815{
5816 cpp_tokent tk;
5817
5818#ifdef DEBUG
5819 indenter _i;
5820 std::cout << std::string(__indent, ' ') << "Parser::rThrowExpr 0\n";
5821#endif
5822
5824 return false;
5825
5826 int t=lex.LookAhead(0);
5827
5829 set_location(exp, tk);
5830
5831 if(t==':' || t==';')
5832 {
5833 // done
5834 }
5835 else
5836 {
5837 exprt e;
5838
5839 if(!rExpression(e, false))
5840 return false;
5841
5842 exp.add_to_operands(std::move(e));
5843 }
5844
5845 return true;
5846}
5847
5848/*
5849 typeid.expr
5850 : TYPEID '(' expression ')'
5851 | TYPEID '(' type.name ')'
5852*/
5854{
5855 cpp_tokent tk;
5856
5857#ifdef DEBUG
5858 indenter _i;
5859 std::cout << std::string(__indent, ' ') << "Parser::rTypeidExpr 0\n";
5860#endif
5861
5863 return false;
5864
5865 if(lex.LookAhead(0)=='(')
5866 {
5867 typet tname;
5868 exprt subexp;
5869 cpp_tokent op, cp;
5870
5872 lex.get_token(op);
5873 if(rTypeName(tname))
5874 {
5875 if(lex.get_token(cp)==')')
5876 {
5877 // exp=new PtreeTypeidExpr(new Leaf(tk),
5878 // Ptree::List(new Leaf(op), tname,
5879 // new Leaf(cp)));
5880
5881 exp = exprt(ID_typeid);
5882 set_location(exp, tk);
5883 return true;
5884 }
5885 }
5886
5887 lex.Restore(pos);
5888 lex.get_token(op);
5889
5890 if(rExpression(subexp, false))
5891 {
5892 if(lex.get_token(cp)==')')
5893 {
5894 // exp=new PtreeTypeidExpr(
5895 // new Leaf(tk),
5896 // Ptree::List(
5897 // Ptree::List(new Leaf(op), subexp, new Leaf(cp))
5898 // ));
5899
5900 exp = exprt(ID_typeid);
5901 set_location(exp, tk);
5902 return true;
5903 }
5904 }
5905
5906 lex.Restore(pos);
5907 }
5908
5909 return false;
5910}
5911
5912/*
5913 sizeof.expr
5914 : SIZEOF unary.expr
5915 | SIZEOF '(' type.name ')'
5916 | SIZEOF Ellipsis '(' Identifier ')'
5917*/
5918
5920{
5921 cpp_tokent tk;
5922
5923#ifdef DEBUG
5924 indenter _i;
5925 std::cout << std::string(__indent, ' ') << "Parser::rSizeofExpr 0\n";
5926#endif
5927
5929 return false;
5930
5931 if(lex.LookAhead(0)=='(')
5932 {
5933 typet tname;
5934 cpp_tokent op, cp;
5935
5937 lex.get_token(op);
5938
5939 if(rTypeName(tname))
5940 {
5941 if(lex.get_token(cp)==')')
5942 {
5943 exp=exprt(ID_sizeof);
5944 exp.add(ID_type_arg).swap(tname);
5945 set_location(exp, tk);
5946 return true;
5947 }
5948 }
5949
5950 lex.Restore(pos);
5951 }
5952 else if(lex.LookAhead(0)==TOK_ELLIPSIS)
5953 {
5954 typet tname;
5955 cpp_tokent ell, op, cp;
5956
5957 lex.get_token(ell);
5958
5959 lex.get_token(op);
5960
5961 if(rTypeName(tname))
5962 {
5963 if(lex.get_token(cp)==')')
5964 {
5965 exp=exprt(ID_sizeof);
5966 exp.add(ID_type_arg).swap(tname);
5967 set_location(exp, tk);
5968 return true;
5969 }
5970 }
5971
5972 return false;
5973 }
5974
5975 exprt unary;
5976
5977 if(!rUnaryExpr(unary))
5978 return false;
5979
5980 exp=exprt(ID_sizeof);
5981 exp.add_to_operands(std::move(unary));
5982 set_location(exp, tk);
5983 return true;
5984}
5985
5986/*
5987 alignof.expr
5988 | ALIGNOF '(' type.name ')'
5989*/
5990
5992{
5993 cpp_tokent tk;
5994
5996 return false;
5997
5998 typet tname;
5999 cpp_tokent op, cp;
6000
6001 lex.get_token(op);
6002
6003 if(!rTypeName(tname))
6004 return false;
6005
6006 if(lex.get_token(cp)!=')')
6007 return false;
6008
6009 exp=exprt(ID_alignof);
6010 exp.add(ID_type_arg).swap(tname);
6011 set_location(exp, tk);
6012 return true;
6013}
6014
6015/*
6016 noexcept.expr
6017 : NOEXCEPT '(' expression ')'
6018*/
6020{
6021 cpp_tokent tk;
6022
6023#ifdef DEBUG
6024 indenter _i;
6025 std::cout << std::string(__indent, ' ') << "Parser::rNoexceptExpr 0\n";
6026#endif
6027
6029 return false;
6030
6031 if(lex.LookAhead(0)=='(')
6032 {
6033 exprt subexp;
6034 cpp_tokent op, cp;
6035
6036 lex.get_token(op);
6037
6038 if(rExpression(subexp, false))
6039 {
6040 if(lex.get_token(cp)==')')
6041 {
6042 // TODO
6043 exp=exprt(ID_noexcept);
6044 exp.add_to_operands(std::move(subexp));
6045 set_location(exp, tk);
6046 return true;
6047 }
6048 }
6049 }
6050 else
6051 return true;
6052
6053 return false;
6054}
6055
6057{
6058 if(t==TOK_SCOPE)
6059 t=lex.LookAhead(1);
6060
6061 return t==TOK_NEW || t==TOK_DELETE;
6062}
6063
6064/*
6065 allocate.expr
6066 : {Scope | userdef.keyword} NEW allocate.type
6067 | {Scope} DELETE {'[' ']'} cast.expr
6068*/
6070{
6071 cpp_tokent tk;
6072 irept head=get_nil_irep();
6073
6074#ifdef DEBUG
6075 indenter _i;
6076 std::cout << std::string(__indent, ' ') << "Parser::rAllocateExpr 0\n";
6077#endif
6078
6079 int t=lex.LookAhead(0);
6080 if(t==TOK_SCOPE)
6081 {
6082 lex.get_token(tk);
6083 // TODO one can put 'new'/'delete' into a namespace!
6084 }
6085
6086#ifdef DEBUG
6087 std::cout << std::string(__indent, ' ') << "Parser::rAllocateExpr 1\n";
6088#endif
6089
6090 t=lex.get_token(tk);
6091
6092#ifdef DEBUG
6093 std::cout << std::string(__indent, ' ') << "Parser::rAllocateExpr 2\n";
6094#endif
6095
6096 if(t==TOK_DELETE)
6097 {
6098 exprt obj;
6099
6100 if(lex.LookAhead(0)=='[')
6101 {
6102 lex.get_token(tk);
6103
6104 if(lex.get_token(tk)!=']')
6105 return false;
6106
6107 exp=exprt(ID_side_effect);
6109 }
6110 else
6111 {
6112 exp=exprt(ID_side_effect);
6114 }
6115
6116 set_location(exp, tk);
6117
6118 if(!rCastExpr(obj))
6119 return false;
6120
6121 exp.add_to_operands(std::move(obj));
6122
6123 return true;
6124 }
6125 else if(t==TOK_NEW)
6126 {
6127#ifdef DEBUG
6128 std::cout << std::string(__indent, ' ') << "Parser::rAllocateExpr 3\n";
6129#endif
6130
6131 exp=exprt(ID_side_effect);
6133 set_location(exp, tk);
6134
6135 exprt arguments, initializer;
6136
6137 if(!rAllocateType(arguments, exp.type(), initializer))
6138 return false;
6139
6140#ifdef DEBUG
6141 std::cout << std::string(__indent, ' ') << "Parser::rAllocateExpr 4\n";
6142#endif
6143
6144 exp.add(ID_initializer).swap(initializer);
6145 exp.operands().swap(arguments.operands());
6146 return true;
6147 }
6148 else
6149 return false;
6150}
6151
6152/*
6153 allocate.type
6154 : {'(' function.arguments ')'} type.specifier new.declarator
6155 {allocate.initializer}
6156 | {'(' function.arguments ')'} '(' type.name ')' {allocate.initializer}
6157*/
6158
6160 exprt &arguments,
6161 typet &atype,
6162 exprt &initializer)
6163{
6164 if(lex.LookAhead(0)!='(')
6165 {
6166 atype.make_nil();
6167 }
6168 else
6169 {
6170 // reads the '('
6171 lex.get_token();
6172
6173 // we may need to backtrack
6175
6176 if(rTypeName(atype))
6177 {
6178 if(lex.get_token()==')')
6179 {
6180 // we have "( type.name )"
6181
6182 if(lex.LookAhead(0)!='(')
6183 {
6184 if(!isTypeSpecifier())
6185 return true;
6186 }
6187 else if(rAllocateInitializer(initializer))
6188 {
6189 // the next token cannot be '('
6190 if(lex.LookAhead(0)!='(')
6191 return true;
6192 }
6193 }
6194 }
6195
6196 // if we reach here, it's not '(' type.name ')',
6197 // and we have to process '(' function.arguments ')'.
6198
6199 lex.Restore(pos);
6200 if(!rFunctionArguments(arguments))
6201 return false;
6202
6203 if(lex.get_token()!=')')
6204 return false;
6205 }
6206
6207 if(lex.LookAhead(0)=='(')
6208 {
6209 lex.get_token();
6210
6211 typet tname;
6212
6213 if(!rTypeName(tname))
6214 return false;
6215
6216 if(lex.get_token()!=')')
6217 return false;
6218
6219 atype.swap(tname);
6220 }
6221 else
6222 {
6223 typet tname;
6224
6225 if(!rTypeSpecifier(tname, false))
6226 return false;
6227
6228 if(!rNewDeclarator(tname))
6229 return false;
6230
6231 atype.swap(tname);
6232 }
6233
6234 if(lex.LookAhead(0)=='(')
6235 {
6236 if(!rAllocateInitializer(initializer))
6237 return false;
6238 }
6239 else if(lex.LookAhead(0)=='{')
6240 {
6241 // this is a C++11 extension
6242 if(!rInitializeExpr(initializer))
6243 return false;
6244 }
6245
6246 return true;
6247}
6248
6249/*
6250 new.declarator
6251 : empty
6252 | ptr.operator
6253 | {ptr.operator} ('[' comma.expression ']')+
6254*/
6256{
6257 if(lex.LookAhead(0)!='[')
6258 if(!optPtrOperator(decl))
6259 return false;
6260
6261 while(lex.LookAhead(0)=='[')
6262 {
6263 cpp_tokent ob, cb;
6264 exprt expr;
6265
6266 lex.get_token(ob);
6267 if(!rCommaExpression(expr))
6268 return false;
6269
6270 if(lex.get_token(cb)!=']')
6271 return false;
6272
6273 array_typet array_type(decl, expr);
6275
6276 decl.swap(array_type);
6277 }
6278
6279 return true;
6280}
6281
6282/*
6283 allocate.initializer
6284 : '(' {initialize.expr (',' initialize.expr)* } ')'
6285*/
6287{
6288 if(lex.get_token()!='(')
6289 return false;
6290
6291 init.clear();
6292
6293 if(lex.LookAhead(0)==')')
6294 {
6295 lex.get_token();
6296 return true;
6297 }
6298
6299 for(;;)
6300 {
6301 exprt exp;
6302 if(!rInitializeExpr(exp))
6303 return false;
6304
6305 init.add_to_operands(std::move(exp));
6306
6307 if(lex.LookAhead(0)==TOK_ELLIPSIS)
6308 {
6309 lex.get_token();
6310 // TODO
6311 }
6312
6313 if(lex.LookAhead(0)==',')
6314 lex.get_token();
6315 else if(lex.LookAhead(0)==')')
6316 {
6317 lex.get_token();
6318 break;
6319 }
6320 else
6321 return false;
6322 }
6323
6324 return true;
6325}
6326
6327/*
6328 postfix.exp
6329 : primary.exp
6330 | postfix.expr '[' comma.expression ']'
6331 | postfix.expr '(' function.arguments ')'
6332 | postfix.expr '.' var.name
6333 | postfix.expr ArrowOp var.name
6334 | postfix.expr IncOp
6335 | openc++.postfix.expr
6336
6337 openc++.postfix.expr
6338 : postfix.expr '.' userdef.statement
6339 | postfix.expr ArrowOp userdef.statement
6340
6341 Note: function-style casts are accepted as function calls.
6342*/
6344{
6345#ifdef DEBUG
6346 indenter _i;
6347 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 0\n";
6348#endif
6349
6350 if(!rPrimaryExpr(exp))
6351 return false;
6352
6353#ifdef DEBUG
6354 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 1\n";
6355#endif
6356
6357 exprt e;
6358 cpp_tokent cp, op;
6359 int t2;
6360
6361 for(;;)
6362 {
6363 switch(lex.LookAhead(0))
6364 {
6365 case '[':
6366 lex.get_token(op);
6367 if(!rCommaExpression(e))
6368 return false;
6369
6370#ifdef DEBUG
6371 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 2\n";
6372#endif
6373
6374 if(lex.get_token(cp)!=']')
6375 return false;
6376
6377 {
6378 exprt left;
6379 left.swap(exp);
6380
6381 exp=exprt(ID_index);
6382 exp.add_to_operands(std::move(left), std::move(e));
6383 set_location(exp, op);
6384 }
6385 break;
6386
6387 case '(':
6388#ifdef DEBUG
6389 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 3\n";
6390#endif
6391
6392 lex.get_token(op);
6393 if(!rFunctionArguments(e))
6394 return false;
6395
6396 if(lex.get_token(cp)!=')')
6397 return false;
6398
6399#ifdef DEBUG
6400 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 4\n";
6401#endif
6402
6403 {
6405 std::move(exp), {}, typet{}, source_locationt{});
6406 fc.arguments().reserve(e.operands().size());
6407 set_location(fc, op);
6408
6409 Forall_operands(it, e)
6410 fc.arguments().push_back(*it);
6411 e.operands().clear(); // save some
6412 exp.swap(fc);
6413 }
6414 break;
6415
6416 case TOK_INCR:
6417 lex.get_token(op);
6418
6419 {
6421 tmp.add_to_operands(std::move(exp));
6422 set_location(tmp, op);
6423 exp.swap(tmp);
6424 }
6425 break;
6426
6427 case TOK_DECR:
6428 lex.get_token(op);
6429
6430 {
6432 ID_postdecrement, {std::move(exp)}, typet(), source_locationt());
6433 set_location(tmp, op);
6434 exp.swap(tmp);
6435 }
6436 break;
6437
6438 case '.':
6439 case TOK_ARROW:
6440 t2=lex.get_token(op);
6441
6442#ifdef DEBUG
6443 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 5\n";
6444#endif
6445
6446 if(!rVarName(e))
6447 return false;
6448
6449#ifdef DEBUG
6450 std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 6\n";
6451#endif
6452
6453 {
6454 exprt left;
6455 left.swap(exp);
6456
6457 if(t2=='.')
6458 exp=exprt(ID_member);
6459 else // ARROW
6460 exp=exprt(ID_ptrmember);
6461
6462 exp.add_to_operands(std::move(left));
6463 set_location(exp, op);
6464 }
6465
6467
6468 break;
6469
6470 default:
6471 return true;
6472 }
6473 }
6474}
6475
6476/*
6477 __uuidof( expression )
6478 __uuidof( type )
6479 This is a Visual Studio Extension.
6480*/
6481
6483{
6484 cpp_tokent tk;
6485
6487 return false;
6488
6489 if(lex.get_token(tk)!='(')
6490 return false;
6491
6492 {
6493 typet tname;
6494 cpp_tokent cp;
6495
6497
6498 if(rTypeName(tname))
6499 {
6500 if(lex.get_token(cp)==')')
6501 {
6502 expr=exprt(ID_msc_uuidof);
6503 expr.add(ID_type_arg).swap(tname);
6504 set_location(expr, tk);
6505 return true;
6506 }
6507 }
6508
6509 lex.Restore(pos);
6510 }
6511
6512 exprt unary;
6513
6514 if(!rUnaryExpr(unary))
6515 return false;
6516
6517 if(lex.get_token(tk)!=')')
6518 return false;
6519
6520 expr=exprt(ID_msc_uuidof);
6521 expr.add_to_operands(std::move(unary));
6522 set_location(expr, tk);
6523 return true;
6524}
6525
6526/*
6527 __if_exists ( identifier ) { token stream }
6528 __if_not_exists ( identifier ) { token stream }
6529*/
6530
6532{
6534
6535 lex.get_token(tk1);
6536
6537 if(tk1.kind!=TOK_MSC_IF_EXISTS &&
6539 return false;
6540
6542
6543 if(lex.get_token(tk2)!='(')
6544 return false;
6545
6546 exprt name;
6547
6548 if(!rVarName(name))
6549 return false;
6550
6551 if(lex.get_token(tk2)!=')')
6552 return false;
6553
6554 if(lex.get_token(tk2)!='{')
6555 return false;
6556
6557 exprt op;
6558
6559 if(!rUnaryExpr(op))
6560 return false;
6561
6562 if(lex.get_token(tk2)!='}')
6563 return false;
6564
6565 expr=exprt(
6568
6569 expr.add_to_operands(std::move(name), std::move(op));
6570
6571 set_location(expr, tk1);
6572
6573 return true;
6574}
6575
6577{
6579
6580 lex.get_token(tk1);
6581
6582 if(tk1.kind != TOK_MSC_IF_EXISTS && tk1.kind != TOK_MSC_IF_NOT_EXISTS)
6583 return {};
6584
6586
6587 if(lex.get_token(tk2)!='(')
6588 return {};
6589
6590 exprt name;
6591
6592 if(!rVarName(name))
6593 return {};
6594
6595 if(lex.get_token(tk2)!=')')
6596 return {};
6597
6598 if(lex.get_token(tk2)!='{')
6599 return {};
6600
6601 code_blockt block;
6602
6603 while(lex.LookAhead(0)!='}')
6604 {
6605 if(auto statement = rStatement())
6606 block.add(std::move(*statement));
6607 else
6608 return {};
6609 }
6610
6611 if(lex.get_token(tk2)!='}')
6612 return {};
6613
6614 codet code(
6616
6617 code.add_to_operands(std::move(name), std::move(block));
6618
6619 set_location(code, tk1);
6620
6621 return std::move(code);
6622}
6623
6624/*
6625 __is_base_of ( base, derived )
6626 __is_convertible_to ( from, to )
6627 __is_class ( t )
6628 __is_... (t)
6629*/
6630
6632{
6633 cpp_tokent tk;
6634
6635 lex.get_token(tk);
6636
6637 expr.id(irep_idt(tk.text));
6638 set_location(expr, tk);
6639
6641
6642 switch(tk.kind)
6643 {
6645 if(lex.get_token(tk)!='(')
6646 return false;
6647 if(!rTypeName(tname1))
6648 return false;
6649 if(lex.get_token(tk)!=')')
6650 return false;
6651 expr.add(ID_type_arg).swap(tname1);
6652 break;
6653
6655 if(lex.get_token(tk)!='(')
6656 return false;
6657 if(!rTypeName(tname1))
6658 return false;
6659 if(lex.get_token(tk)!=',')
6660 return false;
6661 if(!rTypeName(tname2))
6662 return false;
6663 if(lex.get_token(tk)!=')')
6664 return false;
6665 expr.add("type_arg1").swap(tname1);
6666 expr.add("type_arg2").swap(tname2);
6667 break;
6668
6669 default:
6671 }
6672
6673 return true;
6674}
6675
6676/*
6677 primary.exp
6678 : Constant
6679 | CharConst
6680 | WideCharConst !!! new
6681 | String
6682 | WideStringL !!! new
6683 | THIS
6684 | var.name
6685 | '(' comma.expression ')'
6686 | integral.or.class.spec '(' function.arguments ')'
6687 | integral.or.class.spec initializer
6688 | typeid.expr
6689 | true
6690 | false
6691 | nullptr
6692*/
6694{
6695 cpp_tokent tk, tk2;
6696
6697#ifdef DEBUG
6698 indenter _i;
6699 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 0 "
6700 << lex.LookAhead(0) << ' ' << lex.current_token().text << '\n';
6701#endif
6702
6703 switch(lex.LookAhead(0))
6704 {
6705 case TOK_INTEGER:
6706 case TOK_CHARACTER:
6707 case TOK_FLOATING:
6708 lex.get_token(tk);
6709 exp.swap(tk.data);
6710 set_location(exp, tk);
6711#ifdef DEBUG
6712 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 1\n";
6713#endif
6714 return true;
6715
6716 case TOK_STRING:
6717 rString(tk);
6718 exp.swap(tk.data);
6719 set_location(exp, tk);
6720#ifdef DEBUG
6721 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 2\n";
6722#endif
6723 return true;
6724
6725 case TOK_THIS:
6726 lex.get_token(tk);
6727 exp=exprt("cpp-this");
6728 set_location(exp, tk);
6729#ifdef DEBUG
6730 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 3\n";
6731#endif
6732 return true;
6733
6734 case TOK_TRUE:
6735 lex.get_token(tk);
6737 set_location(exp, tk);
6738#ifdef DEBUG
6739 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 4\n";
6740#endif
6741 return true;
6742
6743 case TOK_FALSE:
6744 lex.get_token(tk);
6746 set_location(exp, tk);
6747#ifdef DEBUG
6748 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 5\n";
6749#endif
6750 return true;
6751
6752 case TOK_NULLPTR:
6753 lex.get_token(tk);
6754 // as an exception, we set the width of pointer
6756 set_location(exp, tk);
6757#ifdef DEBUG
6758 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 6\n";
6759#endif
6760 return true;
6761
6762 case '(':
6763#ifdef DEBUG
6764 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 7\n";
6765#endif
6766 lex.get_token(tk);
6767
6768 if(lex.LookAhead(0)=='{') // GCC extension
6769 {
6770 if(auto code = rCompoundStatement())
6771 {
6772 exp = exprt(ID_side_effect);
6774 set_location(exp, tk);
6775 exp.add_to_operands(std::move(*code));
6776 }
6777 else
6778 return false;
6779
6780 if(lex.get_token(tk2)!=')')
6781 return false;
6782 }
6783 else
6784 {
6785 exprt exp2;
6786
6788 return false;
6789
6790#ifdef DEBUG
6791 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 8\n";
6792#endif
6793
6794 if(lex.get_token(tk2)!=')')
6795 return false;
6796
6797 exp.swap(exp2);
6798 }
6799
6800#ifdef DEBUG
6801 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 9\n";
6802#endif
6803 return true;
6804
6805 case '{': // C++11 initialisation expression
6806#ifdef DEBUG
6807 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 10\n";
6808#endif
6809 return rInitializeExpr(exp);
6810
6811 case TOK_TYPEID:
6812 return rTypeidExpr(exp);
6813
6816#ifdef DEBUG
6817 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 11\n";
6818#endif
6819 return rTypePredicate(exp);
6820
6821 case TOK_MSC_UUIDOF:
6822#ifdef DEBUG
6823 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 12\n";
6824#endif
6825 return rMSCuuidof(exp);
6826
6827 // not quite appropriate: these allow more general
6828 // token streams, not just expressions
6829 case TOK_MSC_IF_EXISTS:
6831#ifdef DEBUG
6832 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 13\n";
6833#endif
6834 return rMSC_if_existsExpr(exp);
6835
6836 default:
6837#ifdef DEBUG
6838 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 14\n";
6839#endif
6840 {
6841 typet type;
6842
6844 return false;
6845
6846#ifdef DEBUG
6847 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 15\n";
6848#endif
6849
6850 if(type.is_not_nil() && lex.LookAhead(0)==TOK_SCOPE)
6851 {
6852 lex.get_token(tk);
6853 lex.get_token(tk);
6854
6855 // TODO
6856 }
6857 else if(type.is_not_nil())
6858 {
6859#ifdef DEBUG
6860 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 16\n";
6861#endif
6862 if(lex.LookAhead(0)=='{')
6863 {
6864 lex.LookAhead(0, tk);
6865
6866 exprt exp2;
6867 if(!rInitializeExpr(exp2))
6868 return false;
6869
6870 exp=exprt("explicit-constructor-call");
6871 exp.type().swap(type);
6872 exp.add_to_operands(std::move(exp2));
6873 set_location(exp, tk);
6874 }
6875 else if(lex.LookAhead(0)=='(')
6876 {
6877 lex.get_token(tk);
6878
6879 exprt exp2;
6881 return false;
6882
6883 if(lex.get_token(tk2)!=')')
6884 return false;
6885
6886 exp=exprt("explicit-constructor-call");
6887 exp.type().swap(type);
6888 exp.operands().swap(exp2.operands());
6889 set_location(exp, tk);
6890 }
6891 else
6892 return false;
6893 }
6894 else
6895 {
6896 if(!rVarName(exp))
6897 return false;
6898
6899 if(lex.LookAhead(0)==TOK_SCOPE)
6900 {
6901 lex.get_token(tk);
6902
6903 // exp=new PtreeStaticUserStatementExpr(exp,
6904 // Ptree::Cons(new Leaf(tk), exp2));
6905 // TODO
6906 }
6907 }
6908 }
6909#ifdef DEBUG
6910 std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 17\n";
6911#endif
6912
6913 return true;
6914 }
6915}
6916
6917/*
6918 var.name : {'::'} name2 ('::' name2)*
6919
6920 name2
6921 : Identifier {template.args}
6922 | '~' Identifier
6923 | OPERATOR operator.name
6924
6925 if var.name ends with a template type, the next token must be '('
6926*/
6928{
6929#ifdef DEBUG
6930 indenter _i;
6931 std::cout << std::string(__indent, ' ') << "Parser::rVarName 0\n";
6932#endif
6933
6934 if(rVarNameCore(name))
6935 return true;
6936 else
6937 return false;
6938}
6939
6941{
6942#ifdef DEBUG
6943 indenter _i;
6944 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 0\n";
6945#endif
6946
6947 name = cpp_namet().as_expr();
6948 irept::subt &components=name.get_sub();
6949
6950 if(lex.LookAhead(0)==TOK_TYPENAME)
6951 {
6952 cpp_tokent tk;
6953 lex.get_token(tk);
6954 name.set(ID_typename, true);
6955 }
6956
6957 {
6958 cpp_tokent tk;
6959 lex.LookAhead(0, tk);
6960 set_location(name, tk);
6961 }
6962
6963#ifdef DEBUG
6964 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 1\n";
6965#endif
6966
6967 for(;;)
6968 {
6969 cpp_tokent tk;
6970
6971#ifdef DEBUG
6972 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 1.1 "
6973 << lex.LookAhead(0)
6974 << '\n';
6975#endif
6976
6977 switch(lex.LookAhead(0))
6978 {
6979 case TOK_TEMPLATE:
6980 // this may be a template member function, for example
6981#ifdef DEBUG
6982 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 2\n";
6983#endif
6984 lex.get_token(tk);
6985 // Skip template token, next will be identifier
6986 if(!is_identifier(lex.LookAhead(0)))
6987 return false;
6988 break;
6989
6990 case TOK_GCC_IDENTIFIER:
6991 case TOK_MSC_IDENTIFIER:
6992#ifdef DEBUG
6993 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 3\n";
6994#endif
6995
6996 lex.get_token(tk);
6997 components.push_back(cpp_namet::namet(tk.data.get(ID_C_base_name)));
6998 set_location(components.back(), tk);
6999
7000 // may be followed by template arguments
7001 if(maybeTemplateArgs())
7002 {
7004
7005#ifdef DEBUG
7006 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 4\n";
7007#endif
7008
7009 irept args;
7010 if(!rTemplateArgs(args))
7011 {
7012 lex.Restore(pos);
7013 return true;
7014 }
7015
7016 components.push_back(irept(ID_template_args));
7017 components.back().add(ID_arguments).swap(args);
7018 }
7019
7020 if(!moreVarName())
7021 return true;
7022 break;
7023
7024 case TOK_SCOPE:
7025#ifdef DEBUG
7026 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 5\n";
7027#endif
7028
7029 lex.get_token(tk);
7030 components.push_back(irept("::"));
7031 set_location(components.back(), tk);
7032 break;
7033
7034 case '~':
7035#ifdef DEBUG
7036 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 6\n";
7037#endif
7038
7039 lex.get_token(tk);
7040
7041 if(!is_identifier(lex.LookAhead(0)))
7042 return false;
7043
7044 components.push_back(irept("~"));
7045 set_location(components.back(), tk);
7046 break;
7047
7048 case TOK_OPERATOR:
7049#ifdef DEBUG
7050 std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 7\n";
7051#endif
7052
7053 lex.get_token(tk);
7054
7055 components.push_back(irept(ID_operator));
7056 set_location(components.back(), tk);
7057
7058 {
7059 irept op;
7060 if(!rOperatorName(op))
7061 return false;
7062
7063 components.push_back(op);
7064 }
7065 return true;
7066
7067 default:
7068 return false;
7069 }
7070 }
7071}
7072
7074{
7075 if(lex.LookAhead(0)==TOK_SCOPE)
7076 {
7077 int t=lex.LookAhead(1);
7078 if(is_identifier(t) || t == '~' || t == TOK_OPERATOR || t == TOK_TEMPLATE)
7079 return true;
7080 }
7081
7082 return false;
7083}
7084
7085/*
7086 template.args : '<' any* '>'
7087
7088 template.args must be followed by '(' or '::'
7089*/
7091{
7092 int i=0;
7093 int t=lex.LookAhead(i++);
7094
7095#ifdef DEBUG
7096 indenter _i;
7097 std::cout << std::string(__indent, ' ') << "Parser::maybeTemplateArgs 0\n";
7098#endif
7099
7100 if(t=='<')
7101 {
7102#if 1
7103 for(;;)
7104 {
7105 int u=lex.LookAhead(i++);
7106 if(u=='\0' || u==';' || u=='}')
7107 return false;
7108 else if((u=='>' || u==TOK_SHIFTRIGHT) &&
7109 (lex.LookAhead(i)==TOK_SCOPE || lex.LookAhead(i)=='(' ||
7110 lex.LookAhead(i)==')'))
7111 return true;
7112 }
7113#else
7114 int n=1;
7115
7116 while(n>0)
7117 {
7118#ifdef DEBUG
7119 std::cout << std::string(__indent, ' ')
7120 << "Parser::maybeTemplateArgs 1\n";
7121#endif
7122
7123 int u=lex.LookAhead(i++);
7124
7125#ifdef DEBUG
7126 std::cout << std::string(__indent, ' ')
7127 << "Parser::maybeTemplateArgs 2\n";
7128#endif
7129
7130 if(u=='<')
7131 ++n;
7132 else if(u=='>')
7133 --n;
7134 else if(u=='(')
7135 {
7136 int m=1;
7137 while(m>0)
7138 {
7139 int v=lex.LookAhead(i++);
7140
7141#ifdef DEBUG
7142 std::cout << std::string(__indent, ' ')
7143 << "Parser::maybeTemplateArgs 3\n";
7144#endif
7145
7146 if(v=='(')
7147 ++m;
7148 else if(v==')')
7149 --m;
7150 else if(v=='\0' || v==';' || v=='}')
7151 return false;
7152 }
7153 }
7154 else if(u=='\0' || u==';' || u=='}')
7155 return false;
7156 else if(u==TOK_SHIFTRIGHT && n>=2)
7157 n-=2;
7158
7159#ifdef DEBUG
7160 std::cout << std::string(__indent, ' ')
7161 << "Parser::maybeTemplateArgs 4\n";
7162#endif
7163 }
7164
7165#ifdef DEBUG
7166 std::cout << std::string(__indent, ' ') << "Parser::maybeTemplateArgs 5\n";
7167#endif
7168
7169 t=lex.LookAhead(i);
7170
7171#ifdef DEBUG
7172 std::cout << std::string(__indent, ' ') << "Parser::maybeTemplateArgs 6\n";
7173#endif
7174
7175 return t==TOK_SCOPE || t=='(';
7176#endif
7177 }
7178
7179#ifdef DEBUG
7180 std::cout << std::string(__indent, ' ') << "Parser::maybeTemplateArgs 7\n";
7181#endif
7182
7183 return false;
7184}
7185
7186/*
7187 function.body : compound.statement
7188 | { asm }
7189*/
7190
7192{
7193 // The following is an extension in GCC,
7194 // ARMCC, CodeWarrior...
7195
7196 if(lex.LookAhead(0)=='{' &&
7198 {
7199 cpp_tokent ob, tk, cb;
7200 lex.get_token(ob);
7201
7202 codet body=code_blockt();
7203 set_location(body, ob);
7204
7205 lex.get_token(tk);
7206 // TODO: add to body
7207
7208 if(lex.get_token(cb)!='}')
7209 return false;
7210
7211 declarator.value()=body;
7212 return true;
7213 }
7214 else
7215 {
7216 // this is for the benefit of set_location
7217 const cpp_namet &cpp_name=declarator.name();
7218 current_function=cpp_name.get_base_name();
7219
7220 if(auto body = rCompoundStatement())
7221 declarator.value() = std::move(*body);
7222 else
7223 {
7225 return false;
7226 }
7227
7229
7230 return true;
7231 }
7232}
7233
7234/*
7235 compound.statement
7236 : '{' (statement)* '}'
7237*/
7239{
7240 cpp_tokent ob, cb;
7241
7242#ifdef DEBUG
7243 indenter _i;
7244 std::cout << std::string(__indent, ' ') << "Parser::rCompoundStatement 1\n";
7245#endif
7246
7247 if(lex.get_token(ob)!='{')
7248 return {};
7249
7250#ifdef DEBUG
7251 std::cout << std::string(__indent, ' ') << "Parser::rCompoundStatement 2\n";
7252#endif
7253
7254 code_blockt statement;
7255 set_location(statement, ob);
7256
7257 while(lex.LookAhead(0)!='}')
7258 {
7259 if(auto statement2 = rStatement())
7260 statement.add(std::move(*statement2));
7261 else
7262 {
7263 if(!SyntaxError())
7264 return {}; // too many errors
7265
7266 SkipTo('}');
7267 lex.get_token(cb);
7268 return std::move(statement); // error recovery
7269 }
7270 }
7271
7272 if(lex.get_token(cb)!='}')
7273 return {};
7274
7275 return std::move(statement);
7276}
7277
7278/*
7279 statement
7280 : compound.statement
7281 | typedef
7282 | if.statement
7283 | switch.statement
7284 | while.statement
7285 | do.statement
7286 | for.statement
7287 | try.statement
7288 | BREAK ';'
7289 | CONTINUE ';'
7290 | RETURN { comma.expression } ';'
7291 | GOTO Identifier ';'
7292 | CASE expression ':' statement
7293 | DEFAULT ':' statement
7294 | Identifier ':' statement
7295 | expr.statement
7296 | USING { NAMESPACE } identifier ';'
7297 | STATIC_ASSERT ( expression ',' expression ) ';'
7298*/
7300{
7302 int k;
7303
7304#ifdef DEBUG
7305 indenter _i;
7306 std::cout << std::string(__indent, ' ') << "Parser::rStatement 0 "
7307 << lex.LookAhead(0) << '\n';
7308#endif
7309
7310 switch(k=lex.LookAhead(0))
7311 {
7312 case '{':
7313 return rCompoundStatement();
7314
7315 case TOK_TYPEDEF:
7316 return rTypedefStatement();
7317
7318 case TOK_IF:
7319 return rIfStatement();
7320
7321 case TOK_SWITCH:
7322 return rSwitchStatement();
7323
7324 case TOK_WHILE:
7325 return rWhileStatement();
7326
7327 case TOK_DO:
7328 return rDoStatement();
7329
7330 case TOK_FOR:
7331 return rForStatement();
7332
7333 case TOK_TRY:
7334 return rTryStatement();
7335
7336 case TOK_MSC_TRY:
7337 return rMSC_tryStatement();
7338
7339 case TOK_MSC_LEAVE:
7340 return rMSC_leaveStatement();
7341
7342 case TOK_BREAK:
7343 case TOK_CONTINUE:
7344 {
7345 lex.get_token(tk1);
7346
7347 codet statement(k == TOK_BREAK ? ID_break : ID_continue);
7348 set_location(statement, tk1);
7349
7350 if(lex.get_token(tk2)!=';')
7351 return {};
7352
7353 return std::move(statement);
7354 }
7355 case TOK_RETURN:
7356 {
7357#ifdef DEBUG
7358 std::cout << std::string(__indent, ' ') << "Parser::rStatement RETURN 0\n";
7359#endif
7360
7361 lex.get_token(tk1);
7362
7363 code_frontend_returnt statement;
7364 set_location(statement, tk1);
7365
7366 if(lex.LookAhead(0)==';')
7367 {
7368#ifdef DEBUG
7369 std::cout << std::string(__indent, ' ')
7370 << "Parser::rStatement RETURN 1\n";
7371#endif
7372 lex.get_token(tk2);
7373 }
7374 else
7375 {
7376#ifdef DEBUG
7377 std::cout << std::string(__indent, ' ')
7378 << "Parser::rStatement RETURN 2\n";
7379#endif
7380
7381 if(!rCommaExpression(statement.return_value()))
7382 return {};
7383
7384#ifdef DEBUG
7385 std::cout << std::string(__indent, ' ')
7386 << "Parser::rStatement RETURN 3\n";
7387#endif
7388
7389 if(lex.get_token(tk2)!=';')
7390 return {};
7391 }
7392
7393 return std::move(statement);
7394 }
7395 case TOK_GOTO:
7396 {
7397 lex.get_token(tk1);
7398
7400 return {};
7401
7402 if(lex.get_token(tk3)!=';')
7403 return {};
7404
7405 code_gotot statement(tk2.data.get(ID_C_base_name));
7406 set_location(statement, tk1);
7407
7408 return std::move(statement);
7409 }
7410 case TOK_CASE:
7411 {
7412 lex.get_token(tk1);
7413
7415 if(!rExpression(case_expr, false))
7416 return {};
7417
7418 if(lex.LookAhead(0)==TOK_ELLIPSIS)
7419 {
7420 // This is a gcc extension for case ranges.
7421 // Should really refuse in non-GCC modes.
7422 lex.get_token(tk2);
7423
7425 if(!rExpression(range_end, false))
7426 return {};
7427
7428 if(lex.get_token(tk2)!=':')
7429 return {};
7430
7431 if(auto statement2 = rStatement())
7432 {
7434 std::move(case_expr), std::move(range_end), std::move(*statement2));
7435 set_location(code, tk1);
7436 return std::move(code);
7437 }
7438 else
7439 return {};
7440 }
7441 else
7442 {
7443 if(lex.get_token(tk2)!=':')
7444 return {};
7445
7446 if(auto statement2 = rStatement())
7447 {
7448 code_switch_caset statement(
7449 std::move(case_expr), std::move(*statement2));
7450 set_location(statement, tk1);
7451 return std::move(statement);
7452 }
7453 else
7454 return {};
7455 }
7456 }
7457
7458 case TOK_DEFAULT:
7459 {
7460 lex.get_token(tk1);
7461
7462 if(lex.get_token(tk2)!=':')
7463 return {};
7464
7465 if(auto statement2 = rStatement())
7466 {
7467 code_switch_caset statement(exprt{}, std::move(*statement2));
7468 statement.set_default();
7469 set_location(statement, tk1);
7470 return std::move(statement);
7471 }
7472 else
7473 return {};
7474 }
7475
7476 case TOK_GCC_ASM:
7477 return rGCCAsmStatement();
7478
7479 case TOK_MSC_ASM:
7480 return rMSCAsmStatement();
7481
7482 case TOK_MSC_IF_EXISTS:
7484 return rMSC_if_existsStatement();
7485
7486 case TOK_GCC_IDENTIFIER:
7487 case TOK_MSC_IDENTIFIER:
7488 if(lex.LookAhead(1)==':') // label statement
7489 {
7490 // the label
7491 lex.get_token(tk1);
7492 // the colon
7493 lex.get_token(tk2);
7494
7495 if(auto statement2 = rStatement())
7496 {
7497 code_labelt label(tk1.data.get(ID_C_base_name), std::move(*statement2));
7498 set_location(label, tk1);
7499 return std::move(label);
7500 }
7501 else
7502 return {};
7503 }
7504
7505 return rExprStatement();
7506
7507 case TOK_USING:
7508 {
7509 if(is_identifier(lex.LookAhead(1)) && lex.LookAhead(2) == '=')
7510 {
7511 cpp_declarationt declaration;
7512 if(!rTypedefUsing(declaration))
7513 return {};
7514 code_frontend_declt statement(
7515 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
7516 statement.add_source_location() = declaration.source_location();
7517 return std::move(statement);
7518 }
7519
7521
7522 if(!rUsing(cpp_using))
7523 return {};
7524
7526 }
7527
7528 case TOK_STATIC_ASSERT:
7529 {
7531
7533 return {};
7534
7535 codet statement(ID_static_assert);
7536 statement.add_source_location()=cpp_static_assert.source_location();
7537 statement.operands().swap(cpp_static_assert.operands());
7538
7539 return std::move(statement);
7540 }
7541
7542 default:
7543 return rExprStatement();
7544 }
7545}
7546
7547/*
7548 if.statement
7549 : IF '(' comma.expression ')' statement { ELSE statement }
7550*/
7552{
7554
7555 if(lex.get_token(tk1)!=TOK_IF)
7556 return {};
7557
7558 if(lex.get_token(tk2)!='(')
7559 return {};
7560
7561 exprt exp;
7562 if(!rCondition(exp))
7563 return {};
7564
7565 if(lex.get_token(tk3)!=')')
7566 return {};
7567
7568 auto then = rStatement();
7569 if(!then.has_value())
7570 return {};
7571
7572 if(lex.LookAhead(0)==TOK_ELSE)
7573 {
7574 lex.get_token(tk4);
7575
7576 if(auto otherwise = rStatement())
7577 {
7578 code_ifthenelset statement(
7579 std::move(exp), std::move(*then), std::move(*otherwise));
7580 set_location(statement, tk1);
7581 return std::move(statement);
7582 }
7583 else
7584 return {};
7585 }
7586 else
7587 {
7588 code_ifthenelset statement(std::move(exp), std::move(*then));
7589 set_location(statement, tk1);
7590 return std::move(statement);
7591 }
7592}
7593
7594/*
7595 switch.statement
7596 : SWITCH '(' comma.expression ')' statement
7597*/
7599{
7601
7603 return {};
7604
7605 if(lex.get_token(tk2)!='(')
7606 return {};
7607
7608 exprt exp;
7609 if(!rCondition(exp))
7610 return {};
7611
7612 if(lex.get_token(tk3)!=')')
7613 return {};
7614
7615 if(auto body = rStatement())
7616 {
7617 code_switcht statement(std::move(exp), std::move(*body));
7618 set_location(statement, tk1);
7619 return std::move(statement);
7620 }
7621 else
7622 return {};
7623}
7624
7625/*
7626 while.statement
7627 : WHILE '(' comma.expression ')' statement
7628*/
7630{
7632
7634 return {};
7635
7636 if(lex.get_token(tk2)!='(')
7637 return {};
7638
7639 exprt exp;
7640 if(!rCondition(exp))
7641 return {};
7642
7643 if(lex.get_token(tk3)!=')')
7644 return {};
7645
7646 if(auto body = rStatement())
7647 {
7648 code_whilet statement(std::move(exp), std::move(*body));
7649 set_location(statement, tk1);
7650 return std::move(statement);
7651 }
7652 else
7653 return {};
7654}
7655
7656/*
7657 do.statement
7658 : DO statement WHILE '(' comma.expression ')' ';'
7659*/
7661{
7663
7664 if(lex.get_token(tk0)!=TOK_DO)
7665 return {};
7666
7667 auto body = rStatement();
7668 if(!body.has_value())
7669 return {};
7670
7672 return {};
7673
7674 if(lex.get_token(tk2)!='(')
7675 return {};
7676
7677 exprt exp;
7678 if(!rCommaExpression(exp))
7679 return {};
7680
7681 if(lex.get_token(tk3)!=')')
7682 return {};
7683
7684 if(lex.get_token(tk4)!=';')
7685 return {};
7686
7687 code_dowhilet statement(std::move(exp), std::move(*body));
7688 set_location(statement, tk0);
7689 return std::move(statement);
7690}
7691
7692/*
7693 for.statement
7694 : FOR '(' expr.statement {comma.expression} ';' {comma.expression} ')'
7695 statement
7696*/
7698{
7700
7701 if(lex.get_token(tk1)!=TOK_FOR)
7702 return {};
7703
7704 if(lex.get_token(tk2)!='(')
7705 return {};
7706
7707 auto exp1 = rExprStatement();
7708
7709 if(!exp1.has_value())
7710 return {};
7711
7712 exprt exp2;
7713
7714 if(lex.LookAhead(0)==';')
7715 exp2.make_nil();
7716 else
7718 return {};
7719
7720 if(lex.get_token(tk3)!=';')
7721 return {};
7722
7723 exprt exp3;
7724
7725 if(lex.LookAhead(0)==')')
7726 exp3.make_nil();
7727 else
7728 {
7730 return {};
7731 }
7732
7733 if(lex.get_token(tk4)!=')')
7734 return {};
7735
7736 if(auto body = rStatement())
7737 {
7738 code_fort statement(
7739 std::move(*exp1), std::move(exp2), std::move(exp3), std::move(*body));
7740 set_location(statement, tk1);
7741 return std::move(statement);
7742 }
7743 else
7744 return {};
7745}
7746
7747/*
7748 try.statement
7749 : TRY compound.statement (exception.handler)+ ';'
7750
7751 exception.handler
7752 : CATCH '(' (arg.declaration | Ellipsis) ')' compound.statement
7753*/
7755{
7757
7758 // The 'try' block
7760 return {};
7761
7763 if(!try_body.has_value())
7764 return {};
7765
7766 code_try_catcht statement(std::move(*try_body));
7767 set_location(statement, try_token);
7768
7769 // iterate while there are catch clauses
7770 do
7771 {
7773
7775 return {};
7776
7777 if(lex.get_token(op_token)!='(')
7778 return {};
7779
7781
7782 if(lex.LookAhead(0)==TOK_ELLIPSIS)
7783 {
7788 catch_op = std::move(ellipsis);
7789 }
7790 else
7791 {
7792 cpp_declarationt declaration;
7793
7794 if(!rArgDeclaration(declaration))
7795 return {};
7796
7797 // No name in the declarator? Make one.
7799 declaration.declarators().size() == 1, "exactly one declarator");
7800
7801 if(declaration.declarators().front().name().is_nil())
7802 declaration.declarators().front().name() = cpp_namet("#anon");
7803
7805 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
7807
7808 catch_op = std::move(code_decl);
7809 }
7810
7811 if(lex.get_token(cp_token)!=')')
7812 return {};
7813
7814 if(auto body = rCompoundStatement())
7815 {
7816 code_blockt &block = to_code_block(*body);
7817
7818 block.statements().insert(block.statements().begin(), *catch_op);
7819
7820 statement.add_to_operands(std::move(*body));
7821 }
7822 else
7823 return {};
7824 }
7825 while(lex.LookAhead(0)==TOK_CATCH);
7826
7827 return std::move(statement);
7828}
7829
7831{
7832 // These are for 'structured exception handling',
7833 // and are a relic from Visual C.
7834
7835 cpp_tokent tk, tk2, tk3;
7836
7838 return {};
7839
7840 auto body1 = rCompoundStatement();
7841
7842 if(!body1.has_value())
7843 return {};
7844
7846 {
7847 codet statement(ID_msc_try_except);
7848 set_location(statement, tk);
7849
7850 lex.get_token(tk);
7851
7852 // get '(' comma.expression ')'
7853
7854 if(lex.get_token(tk2)!='(')
7855 return {};
7856
7857 exprt exp;
7858 if(!rCommaExpression(exp))
7859 return {};
7860
7861 if(lex.get_token(tk3)!=')')
7862 return {};
7863
7864 if(auto body2 = rCompoundStatement())
7865 {
7866 statement.add_to_operands(
7867 std::move(*body1), std::move(exp), std::move(*body2));
7868 return std::move(statement);
7869 }
7870 else
7871 return {};
7872 }
7873 else if(lex.LookAhead(0)==TOK_MSC_FINALLY)
7874 {
7875 codet statement(ID_msc_try_finally);
7876 set_location(statement, tk);
7877
7878 lex.get_token(tk);
7879
7880 if(auto body2 = rCompoundStatement())
7881 {
7882 statement.add_to_operands(std::move(*body1), std::move(*body2));
7883 return std::move(statement);
7884 }
7885 else
7886 return {};
7887 }
7888 else
7889 return {};
7890}
7891
7893{
7894 // These are for 'structured exception handling',
7895 // and are a relic from Visual C.
7896
7897 cpp_tokent tk;
7898
7900 return {};
7901
7902 codet statement(ID_msc_leave);
7903 set_location(statement, tk);
7904
7905 return std::move(statement);
7906}
7907
7909{
7910 cpp_tokent tk;
7911
7912#ifdef DEBUG
7913 indenter _i;
7914 std::cout << std::string(__indent, ' ') << "Parser::rGCCAsmStatement 1\n";
7915#endif // DEBUG
7916
7917 // asm [volatile] ("stuff" [ : ["=S" [(__res)], ... ]]) ;
7918
7920 return {};
7921
7922 code_asm_gcct statement;
7923 set_location(statement, tk);
7924
7925 if(lex.LookAhead(0)==TOK_VOLATILE)
7926 lex.get_token(tk);
7927
7928#ifdef DEBUG
7929 std::cout << std::string(__indent, ' ') << "Parser::rGCCAsmStatement 3\n";
7930#endif // DEBUG
7931
7932 if(lex.get_token(tk)!='(')
7933 return {};
7934 if(!rString(tk))
7935 return {};
7936
7937 statement.asm_text() = tk.data;
7938
7939#ifdef DEBUG
7940 std::cout << std::string(__indent, ' ') << "Parser::rGCCAsmStatement 3\n";
7941#endif // DEBUG
7942
7943 while(lex.LookAhead(0)!=')')
7944 {
7945#ifdef DEBUG
7946 std::cout << std::string(__indent, ' ') << "Parser::rGCCAsmStatement 4\n";
7947#endif // DEBUG
7948
7949 // get ':'
7950 if(lex.get_token(tk)!=':')
7951 return {};
7952
7953 for(;;)
7954 {
7955 if(lex.LookAhead(0)!=TOK_STRING)
7956 break;
7957
7958 // get String
7959 rString(tk);
7960
7961 if(lex.LookAhead(0)=='(')
7962 {
7963 // get '('
7964 lex.get_token(tk);
7965
7966#ifdef DEBUG
7967 std::cout << std::string(__indent, ' ')
7968 << "Parser::rGCCAsmStatement 5\n";
7969#endif // DEBUG
7970
7971 exprt expr;
7972 if(!rCommaExpression(expr))
7973 return {};
7974
7975#ifdef DEBUG
7976 std::cout << std::string(__indent, ' ')
7977 << "Parser::rGCCAsmStatement 6\n";
7978#endif // DEBUG
7979
7980 if(lex.get_token(tk)!=')')
7981 return {};
7982 }
7983
7984 // more?
7985 if(lex.LookAhead(0)!=',')
7986 break;
7987 lex.get_token(tk);
7988 }
7989 }
7990
7991#ifdef DEBUG
7992 std::cout << std::string(__indent, ' ') << "Parser::rGCCAsmStatement 7\n";
7993#endif // DEBUG
7994
7995 if(lex.get_token(tk)!=')')
7996 return {};
7997 if(lex.get_token(tk)!=';')
7998 return {};
7999
8000#ifdef DEBUG
8001 std::cout << std::string(__indent, ' ') << "Parser::rGCCAsmStatement 8\n";
8002#endif // DEBUG
8003
8004 return std::move(statement);
8005}
8006
8008{
8009 cpp_tokent tk;
8010
8011#ifdef DEBUG
8012 indenter _i;
8013 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 1\n";
8014#endif // DEBUG
8015
8016 // asm "STUFF"
8017 // asm { "STUFF" }
8018
8020 return {};
8021
8022 code_asmt statement;
8023 statement.set_flavor(ID_msc);
8024 set_location(statement, tk);
8025
8026#ifdef DEBUG
8027 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 2\n";
8028#endif // DEBUG
8029
8030 if(lex.LookAhead(0)=='{')
8031 {
8032 lex.get_token(tk); // eat the '{'
8033
8034#ifdef DEBUG
8035 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 3\n";
8036#endif // DEBUG
8037
8039 return {};
8040
8041 lex.get_token(tk);
8042
8043 statement.add_to_operands(std::move(tk.data));
8044 if(lex.get_token(tk)!='}')
8045 return {};
8046
8047#ifdef DEBUG
8048 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 4\n";
8049#endif // DEBUG
8050 }
8051 else
8052 {
8053#ifdef DEBUG
8054 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 5\n";
8055#endif // DEBUG
8056
8058 return std::move(statement);
8059
8060 lex.get_token(tk);
8061 statement.add_to_operands(std::move(tk.data));
8062
8063#ifdef DEBUG
8064 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 6\n";
8065#endif // DEBUG
8066 }
8067
8068#ifdef DEBUG
8069 std::cout << std::string(__indent, ' ') << "Parser::rMSCAsmStatement 7\n";
8070#endif // DEBUG
8071
8072 return std::move(statement);
8073}
8074
8075/*
8076 expr.statement
8077 : ';'
8078 | declaration.statement
8079 | comma.expression ';'
8080 | openc++.postfix.expr
8081 | openc++.primary.exp
8082*/
8084{
8085 cpp_tokent tk;
8086
8087#ifdef DEBUG
8088 indenter _i;
8089 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 0\n";
8090#endif
8091
8092 if(lex.LookAhead(0)==';')
8093 {
8094#ifdef DEBUG
8095 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 1\n";
8096#endif
8097
8098 lex.get_token(tk);
8099 code_skipt statement;
8100 set_location(statement, tk);
8101 return std::move(statement);
8102 }
8103 else
8104 {
8105#ifdef DEBUG
8106 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 2\n";
8107#endif
8108
8110
8111 if(auto statement = rDeclarationStatement())
8112 {
8113#ifdef DEBUG
8114 std::cout << std::string(__indent, ' ') << "rDe " << statement->pretty()
8115 << '\n';
8116#endif
8117 return statement;
8118 }
8119 else
8120 {
8121 exprt exp;
8122
8123 lex.Restore(pos);
8124
8125#ifdef DEBUG
8126 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 3\n";
8127#endif
8128
8129 if(!rCommaExpression(exp))
8130 return {};
8131
8132#ifdef DEBUG
8133 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 4\n";
8134#endif
8135
8136#ifdef DEBUG
8137 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 5 "
8138 << lex.LookAhead(0) << '\n';
8139#endif
8140
8141 if(lex.get_token(tk)!=';')
8142 return {};
8143
8144#ifdef DEBUG
8145 std::cout << std::string(__indent, ' ') << "Parser::rExprStatement 6\n";
8146#endif
8147
8149 expr_statement.add_source_location() = exp.source_location();
8150 return std::move(expr_statement);
8151 }
8152 }
8153}
8154
8156{
8158
8159 // C++ conditions can be a declaration!
8160
8161 cpp_declarationt declaration;
8162
8163 if(rSimpleDeclaration(declaration))
8164 {
8165 statement=codet(ID_decl);
8166 statement.add_to_operands(std::move(declaration));
8167 return true;
8168 }
8169 else
8170 {
8171 lex.Restore(pos);
8172
8173 if(!rCommaExpression(statement))
8174 return false;
8175
8176 return true;
8177 }
8178}
8179
8180/*
8181 declaration.statement
8182 : decl.head integral.or.class.spec {cv.qualify} {declarators} ';'
8183 | decl.head name {cv.qualify} declarators ';'
8184 | const.declaration
8185
8186 decl.head
8187 : {storage.spec} {cv.qualify}
8188
8189 const.declaration
8190 : cv.qualify {'*'} Identifier '=' expression {',' declarators} ';'
8191
8192 Note: if you modify this function, take a look at rDeclaration(), too.
8193*/
8195{
8196 cpp_storage_spect storage_spec;
8198 cpp_member_spect member_spec;
8199
8200#ifdef DEBUG
8201 indenter _i;
8202 std::cout << std::string(__indent, ' ')
8203 << "Parser::rDeclarationStatement 1\n";
8204#endif
8205
8206 if(!optStorageSpec(storage_spec))
8207 return {};
8208
8209 cv_q.make_nil();
8210
8211 if(!optCvQualify(cv_q))
8212 return {};
8213
8214 // added for junk like const volatile static ...
8215 if(!optStorageSpec(storage_spec))
8216 return {};
8217
8218 if(!optCvQualify(cv_q))
8219 return {};
8220
8222 return {};
8223
8224#ifdef DEBUG
8225 std::cout << std::string(__indent, ' ')
8226 << "Parser::rDeclarationStatement 2\n";
8227#endif
8228
8229 if(integral.is_not_nil())
8230 return rIntegralDeclStatement(storage_spec, integral, cv_q);
8231 else
8232 {
8233 int t=lex.LookAhead(0);
8234
8235#ifdef DEBUG
8236 std::cout << std::string(__indent, ' ')
8237 << "Parser::rDeclarationStatement 3 " << t << '\n';
8238#endif
8239
8240 if(
8241 cv_q.is_not_nil() &&
8242 ((is_identifier(t) && lex.LookAhead(1) == '=') || t == '*'))
8243 {
8244#ifdef DEBUG
8245 std::cout << std::string(__indent, ' ')
8246 << "Parser::rDeclarationStatement 4\n";
8247#endif
8248
8249 cpp_declarationt declaration;
8250 if(!rConstDeclaration(declaration))
8251 return {};
8252 return code_frontend_declt(
8253 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
8254 }
8255 else
8256 return rOtherDeclStatement(storage_spec, cv_q);
8257 }
8258}
8259
8260/*
8261 integral.decl.statement
8262 : decl.head integral.or.class.spec {cv.qualify} {declarators} ';'
8263*/
8265 cpp_storage_spect &storage_spec,
8266 typet &integral,
8267 typet &cv_q)
8268{
8269 cpp_tokent tk;
8270
8271 if(!optCvQualify(cv_q))
8272 return {};
8273
8275
8276 cpp_declarationt declaration;
8277 declaration.type().swap(integral);
8278 declaration.storage_spec().swap(storage_spec);
8279
8280 if(lex.LookAhead(0)==';')
8281 {
8282 lex.get_token(tk);
8283 code_frontend_declt statement(
8284 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
8285 set_location(statement, tk);
8286 return std::move(statement);
8287 }
8288 else
8289 {
8290 if(!rDeclarators(declaration.declarators(), false, true))
8291 return {};
8292
8293 if(lex.get_token(tk)!=';')
8294 return {};
8295
8296 code_frontend_declt statement(
8297 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
8298 set_location(statement, tk);
8299 return std::move(statement);
8300 }
8301}
8302
8303/*
8304 other.decl.statement
8305 :decl.head name {cv.qualify} declarators ';'
8306*/
8309{
8311 cpp_tokent tk;
8312
8313#ifdef DEBUG
8314 indenter _i;
8315 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclStatement 1\n";
8316#endif // DEBUG
8317
8318 if(!rName(type_name))
8319 return {};
8320
8321#ifdef DEBUG
8322 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclStatement 2\n";
8323#endif // DEBUG
8324
8325 if(!optCvQualify(cv_q))
8326 return {};
8327
8328#ifdef DEBUG
8329 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclStatement 3\n";
8330#endif // DEBUG
8331
8333
8334 cpp_declarationt declaration;
8335 declaration.type().swap(type_name);
8336 declaration.storage_spec().swap(storage_spec);
8337
8338 if(!rDeclarators(declaration.declarators(), false, true))
8339 return {};
8340
8341#ifdef DEBUG
8342 std::cout << std::string(__indent, ' ') << "Parser::rOtherDeclStatement 4\n";
8343#endif // DEBUG
8344
8345 if(lex.get_token(tk)!=';')
8346 return {};
8347
8348 code_frontend_declt statement(
8349 static_cast<symbol_exprt &>(static_cast<exprt &>(declaration)));
8350 set_location(statement, tk);
8351 return std::move(statement);
8352}
8353
8355{
8356 return true;
8357}
8358
8359void Parser::SkipTo(int token)
8360{
8361 cpp_tokent tk;
8362
8363 for(;;)
8364 {
8365 int t=lex.LookAhead(0);
8366 if(t==token || t=='\0')
8367 break;
8368 else
8369 lex.get_token(tk);
8370 }
8371}
8372
8374{
8376 max_errors=10;
8377
8379
8380 while(rProgram(item))
8381 {
8382 parser.parse_tree.items.push_back(item);
8383 item.clear();
8384 }
8385
8386#if 0
8387 root_scope.print(std::cout);
8388#endif
8389
8390 return number_of_errors!=0;
8391}
8392
8394{
8395 Parser parser(cpp_parser);
8396 return parser();
8397}
ansi_c_parsert ansi_c_parser
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:240
typet c_bool_type()
Definition c_types.cpp:105
bool optCvQualify(typet &)
Definition parse.cpp:2021
bool rDeclaratorQualifier()
Definition parse.cpp:2978
bool rShiftExpr(exprt &, bool)
Definition parse.cpp:5239
optionalt< codet > rStatement()
Definition parse.cpp:7299
bool rThrowExpr(exprt &)
Definition parse.cpp:5814
bool rPostfixExpr(exprt &)
Definition parse.cpp:6343
bool rIntegralDeclaration(cpp_declarationt &, cpp_storage_spect &, cpp_member_spect &, typet &, typet &)
Definition parse.cpp:1527
bool MaybeTypeNameOrClassTemplate(cpp_tokent &)
Definition parse.cpp:8354
bool rClassMember(cpp_itemt &)
Definition parse.cpp:4684
bool rDefinition(cpp_itemt &)
Definition parse.cpp:552
bool rTypedefUsing(cpp_declarationt &)
Definition parse.cpp:634
bool rAllocateExpr(exprt &)
Definition parse.cpp:6069
bool rMSC_if_existsExpr(exprt &)
Definition parse.cpp:6531
bool rClassBody(exprt &)
Definition parse.cpp:4624
bool rCastExpr(exprt &)
Definition parse.cpp:5423
bool rBaseSpecifiers(irept &)
Definition parse.cpp:4553
bool rPtrToMember(irept &)
Definition parse.cpp:3791
bool optMemberSpec(cpp_member_spect &)
Definition parse.cpp:1950
void make_sub_scope(const irept &name, new_scopet::kindt)
Definition parse.cpp:442
bool rLinkageBody(cpp_linkage_spect::itemst &)
Definition parse.cpp:946
bool rTypePredicate(exprt &)
Definition parse.cpp:6631
void SkipTo(int token)
Definition parse.cpp:8359
bool rAndExpr(exprt &, bool)
Definition parse.cpp:5108
bool optPtrOperator(typet &)
Definition parse.cpp:3269
Parser(cpp_parsert &_cpp_parser)
Definition parse.cpp:198
bool rLogicalAndExpr(exprt &, bool)
Definition parse.cpp:4991
bool rExpression(exprt &, bool)
Definition parse.cpp:4822
optionalt< codet > rTypedefStatement()
Definition parse.cpp:683
bool isTypeSpecifier()
Definition parse.cpp:757
bool rString(cpp_tokent &tk)
Definition parse.cpp:454
bool isConstructorDecl()
Definition parse.cpp:1857
bool moreVarName()
Definition parse.cpp:7073
bool rOtherDeclaration(cpp_declarationt &, cpp_storage_spect &, cpp_member_spect &, typet &)
Definition parse.cpp:1671
optionalt< codet > rWhileStatement()
Definition parse.cpp:7629
bool optAttribute(typet &)
Definition parse.cpp:2364
bool rAdditiveExpr(exprt &)
Definition parse.cpp:5279
bool rMemberInit(exprt &)
Definition parse.cpp:3421
optionalt< codet > rExprStatement()
Definition parse.cpp:8083
bool rConstDeclaration(cpp_declarationt &)
Definition parse.cpp:1652
bool rCondition(exprt &)
Definition parse.cpp:8155
bool rSimpleDeclaration(cpp_declarationt &)
Definition parse.cpp:1469
bool rInclusiveOrExpr(exprt &, bool)
Definition parse.cpp:5030
bool rAllocateInitializer(exprt &)
Definition parse.cpp:6286
bool rPrimaryExpr(exprt &)
Definition parse.cpp:6693
bool rStaticAssert(cpp_static_assertt &)
Definition parse.cpp:905
optionalt< codet > rDoStatement()
Definition parse.cpp:7660
bool rArgDeclListOrInit(exprt &, bool &, bool)
Definition parse.cpp:4039
bool rNewDeclarator(typet &)
Definition parse.cpp:6255
void make_subtype(const typet &src, typet &dest)
Definition parse.cpp:392
optionalt< codet > rIntegralDeclStatement(cpp_storage_spect &, typet &, typet &)
Definition parse.cpp:8264
optionalt< codet > rTryStatement()
Definition parse.cpp:7754
bool rAccessDecl(cpp_declarationt &)
Definition parse.cpp:4754
optionalt< codet > rDeclarationStatement()
Definition parse.cpp:8194
bool rRelationalExpr(exprt &, bool)
Definition parse.cpp:5187
bool rMSCuuidof(exprt &)
Definition parse.cpp:6482
bool rNoexceptExpr(exprt &)
Definition parse.cpp:6019
new_scopet root_scope
Definition parse.cpp:214
bool rNamespaceSpec(cpp_namespace_spect &)
Definition parse.cpp:821
cpp_token_buffert & lex
Definition parse.cpp:210
bool rArgDeclaration(cpp_declarationt &)
Definition parse.cpp:4131
bool rTypeName(typet &)
Definition parse.cpp:5483
optionalt< codet > rCompoundStatement()
Definition parse.cpp:7238
bool operator()()
Definition parse.cpp:8373
new_scopet & add_id(const irept &name, new_scopet::kindt)
Definition parse.cpp:418
bool rVarNameCore(exprt &)
Definition parse.cpp:6940
bool rDeclarators(cpp_declarationt::declaratorst &, bool, bool=false)
Definition parse.cpp:2840
bool rLinkageSpec(cpp_linkage_spect &)
Definition parse.cpp:781
bool rDeclarator(cpp_declaratort &, DeclKind, bool, bool)
Definition parse.cpp:3011
bool rAllocateType(exprt &, typet &, exprt &)
Definition parse.cpp:6159
bool rTypeSpecifier(typet &, bool)
Definition parse.cpp:697
bool optThrowDecl(irept &)
Definition parse.cpp:2772
bool rExclusiveOrExpr(exprt &, bool)
Definition parse.cpp:5069
optionalt< codet > rIfStatement()
Definition parse.cpp:7551
bool rEqualityExpr(exprt &, bool)
Definition parse.cpp:5147
bool rVarName(exprt &)
Definition parse.cpp:6927
bool rCommaExpression(exprt &)
Definition parse.cpp:4779
bool rGCCAttribute(typet &)
Definition parse.cpp:2163
bool rTempArgList(irept &)
Definition parse.cpp:1109
optionalt< codet > rMSC_leaveStatement()
Definition parse.cpp:7892
TemplateDeclKind
Definition parse.cpp:222
@ tdk_decl
Definition parse.cpp:222
@ tdk_instantiation
Definition parse.cpp:222
@ num_tdks
Definition parse.cpp:223
@ tdk_specialization
Definition parse.cpp:223
@ tdk_unknown
Definition parse.cpp:222
bool rArgDeclList(irept &)
Definition parse.cpp:4078
bool rMultiplyExpr(exprt &)
Definition parse.cpp:5326
optionalt< codet > rMSC_if_existsStatement()
Definition parse.cpp:6576
optionalt< codet > rMSCAsmStatement()
Definition parse.cpp:8007
bool rTypedef(cpp_declarationt &)
Definition parse.cpp:606
bool rTemplateArgs(irept &)
Definition parse.cpp:3891
bool rSizeofExpr(exprt &)
Definition parse.cpp:5919
optionalt< codet > rGCCAsmStatement()
Definition parse.cpp:7908
bool rTypeNameOrFunctionType(typet &)
Definition parse.cpp:5527
bool rMemberInitializers(irept &)
Definition parse.cpp:3388
bool rDeclaratorWithInit(cpp_declaratort &, bool, bool)
Definition parse.cpp:2869
unsigned int max_errors
Definition parse.cpp:410
bool SyntaxError()
Definition parse.cpp:488
bool isPtrToMember(int)
Definition parse.cpp:1893
optionalt< codet > rForStatement()
Definition parse.cpp:7697
bool rFunctionArguments(exprt &)
Definition parse.cpp:4264
cpp_parsert & parser
Definition parse.cpp:211
optionalt< codet > rOtherDeclStatement(cpp_storage_spect &, typet &)
Definition parse.cpp:8308
irep_idt current_function
Definition parse.cpp:378
new_scopet * current_scope
Definition parse.cpp:215
bool optIntegralTypeOrClassSpec(typet &)
Definition parse.cpp:2417
bool isAllocateExpr(int)
Definition parse.cpp:6056
bool rPmExpr(exprt &)
Definition parse.cpp:5379
bool rTempArgDeclaration(cpp_declarationt &)
Definition parse.cpp:1143
@ kArgDeclarator
Definition parse.cpp:221
@ kDeclarator
Definition parse.cpp:221
@ kCastDeclarator
Definition parse.cpp:221
bool rEnumBody(irept &)
Definition parse.cpp:4387
bool rLogicalOrExpr(exprt &, bool)
Definition parse.cpp:4952
bool rProgram(cpp_itemt &item)
Definition parse.cpp:522
bool rName(irept &)
Definition parse.cpp:3503
optionalt< codet > rSwitchStatement()
Definition parse.cpp:7598
bool rTemplateDecl2(typet &, TemplateDeclKind &kind)
Definition parse.cpp:1050
bool optAlignas(typet &)
Definition parse.cpp:2107
bool rEnumSpec(typet &)
Definition parse.cpp:4304
bool rTypeidExpr(exprt &)
Definition parse.cpp:5853
void merge_types(const typet &src, typet &dest)
Definition parse.cpp:462
bool rAlignofExpr(exprt &)
Definition parse.cpp:5991
optionalt< codet > rMSC_tryStatement()
Definition parse.cpp:7830
bool rCastOperatorName(irept &)
Definition parse.cpp:3751
bool rInitializeExpr(exprt &)
Definition parse.cpp:4176
bool rFunctionBody(cpp_declaratort &)
Definition parse.cpp:7191
bool optStorageSpec(cpp_storage_spect &)
Definition parse.cpp:1985
bool rDeclaration(cpp_declarationt &)
Definition parse.cpp:1374
bool rUsing(cpp_usingt &)
Definition parse.cpp:877
void set_location(irept &dest, const cpp_tokent &token)
Definition parse.cpp:382
std::size_t number_of_errors
Definition parse.cpp:377
bool rClassSpec(typet &)
Definition parse.cpp:4443
bool rUnaryExpr(exprt &)
Definition parse.cpp:5707
bool rOperatorName(irept &)
Definition parse.cpp:3647
bool rExternTemplateDecl(cpp_declarationt &)
Definition parse.cpp:1326
bool maybeTemplateArgs()
Definition parse.cpp:7090
bool rNullDeclaration(cpp_declarationt &)
Definition parse.cpp:590
bool rTemplateDecl(cpp_declarationt &)
Definition parse.cpp:994
bool rConstructorDecl(cpp_declaratort &, typet &, typet &trailing_return_type)
Definition parse.cpp:2642
bool rConditionalExpr(exprt &, bool)
Definition parse.cpp:4903
virtual void clear()
Reset the abstract state.
Definition ai.h:266
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:563
ait()
Definition ai.h:566
Arrays with given size.
Definition std_types.h:763
codet representation of an inline assembler statement, for the gcc flavor.
Definition std_code.h:1297
exprt & asm_text()
Definition std_code.h:1305
codet representation of an inline assembler statement.
Definition std_code.h:1253
void set_flavor(const irep_idt &f)
Definition std_code.h:1268
A codet representing sequential composition of program statements.
Definition std_code.h:130
code_operandst & statements()
Definition std_code.h:138
void add(const codet &code)
Definition std_code.h:168
codet representation of a do while statement.
Definition std_code.h:672
codet representation of an expression statement.
Definition std_code.h:1394
codet representation of a for statement.
Definition std_code.h:734
A codet representing the declaration of a local variable.
Definition std_code.h:347
codet representation of a "return from a function" statement.
Definition std_code.h:893
const exprt & return_value() const
Definition std_code.h:903
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1097
codet representation of a goto statement.
Definition std_code.h:841
codet representation of an if-then-else statement.
Definition std_code.h:460
codet representation of a label for branch targets.
Definition std_code.h:959
A codet representing a skip statement.
Definition std_code.h:322
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1023
codet representing a switch statement.
Definition std_code.h:548
codet representation of a try/catch block.
Definition std_code.h:1986
Base type of functions.
Definition std_types.h:539
codet representing a while statement.
Definition std_code.h:610
Data structure for representing an arbitrary statement in a program.
const declaratorst & declarators() const
const cpp_member_spect & member_spec() const
const cpp_storage_spect & storage_spec() const
std::vector< cpp_declaratort > declaratorst
irept & throw_decl()
irept & member_initializers()
cpp_namet & name()
irept & method_qualifier()
exprt & init_args()
cpp_static_assertt & make_static_assert()
Definition cpp_item.h:126
cpp_usingt & make_using()
Definition cpp_item.h:101
cpp_declarationt & make_declaration()
Definition cpp_item.h:26
std::vector< class cpp_itemt > itemst
const itemst & items() const
void set_inline(bool value)
bool is_empty() const
void set_virtual(bool value)
void set_friend(bool value)
void set_explicit(bool value)
const exprt & as_expr() const
Definition cpp_name.h:137
cpp_parse_treet parse_tree
Definition cpp_parser.h:27
bool is_empty() const
int LookAhead(unsigned offset)
int get_token(cpp_tokent &token)
void Replace(const cpp_tokent &token)
cpp_tokent & current_token()
void Insert(const cpp_tokent &token)
irep_idt filename
Definition cpp_token.h:26
unsigned line_no
Definition cpp_token.h:25
std::string text
Definition cpp_token.h:24
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:39
bool empty() const
Definition dstring.h:90
void clear()
Definition dstring.h:160
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
const source_locationt & source_location() const
Definition expr.h:223
source_locationt & add_source_location()
Definition expr.h:228
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition expr.h:162
The Boolean constant false.
Definition std_expr.h:3017
The trinary if-then-else operator.
Definition std_expr.h:2323
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:372
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:490
const irept & find(const irep_idt &name) const
Definition irep.cpp:101
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:420
void clear()
Definition irep.h:452
bool is_not_nil() const
Definition irep.h:380
subt & get_sub()
Definition irep.h:456
void make_nil()
Definition irep.h:454
void move_to_sub(irept &irep)
Definition irep.cpp:35
void swap(irept &irep)
Definition irep.h:442
const irep_idt & id() const
Definition irep.h:396
irept & add(const irep_idt &name)
Definition irep.cpp:111
bool is_nil() const
Definition irep.h:376
holds a combination of types
Definition merged_type.h:16
source_locationt source_location
Definition message.h:247
mstreamt & error() const
Definition message.h:399
static eomt eom
Definition message.h:297
void print_rec(std::ostream &, unsigned indent) const
Definition parse.cpp:182
id_mapt id_map
Definition parse.cpp:137
new_scopet * parent
Definition parse.cpp:141
irep_idt id
Definition parse.cpp:73
kindt kind
Definition parse.cpp:72
std::string full_name() const
Definition parse.cpp:154
std::map< irep_idt, new_scopet > id_mapt
Definition parse.cpp:136
void print(std::ostream &out) const
Definition parse.cpp:143
bool is_named_scope() const
Definition parse.cpp:90
std::size_t anon_count
Definition parse.cpp:139
new_scopet()
Definition parse.cpp:49
static const char * kind2string(kindt kind)
Definition parse.cpp:97
irep_idt get_anon_id()
Definition parse.cpp:148
bool is_template() const
Definition parse.cpp:83
bool is_type() const
Definition parse.cpp:75
The NIL expression.
Definition std_expr.h:3026
The null pointer constant.
messaget log
Definition parser.h:136
new_scopet * old_scope
Definition parse.cpp:179
new_scopet *& scope_ptr
Definition parse.cpp:178
save_scopet(new_scopet *&_scope)
Definition parse.cpp:167
A side_effect_exprt representation of a function call side effect.
Definition std_code.h:1692
A side_effect_exprt representation of a side effect that throws an exception.
Definition std_code.h:1757
An expression containing a side effect.
Definition std_code.h:1450
void set_file(const irep_idt &file)
void set_line(const irep_idt &line)
void set_function(const irep_idt &function)
Expression to hold a symbol (variable)
Definition std_expr.h:113
The Boolean constant true.
Definition std_expr.h:3008
Type with a single subtype.
Definition type.h:147
Semantic type conversion.
Definition std_expr.h:2017
The type of an expression, extends irept.
Definition type.h:29
const source_locationt & source_location() const
Definition type.h:72
typet & add_subtype()
Definition type.h:53
C++ Language Type Checking.
cpp_namet & to_cpp_name(irept &cpp_name)
Definition cpp_name.h:148
cpp_parsert cpp_parser
C++ Parser.
C++ Parser: Token Buffer.
static bool is_operator(const ctokent &t)
Definition ctoken.h:78
#define Forall_operands(it, expr)
Definition expr.h:27
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
const irept & get_nil_irep()
Definition irep.cpp:19
const std::string & id2string(const irep_idt &d)
Definition irep.h:47
static bool is_constructor(const irep_idt &method_name)
literalt pos(literalt a)
Definition literal.h:194
const merged_typet & to_merged_type(const typet &type)
conversion to merged_typet
Definition merged_type.h:29
bool cpp_parse()
Definition parse.cpp:8393
#define ERROR_TOKENS
static bool is_identifier(int token)
Definition parse.cpp:413
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define UNIMPLEMENTED
Definition invariant.h:558
const code_blockt & to_code_block(const codet &code)
Definition std_code.h:203
const type_with_subtypest & to_type_with_subtypes(const typet &type)
Definition type.h:219
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:175
dstringt irep_idt