source: src/SymTab/Indexer.cc @ aa99647

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since aa99647 was ae4c85a, checked in by Rob Schluntz <rschlunt@…>, 9 years ago

fix function type parameter names leaking into the enclosing scope, first attempt

  • Property mode set to 100644
File size: 12.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Indexer.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 21:37:33 2015
11// Last Modified By : Rob Schluntz
12// Last Modified On : Wed Aug 05 13:52:42 2015
13// Update Count     : 10
14//
15
16#include "SynTree/Declaration.h"
17#include "SynTree/Type.h"
18#include "SynTree/Expression.h"
19#include "SynTree/Initializer.h"
20#include "SynTree/Statement.h"
21#include "Indexer.h"
22#include <typeinfo>
23#include "utility.h"
24
25#define debugPrint(x) if ( doDebug ) { std::cout << x; }
26
27namespace SymTab {
28        template< typename Container, typename VisitorType >
29        inline void acceptAllNewScope( Container &container, VisitorType &visitor ) {
30                visitor.enterScope();
31                acceptAll( container, visitor );
32                visitor.leaveScope();
33        }
34
35        Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {}
36
37        Indexer::~Indexer() {}
38
39        void Indexer::visit( ObjectDecl *objectDecl ) {
40                enterScope();
41                maybeAccept( objectDecl->get_type(), *this );
42                leaveScope();
43                maybeAccept( objectDecl->get_init(), *this );
44                maybeAccept( objectDecl->get_bitfieldWidth(), *this );
45                if ( objectDecl->get_name() != "" ) {
46                        debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
47                        idTable.addDecl( objectDecl );
48                } // if
49        }
50
51        void Indexer::visit( FunctionDecl *functionDecl ) {
52                if ( functionDecl->get_name() == "" ) return;
53                debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
54                idTable.addDecl( functionDecl );
55                enterScope();
56                maybeAccept( functionDecl->get_functionType(), *this );
57                acceptAll( functionDecl->get_oldDecls(), *this );
58                maybeAccept( functionDecl->get_statements(), *this );
59                leaveScope();
60        }
61
62
63// A NOTE ON THE ORDER OF TRAVERSAL
64//
65// Types and typedefs have their base types visited before they are added to the type table.  This is ok, since there is
66// no such thing as a recursive type or typedef.
67//
68//             typedef struct { T *x; } T; // never allowed
69//
70// for structs/unions, it is possible to have recursion, so the decl should be added as if it's incomplete to begin, the
71// members are traversed, and then the complete type should be added (assuming the type is completed by this particular
72// declaration).
73//
74//             struct T { struct T *x; }; // allowed
75//
76// It is important to add the complete type to the symbol table *after* the members/base has been traversed, since that
77// traversal may modify the definition of the type and these modifications should be visible when the symbol table is
78// queried later in this pass.
79//
80// TODO: figure out whether recursive contexts are sensible/possible/reasonable.
81
82
83        void Indexer::visit( TypeDecl *typeDecl ) {
84                // see A NOTE ON THE ORDER OF TRAVERSAL, above
85                // note that assertions come after the type is added to the symtab, since they are not part of the type proper
86                // and may depend on the type itself
87                enterScope();
88                acceptAll( typeDecl->get_parameters(), *this );
89                maybeAccept( typeDecl->get_base(), *this );
90                leaveScope();
91                debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
92                typeTable.add( typeDecl );
93                acceptAll( typeDecl->get_assertions(), *this );
94        }
95
96        void Indexer::visit( TypedefDecl *typeDecl ) {
97                enterScope();
98                acceptAll( typeDecl->get_parameters(), *this );
99                maybeAccept( typeDecl->get_base(), *this );
100                leaveScope();
101                debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
102                typeTable.add( typeDecl );
103        }
104
105        void Indexer::visit( StructDecl *aggregateDecl ) {
106                // make up a forward declaration and add it before processing the members
107                StructDecl fwdDecl( aggregateDecl->get_name() );
108                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
109                debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
110                structTable.add( &fwdDecl );
111 
112                enterScope();
113                acceptAll( aggregateDecl->get_parameters(), *this );
114                acceptAll( aggregateDecl->get_members(), *this );
115                leaveScope();
116 
117                debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
118                // this addition replaces the forward declaration
119                structTable.add( aggregateDecl );
120        }
121
122        void Indexer::visit( UnionDecl *aggregateDecl ) {
123                // make up a forward declaration and add it before processing the members
124                UnionDecl fwdDecl( aggregateDecl->get_name() );
125                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
126                debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
127                unionTable.add( &fwdDecl );
128 
129                enterScope();
130                acceptAll( aggregateDecl->get_parameters(), *this );
131                acceptAll( aggregateDecl->get_members(), *this );
132                leaveScope();
133 
134                debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
135                unionTable.add( aggregateDecl );
136        }
137
138        void Indexer::visit( EnumDecl *aggregateDecl ) {
139                debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
140                enumTable.add( aggregateDecl );
141                // unlike structs, contexts, and unions, enums inject their members into the global scope
142                acceptAll( aggregateDecl->get_members(), *this );
143        }
144
145        void Indexer::visit( ContextDecl *aggregateDecl ) {
146                enterScope();
147                acceptAll( aggregateDecl->get_parameters(), *this );
148                acceptAll( aggregateDecl->get_members(), *this );
149                leaveScope();
150 
151                debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
152                contextTable.add( aggregateDecl );
153        }
154
155        void Indexer::visit( CompoundStmt *compoundStmt ) {
156                enterScope();
157                acceptAll( compoundStmt->get_kids(), *this );
158                leaveScope();
159        }
160
161
162        void Indexer::visit( ApplicationExpr *applicationExpr ) {
163                acceptAllNewScope( applicationExpr->get_results(), *this );
164                maybeAccept( applicationExpr->get_function(), *this );
165                acceptAll( applicationExpr->get_args(), *this );
166        }
167
168        void Indexer::visit( UntypedExpr *untypedExpr ) {
169                acceptAllNewScope( untypedExpr->get_results(), *this );
170                acceptAll( untypedExpr->get_args(), *this );
171        }
172
173        void Indexer::visit( NameExpr *nameExpr ) {
174                acceptAllNewScope( nameExpr->get_results(), *this );
175        }
176
177        void Indexer::visit( AddressExpr *addressExpr ) {
178                acceptAllNewScope( addressExpr->get_results(), *this );
179                maybeAccept( addressExpr->get_arg(), *this );
180        }
181
182        void Indexer::visit( LabelAddressExpr *labAddressExpr ) {
183                acceptAllNewScope( labAddressExpr->get_results(), *this );
184                maybeAccept( labAddressExpr->get_arg(), *this );
185        }
186
187        void Indexer::visit( CastExpr *castExpr ) {
188                acceptAllNewScope( castExpr->get_results(), *this );
189                maybeAccept( castExpr->get_arg(), *this );
190        }
191
192        void Indexer::visit( UntypedMemberExpr *memberExpr ) {
193                acceptAllNewScope( memberExpr->get_results(), *this );
194                maybeAccept( memberExpr->get_aggregate(), *this );
195        }
196
197        void Indexer::visit( MemberExpr *memberExpr ) {
198                acceptAllNewScope( memberExpr->get_results(), *this );
199                maybeAccept( memberExpr->get_aggregate(), *this );
200        }
201
202        void Indexer::visit( VariableExpr *variableExpr ) {
203                acceptAllNewScope( variableExpr->get_results(), *this );
204        }
205
206        void Indexer::visit( ConstantExpr *constantExpr ) {
207                acceptAllNewScope( constantExpr->get_results(), *this );
208                maybeAccept( constantExpr->get_constant(), *this );
209        }
210
211        void Indexer::visit( SizeofExpr *sizeofExpr ) {
212                acceptAllNewScope( sizeofExpr->get_results(), *this );
213                if ( sizeofExpr->get_isType() ) {
214                        maybeAccept( sizeofExpr->get_type(), *this );
215                } else {
216                        maybeAccept( sizeofExpr->get_expr(), *this );
217                }
218        }
219
220        void Indexer::visit( AttrExpr *attrExpr ) {
221                acceptAllNewScope( attrExpr->get_results(), *this );
222                if ( attrExpr->get_isType() ) {
223                        maybeAccept( attrExpr->get_type(), *this );
224                } else {
225                        maybeAccept( attrExpr->get_expr(), *this );
226                }
227        }
228
229        void Indexer::visit( LogicalExpr *logicalExpr ) {
230                acceptAllNewScope( logicalExpr->get_results(), *this );
231                maybeAccept( logicalExpr->get_arg1(), *this );
232                maybeAccept( logicalExpr->get_arg2(), *this );
233        }
234
235        void Indexer::visit( ConditionalExpr *conditionalExpr ) {
236                acceptAllNewScope( conditionalExpr->get_results(), *this );
237                maybeAccept( conditionalExpr->get_arg1(), *this );
238                maybeAccept( conditionalExpr->get_arg2(), *this );
239                maybeAccept( conditionalExpr->get_arg3(), *this );
240        }
241
242        void Indexer::visit( CommaExpr *commaExpr ) {
243                acceptAllNewScope( commaExpr->get_results(), *this );
244                maybeAccept( commaExpr->get_arg1(), *this );
245                maybeAccept( commaExpr->get_arg2(), *this );
246        }
247
248        void Indexer::visit( TupleExpr *tupleExpr ) {
249                acceptAllNewScope( tupleExpr->get_results(), *this );
250                acceptAll( tupleExpr->get_exprs(), *this );
251        }
252
253        void Indexer::visit( SolvedTupleExpr *tupleExpr ) {
254                acceptAllNewScope( tupleExpr->get_results(), *this );
255                acceptAll( tupleExpr->get_exprs(), *this );
256        }
257
258        void Indexer::visit( TypeExpr *typeExpr ) {
259                acceptAllNewScope( typeExpr->get_results(), *this );
260                maybeAccept( typeExpr->get_type(), *this );
261        }
262
263        void Indexer::visit( AsmExpr *asmExpr ) {
264                maybeAccept( asmExpr->get_inout(), *this );
265                maybeAccept( asmExpr->get_constraint(), *this );
266                maybeAccept( asmExpr->get_operand(), *this );
267        }
268
269        void Indexer::visit( UntypedValofExpr *valofExpr ) {
270                acceptAllNewScope( valofExpr->get_results(), *this );
271                maybeAccept( valofExpr->get_body(), *this );
272        }
273
274
275        void Indexer::visit( ContextInstType *contextInst ) {
276                acceptAll( contextInst->get_parameters(), *this );
277                acceptAll( contextInst->get_members(), *this );
278        }
279
280        void Indexer::visit( StructInstType *structInst ) {
281                if ( ! structTable.lookup( structInst->get_name() ) ) {
282                        debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
283                        structTable.add( structInst->get_name() );
284                }
285                enterScope();
286                acceptAll( structInst->get_parameters(), *this );
287                leaveScope();
288        }
289
290        void Indexer::visit( UnionInstType *unionInst ) {
291                if ( ! unionTable.lookup( unionInst->get_name() ) ) {
292                        debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
293                        unionTable.add( unionInst->get_name() );
294                }
295                enterScope();
296                acceptAll( unionInst->get_parameters(), *this );
297                leaveScope();
298        }
299
300        void Indexer::visit( ForStmt *forStmt ) {
301            // for statements introduce a level of scope
302            enterScope();
303            Visitor::visit( forStmt );
304            leaveScope();
305        }
306
307
308        void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const {
309                idTable.lookupId( id, list );
310        }
311
312        DeclarationWithType* Indexer::lookupId( const std::string &id) const {
313                return idTable.lookupId(id);
314        }
315
316        NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
317                return typeTable.lookup( id );
318        }
319
320        StructDecl *Indexer::lookupStruct( const std::string &id ) const {
321                return structTable.lookup( id );
322        }
323
324        EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
325                return enumTable.lookup( id );
326        }
327
328        UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
329                return unionTable.lookup( id );
330        }
331
332        ContextDecl  * Indexer::lookupContext( const std::string &id ) const {
333                return contextTable.lookup( id );
334        }
335
336        void Indexer::enterScope() {
337                if ( doDebug ) {
338                        std::cout << "--- Entering scope" << std::endl;
339                }
340                idTable.enterScope();
341                typeTable.enterScope();
342                structTable.enterScope();
343                enumTable.enterScope();
344                unionTable.enterScope();
345                contextTable.enterScope();
346        }
347
348        void Indexer::leaveScope() {
349                using std::cout;
350                using std::endl;
351 
352                if ( doDebug ) {
353                        cout << "--- Leaving scope containing" << endl;
354                        idTable.dump( cout );
355                        typeTable.dump( cout );
356                        structTable.dump( cout );
357                        enumTable.dump( cout );
358                        unionTable.dump( cout );
359                        contextTable.dump( cout );
360                }
361                idTable.leaveScope();
362                typeTable.leaveScope();
363                structTable.leaveScope();
364                enumTable.leaveScope();
365                unionTable.leaveScope();
366                contextTable.leaveScope();
367        }
368
369        void Indexer::print( std::ostream &os, int indent ) const {
370            using std::cerr;
371            using std::endl;
372
373            cerr << "===idTable===" << endl;
374            idTable.dump( os );
375            cerr << "===typeTable===" << endl;
376            typeTable.dump( os );
377            cerr << "===structTable===" << endl;
378            structTable.dump( os );
379            cerr << "===enumTable===" << endl;
380            enumTable.dump( os );
381            cerr << "===unionTable===" << endl;
382            unionTable.dump( os );
383            cerr << "===contextTable===" << endl;
384            contextTable.dump( os );
385#if 0
386                idTable.dump( os );
387                typeTable.dump( os );
388                structTable.dump( os );
389                enumTable.dump( os );
390                unionTable.dump( os );
391                contextTable.dump( os );
392#endif
393        }
394} // namespace SymTab
395
396// Local Variables: //
397// tab-width: 4 //
398// mode: c++ //
399// compile-command: "make install" //
400// End: //
Note: See TracBrowser for help on using the repository browser.