source: src/Validate/ReplaceTypedef.cpp@ fa2c005

ADT
Last change on this file since fa2c005 was fa2c005, checked in by JiadaL <j82liang@…>, 3 years ago

Finish Adt POC

  • Property mode set to 100644
File size: 12.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 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// ReplaceTypedef.cpp -- Fill in all typedefs with the underlying type.
8//
9// Author : Andrew Beach
10// Created On : Tue Jun 29 14:59:00 2022
11// Last Modified By : Andrew Beach
12// Last Modified On : Tue Sep 20 17:00:00 2022
13// Update Count : 2
14//
15
16#include "ReplaceTypedef.hpp"
17
18#include "AST/Pass.hpp"
19#include "Common/ScopedMap.h"
20#include "Common/UniqueName.h"
21#include "Common/utility.h"
22#include "ResolvExpr/Unify.h"
23
24namespace Validate {
25
26namespace {
27
28bool isNonParameterAttribute( ast::Attribute const * attr ) {
29 static const std::vector<std::string> bad_names = {
30 "aligned", "__aligned__",
31 };
32 for ( auto name : bad_names ) {
33 if ( name == attr->name ) {
34 return true;
35 }
36 }
37 return false;
38}
39
40struct ReplaceTypedefCore final :
41 public ast::WithCodeLocation,
42 public ast::WithDeclsToAdd<>,
43 public ast::WithGuards,
44 public ast::WithShortCircuiting,
45 public ast::WithVisitorRef<ReplaceTypedefCore> {
46
47 void previsit( ast::QualifiedType const * );
48 ast::Type const * postvisit( ast::QualifiedType const * );
49 ast::Type const * postvisit( ast::TypeInstType const * );
50 ast::Decl const * postvisit( ast::TypedefDecl const * );
51 void previsit( ast::TypeDecl const * );
52 void previsit( ast::FunctionDecl const * );
53 void previsit( ast::ObjectDecl const * );
54 ast::DeclWithType const * postvisit( ast::ObjectDecl const * );
55
56 void previsit( ast::CastExpr const * );
57 void previsit( ast::CompoundStmt const * );
58 void postvisit( ast::CompoundStmt const * );
59
60 ast::StructDecl const * previsit( ast::StructDecl const * );
61 ast::UnionDecl const * previsit( ast::UnionDecl const * );
62 ast::AdtDecl const * previsit( ast::AdtDecl const * );
63 void previsit( ast::EnumDecl const * );
64 void previsit( ast::TraitDecl const * );
65
66 template<typename AggrDecl>
67 void addImplicitTypedef( AggrDecl * aggDecl );
68 template<typename AggrDecl>
69 AggrDecl const * handleAggregate( AggrDecl const * aggDecl );
70
71 using TypedefDeclPtr = ast::ptr<ast::TypedefDecl>;
72 using TypedefMap = ScopedMap<std::string, std::pair<TypedefDeclPtr, int>>;
73 using TypeDeclMap = ScopedMap<std::string, ast::TypeDecl const *>;
74
75 TypedefMap typedefNames;
76 TypeDeclMap typedeclNames;
77 int scopeLevel;
78 bool isAtFunctionTop = false;
79};
80
81void ReplaceTypedefCore::previsit( ast::QualifiedType const * ) {
82 visit_children = false;
83}
84
85ast::Type const * ReplaceTypedefCore::postvisit(
86 ast::QualifiedType const * type ) {
87 // Replacing typedefs only makes sense for the 'oldest ancestor'
88 // of the qualified type.
89 return ast::mutate_field( type, &ast::QualifiedType::parent,
90 type->parent->accept( *visitor ) );
91}
92
93// Here, 5/30
94ast::Type const * ReplaceTypedefCore::postvisit(
95 ast::TypeInstType const * type ) {
96 // Instances of typedef types will come here. If it is an instance
97 // of a typedef type, link the instance to its actual type.
98 TypedefMap::const_iterator def = typedefNames.find( type->name ); // because of this
99 if ( def != typedefNames.end() ) {
100 ast::Type * ret = ast::deepCopy( def->second.first->base );
101 ret->qualifiers |= type->qualifiers;
102 // We ignore certain attributes on function parameters if they arrive
103 // by typedef. GCC appears to do the same thing.
104 if ( isAtFunctionTop ) {
105 erase_if( ret->attributes, isNonParameterAttribute );
106 }
107 for ( const auto & attribute : type->attributes ) {
108 ret->attributes.push_back( attribute );
109 }
110 // Place instance parameters on the typedef'd type.
111 if ( !type->params.empty() ) {
112 auto rtt = dynamic_cast<ast::BaseInstType *>( ret );
113 if ( !rtt ) {
114 assert( location );
115 SemanticError( *location, "Cannot apply type parameters to base type of " + type->name );
116 }
117 rtt->params.clear();
118 for ( auto it : type->params ) {
119 rtt->params.push_back( ast::deepCopy( it ) );
120 }
121 // Recursively fix typedefs on parameters.
122 ast::mutate_each( rtt, &ast::BaseInstType::params, *visitor );
123 }
124 return ret;
125 } else {
126 TypeDeclMap::const_iterator base = typedeclNames.find( type->name );
127 if ( base == typedeclNames.end() ) {
128 assert( location );
129 SemanticError( *location, toString( "Use of undefined type ", type->name ) );
130 }
131 return ast::mutate_field( type, &ast::TypeInstType::base, base->second );
132 }
133}
134
135struct VarLenChecker : public ast::WithShortCircuiting {
136 bool result = false;
137 void previsit( ast::FunctionType const * ) { visit_children = false; }
138 void previsit( ast::ArrayType const * at ) { result |= at->isVarLen; }
139};
140
141ast::Decl const * ReplaceTypedefCore::postvisit(
142 ast::TypedefDecl const * decl ) {
143 if ( 1 == typedefNames.count( decl->name ) &&
144 typedefNames[ decl->name ].second == scopeLevel ) {
145 ast::Type const * t0 = decl->base;
146 ast::Type const * t1 = typedefNames[ decl->name ].first->base;
147 // Cannot redefine VLA typedefs. Note: this is slightly incorrect,
148 // because our notion of VLAs at this point in the translator is
149 // imprecise. In particular, this will disallow redefining typedefs
150 // with arrays whose dimension is an enumerator or a cast of a
151 // constant/enumerator. The effort required to fix this corner case
152 // likely outweighs the utility of allowing it.
153 if ( !ResolvExpr::typesCompatible( t0, t1, ast::SymbolTable() )
154 || ast::Pass<VarLenChecker>::read( t0 )
155 || ast::Pass<VarLenChecker>::read( t1 ) ) {
156 SemanticError( decl->location, "Cannot redefine typedef: " + decl->name );
157 }
158 } else {
159 typedefNames[ decl->name ] =
160 std::make_pair( TypedefDeclPtr( decl ), scopeLevel );
161 }
162
163 // When a typedef is a forward declaration:
164 // > typedef struct screen SCREEN;
165 // the declaration portion must be retained:
166 // > struct screen;
167 // because the expansion of the typedef is:
168 // > void func( SCREEN * p ) -> void func( struct screen * p );
169 // hence type name "screen" must be defined.
170 // Note: qualifiers on the typedef are not used for the forward declaration.
171
172 ast::Type const * designatorType = decl->base->stripDeclarator();
173 if ( auto structType = dynamic_cast<ast::StructInstType const *>( designatorType ) ) {
174 declsToAddBefore.push_back( new ast::StructDecl(
175 decl->location, structType->name, ast::AggregateDecl::Struct, {},
176 decl->linkage ) );
177 } else if ( auto unionType = dynamic_cast<ast::UnionInstType const *>( designatorType ) ) {
178 declsToAddBefore.push_back( new ast::UnionDecl(
179 decl->location, unionType->name, {}, decl->linkage ) );
180 } else if ( auto enumType = dynamic_cast<ast::EnumInstType const *>( designatorType ) ) {
181 declsToAddBefore.push_back( new ast::EnumDecl(
182 decl->location, enumType->name, false, {}, decl->linkage,
183 ( (enumType->base) ? enumType->base->base : nullptr )
184 ) );
185 }
186 return ast::deepCopy( decl );
187}
188
189void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
190 typedefNames.erase( decl->name );
191 typedeclNames.insert( decl->name, decl );
192}
193
194void ReplaceTypedefCore::previsit( ast::FunctionDecl const * ) {
195 GuardScope( typedefNames );
196 GuardScope( typedeclNames );
197 GuardValue( isAtFunctionTop ) = true;
198}
199
200void ReplaceTypedefCore::previsit( ast::ObjectDecl const * ) {
201 GuardScope( typedefNames );
202 GuardScope( typedeclNames );
203}
204
205ast::DeclWithType const * ReplaceTypedefCore::postvisit(
206 ast::ObjectDecl const * decl ) {
207 if ( ast::FunctionType const * type = decl->type.as<ast::FunctionType>() ) {
208 using DWTVector = std::vector<ast::ptr<ast::DeclWithType>>;
209 using DeclVector = std::vector<ast::ptr<ast::TypeDecl>>;
210 CodeLocation const & declLocation = decl->location;
211 UniqueName paramNamer( decl->name + "Param" );
212
213 // Replace the current object declaration with a function declaration.
214 ast::FunctionDecl const * newDecl = new ast::FunctionDecl(
215 declLocation,
216 decl->name,
217 map_range<DeclVector>( type->forall, []( const ast::TypeInstType * inst ) {
218 return ast::deepCopy( inst->base );
219 } ),
220 map_range<DWTVector>( type->assertions, []( const ast::VariableExpr * expr ) {
221 return ast::deepCopy( expr->var );
222 } ),
223 map_range<DWTVector>( type->params, [&declLocation, &paramNamer]( const ast::Type * type ) {
224 assert( type );
225 return new ast::ObjectDecl( declLocation, paramNamer.newName(), ast::deepCopy( type ) );
226 } ),
227 map_range<DWTVector>( type->returns, [&declLocation, &paramNamer]( const ast::Type * type ) {
228 assert( type );
229 return new ast::ObjectDecl( declLocation, paramNamer.newName(), ast::deepCopy( type ) );
230 } ),
231 nullptr,
232 decl->storage,
233 decl->linkage,
234 {/* attributes */},
235 decl->funcSpec
236 );
237 return newDecl;
238 }
239 return decl;
240}
241
242void ReplaceTypedefCore::previsit( ast::CastExpr const * ) {
243 GuardScope( typedefNames );
244 GuardScope( typedeclNames );
245}
246
247void ReplaceTypedefCore::previsit( ast::CompoundStmt const * ) {
248 GuardScope( typedefNames );
249 GuardScope( typedeclNames );
250 GuardValue( isAtFunctionTop ) = false;
251 scopeLevel += 1;
252}
253
254void ReplaceTypedefCore::postvisit( ast::CompoundStmt const * ) {
255 scopeLevel -= 1;
256}
257
258ast::StructDecl const * ReplaceTypedefCore::previsit( ast::StructDecl const * decl ) {
259 visit_children = false;
260 addImplicitTypedef( decl );
261 return handleAggregate( decl );
262}
263
264ast::AdtDecl const * ReplaceTypedefCore::previsit( ast::AdtDecl const * decl ) {
265 visit_children = false;
266 addImplicitTypedef( decl );
267 return handleAggregate( decl );
268}
269
270ast::UnionDecl const * ReplaceTypedefCore::previsit( ast::UnionDecl const * decl ) {
271 visit_children = false;
272 addImplicitTypedef( decl );
273 return handleAggregate( decl );
274}
275
276void ReplaceTypedefCore::previsit( ast::EnumDecl const * decl ) {
277 addImplicitTypedef( decl );
278}
279
280void ReplaceTypedefCore::previsit( ast::TraitDecl const * ) {
281 GuardScope( typedefNames );
282 GuardScope( typedeclNames );
283}
284
285template<typename AggrDecl>
286void ReplaceTypedefCore::addImplicitTypedef( AggrDecl * aggrDecl ) {
287 if ( 0 != typedefNames.count( aggrDecl->name ) ) {
288 return;
289 }
290 ast::Type * type = nullptr;
291 if ( auto structDecl = dynamic_cast<const ast::StructDecl *>( aggrDecl ) ) {
292 type = new ast::StructInstType( structDecl->name );
293 } else if ( auto unionDecl = dynamic_cast<const ast::UnionDecl *>( aggrDecl ) ) {
294 type = new ast::UnionInstType( unionDecl->name );
295 } else if ( auto enumDecl = dynamic_cast<const ast::EnumDecl *>( aggrDecl ) ) {
296 type = new ast::EnumInstType( enumDecl->name );
297 } else if ( auto adtDecl = dynamic_cast<const ast::AdtDecl *>( aggrDecl )) {
298 type = new ast::AdtInstType( adtDecl->name );
299 }
300 assert( type );
301
302 TypedefDeclPtr typeDecl = new ast::TypedefDecl( aggrDecl->location,
303 aggrDecl->name, ast::Storage::Classes(), type, aggrDecl->linkage );
304 // Add the implicit typedef to the AST.
305 declsToAddBefore.push_back( ast::deepCopy( typeDecl.get() ) );
306 // Shore the name in the map of names.
307 typedefNames[ aggrDecl->name ] =
308 std::make_pair( std::move( typeDecl ), scopeLevel );
309}
310
311template<typename AggrDecl>
312AggrDecl const * ReplaceTypedefCore::handleAggregate( AggrDecl const * decl ) {
313 SemanticErrorException errors;
314
315 ValueGuard<decltype(declsToAddBefore)> oldBeforeDecls( declsToAddBefore );
316 ValueGuard<decltype(declsToAddAfter )> oldAfterDecls( declsToAddAfter );
317 declsToAddBefore.clear();
318 declsToAddAfter.clear();
319
320 GuardScope( typedefNames );
321 GuardScope( typedeclNames );
322 decl = mutate_each( decl, &ast::AggregateDecl::params, *visitor );
323 decl = mutate_each( decl, &ast::AggregateDecl::attributes, *visitor );
324
325 auto mut = ast::mutate( decl );
326
327 std::vector<ast::ptr<ast::Decl>> members;
328 // Unroll accept_all for decl->members so that implicit typedefs for
329 // nested types are added to the aggregate body.
330 for ( ast::ptr<ast::Decl> const & member : mut->members ) {
331 assert( declsToAddAfter.empty() );
332 ast::Decl const * newMember = nullptr;
333 try {
334 newMember = member->accept( *visitor );
335 } catch ( SemanticErrorException & e ) {
336 errors.append( e );
337 }
338 if ( !declsToAddBefore.empty() ) {
339 for ( auto declToAdd : declsToAddBefore ) {
340 members.push_back( declToAdd );
341 }
342 declsToAddBefore.clear();
343 }
344 members.push_back( newMember );
345 }
346 assert( declsToAddAfter.empty() );
347 if ( !errors.isEmpty() ) { throw errors; }
348
349 mut->members.clear();
350 for ( auto member : members ) {
351 mut->members.push_back( member );
352 }
353
354 return mut;
355}
356
357} // namespace
358
359void replaceTypedef( ast::TranslationUnit & translationUnit ) {
360 ast::Pass<ReplaceTypedefCore> pass;
361 ast::accept_all( translationUnit, pass );
362 if ( pass.core.typedefNames.count( "size_t" ) ) {
363 translationUnit.global.sizeType =
364 ast::deepCopy( pass.core.typedefNames["size_t"].first->base );
365 } else {
366 // Missing the global definition, default to long unsigned int.
367 // Perhaps this should be a warning instead.
368 translationUnit.global.sizeType =
369 new ast::BasicType( ast::BasicType::LongUnsignedInt );
370 }
371}
372
373} // namespace Validate
374
375// Local Variables: //
376// tab-width: 4 //
377// mode: c++ //
378// compile-command: "make install" //
379// End: //
Note: See TracBrowser for help on using the repository browser.