source: src/SymTab/Indexer.cc @ fdae913

arm-ehcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since fdae913 was fdae913, checked in by Aaron Moss <a3moss@…>, 4 years ago

modify persistent map to not re-initialize history nodes facing deletion

  • Property mode set to 100644
File size: 22.4 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 : Aaron B. Moss
12// Last Modified On : Fri Mar  8 13:55:00 2019
13// Update Count     : 21
14//
15
16#include "Indexer.h"
17
18#include <cassert>                 // for assert, strict_dynamic_cast
19#include <string>                  // for string, operator<<, operator!=
20#include <memory>                  // for shared_ptr, make_shared
21#include <unordered_map>           // for operator!=, unordered_map<>::const...
22#include <unordered_set>           // for unordered_set
23#include <utility>                 // for pair, make_pair, move
24
25#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
26#include "Common/SemanticError.h"  // for SemanticError
27#include "Common/utility.h"        // for cloneAll
28#include "Common/Stats/Counter.h"  // for counters
29#include "GenPoly/GenPoly.h"       // for getFunctionType
30#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
31#include "Mangler.h"               // for Mangler
32#include "Parser/LinkageSpec.h"    // for isMangled, isOverridable, Spec
33#include "ResolvExpr/typeops.h"    // for typesCompatible
34#include "SynTree/Constant.h"      // for Constant
35#include "SynTree/Declaration.h"   // for DeclarationWithType, FunctionDecl
36#include "SynTree/Expression.h"    // for Expression, ImplicitCopyCtorExpr
37#include "SynTree/Initializer.h"   // for Initializer
38#include "SynTree/Statement.h"     // for CompoundStmt, Statement, ForStmt (...
39#include "SynTree/Type.h"          // for Type, StructInstType, UnionInstType
40
41namespace SymTab {
42
43        // Statistics block
44        namespace {
45                static inline auto stats() {
46                        using namespace Stats::Counters;
47                        static auto group   = build<CounterGroup>("Indexers");
48                        static struct {
49                                SimpleCounter * count;
50                                AverageCounter<double> * size;
51                                SimpleCounter * new_scopes;
52                                SimpleCounter * lazy_scopes;
53                                AverageCounter<double> * avg_scope_depth;
54                                MaxCounter<size_t> * max_scope_depth;
55                                SimpleCounter * add_calls;
56                                SimpleCounter * lookup_calls;
57                                SimpleCounter * map_lookups;
58                                SimpleCounter * map_mutations;
59                        } ret = {
60                                .count   = build<SimpleCounter>("Count", group),
61                                .size    = build<AverageCounter<double>>("Average Size", group),
62                                .new_scopes = build<SimpleCounter>("Scopes", group),
63                                .lazy_scopes = build<SimpleCounter>("Lazy Scopes", group),
64                                .avg_scope_depth = build<AverageCounter<double>>("Average Scope", group),
65                                .max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group),
66                                .add_calls = build<SimpleCounter>("Add Calls", group),
67                                .lookup_calls = build<SimpleCounter>("Lookup Calls", group),
68                                .map_lookups = build<SimpleCounter>("Map Lookups", group),
69                                .map_mutations = build<SimpleCounter>("Map Mutations", group)
70                        };
71                        return ret;
72                }
73        }
74
75        void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const {
76                // only need to perform this step for constructors, destructors, and assignment functions
77                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
78
79                // helpful data structure to organize properties for a type
80                struct ValueType {
81                        struct DeclBall { // properties for this particular decl
82                                IdData decl;
83                                bool isUserDefinedFunc;
84                                bool isCopyFunc;
85                        };
86                        // properties for this type
87                        bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
88                        BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
89                        std::list< DeclBall > decls;
90
91                        // another FunctionDecl for the current type was found - determine
92                        // if it has special properties and update data structure accordingly
93                        ValueType & operator+=( IdData data ) {
94                                DeclarationWithType * function = data.id;
95                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
96                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
97                                decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
98                                existsUserDefinedCopyFunc |= (isUserDefinedFunc && isCopyFunc);
99                                if ( isUserDefinedFunc && ! deleteStmt ) {
100                                        // any user-defined function can act as an implicit delete statement for generated constructors.
101                                        // a delete stmt should not act as an implicit delete statement.
102                                        deleteStmt = data.id;
103                                }
104                                return *this;
105                        }
106                }; // ValueType
107
108                std::list< IdData > copy;
109                copy.splice( copy.end(), out );
110
111                // organize discovered declarations by type
112                std::unordered_map< std::string, ValueType > funcMap;
113                for ( auto decl : copy ) {
114                        if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
115                                std::list< DeclarationWithType * > & params = function->type->parameters;
116                                assert( ! params.empty() );
117                                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
118                                Type * base = InitTweak::getPointerBase( params.front()->get_type() );
119                                assert( base );
120                                funcMap[ Mangler::mangle( base ) ] += decl;
121                        } else {
122                                out.push_back( decl );
123                        }
124                }
125
126                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which
127                // determinethe set of ctor/dtor/assign that can be used  by the requester. In particular,
128                // if the user defines a default ctor, then the generated default ctor is unavailable,
129                // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated
130                // field ctors are available. If the user defines any ctor then the generated default ctor
131                // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines
132                // anything that looks like a copy constructor, then the generated copy constructor is
133                // unavailable, and likewise for the assignment operator.
134                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
135                        ValueType & val = pair.second;
136                        for ( ValueType::DeclBall ball : val.decls ) {
137                                bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic;
138                                bool isCopyFunc = ball.isCopyFunc;
139                                bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
140
141                                // only implicitly delete non-user defined functions that are not intrinsic, and are
142                                // not copy functions (assignment or copy constructor). If a  user-defined copy
143                                // function exists, do not pass along the non-user-defined copy functions since
144                                // signatures do not have to match, and the generated functions will often be
145                                // cheaper.
146                                if ( isNotUserDefinedFunc ) {
147                                        if ( isCopyFunc ) {
148                                                // Skip over non-user-defined copy functions when there is a user-defined
149                                                // copy function. Since their signatures do not have to be exact, deleting
150                                                // them is the wrong choice.
151                                                if ( existsUserDefinedCopyFunc ) continue;
152                                        } else {
153                                                // delete non-user-defined non-copy functions if applicable.
154                                                // deleteStmt will be non-null only if a user-defined function is found.
155                                                ball.decl.deleteStmt = val.deleteStmt;
156                                        }
157                                }
158                                out.push_back( ball.decl );
159                        }
160                }
161        }
162
163        Indexer::Indexer() 
164        : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 
165          prevScope(), scope( 0 ), repScope( 0 ) { ++*stats().count; }
166
167        Indexer::~Indexer() {
168                stats().size->push( idTable ? idTable->size() : 0 );
169        }
170
171        void Indexer::lazyInitScope() {
172                if ( repScope < scope ) {
173                        ++*stats().lazy_scopes;
174                        // create rollback
175                        prevScope = std::make_shared<Indexer>( *this );
176                        // update repScope
177                        repScope = scope;
178                }
179        }
180
181        void Indexer::enterScope() {
182                ++scope;
183
184                ++*stats().new_scopes;
185                stats().avg_scope_depth->push( scope );
186                stats().max_scope_depth->push( scope );
187        }
188
189        void Indexer::leaveScope() {
190                if ( repScope == scope ) {
191                        Ptr prev = prevScope;           // make sure prevScope stays live
192                        *this = std::move(*prevScope);  // replace with previous scope
193                }
194
195                --scope;
196        }
197
198        void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const {
199                ++*stats().lookup_calls;
200                if ( ! idTable ) return;
201
202                ++*stats().map_lookups;
203                auto decls = idTable->find( id );
204                if ( decls == idTable->end() ) return;
205
206                for ( auto decl : *(decls->second) ) {
207                        out.push_back( decl.second );
208                }
209               
210                // some special functions, e.g. constructors and destructors
211                // remove autogenerated functions when they are defined so that
212                // they can never be matched
213                removeSpecialOverrides( id, out );
214        }
215
216        NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
217                ++*stats().lookup_calls;
218                if ( ! typeTable ) return nullptr;
219                ++*stats().map_lookups;
220                auto it = typeTable->find( id );
221                return it == typeTable->end() ? nullptr : it->second.decl;
222        }
223
224        StructDecl *Indexer::lookupStruct( const std::string &id ) const {
225                ++*stats().lookup_calls;
226                if ( ! structTable ) return nullptr;
227                ++*stats().map_lookups;
228                auto it = structTable->find( id );
229                return it == structTable->end() ? nullptr : it->second.decl;
230        }
231
232        EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
233                ++*stats().lookup_calls;
234                if ( ! enumTable ) return nullptr;
235                ++*stats().map_lookups;
236                auto it = enumTable->find( id );
237                return it == enumTable->end() ? nullptr : it->second.decl;
238        }
239
240        UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
241                ++*stats().lookup_calls;
242                if ( ! unionTable ) return nullptr;
243                ++*stats().map_lookups;
244                auto it = unionTable->find( id );
245                return it == unionTable->end() ? nullptr : it->second.decl;
246        }
247
248        TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
249                ++*stats().lookup_calls;
250                if ( ! traitTable ) return nullptr;
251                ++*stats().map_lookups;
252                auto it = traitTable->find( id );
253                return it == traitTable->end() ? nullptr : it->second.decl;
254        }
255
256        const Indexer* Indexer::atScope( unsigned long target ) const {
257                // by lazy construction, final indexer in list has repScope 0, cannot be > target
258                // otherwise, will find first scope representing the target
259                const Indexer* indexer = this;
260                while ( indexer->repScope > target ) {
261                        indexer = indexer->prevScope.get();
262                }
263                return indexer;
264        }
265
266        NamedTypeDecl *Indexer::globalLookupType( const std::string &id ) const {
267                return atScope( 0 )->lookupType( id );
268        }
269
270        StructDecl *Indexer::globalLookupStruct( const std::string &id ) const {
271                return atScope( 0 )->lookupStruct( id );
272        }
273
274        UnionDecl *Indexer::globalLookupUnion( const std::string &id ) const {
275                return atScope( 0 )->lookupUnion( id );
276        }
277
278        EnumDecl *Indexer::globalLookupEnum( const std::string &id ) const {
279                return atScope( 0 )->lookupEnum( id );
280        }
281
282        bool isFunction( DeclarationWithType * decl ) {
283                return GenPoly::getFunctionType( decl->get_type() );
284        }
285
286        bool isObject( DeclarationWithType * decl ) {
287                return ! isFunction( decl );
288        }
289
290        bool isDefinition( DeclarationWithType * decl ) {
291                if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
292                        // a function is a definition if it has a body
293                        return func->statements;
294                } else {
295                        // an object is a definition if it is not marked extern.
296                        // both objects must be marked extern
297                        return ! decl->get_storageClasses().is_extern;
298                }
299        }
300
301       
302        bool Indexer::addedIdConflicts( 
303                        const Indexer::IdData & existing, DeclarationWithType *added, 
304                        Indexer::OnConflict handleConflicts, BaseSyntaxNode * deleteStmt ) {
305                // if we're giving the same name mangling to things of different types then there is
306                // something wrong
307                assert( (isObject( added ) && isObject( existing.id ) )
308                        || ( isFunction( added ) && isFunction( existing.id ) ) );
309
310                if ( LinkageSpec::isOverridable( existing.id->linkage ) ) {
311                        // new definition shadows the autogenerated one, even at the same scope
312                        return false;
313                } else if ( LinkageSpec::isMangled( added->linkage ) 
314                                || ResolvExpr::typesCompatible( 
315                                        added->get_type(), existing.id->get_type(), Indexer() ) ) {
316
317                        // it is a conflict if one declaration is deleted and the other is not
318                        if ( deleteStmt && ! existing.deleteStmt ) {
319                                if ( handleConflicts.mode == OnConflict::Error ) {
320                                        SemanticError( added, "deletion of defined identifier " );
321                                }
322                                return true;
323                        } else if ( ! deleteStmt && existing.deleteStmt ) {
324                                if ( handleConflicts.mode == OnConflict::Error ) {
325                                        SemanticError( added, "definition of deleted identifier " );
326                                }
327                                return true;
328                        }
329
330                        if ( isDefinition( added ) && isDefinition( existing.id ) ) {
331                                if ( handleConflicts.mode == OnConflict::Error ) {
332                                        SemanticError( added, 
333                                                isFunction( added ) ? 
334                                                        "duplicate function definition for " : 
335                                                        "duplicate object definition for " );
336                                }
337                                return true;
338                        } // if
339                } else {
340                        if ( handleConflicts.mode == OnConflict::Error ) {
341                                SemanticError( added, "duplicate definition for " );
342                        }
343                        return true;
344                } // if
345
346                return true;
347        }
348
349        bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName ) const {
350                if ( ! idTable ) return false;
351
352                ++*stats().map_lookups;
353                auto decls = idTable->find( id );
354                if ( decls == idTable->end() ) return false;
355
356                for ( auto decl : *(decls->second) ) {
357                        // skip other scopes (hidden by this decl)
358                        if ( decl.second.scope != scope ) continue;
359                        // check for C decl with compatible type (by mangleName)
360                        if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) {
361                                return true;
362                        }
363                }
364               
365                return false;
366        }
367
368        bool Indexer::hasIncompatibleCDecl( 
369                        const std::string &id, const std::string &mangleName ) const {
370                if ( ! idTable ) return false;
371
372                ++*stats().map_lookups;
373                auto decls = idTable->find( id );
374                if ( decls == idTable->end() ) return false;
375
376                for ( auto decl : *(decls->second) ) {
377                        // skip other scopes (hidden by this decl)
378                        if ( decl.second.scope != scope ) continue;
379                        // check for C decl with incompatible type (by manglename)
380                        if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) {
381                                return true;
382                        }
383                }
384
385                return false;
386        }
387
388        void Indexer::addId( 
389                        DeclarationWithType *decl, OnConflict handleConflicts, Expression * baseExpr, 
390                        BaseSyntaxNode * deleteStmt ) {
391                ++*stats().add_calls;
392                if ( decl->name == "" ) return;
393               
394                const std::string &name = decl->name;
395                std::string mangleName;
396                if ( LinkageSpec::isOverridable( decl->linkage ) ) {
397                        // mangle the name without including the appropriate suffix, so overridable routines
398                        // are placed into the same "bucket" as their user defined versions.
399                        mangleName = Mangler::mangle( decl, false );
400                } else {
401                        mangleName = Mangler::mangle( decl );
402                } // if
403
404                // this ensures that no two declarations with the same unmangled name at the same scope
405                // both have C linkage
406                if ( LinkageSpec::isMangled( decl->linkage ) ) {
407                        // Check that a Cforall declaration doesn't override any C declaration
408                        if ( hasCompatibleCDecl( name, mangleName ) ) {
409                                SemanticError( decl, "Cforall declaration hides C function " );
410                        }
411                } else {
412                        // NOTE: only correct if name mangling is completely isomorphic to C
413                        // type-compatibility, which it may not be.
414                        if ( hasIncompatibleCDecl( name, mangleName ) ) {
415                                SemanticError( decl, "conflicting overload of C function " );
416                        }
417                }
418
419                // ensure tables exist and add identifier
420                MangleTable::Ptr mangleTable;
421                if ( ! idTable ) {
422                        idTable = IdTable::new_ptr();
423                        mangleTable = MangleTable::new_ptr();
424                } else {
425                        ++*stats().map_lookups;
426                        auto decls = idTable->find( name );
427                        if ( decls == idTable->end() ) {
428                                mangleTable = MangleTable::new_ptr();
429                        } else {
430                                mangleTable = decls->second;
431                                // skip in-scope repeat declarations of same identifier
432                                ++*stats().map_lookups;
433                                auto existing = mangleTable->find( mangleName );
434                                if ( existing != mangleTable->end()
435                                                && existing->second.scope == scope
436                                                && existing->second.id ) {
437                                        if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) {
438                                                if ( handleConflicts.mode == OnConflict::Delete ) {
439                                                        // set delete expression for conflicting identifier
440                                                        lazyInitScope();
441                                                        *stats().map_mutations += 2;
442                                                        idTable = idTable->set(
443                                                                name,
444                                                                mangleTable->set( 
445                                                                        mangleName, 
446                                                                        IdData{ existing->second, handleConflicts.deleteStmt } ) );
447                                                }
448                                                return;
449                                        }
450                                }
451                        }
452                }
453
454                // add/overwrite with new identifier
455                lazyInitScope();
456                *stats().map_mutations += 2;
457                idTable = idTable->set( 
458                        name,
459                        mangleTable->set( mangleName, IdData{ decl, baseExpr, deleteStmt, scope } ) );
460        }
461
462        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
463                // default handling of conflicts is to raise an error
464                addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
465        }
466
467        void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
468                // default handling of conflicts is to raise an error
469                addId( decl, OnConflict::error(), nullptr, deleteStmt );
470        }
471
472        bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
473                if ( existing->base == nullptr ) {
474                        return false;
475                } else if ( added->base == nullptr ) {
476                        return true;
477                } else {
478                        assert( existing->base && added->base );
479                        // typedef redeclarations are errors only if types are different
480                        if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) {
481                                SemanticError( added->location, "redeclaration of " + added->name );
482                        }
483                }
484                // does not need to be added to the table if both existing and added have a base that are
485                // the same
486                return true;
487        }
488
489        void Indexer::addType( NamedTypeDecl *decl ) {
490                ++*stats().add_calls;
491                const std::string &id = decl->name;
492
493                if ( ! typeTable ) { 
494                        typeTable = TypeTable::new_ptr();
495                } else {
496                        ++*stats().map_lookups;
497                        auto existing = typeTable->find( id );
498                        if ( existing != typeTable->end() 
499                                && existing->second.scope == scope
500                                && addedTypeConflicts( existing->second.decl, decl ) ) return;
501                }
502               
503                lazyInitScope();
504                ++*stats().map_mutations;
505                typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } );
506        }
507
508        bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
509                if ( ! existing->body ) {
510                        return false;
511                } else if ( added->body ) {
512                        SemanticError( added, "redeclaration of " );
513                } // if
514                return true;
515        }
516
517        void Indexer::addStruct( const std::string &id ) {
518                addStruct( new StructDecl( id ) );
519        }
520
521        void Indexer::addStruct( StructDecl *decl ) {
522                ++*stats().add_calls;
523                const std::string &id = decl->name;
524
525                if ( ! structTable ) {
526                        structTable = StructTable::new_ptr();
527                } else {
528                        ++*stats().map_lookups;
529                        auto existing = structTable->find( id );
530                        if ( existing != structTable->end() 
531                                && existing->second.scope == scope
532                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
533                }
534
535                lazyInitScope();
536                ++*stats().map_mutations;
537                structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } );
538        }
539
540        void Indexer::addEnum( EnumDecl *decl ) {
541                ++*stats().add_calls;
542                const std::string &id = decl->name;
543
544                if ( ! enumTable ) {
545                        enumTable = EnumTable::new_ptr();
546                } else {
547                        ++*stats().map_lookups;
548                        auto existing = enumTable->find( id );
549                        if ( existing != enumTable->end() 
550                                && existing->second.scope == scope
551                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
552                }
553               
554                lazyInitScope();
555                ++*stats().map_mutations;
556                enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } );
557        }
558
559        void Indexer::addUnion( const std::string &id ) {
560                addUnion( new UnionDecl( id ) );
561        }
562
563        void Indexer::addUnion( UnionDecl *decl ) {
564                ++*stats().add_calls;
565                const std::string &id = decl->name;
566
567                if ( ! unionTable ) {
568                        unionTable = UnionTable::new_ptr();
569                } else {
570                        ++*stats().map_lookups;
571                        auto existing = unionTable->find( id );
572                        if ( existing != unionTable->end() 
573                                && existing->second.scope == scope
574                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
575                }
576
577                lazyInitScope();
578                ++*stats().map_mutations;
579                unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } );
580        }
581
582        void Indexer::addTrait( TraitDecl *decl ) {
583                ++*stats().add_calls;
584                const std::string &id = decl->name;
585
586                if ( ! traitTable ) {
587                        traitTable = TraitTable::new_ptr();
588                } else {
589                        ++*stats().map_lookups;
590                        auto existing = traitTable->find( id );
591                        if ( existing != traitTable->end() 
592                                && existing->second.scope == scope
593                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
594                }
595
596                lazyInitScope();
597                ++*stats().map_mutations;
598                traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } );
599        }
600
601        void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 
602                        OnConflict handleConflicts ) {
603                for ( Declaration * decl : aggr->members ) {
604                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
605                                addId( dwt, handleConflicts, expr );
606                                if ( dwt->name == "" ) {
607                                        Type * t = dwt->get_type()->stripReferences();
608                                        if ( dynamic_cast<StructInstType*>( t ) || dynamic_cast<UnionInstType*>( t ) ) {
609                                                Expression * base = expr->clone();
610                                                ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
611                                                ResolvExpr::referenceToRvalueConversion( base, cost );
612                                                addMembers( t->getAggr(), new MemberExpr( dwt, base ), handleConflicts );
613                                        }
614                                }
615                        }
616                }
617        }
618
619        void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
620                for ( Expression * expr : withExprs ) {
621                        if ( expr->result ) {
622                                AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
623                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
624
625                                addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) );
626                        }
627                }
628        }
629
630        void Indexer::addIds( const std::list< DeclarationWithType * > & decls ) {
631                for ( auto d : decls ) {
632                        addId( d );
633                }
634        }
635
636        void Indexer::addTypes( const std::list< TypeDecl * > & tds ) {
637                for ( auto td : tds ) {
638                        addType( td );
639                        addIds( td->assertions );
640                }
641        }
642
643        void Indexer::addFunctionType( FunctionType * ftype ) {
644                addTypes( ftype->forall );
645                addIds( ftype->returnVals );
646                addIds( ftype->parameters );
647        }
648
649        Expression * Indexer::IdData::combine( ResolvExpr::Cost & cost ) const {
650                Expression * ret = nullptr;
651                if ( baseExpr ) {
652                        Expression * base = baseExpr->clone();
653                        ResolvExpr::referenceToRvalueConversion( base, cost );
654                        ret = new MemberExpr( id, base );
655                        // xxx - this introduces hidden environments, for now remove them.
656                        // std::swap( base->env, ret->env );
657                        delete base->env;
658                        base->env = nullptr;
659                } else {
660                        ret = new VariableExpr( id );
661                }
662                if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
663                return ret;
664        }
665} // namespace SymTab
666
667// Local Variables: //
668// tab-width: 4 //
669// mode: c++ //
670// compile-command: "make install" //
671// End: //
Note: See TracBrowser for help on using the repository browser.