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