source: src/Validate/ReplaceTypedef.cpp@ 4520b77e

ADT ast-experimental pthread-emulation
Last change on this file since 4520b77e was b0d9ff7, checked in by JiadaL <j82liang@…>, 3 years ago

Fix up the QualifiedNameExpr. It should now work on both old AST and new AST. There are some known bugs to fix so make all-tests will fail.

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