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