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