Changeset 14c0f7b for src/AST/Util.cpp
- Timestamp:
- Jul 31, 2023, 11:25:51 AM (11 months ago)
- Branches:
- master
- Children:
- f496046
- Parents:
- e0332dd
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Util.cpp
re0332dd r14c0f7b 20 20 #include "Pass.hpp" 21 21 #include "TranslationUnit.hpp" 22 #include "Common/utility.h" 23 #include "GenPoly/ScopedSet.h" 22 24 23 25 #include <vector> 26 27 using GenPoly::ScopedSet; 24 28 25 29 namespace ast { … … 173 177 }; 174 178 179 /// Checks that referred to nodes are in scope. 180 /// This checks many readonly pointers to see if the declaration they are 181 /// 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. at 187 // 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 ( isInGlobal 220 && 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 the 239 // 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->name 292 || "__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->name 302 || "__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 175 365 } // namespace 176 366 177 367 void checkInvariants( TranslationUnit & transUnit ) { 178 ast::Pass<InvariantCore>::run( transUnit ); 368 Pass<InvariantCore>::run( transUnit ); 369 Pass<InScopeCore>::run( transUnit ); 179 370 } 180 371
Note: See TracChangeset
for help on using the changeset viewer.