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