source: src/SymTab/IdTable.cc@ 4389966

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new string with_gc
Last change on this file since 4389966 was 59cde21, checked in by Rob Schluntz <rschlunt@…>, 10 years ago

rearrange IdTable checks

  • Property mode set to 100644
File size: 7.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// 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 Oct 07 12:21:13 2015
13// Update Count : 73
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 // xxx - should be while?
40 if ( ! entry.empty() && entry.top().second == scopeLevel ) {
41 entry.pop();
42 } // if
43 } // for
44 } // for
45
46 scopeLevel--;
47 assert( scopeLevel >= 0 );
48 }
49
50 void IdTable::addDecl( DeclarationWithType *decl ) {
51 const string &name = decl->get_name();
52 string manglename;
53 if ( decl->get_linkage() == LinkageSpec::C ) {
54 manglename = name;
55 } else if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
56 // mangle the name without including the appropriate suffix
57 // this will make it so that overridable routines are placed
58 // into the same "bucket" as their user defined versions.
59 manglename = Mangler::mangle( decl, false );
60 } else {
61 manglename = Mangler::mangle( decl );
62 } // if
63
64 InnerTableType &declTable = table[ name ];
65 InnerTableType::iterator it = declTable.find( manglename );
66
67 if ( it == declTable.end() ) {
68 // first time this name mangling has been defined
69 declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
70 } else {
71 std::stack< DeclEntry >& entry = it->second;
72 if ( ! entry.empty() && entry.top().second == scopeLevel ) {
73 // if we're giving the same name mangling to things of
74 // different types then there is something wrong
75 Declaration *old = entry.top().first;
76 assert( (dynamic_cast<ObjectDecl*>( decl ) && dynamic_cast<ObjectDecl*>( old ) )
77 || (dynamic_cast<FunctionDecl*>( decl ) && dynamic_cast<FunctionDecl*>( old ) ) );
78
79 if ( LinkageSpec::isOverridable( old->get_linkage() ) ) {
80 // new definition shadows the autogenerated one, even at the same scope
81 declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
82 } else if ( decl->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( decl->get_type(), entry.top().first->get_type(), Indexer() ) ) {
83 // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
84 // we should ignore outermost pointer qualifiers, except _Atomic?
85 FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( decl );
86 FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( old );
87 if ( newentry && oldentry ) {
88 if ( newentry->get_statements() && oldentry->get_statements() ) {
89 throw SemanticError( "duplicate function definition for 1 ", decl );
90 } // if
91 } else {
92 // two objects with the same mangled name defined in the same scope.
93 // both objects must be marked extern or both must be intrinsic for this to be okay
94 // xxx - perhaps it's actually if either is intrinsic then this is okay?
95 // might also need to be same storage class?
96 ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( decl );
97 ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( old );
98 if (newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) {
99 throw SemanticError( "duplicate definition for 3 ", decl );
100 } // if
101 } // if
102 } else {
103 throw SemanticError( "duplicate definition for ", decl );
104 } // if
105 } else {
106 // new scope level - shadow existing definition
107 declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
108 } // if
109 } // if
110 // this ensures that no two declarations with the same unmangled name both have C linkage
111 for ( InnerTableType::iterator i = declTable.begin(); i != declTable.end(); ++i ) {
112 if ( ! i->second.empty() && i->second.top().first->get_linkage() == LinkageSpec::C && declTable.size() > 1 ) {
113 InnerTableType::iterator j = i;
114 for ( j++; j != declTable.end(); ++j ) {
115 if ( ! j->second.empty() && j->second.top().first->get_linkage() == LinkageSpec::C ) {
116 throw SemanticError( "invalid overload of C function " );
117 } // if
118 } // for
119 } // if
120 } // for
121 }
122
123 void IdTable::lookupId( const std::string &id, std::list< DeclarationWithType* >& decls ) const {
124 OuterTableType::const_iterator outer = table.find( id );
125 if ( outer == table.end() ) return;
126 const InnerTableType &declTable = outer->second;
127 for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) {
128 const std::stack< DeclEntry >& entry = it->second;
129 if ( ! entry.empty() ) {
130 decls.push_back( entry.top().first );
131 } // if
132 } // for
133 }
134
135 DeclarationWithType * IdTable::lookupId( const std::string &id) const {
136 DeclarationWithType* result = 0;
137 int depth = -1;
138
139 OuterTableType::const_iterator outer = table.find( id );
140 if ( outer == table.end() ) return 0;
141 const InnerTableType &declTable = outer->second;
142 for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) {
143 const std::stack< DeclEntry >& entry = it->second;
144 if ( ! entry.empty() && entry.top().second > depth ) {
145 result = entry.top().first;
146 depth = entry.top().second;
147 } // if
148 } // for
149 return result;
150 }
151
152 void IdTable::dump( std::ostream &os ) const {
153 for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) {
154 for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
155#if 0
156 const std::stack< DeclEntry >& entry = inner->second;
157 if ( ! entry.empty() ) { // && entry.top().second == scopeLevel ) {
158 os << outer->first << " (" << inner->first << ") (" << entry.top().second << ")" << std::endl;
159 } else {
160 os << outer->first << " (" << inner->first << ") ( entry-empty)" << std::endl;
161 } // if
162#endif
163#if 0
164 std::stack<DeclEntry> stack = inner->second;
165 os << "dumping a stack" << std::endl;
166 while ( ! stack.empty()) {
167 DeclEntry d = stack.top();
168 os << outer->first << " (" << inner->first << ") (" << d.second << ") " << std::endl;
169 stack.pop();
170 } // while
171#endif
172 } // for
173 } // for
174#if 0
175 for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) {
176 for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
177 const std::stack< DeclEntry >& entry = inner->second;
178 if ( ! entry.empty() && entry.top().second == scopeLevel ) {
179 os << outer->first << " (" << inner->first << ") (" << scopeLevel << ")" << std::endl;
180 } // if
181 } // for
182 } // for
183#endif
184 }
185} // namespace SymTab
186
187// Local Variables: //
188// tab-width: 4 //
189// mode: c++ //
190// compile-command: "make install" //
191// End: //
Note: See TracBrowser for help on using the repository browser.