Changes in src/AST/Util.cpp [14c0f7b:b7c53a9d]
- File:
-
- 1 edited
-
src/AST/Util.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Util.cpp
r14c0f7b rb7c53a9d 20 20 #include "Pass.hpp" 21 21 #include "TranslationUnit.hpp" 22 #include "Common/utility.h"23 #include "GenPoly/ScopedSet.h"24 22 25 23 #include <vector> 26 27 using GenPoly::ScopedSet;28 24 29 25 namespace ast { … … 177 173 }; 178 174 179 /// Checks that referred to nodes are in scope.180 /// This checks many readonly pointers to see if the declaration they are181 /// referring to is in scope by the structural rules of code.182 // Any escapes marked with a bug should be removed once the bug is fixed.183 struct InScopeCore : public ast::WithShortCircuiting {184 ScopedSet<DeclWithType const *> typedDecls;185 ScopedSet<TypeDecl const *> typeDecls;186 // These 3 are really hard to check, because uses that originally ref. at187 // a forward declaration can be rewired to point a later full definition.188 ScopedSet<StructDecl const *> structDecls;189 ScopedSet<UnionDecl const *> unionDecls;190 ScopedSet<EnumDecl const *> enumDecls;191 ScopedSet<TraitDecl const *> traitDecls;192 193 bool isInGlobal = false;194 195 void beginScope() {196 typedDecls.beginScope();197 typeDecls.beginScope();198 structDecls.beginScope();199 unionDecls.beginScope();200 enumDecls.beginScope();201 traitDecls.beginScope();202 }203 204 void endScope() {205 typedDecls.endScope();206 typeDecls.endScope();207 structDecls.endScope();208 unionDecls.endScope();209 enumDecls.endScope();210 traitDecls.endScope();211 }212 213 void previsit( ApplicationExpr const * expr ) {214 // All isInGlobal manipulation is just to isolate this check.215 // The invalid compound literals lead to bad ctor/dtors. [#280]216 VariableExpr const * func = nullptr;217 CastExpr const * cast = nullptr;218 VariableExpr const * arg = nullptr;219 if ( isInGlobal220 && 1 == expr->args.size()221 && ( func = expr->func.as<VariableExpr>() )222 && ( "?{}" == func->var->name || "^?{}" == func->var->name )223 && ( cast = expr->args[0].as<CastExpr>() )224 && ( arg = cast->arg.as<VariableExpr>() )225 && isPrefix( arg->var->name, "_compLit" ) ) {226 visit_children = false;227 }228 }229 230 void previsit( VariableExpr const * expr ) {231 if ( !expr->var ) return;232 // bitwise assignment escape [#281]233 if ( expr->var->location.isUnset() ) return;234 assert( typedDecls.contains( expr->var ) );235 }236 237 void previsit( FunctionType const * type ) {238 // This is to avoid checking the assertions, which can point at the239 // function's declaration and not the enclosing function.240 for ( auto type_param : type->forall ) {241 if ( type_param->formal_usage ) {242 visit_children = false;243 // We could check non-assertion fields here.244 }245 }246 }247 248 void previsit( TypeInstType const * type ) {249 if ( !type->base ) return;250 assertf( type->base->isManaged(), "Floating Node" );251 252 // bitwise assignment escape [#281]253 if ( type->base->location.isUnset() ) return;254 // Formal types can actually look at out of scope variables.255 if ( type->formal_usage ) return;256 assert( typeDecls.contains( type->base ) );257 }258 259 void previsit( TraitInstType const * type ) {260 if ( !type->base ) return;261 assert( traitDecls.contains( type->base ) );262 }263 264 void previsit( ObjectDecl const * decl ) {265 typedDecls.insert( decl );266 // There are some ill-formed compound literals. [#280]267 // The only known problem cases are at the top level.268 if ( isPrefix( decl->name, "_compLit" ) ) {269 visit_children = false;270 }271 }272 273 void previsit( FunctionDecl const * decl ) {274 typedDecls.insert( decl );275 beginScope();276 for ( auto & type_param : decl->type_params ) {277 typeDecls.insert( type_param );278 }279 for ( auto & assertion : decl->assertions ) {280 typedDecls.insert( assertion );281 }282 for ( auto & param : decl->params ) {283 typedDecls.insert( param );284 }285 for ( auto & ret : decl->returns ) {286 typedDecls.insert( ret );287 }288 // No special handling of withExprs.289 290 // Part of the compound literal escape. [#280]291 if ( "__global_init__" == decl->name292 || "__global_destroy__" == decl->name ) {293 assert( !isInGlobal );294 isInGlobal = true;295 }296 }297 298 void postvisit( FunctionDecl const * decl ) {299 endScope();300 // Part of the compound literal escape. [#280]301 if ( isInGlobal && ( "__global_init__" == decl->name302 || "__global_destroy__" == decl->name ) ) {303 isInGlobal = false;304 }305 }306 307 void previsit( StructDecl const * decl ) {308 structDecls.insert( decl );309 beginScope();310 for ( auto & type_param : decl->params ) {311 typeDecls.insert( type_param );312 }313 }314 315 void postvisit( StructDecl const * ) {316 endScope();317 }318 319 void previsit( UnionDecl const * decl ) {320 unionDecls.insert( decl );321 beginScope();322 for ( auto & type_param : decl->params ) {323 typeDecls.insert( type_param );324 }325 }326 327 void postvisit( UnionDecl const * ) {328 endScope();329 }330 331 void previsit( EnumDecl const * decl ) {332 enumDecls.insert( decl );333 if ( ast::EnumDecl::EnumHiding::Visible == decl->hide ) {334 for ( auto & member : decl->members ) {335 typedDecls.insert( member.strict_as<ast::DeclWithType>() );336 }337 }338 beginScope();339 for ( auto & type_param : decl->params ) {340 typeDecls.insert( type_param );341 }342 }343 344 void postvisit( EnumDecl const * ) {345 endScope();346 }347 348 void previsit( TraitDecl const * decl ) {349 traitDecls.insert( decl );350 beginScope();351 for ( auto & type_param : decl->params ) {352 typeDecls.insert( type_param );353 }354 }355 356 void postvisit( TraitDecl const * ) {357 endScope();358 }359 360 void previsit( Designation const * ) {361 visit_children = false;362 }363 };364 365 175 } // namespace 366 176 367 177 void checkInvariants( TranslationUnit & transUnit ) { 368 Pass<InvariantCore>::run( transUnit ); 369 Pass<InScopeCore>::run( transUnit ); 178 ast::Pass<InvariantCore>::run( transUnit ); 370 179 } 371 180
Note:
See TracChangeset
for help on using the changeset viewer.