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