1 /*
2 * (C) Copyright 2001-2015 Diomidis Spinellis
3 *
4 * This file is part of CScout.
5 *
6 * CScout is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CScout is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CScout. If not, see <http://www.gnu.org/licenses/>.
18 *
19 *
20 * The type-system structure
21 * See also type2.h for derived classes depending on Stab
22 *
23 */
24
25 #ifndef TYPE_
26 #define TYPE_
27
28 #include "ctconst.h"
29 #include "ctoken.h"
30
31 enum e_btype {
32 b_abstract, // Abstract declaration target, to be filled-in
33 b_void, b_char, b_short, b_int, b_long, b_float, b_double, b_ldouble,
34 b_bool,
35 b_padbit,
36 b_undeclared, // Undeclared object
37 b_llong, // long long
38 b_complex, // complex
39 b_imaginary, // imaginary
40 };
41
42 enum e_sign {
43 s_none, // Neither signed, nor unsigned
44 s_signed,
45 s_unsigned
46 };
47
48 enum e_storage_class {
49 c_unspecified,
50 c_typedef,
51 c_extern,
52 c_static,
53 c_auto,
54 c_register,
55 c_enum,
56 c_thread_local
57 };
58
59 enum e_qualifier {
60 q_none = 0x00,
61 q_const = 0x01,
62 q_volatile = 0x02,
63 q_unused = 0x04, // gcc __attribute__((unused))
64 q_restrict = 0x08,
65 q_complex = 0x09,
66 q_imaginary = 0x10
67 };
68
69
70 class Id;
71 class Tbasic;
72 class Type;
73 class Stab;
74 class Tqualifier;
75
76 // Type used to construct unnamed struct/union members
77 class Tsu_unnamed {};
78
79 class Type_node {
80 friend class Type;
81 private:
82 #ifdef NODE_USE_PROFILE
83 static int count;
84 #endif
85 int use; // Use count
86 // Do not allow copy and assignment; it has to be performed around Type
87 Type_node(const Type_node &);
88 Type_node& operator=(const Type_node &);
89 protected:
Type_node()90 Type_node() : use(1) {
91 #ifdef NODE_USE_PROFILE
92 count++;
93 #endif
94 }
95
~Type_node()96 virtual ~Type_node() {
97 #ifdef NODE_USE_PROFILE
98 count--;
99 #endif
100 }
101 virtual Type subscript() const; // Arrays and pointers
102 virtual Type deref() const; // Arrays and pointers
103 virtual Type call() const; // Function
104 virtual Type type(Type dftl) const; // Identifier
105 virtual Type clone() const; // Deep copy
106 virtual Id const* member(const string& name) const; // Structure and union
107 virtual Type member(int n); // For > 0 on structure, union, array
is_abstract()108 virtual bool is_abstract() const { return false; } // True for abstract types
is_array()109 virtual bool is_array() const { return false; } // True for arrays
is_basic()110 virtual bool is_basic() const { return false; }// False for undeclared
is_cfunction()111 virtual bool is_cfunction() const { return false; } // True for functions
is_identifier()112 virtual bool is_identifier() const { return false; }// True only for identifiers
is_incomplete()113 virtual bool is_incomplete() const { return false; } // True incomplete struct/union
is_padbit()114 virtual bool is_padbit() const { return false; }// True for pad bit field
is_char()115 virtual bool is_char() const { return false; }// True for pad bit field
is_ptr()116 virtual bool is_ptr() const { return false; }// True for ptr arithmetic types
is_su()117 virtual bool is_su() const { return false; }// True for struct/union
is_valid()118 virtual bool is_valid() const { return true; }// False for undeclared
is_void()119 virtual bool is_void() const { return false; }// True only for the void basic type
ctags_kind()120 virtual char ctags_kind() const { return 'X'; } // The ctags kind of the corresponding type (ctags --list-kinds)
qualified_const()121 virtual bool qualified_const() const { return false; }// True for constructs containing the const attribute
qualified_restrict()122 virtual bool qualified_restrict() const { return false; }// True for constructs containing the restrict attribute
qualified_unused()123 virtual bool qualified_unused() const { return false; }// True for constructs containing the unused attribute
qualified_volatile()124 virtual bool qualified_volatile() const { return false; }// True for constructs containing the volatile attribute
125 virtual const string get_name() const; // True for identifiers
126 virtual const Ctoken& get_token() const;// True for identifiers
127 virtual void set_abstract(Type t); // Set abstract basic type to t
128 virtual void set_storage_class(Type t); // Set typedef's underlying storage class to t
129 virtual void clear_storage_class(); // Clear underlying storage class
130 virtual enum e_storage_class get_storage_class() const;// Return the declaration's storage class
131 virtual int get_qualifiers() const;// Return the declaration's qualifiers
132 virtual int get_nparam() const; // Return the number of parameters
133 virtual void add_param(); // Add another parameter to the list
get_value()134 virtual CTConst get_value() const {return CTConst(); } // Return the value of a compile-time constant
135 // Return the number of elements this type can hold (array, structure, union)
get_nelem()136 virtual CTConst get_nelem() const { return CTConst(1); }
137 virtual void set_union(bool v); // True for union false for struct
set_value(CTConst v)138 virtual void set_value(CTConst v) {} // Set the value of a compile-time constant
139 virtual void add_qualifiers(Type t); // Set our qualifiers to t
140 virtual void add_member(const Token &tok, const Type &typ);
141 virtual Type get_default_specifier() const;
142 virtual void merge_with(Type t);
143 virtual const Stab& get_members_by_name() const;
144 virtual const vector <Id>& get_members_by_ordinal() const;
145
is_typedef()146 bool is_typedef() const { return get_storage_class() == c_typedef; }// True for typedefs
is_static()147 bool is_static() const { return get_storage_class() == c_static; }// True for static
148 public:
149 // For merging
150 virtual Type merge(Tbasic *b);
151 virtual Tbasic *tobasic();
152 virtual void print(ostream &o) const = 0;
153 #ifdef NODE_USE_PROFILE
154 static int get_count();
155 #endif
156 };
157
158 // Used by types with a storage class: Tbasic, Tsu, Tenum, Tincomplete, Tptr, Tarray
159 class Tstorage {
160 private:
161 enum e_storage_class sclass;
162 public:
Tstorage(enum e_storage_class sc)163 Tstorage (enum e_storage_class sc) : sclass(sc) {}
Tstorage()164 Tstorage() : sclass(c_unspecified) {}
get_storage_class()165 enum e_storage_class get_storage_class() const {return sclass; }
166 void set_storage_class(Type t);
167 void clear_storage_class();
168 void print(ostream &o) const;
169 };
170
171 // A type node with a qualifier
172 class QType_node : public Type_node {
173 public:
174 typedef int qualifiers_t;
175 protected:
176 qualifiers_t qualifiers;
177 public:
qualifiers(q)178 QType_node (qualifiers_t q = q_none) : qualifiers(q) {}
qualified_const()179 virtual bool qualified_const() const { return (qualifiers & q_const); }
qualified_restrict()180 virtual bool qualified_restrict() const { return (qualifiers & q_restrict); }
qualified_unused()181 virtual bool qualified_unused() const { return (qualifiers & q_unused); }
qualified_volatile()182 virtual bool qualified_volatile() const { return (qualifiers & q_volatile); }
183 void set_qualifiers(Type t);
set_qualifiers(qualifiers_t q)184 void set_qualifiers(qualifiers_t q) { qualifiers = q; }
get_qualifiers()185 virtual qualifiers_t get_qualifiers() const { return qualifiers; }
add_qualifier(enum e_qualifier q)186 void add_qualifier(enum e_qualifier q) { qualifiers |= q; }
add_qualifiers(qualifiers_t q)187 virtual void add_qualifiers(qualifiers_t q) { qualifiers |= q; }
188 inline void add_qualifiers(Type t);
189 void print(ostream &o) const;
190 };
191
192 typedef QType_node::qualifiers_t qualifiers_t;
193
194 // Basic type
195 class Tbasic: public QType_node {
196 private:
197 enum e_btype type; // Basic type
198 enum e_sign sign; // Sign
199 Tstorage sclass; // Storage class
200 CTConst value; // Value of a compile-time constant
201 public:
202 Tbasic(enum e_btype t = b_abstract, enum e_sign s = s_none,
203 enum e_storage_class sc = c_unspecified, qualifiers_t q = q_none) :
QType_node(q)204 QType_node(q), type(t), sign(s), sclass(sc) {}
205 Type clone() const;
is_valid()206 bool is_valid() const { return type != b_undeclared && type != b_padbit; }
is_abstract()207 bool is_abstract() const { return type == b_abstract; }
is_basic()208 bool is_basic() const { return true; }// False for undeclared
is_void()209 bool is_void() const { return type == b_void; }
is_padbit()210 bool is_padbit() const { return type == b_padbit; }
is_char()211 bool is_char() const { return type == b_char; }
212 void print(ostream &o) const;
213 Type merge(Tbasic *b);
tobasic()214 Tbasic *tobasic() { return this; }
get_storage_class()215 enum e_storage_class get_storage_class() const { return sclass.get_storage_class(); }
216 inline void set_storage_class(Type t);
217 inline void clear_storage_class();
218 void set_abstract(Type t); //For padbits
get_value()219 CTConst get_value() const {return value; }
set_value(CTConst v)220 void set_value(CTConst v) { value = v; }
221 };
222
223 /*
224 * Handle class for representing types.
225 * It encapsulates the type node memory management.
226 * See Koening & Moo: Ruminations on C++ Addison-Wesley 1996, chapter 8
227 */
228 class Type {
229 private:
230 Type_node *p;
231 public:
Type(Type_node * n)232 Type(Type_node *n) : p(n) {}
Type()233 Type() { p = new Tbasic(b_undeclared); }
234 // Creation functions
235 friend Type basic(enum e_btype t, enum e_sign s,
236 enum e_storage_class sc, qualifiers_t);
237 friend Type array_of(Type t, CTConst nelem);
238 friend Type pointer_to(Type t);
239 friend Type function_returning(Type t, int n);
240 friend Type implict_function();
241 friend Type enum_tag();
242 friend Type struct_union(const Token &tok, const Type &typ, const Type &spec);
243 friend Type struct_union(const Type &spec);
244 friend Type struct_union(Tsu_unnamed dummy, const Type &typ);
245 friend Type struct_union();
246 friend Type label();
247 friend Type plist(int n);
248 friend Type identifier(const Ctoken& c);
249 friend Type incomplete(const Ctoken& c, int l);
250 // To print
251 friend ostream& operator<<(ostream& o,const Type &t) { t.p->print(o); return o; }
252
253 // Add the declaration of an identifier to the symbol table
254 void declare();
255
256 // Manage use count of underlying Type_node
Type(const Type & t)257 Type(const Type& t) : p(t.p) { ++p->use; } // Copy
~Type()258 ~Type() { if (--p->use == 0) delete p; }
259 Type& operator=(const Type& t);
260
261 // Interface to the Type_node functionality
clone()262 Type clone() const { return p->clone(); }
subscript()263 Type subscript() const { return p->subscript(); }
deref()264 Type deref() const { return p->deref(); }
call()265 Type call() const { return p->call(); }
type()266 Type type() const { return p->type(*this); }
set_abstract(Type t)267 void set_abstract(Type t) { return p->set_abstract(t); }
set_storage_class(Type t)268 void set_storage_class(Type t) { return p->set_storage_class(t); }
clear_storage_class()269 void clear_storage_class() { return p->clear_storage_class(); }
add_param()270 void add_param() { p->add_param(); }
get_nparam()271 int get_nparam() const { return p->get_nparam(); }
get_value()272 CTConst get_value() const { return p->get_value(); }
get_nelem()273 CTConst get_nelem() const { return p->get_nelem(); }
set_union(bool v)274 void set_union(bool v) { p->set_union(v); }
set_value(CTConst v)275 void set_value(CTConst v) { p->set_value(v); }
is_abstract()276 bool is_abstract() const { return p->is_abstract(); }
is_array()277 bool is_array() const { return p->is_array(); }
is_basic()278 bool is_basic() const { return p->is_basic(); }
is_cfunction()279 bool is_cfunction() const { return p->is_cfunction(); }
is_identifier()280 bool is_identifier() const { return p->is_identifier(); }
is_incomplete()281 bool is_incomplete() const { return p->is_incomplete(); }
is_padbit()282 bool is_padbit() const { return p->is_padbit(); }
is_char()283 bool is_char() const { return p->is_char(); }
is_ptr()284 bool is_ptr() const { return p->is_ptr(); }
is_static()285 bool is_static() const { return p->is_static(); }
is_su()286 bool is_su() const { return p->is_su(); }
is_typedef()287 bool is_typedef() const { return p->is_typedef(); }
is_valid()288 bool is_valid() const { return p->is_valid(); }
is_void()289 bool is_void() const { return p->is_void(); }
ctags_kind()290 char ctags_kind() const { return p->ctags_kind(); }
qualified_const()291 bool qualified_const() const { return p->qualified_const(); }
qualified_restrict()292 bool qualified_restrict() const { return p->qualified_restrict(); }
qualified_unused()293 bool qualified_unused() const { return p->qualified_unused(); }
qualified_volatile()294 bool qualified_volatile() const { return p->qualified_volatile(); }
add_qualifiers(Type t)295 void add_qualifiers(Type t) { return p->add_qualifiers(t); }
get_qualifiers()296 qualifiers_t get_qualifiers() const { return p->get_qualifiers(); }
get_name()297 const string get_name() const { return p->get_name(); }
get_token()298 const Ctoken& get_token() const { return p->get_token(); }
get_storage_class()299 enum e_storage_class get_storage_class() const
300 {return p->get_storage_class(); }
get_default_specifier()301 Type get_default_specifier() const
302 { return p->get_default_specifier(); }
add_member(const Token & tok,const Type & typ)303 void add_member(const Token &tok, const Type &typ)
304 { p->add_member(tok, typ); }
merge_with(Type t)305 void merge_with(Type t) { p->merge_with(t) ; }
get_members_by_name()306 const Stab& get_members_by_name() const { return p->get_members_by_name(); }
get_members_by_ordinal()307 const vector <Id>& get_members_by_ordinal() const { return p->get_members_by_ordinal(); }
member(const string & name)308 Id const* member(const string& name) const // Structure and union
309 { return p->member(name); }
member(int n)310 Type member(int n) // Structure, union, array
311 { return p->member(n); }
312 friend Type merge(Type a, Type b);
313 };
314
315 Type identifier(const Ctoken& c);
316 Type basic(enum e_btype t = b_abstract, enum e_sign s = s_none,
317 enum e_storage_class sc = c_unspecified, qualifiers_t = q_none);
318 Type enum_tag();
319 Type struct_union();
320 Type incomplete(const Ctoken& c, int l);
321 Type label();
322 Type plist(int n);
323
324
add_qualifiers(Type t)325 inline void QType_node::add_qualifiers(Type t) {qualifiers |= t.get_qualifiers(); }
set_storage_class(Type t)326 inline void Tbasic::set_storage_class(Type t) { sclass.set_storage_class(t); }
clear_storage_class()327 inline void Tbasic::clear_storage_class() { sclass.clear_storage_class(); }
328
329 /*
330 * We can not use a union since its members have constructors and desctructors.
331 * We thus define a structure with a single element to turn-on the yacc
332 * type-checking mechanisms
333 * Elements that have a type (which must be of type Type) are defined as <t>
334 */
335 typedef struct {
336 Type t;
337 } YYSTYPE;
338
339 #endif // TYPE_
340