source: src/SymTab/IdTable.cc @ 4aa0858

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newstringwith_gc
Last change on this file since 4aa0858 was 4aa0858, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

allow user defined routines to override autogenerated routines

  • Property mode set to 100644
File size: 6.8 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// IdTable.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 17:04:02 2015
11// Last Modified By : Rob Schluntz
12// Last Modified On : Wed Aug 19 15:47:58 2015
13// Update Count     : 38
14//
15
16#include <cassert>
17
18#include "SynTree/Declaration.h"
19#include "ResolvExpr/typeops.h"
20#include "Indexer.h"
21#include "Mangler.h"
22#include "IdTable.h"
23#include "SemanticError.h"
24
25using std::string;
26
27namespace SymTab {
28        IdTable::IdTable() : scopeLevel( 0 ) {
29        }
30
31        void IdTable::enterScope() {
32                scopeLevel++;
33        }
34
35        void IdTable::leaveScope() {
36                for ( OuterTableType::iterator outer = table.begin(); outer != table.end(); ++outer ) {
37                        for ( InnerTableType::iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
38                                std::stack< DeclEntry >& entry = inner->second;
39                                if ( ! entry.empty() && entry.top().second == scopeLevel ) {
40                                        entry.pop();
41                                } // if
42                        } // for
43                } // for
44
45                scopeLevel--;
46                assert( scopeLevel >= 0 );
47        }
48
49        void IdTable::addDecl( DeclarationWithType *decl ) {
50                const string &name = decl->get_name();
51                string manglename;
52                if ( decl->get_linkage() == LinkageSpec::C ) {
53                        manglename = name;
54                } else if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
55                        // mangle the name without including the appropriate suffix
56                        // this will make it so that overridable routines are placed
57                        // into the same "bucket" as their user defined versions.
58                        manglename = Mangler::mangle( decl, false );
59                } else {
60                        manglename = Mangler::mangle( decl );
61                } // if
62
63                InnerTableType &declTable = table[ name ];
64                InnerTableType::iterator it = declTable.find( manglename );
65
66                if ( it == declTable.end() ) {
67                        declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
68                } else {
69                        std::stack< DeclEntry >& entry = it->second;
70                        if ( ! entry.empty() && entry.top().second == scopeLevel ) {
71                                // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
72                                // we should ignore outermost pointer qualifiers, except _Atomic?
73
74                                if ( decl->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( decl->get_type(), entry.top().first->get_type(), Indexer() ) ) {
75                                        FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( decl );
76                                        FunctionDecl *old = dynamic_cast< FunctionDecl* >( entry.top().first );
77                                        if ( LinkageSpec::isOverridable( old->get_linkage() ) ) {
78                                                // new definition shadows the autogenerated one, even at the same scope
79                                                declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
80                                        } else if ( newentry && old && newentry->get_statements() && old->get_statements() ) {
81                                                throw SemanticError( "duplicate function definition for 1 ", decl );
82                                        } else {
83                                                // two objects with the same mangled name defined in the same scope.
84                                                // both objects must be marked extern for this to be okay
85                                                ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( decl );
86                                                ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( entry.top().first );
87                                                if ( newobj && oldobj && newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) {
88                                                        throw SemanticError( "duplicate definition for ", decl );
89                                                } // if
90                                        } // if
91                                } else {
92                                        // C definitions with the same name but incompatible types
93                                        throw SemanticError( "duplicate definition for 2 ", decl );
94                                } // if
95                        } else {
96                                declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
97                        } // if
98                } // if
99                // ensure the set of routines with C linkage cannot be overloaded
100                // this ensures that no two declarations with the same unmangled name both have C linkage
101                for ( InnerTableType::iterator i = declTable.begin(); i != declTable.end(); ++i ) {
102                        if ( ! i->second.empty() && i->second.top().first->get_linkage() == LinkageSpec::C && declTable.size() > 1 ) {
103                                InnerTableType::iterator j = i;
104                                for ( j++; j != declTable.end(); ++j ) {
105                                        if ( ! j->second.empty() && j->second.top().first->get_linkage() == LinkageSpec::C ) {
106                                                throw SemanticError( "invalid overload of C function " );
107                                        } // if
108                                } // for
109                        } // if
110                } // for
111        }
112
113        void IdTable::lookupId( const std::string &id, std::list< DeclarationWithType* >& decls ) const {
114                OuterTableType::const_iterator outer = table.find( id );
115                if ( outer == table.end() ) return;
116                const InnerTableType &declTable = outer->second;
117                for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) {
118                        const std::stack< DeclEntry >& entry = it->second;
119                        if ( ! entry.empty() ) {
120                                decls.push_back( entry.top().first );
121                        } // if
122                } // for
123        }
124
125        DeclarationWithType * IdTable::lookupId( const std::string &id) const {
126                DeclarationWithType* result = 0;
127                int depth = -1;
128
129                OuterTableType::const_iterator outer = table.find( id );
130                if ( outer == table.end() ) return 0;
131                const InnerTableType &declTable = outer->second;
132                for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) {
133                        const std::stack< DeclEntry >& entry = it->second;
134                        if ( ! entry.empty() && entry.top().second > depth ) {
135                                result = entry.top().first;
136                                depth = entry.top().second;
137                        } // if
138                } // for
139                return result;
140        }
141
142        void IdTable::dump( std::ostream &os ) const {
143                for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) {
144                        for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
145#if 0
146                                const std::stack< DeclEntry >& entry = inner->second;
147                                if ( ! entry.empty() ) { // && entry.top().second == scopeLevel ) {
148                                        os << outer->first << " (" << inner->first << ") (" << entry.top().second << ")" << std::endl;
149                                } else {
150                                        os << outer->first << " (" << inner->first << ") ( entry-empty)" << std::endl;
151                                } // if
152#endif
153#if 0
154                                std::stack<DeclEntry> stack = inner->second;
155                                os << "dumping a stack" << std::endl;
156                                while ( ! stack.empty()) {
157                                        DeclEntry d = stack.top();
158                                        os << outer->first << " (" << inner->first << ") (" << d.second << ") " << std::endl;
159                                        stack.pop();
160                                } // while
161#endif
162                        } // for
163                } // for
164#if 0
165                for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) {
166                        for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
167                                const std::stack< DeclEntry >& entry = inner->second;
168                                if ( ! entry.empty() && entry.top().second == scopeLevel ) {
169                                        os << outer->first << " (" << inner->first << ") (" << scopeLevel << ")" << std::endl;
170                                } // if
171                        } // for
172                } // for
173#endif
174        }
175} // namespace SymTab
176
177// Local Variables: //
178// tab-width: 4 //
179// mode: c++ //
180// compile-command: "make install" //
181// End: //
Note: See TracBrowser for help on using the repository browser.