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