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