cprover
ansi_c_parser.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "ansi_c_parser.h"
10 
11 #include <iostream>
12 
13 #include "c_storage_spec.h"
14 
16 
18  const irep_idt &base_name,
19  irep_idt &identifier, // output
20  bool tag,
21  bool label)
22 {
23  // labels and tags have a separate name space
24  const irep_idt scope_name=
25  tag?"tag-"+id2string(base_name):
26  label?"label-"+id2string(base_name):
27  base_name;
28 
29  for(scopest::const_reverse_iterator it=scopes.rbegin();
30  it!=scopes.rend();
31  it++)
32  {
33  scopet::name_mapt::const_iterator n_it=
34  it->name_map.find(scope_name);
35 
36  if(n_it!=it->name_map.end())
37  {
38  assert(id2string(n_it->second.prefixed_name)==
39  it->prefix+id2string(scope_name));
40  identifier=n_it->second.prefixed_name;
41  return n_it->second.id_class;
42  }
43  }
44 
45  // Not found.
46  // If it's a tag, we will add to current scope.
47  if(tag)
48  {
50  current_scope().name_map[scope_name];
53  i.base_name=base_name;
54  identifier=i.prefixed_name;
56  }
57 
58  identifier=base_name;
60 }
61 
63 {
64  const std::string scope_name=
65  "tag-"+tag.get_string(ID_C_base_name);
66 
67  irep_idt prefixed_name=current_scope().prefix+scope_name;
68 
69  if(prefixed_name!=tag.get(ID_identifier))
70  {
71  // re-defined in a deeper scope
72  ansi_c_identifiert &identifier=
73  current_scope().name_map[scope_name];
75  identifier.prefixed_name=prefixed_name;
76  tag.set(ID_identifier, prefixed_name);
77  }
78 }
79 
80 extern char *yyansi_ctext;
81 
82 int yyansi_cerror(const std::string &error)
83 {
84  ansi_c_parser.parse_error(error, yyansi_ctext);
85  return 0;
86 }
87 
89  exprt &declaration,
90  irept &declarator)
91 {
92  assert(declarator.is_not_nil());
93  ansi_c_declarationt &ansi_c_declaration=
94  to_ansi_c_declaration(declaration);
95 
96  ansi_c_declaratort new_declarator;
97  new_declarator.build(declarator);
98 
99  irep_idt base_name=new_declarator.get_base_name();
100 
101  bool is_member=ansi_c_declaration.get_is_member();
102  bool is_parameter=ansi_c_declaration.get_is_parameter();
103 
104  if(is_member)
105  {
106  // we don't put them into a struct scope (unlike C++)
107  new_declarator.set_name(base_name);
108  ansi_c_declaration.declarators().push_back(new_declarator);
109  return; // done
110  }
111 
112  // global?
113  if(current_scope().prefix=="")
114  ansi_c_declaration.set_is_global(true);
115 
116  // abstract?
117  if(!base_name.empty())
118  {
119  c_storage_spect c_storage_spec(ansi_c_declaration.type());
120  bool is_typedef=c_storage_spec.is_typedef;
121  bool is_extern=c_storage_spec.is_extern;
122 
123  bool force_root_scope=false;
124 
125  // Functions always go into global scope, unless
126  // declared as a parameter or are typedefs.
127  if(new_declarator.type().id()==ID_code &&
128  !is_parameter &&
129  !is_typedef)
130  force_root_scope=true;
131 
132  // variables marked as 'extern' always go into global scope
133  if(is_extern)
134  force_root_scope=true;
135 
136  ansi_c_id_classt id_class=is_typedef?
139 
140  scopet &scope=
141  force_root_scope?root_scope():current_scope();
142 
143  // set the final name
144  irep_idt prefixed_name=force_root_scope?
145  base_name:
146  current_scope().prefix+id2string(base_name);
147  new_declarator.set_name(prefixed_name);
148 
149  // add to scope
150  ansi_c_identifiert &identifier=scope.name_map[base_name];
151  identifier.id_class=id_class;
152  identifier.prefixed_name=prefixed_name;
153  }
154 
155  ansi_c_declaration.declarators().push_back(new_declarator);
156 }
157 
159 {
160  if(type.id()==ID_typedef)
162  else if(type.id()==ID_struct ||
163  type.id()==ID_union ||
164  type.id()==ID_c_enum)
166  else if(type.id()==ID_merged_type)
167  {
168  forall_subtypes(it, type)
171  }
172  else if(type.has_subtype())
173  return get_class(type.subtype());
174 
176 }
The type of an expression.
Definition: type.h:20
#define forall_subtypes(it, type)
Definition: type.h:159
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
bool is_not_nil() const
Definition: irep.h:104
static ansi_c_id_classt get_class(const typet &type)
scopet & current_scope()
Definition: ansi_c_parser.h:96
char * yyansi_ctext
bool has_subtype() const
Definition: type.h:77
int yyansi_cerror(const std::string &error)
void build(irept &src)
void add_tag_with_body(irept &tag)
typet & type()
Definition: expr.h:60
ansi_c_id_classt id_class
Definition: ansi_c_scope.h:29
void parse_error(const std::string &message, const std::string &before)
Definition: parser.cpp:30
const irep_idt & id() const
Definition: irep.h:189
void set_name(const irep_idt &name)
ansi_c_id_classt
Definition: ansi_c_scope.h:15
irep_idt get_base_name() const
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:213
void add_declarator(exprt &declaration, irept &declarator)
Base class for tree-like data structures with sharing.
Definition: irep.h:87
scopet & root_scope()
Definition: ansi_c_parser.h:81
name_mapt name_map
Definition: ansi_c_scope.h:44
Base class for all expressions.
Definition: expr.h:46
ansi_c_parsert ansi_c_parser
const std::string & get_string(const irep_namet &name) const
Definition: irep.h:202
mstreamt & error()
Definition: message.h:223
std::string prefix
Definition: ansi_c_scope.h:46
ansi_c_declarationt & to_ansi_c_declaration(exprt &expr)
const typet & subtype() const
Definition: type.h:31
irep_idt prefixed_name
Definition: ansi_c_scope.h:30
bool empty() const
Definition: dstring.h:61
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:214
ansi_c_id_classt lookup(const irep_idt &base_name, irep_idt &identifier, bool tag, bool label)