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