- Timestamp:
- Jun 6, 2019, 10:23:59 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 46438e4
- Parents:
- c6a1e8a (diff), 5684736 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 2 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
rc6a1e8a r866545b 10 10 // Created On : Thu May 09 15::37::05 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed May 29 17:05:00 201913 // Update Count : 912 // Last Modified On : Thu May 06 19:51:00 2019 13 // Update Count : 10 14 14 // 15 15 … … 49 49 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not) 50 50 // allow us to use the same stratagy in the new ast. 51 ast::Type * sizeType = nullptr; 51 52 ast::FunctionDecl * dereferenceOperator = nullptr; 52 53 ast::StructDecl * dtorStruct = nullptr; … … 147 148 148 149 const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final { 149 if ( inCache( node ) ) return nullptr; 150 auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth ); 151 auto&& type = get<Type>().accept1( node->type ); 152 auto&& init = get<Initializer>().accept1( node->init ); 153 auto&& attr = get<Attribute>().acceptL( node->attributes ); 154 if ( inCache( node ) ) { 155 if(node->name == "tmp") { 156 std::cerr << (void*)node << "(new) in cache " << (void*)this->node << "(old)" << std::endl; 157 } 158 return nullptr; 159 } 150 160 auto decl = new ObjectDecl( 151 161 node->name, 152 162 Type::StorageClasses( node->storage.val ), 153 163 LinkageSpec::Spec( node->linkage.val ), 154 get<Expression>().accept1( node->bitfieldWidth ),155 get<Type>().accept1( node->type ),156 get<Initializer>().accept1( node->init ),157 get<Attribute>().acceptL( node->attributes ),164 bfwd, 165 type, 166 init, 167 attr, 158 168 Type::FuncSpecifiers( node->funcSpec.val ) 159 169 ); 170 if(node->name == "tmp") { 171 std::cerr << (void*)node << "(new) created " << (void*)decl << "(old)" << std::endl; 172 } 160 173 return declWithTypePostamble( decl, node ); 161 174 } … … 709 722 auto expr = visitBaseExpr( node, 710 723 new MemberExpr( 711 inCache(node->member) ? 712 dynamic_cast<DeclarationWithType *>(this->node) : 713 get<DeclarationWithType>().accept1(node->member), 724 get<DeclarationWithType>().accept1(node->member), 714 725 get<Expression>().accept1(node->aggregate) 715 726 ) … … 720 731 721 732 const ast::Expr * visit( const ast::VariableExpr * node ) override final { 722 auto expr = visitBaseExpr( node, 723 new VariableExpr( 724 inCache(node->var) ? 725 dynamic_cast<DeclarationWithType *>(this->node) : 726 get<DeclarationWithType>().accept1(node->var) 727 ) 728 ); 733 auto expr = new VariableExpr(); 734 visitBaseExpr( node, expr ); 735 expr->var = get<DeclarationWithType>().accept1(node->var); 736 Type * type = expr->var->get_type()->clone(); 737 type->set_lvalue( true ); 738 expr->set_result( type ); 729 739 this->node = expr; 730 740 return nullptr; … … 819 829 new OffsetofExpr( 820 830 get<Type>().accept1(node->type), 821 inCache(node->member) ? 822 dynamic_cast<DeclarationWithType *>(this->node) : 823 get<DeclarationWithType>().accept1(node->member) 831 get<DeclarationWithType>().accept1(node->member) 824 832 ) 825 833 ); … … 1082 1090 1083 1091 const ast::Type * visit( const ast::BasicType * node ) override final { 1084 this->node = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind }; 1092 auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind }; 1093 // I believe this should always be a BasicType. 1094 if ( sizeType == node ) { 1095 Validate::SizeType = type; 1096 } 1097 this->node = type; 1085 1098 return nullptr; 1086 1099 } … … 1356 1369 return strict_dynamic_cast< ast::Decl * >( node ); 1357 1370 } 1371 1372 ConverterOldToNew() = default; 1373 ConverterOldToNew(const ConverterOldToNew &) = delete; 1374 ConverterOldToNew(ConverterOldToNew &&) = delete; 1358 1375 private: 1359 1376 /// conversion output 1360 ast::Node * node ;1377 ast::Node * node = nullptr; 1361 1378 /// cache of nodes that might be referenced by readonly<> for de-duplication 1362 std::unordered_map< BaseSyntaxNode *, ast::Node * > cache ;1379 std::unordered_map< BaseSyntaxNode *, ast::Node * > cache = {}; 1363 1380 1364 1381 // Local Utilities: 1382 1383 #define construct(T, key, ...) ({ \ 1384 void * data = ::operator new(sizeof(T)); \ 1385 cache.emplace( key, (T*)data ); \ 1386 new (data) T( __VA_ARGS__ ); \ 1387 }) 1365 1388 1366 1389 template<typename NewT, typename OldT> … … 1424 1447 1425 1448 virtual void visit( ObjectDecl * old ) override final { 1426 if ( inCache( old ) ) return; 1449 if( old->name == "tmp" ) { 1450 std::cerr << "building parameters for" << (void*)old << std::endl; 1451 } 1452 auto&& type = GET_ACCEPT_1(type, Type); 1453 auto&& init = GET_ACCEPT_1(init, Init); 1454 auto&& bfwd = GET_ACCEPT_1(bitfieldWidth, Expr); 1455 auto&& attr = GET_ACCEPT_V(attributes, Attribute); 1456 if( old->name == "tmp" ) { 1457 std::cerr << "checking cache for " << (void*)old << std::endl; 1458 } 1459 if ( inCache( old ) ) { 1460 if( old->name == "tmp" ) { 1461 std::cerr << (void*)old << "(old) in cache " << (void*)this->node << "(new)" << std::endl; 1462 } 1463 return; 1464 } 1427 1465 auto decl = new ast::ObjectDecl( 1428 1466 old->location, 1429 1467 old->name, 1430 GET_ACCEPT_1(type, Type),1431 GET_ACCEPT_1(init, Init),1468 type, 1469 init, 1432 1470 { old->get_storageClasses().val }, 1433 1471 { old->linkage.val }, 1434 GET_ACCEPT_1(bitfieldWidth, Expr),1435 GET_ACCEPT_V(attributes, Attribute),1472 bfwd, 1473 std::move(attr), 1436 1474 { old->get_funcSpec().val } 1437 1475 ); 1438 cache.emplace( old, decl ); 1476 cache.emplace(old, decl); 1477 if( old->name == "tmp" ) { 1478 std::cerr << (void*)old << "(old) added to cache with " << (void*)decl << "(new)" << std::endl; 1479 } 1480 assert(cache.find( old ) != cache.end()); 1439 1481 decl->scopeLevel = old->scopeLevel; 1440 1482 decl->mangleName = old->mangleName; … … 1444 1486 1445 1487 this->node = decl; 1488 1489 if( old->name == "tmp" ) { 1490 std::cerr << (void*)old << "(old) created " << (void*)this->node << "(new)" << std::endl; 1491 } 1446 1492 } 1447 1493 … … 2092 2138 new ast::MemberExpr( 2093 2139 old->location, 2094 inCache(old->member) ? 2095 dynamic_cast<ast::DeclWithType *>(this->node) : 2096 GET_ACCEPT_1(member, DeclWithType), 2140 GET_ACCEPT_1(member, DeclWithType), 2097 2141 GET_ACCEPT_1(aggregate, Expr) 2098 2142 ) … … 2101 2145 2102 2146 virtual void visit( VariableExpr * old ) override final { 2103 this->node = visitBaseExpr( old, 2104 new ast::VariableExpr( 2105 old->location, 2106 inCache(old->var) ? 2107 dynamic_cast<ast::DeclWithType *>(this->node) : 2108 GET_ACCEPT_1(var, DeclWithType) 2109 ) 2110 ); 2147 auto expr = new ast::VariableExpr( 2148 old->location 2149 ); 2150 2151 visitBaseExpr( old, 2152 expr 2153 ); 2154 2155 expr->var = GET_ACCEPT_1(var, DeclWithType); 2156 expr->result = expr->var->get_type(); 2157 add_qualifiers( expr->result, ast::CV::Lvalue ); 2158 this->node = expr; 2111 2159 } 2112 2160 … … 2234 2282 old->location, 2235 2283 GET_ACCEPT_1(type, Type), 2236 inCache(old->member) ? 2237 dynamic_cast<ast::DeclWithType *>(this->node) : 2238 GET_ACCEPT_1(member, DeclWithType) 2284 GET_ACCEPT_1(member, DeclWithType) 2239 2285 ) 2240 2286 ); … … 2472 2518 2473 2519 virtual void visit( BasicType * old ) override final { 2474 this->node = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) }; 2520 auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) }; 2521 // I believe this should always be a BasicType. 2522 if ( Validate::SizeType == old ) { 2523 sizeType = type; 2524 } 2525 this->node = type; 2475 2526 } 2476 2527 -
src/AST/Expr.cpp
rc6a1e8a r866545b 170 170 // --- VariableExpr 171 171 172 VariableExpr::VariableExpr( const CodeLocation & loc ) 173 : Expr( loc ), var( nullptr ) {} 174 172 175 VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v ) 173 176 : Expr( loc ), var( v ) { -
src/AST/Expr.hpp
rc6a1e8a r866545b 315 315 readonly<DeclWithType> var; 316 316 317 VariableExpr( const CodeLocation & loc ); 317 318 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 318 319 -
src/AST/Node.hpp
rc6a1e8a r866545b 18 18 #include <cassert> 19 19 #include <iosfwd> 20 #include <type_traits> // for remove_reference 20 21 21 22 #include "Common/ErrorObjects.h" // for SemanticErrorException … … 82 83 }; 83 84 84 // Mutate a node, non-member function to avoid static type85 // problems and be able to use auto return85 /// Mutate a node, non-member function to avoid static type 86 /// problems and be able to use auto return 86 87 template<typename node_t> 87 88 node_t * mutate( const node_t * node ) { … … 95 96 ); 96 97 return node->clone(); 98 } 99 100 /// Mutate a node field (only clones if not equal to existing value) 101 template<typename node_t, typename field_t> 102 const node_t * mutate_field( 103 const node_t * node, 104 typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field, 105 field_t&& val 106 ) { 107 if ( node->*field == val ) return node; 108 109 node_t * ret = mutate( node ); 110 ret->*field = std::forward< field_t >( val ); 111 return ret; 97 112 } 98 113 … … 191 206 /// wrapper for convenient access to strict_dynamic_cast 192 207 template<typename o_node_t> 193 const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); }208 const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); } 194 209 195 210 /// Returns a mutable version of the pointer in this node. -
src/AST/Pass.hpp
rc6a1e8a r866545b 201 201 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 202 202 203 public: 203 204 /// Logic to call the accept and mutate the parent if needed, delegates call to accept 204 205 template<typename node_t, typename parent_t, typename child_t> -
src/AST/module.mk
rc6a1e8a r866545b 16 16 17 17 SRC_AST = \ 18 AST/AssertAcyclic.cpp \ 18 19 AST/Attribute.cpp \ 19 20 AST/Convert.cpp \ -
src/InitTweak/FixInit.cc
rc6a1e8a r866545b 262 262 // unwrap implicit statement wrapper 263 263 Statement * dtor = input; 264 if ( ImplicitCtorDtorStmt * implicit = dynamic_cast< ImplicitCtorDtorStmt * >( input ) ) {265 // dtor = implicit->callStmt;266 // implicit->callStmt = nullptr;267 }268 264 assert( dtor ); 269 265 std::list< Expression * > matches; … … 291 287 // wraps the more complicated code. 292 288 static UniqueName dtorNamer( "__cleanup_dtor" ); 293 FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() ); 289 std::string name = dtorNamer.newName(); 290 FunctionDecl * dtorFunc = FunctionDecl::newFunction( name, SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() ); 294 291 stmtsToAdd.push_back( new DeclStmt( dtorFunc ) ); 295 292 … … 304 301 replacement = new CastExpr( replacement, base->clone() ); 305 302 } 306 DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } ); 303 size_t replaced = DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } ); 304 if(replaced == 0) { 305 objDecl->print(std::cerr); 306 std::cerr << "-----" << std::endl; 307 dtor->print(std::cerr); 308 std::cerr << "Failed to replace " << objDecl << std::endl; 309 abort(); 310 } 307 311 dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) ); 308 312 -
src/Makefile.in
rc6a1e8a r866545b 165 165 libdemangle_a_LIBADD = 166 166 am__dirstamp = $(am__leading_dot)dirstamp 167 am__objects_1 = AST/A ttribute.$(OBJEXT) AST/Convert.$(OBJEXT) \168 AST/ Decl.$(OBJEXT) AST/DeclReplacer.$(OBJEXT) \169 AST/ Expr.$(OBJEXT) AST/GenericSubstitution.$(OBJEXT) \170 AST/ Init.$(OBJEXT) AST/LinkageSpec.$(OBJEXT) \171 AST/ Node.$(OBJEXT) AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) \172 AST/ Stmt.$(OBJEXT) AST/SymbolTable.$(OBJEXT) \173 AST/ Type.$(OBJEXT) AST/TypeEnvironment.$(OBJEXT) \174 AST/Type Substitution.$(OBJEXT)167 am__objects_1 = AST/AssertAcyclic.$(OBJEXT) AST/Attribute.$(OBJEXT) \ 168 AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \ 169 AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \ 170 AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \ 171 AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \ 172 AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) AST/Stmt.$(OBJEXT) \ 173 AST/SymbolTable.$(OBJEXT) AST/Type.$(OBJEXT) \ 174 AST/TypeEnvironment.$(OBJEXT) AST/TypeSubstitution.$(OBJEXT) 175 175 am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \ 176 176 CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \ … … 577 577 @WITH_LIBTCMALLOC_TRUE@TCMALLOCFLAG = -DTCMALLOC 578 578 SRC_AST = \ 579 AST/AssertAcyclic.cpp \ 579 580 AST/Attribute.cpp \ 580 581 AST/Convert.cpp \ … … 744 745 @$(MKDIR_P) AST/$(DEPDIR) 745 746 @: > AST/$(DEPDIR)/$(am__dirstamp) 747 AST/AssertAcyclic.$(OBJEXT): AST/$(am__dirstamp) \ 748 AST/$(DEPDIR)/$(am__dirstamp) 746 749 AST/Attribute.$(OBJEXT): AST/$(am__dirstamp) \ 747 750 AST/$(DEPDIR)/$(am__dirstamp) … … 1193 1196 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MakeLibCfa.Po@am__quote@ 1194 1197 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ 1198 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/AssertAcyclic.Po@am__quote@ 1195 1199 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Attribute.Po@am__quote@ 1196 1200 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Convert.Po@am__quote@ -
src/ResolvExpr/CurrentObject.cc
rc6a1e8a r866545b 20 20 #include <string> // for string, operator<<, allocator 21 21 22 #include "AST/Expr.hpp" // for InitAlternative 23 #include "AST/Init.hpp" // for Designation 24 #include "AST/Node.hpp" // for readonly 22 25 #include "Common/Indenter.h" // for Indenter, operator<< 23 26 #include "Common/SemanticError.h" // for SemanticError … … 579 582 } // namespace ResolvExpr 580 583 584 namespace ast { 585 586 /// Iterates members of a type by initializer 587 class MemberIterator { 588 public: 589 virtual ~MemberIterator() {} 590 591 /// retrieve the list of possible (Type,Designation) pairs for the current position in the 592 /// current object 593 virtual std::vector< InitAlternative > operator* () const = 0; 594 595 protected: 596 /// helper for operator*; aggregates must add designator to each init alternative, but 597 /// adding designators in operator* creates duplicates 598 virtual std::vector< InitAlternative > first() const = 0; 599 }; 600 601 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry 602 class SimpleIterator final : public MemberIterator { 603 CodeLocation location; 604 readonly< Type > type = nullptr; 605 public: 606 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} 607 608 std::vector< InitAlternative > operator* () const override { return first(); } 609 610 protected: 611 std::vector< InitAlternative > first() const override { 612 if ( type ) return { InitAlternative{ type, new Designation{ location } } }; 613 return {}; 614 } 615 }; 616 617 CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() { 618 objStack.emplace_back( new SimpleIterator{ loc, type } ); 619 } 620 621 std::vector< InitAlternative > CurrentObject::getOptions() { 622 PRINT( std::cerr << "____getting current options" << std::endl; ) 623 assertf( ! objStack.empty(), "objstack empty in getOptions" ); 624 return **objStack.back(); 625 } 626 } 627 581 628 // Local Variables: // 582 629 // tab-width: 4 // -
src/ResolvExpr/CurrentObject.h
rc6a1e8a r866545b 17 17 18 18 #include <list> // for list 19 #include <memory> // for unique_ptr 19 20 #include <stack> // for stack 21 #include <vector> 22 23 #include "Common/CodeLocation.h" 20 24 21 25 class Designation; … … 52 56 } // namespace ResolvExpr 53 57 58 namespace ast { 59 // AST class types 60 class Designation; 61 class InitAlternative; 62 class Type; 63 64 // forward declaration of internal detail 65 class MemberIterator; 66 67 /// Builds initializer lists in resolution 68 class CurrentObject final { 69 std::vector< std::shared_ptr<MemberIterator> > objStack; 70 71 public: 72 CurrentObject() = default; 73 CurrentObject( const CodeLocation & loc, const Type * type ); 74 75 /// produces a list of alternatives (Type *, Designation *) for the current sub-object's 76 /// initializer. 77 std::vector< InitAlternative > getOptions(); 78 }; 79 } // namespace ast 80 54 81 // Local Variables: // 55 82 // tab-width: 4 // -
src/ResolvExpr/ResolveAssertions.cc
rc6a1e8a r866545b 342 342 343 343 /// Limit to depth of recursion of assertion satisfaction 344 static const int recursionLimit = /* 10 */ 4; 344 static const int recursionLimit = 4; 345 /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of 346 static const int deferLimit = 10; 345 347 346 348 void resolveAssertions( Alternative& alt, const SymTab::Indexer& indexer, AltList& out, std::list<std::string>& errors ) { … … 369 371 ss << tabs << "Unsatisfiable alternative:\n"; 370 372 resn.alt.print( ss, ++tabs ); 371 ss << --tabs<< "Could not satisfy assertion:\n";372 assn.decl->print( ss, ++tabs );373 ss << (tabs-1) << "Could not satisfy assertion:\n"; 374 assn.decl->print( ss, tabs ); 373 375 374 376 errors.emplace_back( ss.str() ); … … 384 386 new_resns.emplace_back( std::move(resn), IterateState ); 385 387 } 388 } else if ( resn.deferred.size() > deferLimit ) { 389 // too many deferred assertions to attempt mutual compatibility 390 Indenter tabs{ 3 }; 391 std::ostringstream ss; 392 ss << tabs << "Unsatisfiable alternative:\n"; 393 resn.alt.print( ss, ++tabs ); 394 ss << (tabs-1) << "Too many non-unique satisfying assignments for " 395 "assertions:\n"; 396 for ( const auto& d : resn.deferred ) { 397 d.decl->print( ss, tabs ); 398 } 399 400 errors.emplace_back( ss.str() ); 401 goto nextResn; 386 402 } else { 387 403 // resolve deferred assertions by mutual compatibility … … 395 411 ss << tabs << "Unsatisfiable alternative:\n"; 396 412 resn.alt.print( ss, ++tabs ); 397 ss << --tabs << "No mutually-compatible satisfaction for assertions:\n"; 398 ++tabs; 413 ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n"; 399 414 for ( const auto& d : resn.deferred ) { 400 415 d.decl->print( ss, tabs ); -
src/ResolvExpr/Resolver.cc
rc6a1e8a r866545b 165 165 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 166 166 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 167 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {167 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 168 168 // cast is to the same type as its argument, so it's unnecessary -- remove it 169 169 expr = castExpr->arg; … … 965 965 } 966 966 967 /// always-accept candidate filter 968 bool anyCandidate( const Candidate & ) { return true; } 969 967 970 /// Calls the CandidateFinder and finds the single best candidate 968 971 CandidateRef findUnfinishedKindExpression( 969 972 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 970 std::function<bool(const Candidate &)> pred , ResolvMode mode = {}973 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {} 971 974 ) { 972 975 if ( ! untyped ) return nullptr; … … 1056 1059 ) { 1057 1060 // generated cast is the same type as its argument, remove it after keeping env 1058 ast::ptr<ast::Expr> arg = castExpr->arg; 1059 arg.get_and_mutate()->env = castExpr->env; 1060 return arg; 1061 return ast::mutate_field( 1062 castExpr->arg.get(), &ast::Expr::env, castExpr->env ); 1061 1063 } 1062 1064 return castExpr; … … 1068 1070 } 1069 1071 }; 1072 1073 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 1074 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) { 1075 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 1076 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) { 1077 // cast is to the same type as its argument, remove it 1078 ast::ptr< ast::TypeSubstitution > env = castExpr->env; 1079 expr.set_and_mutate( castExpr->arg )->env = env; 1080 } 1081 } 1082 } 1070 1083 1071 1084 /// Establish post-resolver invariants for expressions … … 1082 1095 StripCasts_new::strip( expr ); 1083 1096 } 1084 1097 1098 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 1099 /// context. 1100 ast::ptr< ast::Expr > resolveInVoidContext( 1101 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1102 ) { 1103 assertf( expr, "expected a non-null expression" ); 1104 1105 // set up and resolve expression cast to void 1106 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1107 CandidateRef choice = findUnfinishedKindExpression( 1108 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1109 1110 // a cast expression has either 0 or 1 interpretations (by language rules); 1111 // if 0, an exception has already been thrown, and this code will not run 1112 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1113 env = std::move( choice->env ); 1114 1115 return castExpr->arg; 1116 } 1117 1118 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1119 /// context. 1120 ast::ptr< ast::Expr > findVoidExpression( 1121 const ast::Expr * untyped, const ast::SymbolTable & symtab 1122 ) { 1123 resetTyVarRenaming(); 1124 ast::TypeEnvironment env; 1125 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env ); 1126 finishExpr( newExpr, env, untyped->env ); 1127 return newExpr; 1128 } 1129 1085 1130 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 1086 1131 /// lowest cost, returning the resolved version 1087 1132 ast::ptr< ast::Expr > findKindExpression( 1088 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 1089 std::function<bool(const Candidate &)> pred, ResolvMode mode = {} 1133 const ast::Expr * untyped, const ast::SymbolTable & symtab, 1134 std::function<bool(const Candidate &)> pred = anyCandidate, 1135 const std::string & kind = "", ResolvMode mode = {} 1090 1136 ) { 1091 1137 if ( ! untyped ) return {}; … … 1094 1140 finishExpr( choice->expr, choice->env, untyped->env ); 1095 1141 return std::move( choice->expr ); 1142 } 1143 1144 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1145 /// given type. 1146 ast::ptr< ast::Expr > findSingleExpression( 1147 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1148 ) { 1149 assert( untyped && type ); 1150 const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type }; 1151 ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab ); 1152 removeExtraneousCast( newExpr, symtab ); 1153 return newExpr; 1096 1154 } 1097 1155 … … 1115 1173 const ast::Expr * untyped, const ast::SymbolTable & symtab 1116 1174 ) { 1117 return findKindExpression( untyped, symtab, "condition", hasIntegralType);1175 return findKindExpression( untyped, symtab, hasIntegralType, "condition" ); 1118 1176 } 1119 1177 } … … 1125 1183 1126 1184 ast::ptr< ast::Type > functionReturn = nullptr; 1127 // ast::CurrentObject currentObject = nullptr;1185 ast::CurrentObject currentObject; 1128 1186 bool inEnumDecl = false; 1129 1187 … … 1141 1199 void previsit( const ast::PointerType * ); 1142 1200 1143 voidprevisit( const ast::ExprStmt * );1144 voidprevisit( const ast::AsmExpr * );1145 voidprevisit( const ast::AsmStmt * );1146 voidprevisit( const ast::IfStmt * );1147 voidprevisit( const ast::WhileStmt * );1148 voidprevisit( const ast::ForStmt * );1149 voidprevisit( const ast::SwitchStmt * );1150 voidprevisit( const ast::CaseStmt * );1151 voidprevisit( const ast::BranchStmt * );1152 voidprevisit( const ast::ReturnStmt * );1153 voidprevisit( const ast::ThrowStmt * );1154 voidprevisit( const ast::CatchStmt * );1201 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 1202 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 1203 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1204 const ast::IfStmt * previsit( const ast::IfStmt * ); 1205 const ast::WhileStmt * previsit( const ast::WhileStmt * ); 1206 const ast::ForStmt * previsit( const ast::ForStmt * ); 1207 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1208 const ast::CaseStmt * previsit( const ast::CaseStmt * ); 1209 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1210 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 1211 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1212 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1155 1213 void previsit( const ast::WaitForStmt * ); 1156 1214 … … 1196 1254 1197 1255 void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) { 1198 #warning unimplemented; Resolver port in progress 1199 (void)objectDecl; 1200 assert(false); 1256 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 1257 // class-variable `initContext` is changed multiple times because the LHS is analyzed 1258 // twice. The second analysis changes `initContext` because a function type can contain 1259 // object declarations in the return and parameter types. Therefore each value of 1260 // `initContext` is retained so the type on the first analysis is preserved and used for 1261 // selecting the RHS. 1262 GuardValue( currentObject ); 1263 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() }; 1264 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) { 1265 // enumerator initializers should not use the enum type to initialize, since the 1266 // enum type is still incomplete at this point. Use `int` instead. 1267 currentObject = ast::CurrentObject{ 1268 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } }; 1269 } 1201 1270 } 1202 1271 … … 1210 1279 const ast::StaticAssertDecl * assertDecl 1211 1280 ) { 1212 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab ); 1213 if ( cond == assertDecl->cond ) return assertDecl; 1281 return ast::mutate_field( 1282 assertDecl, &ast::StaticAssertDecl::cond, 1283 findIntegralExpression( assertDecl->cond, symtab ) ); 1284 } 1285 1286 template< typename PtrType > 1287 void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) { 1288 #warning unimplemented; needs support for new Validate::SizeType global 1289 (void)type; (void)symtab; 1290 assert( false ); 1291 } 1292 1293 void Resolver_new::previsit( const ast::ArrayType * at ) { 1294 handlePtrType( at, symtab ); 1295 } 1296 1297 void Resolver_new::previsit( const ast::PointerType * pt ) { 1298 handlePtrType( pt, symtab ); 1299 } 1300 1301 const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1302 visit_children = false; 1303 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" ); 1214 1304 1215 ast::StaticAssertDecl * ret = mutate( assertDecl ); 1216 ret->cond = cond; 1217 return ret; 1218 } 1219 1220 void Resolver_new::previsit( const ast::ArrayType * at ) { 1221 #warning unimplemented; Resolver port in progress 1222 (void)at; 1223 assert(false); 1224 } 1225 1226 void Resolver_new::previsit( const ast::PointerType * pt ) { 1227 #warning unimplemented; Resolver port in progress 1228 (void)pt; 1229 assert(false); 1230 } 1231 1232 void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1233 #warning unimplemented; Resolver port in progress 1234 (void)exprStmt; 1235 assert(false); 1236 } 1237 1238 void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1239 #warning unimplemented; Resolver port in progress 1240 (void)asmExpr; 1241 assert(false); 1242 } 1243 1244 void Resolver_new::previsit( const ast::AsmStmt * asmStmt ) { 1245 #warning unimplemented; Resolver port in progress 1246 (void)asmStmt; 1247 assert(false); 1248 } 1249 1250 void Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1251 #warning unimplemented; Resolver port in progress 1252 (void)ifStmt; 1253 assert(false); 1254 } 1255 1256 void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1257 #warning unimplemented; Resolver port in progress 1258 (void)whileStmt; 1259 assert(false); 1260 } 1261 1262 void Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1263 #warning unimplemented; Resolver port in progress 1264 (void)forStmt; 1265 assert(false); 1266 } 1267 1268 void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1269 #warning unimplemented; Resolver port in progress 1270 (void)switchStmt; 1271 assert(false); 1272 } 1273 1274 void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1275 #warning unimplemented; Resolver port in progress 1276 (void)caseStmt; 1277 assert(false); 1278 } 1279 1280 void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1281 #warning unimplemented; Resolver port in progress 1282 (void)branchStmt; 1283 assert(false); 1284 } 1285 1286 void Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) { 1287 #warning unimplemented; Resolver port in progress 1288 (void)returnStmt; 1289 assert(false); 1290 } 1291 1292 void Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) { 1293 #warning unimplemented; Resolver port in progress 1294 (void)throwStmt; 1295 assert(false); 1296 } 1297 1298 void Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1299 #warning unimplemented; Resolver port in progress 1300 (void)catchStmt; 1301 assert(false); 1305 return ast::mutate_field( 1306 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) ); 1307 } 1308 1309 const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1310 visit_children = false; 1311 1312 asmExpr = ast::mutate_field( 1313 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) ); 1314 1315 if ( asmExpr->inout ) { 1316 asmExpr = ast::mutate_field( 1317 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) ); 1318 } 1319 1320 return asmExpr; 1321 } 1322 1323 const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) { 1324 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input ); 1325 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output ); 1326 visit_children = false; 1327 return asmStmt; 1328 } 1329 1330 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1331 return ast::mutate_field( 1332 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) ); 1333 } 1334 1335 const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1336 return ast::mutate_field( 1337 whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) ); 1338 } 1339 1340 const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1341 if ( forStmt->cond ) { 1342 forStmt = ast::mutate_field( 1343 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) ); 1344 } 1345 1346 if ( forStmt->inc ) { 1347 forStmt = ast::mutate_field( 1348 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) ); 1349 } 1350 1351 return forStmt; 1352 } 1353 1354 const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1355 GuardValue( currentObject ); 1356 switchStmt = ast::mutate_field( 1357 switchStmt, &ast::SwitchStmt::cond, 1358 findIntegralExpression( switchStmt->cond, symtab ) ); 1359 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 1360 return switchStmt; 1361 } 1362 1363 const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1364 if ( caseStmt->cond ) { 1365 std::vector< ast::InitAlternative > initAlts = currentObject.getOptions(); 1366 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral " 1367 "expression." ); 1368 1369 const ast::Expr * untyped = 1370 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1371 ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab ); 1372 1373 // case condition cannot have a cast in C, so it must be removed here, regardless of 1374 // whether it would perform a conversion. 1375 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) { 1376 ast::ptr< ast::TypeSubstitution > env = castExpr->env; 1377 newExpr.set_and_mutate( castExpr->arg )->env = env; 1378 } 1379 1380 caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr ); 1381 } 1382 return caseStmt; 1383 } 1384 1385 const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1386 visit_children = false; 1387 // must resolve the argument of a computed goto 1388 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1389 // computed goto argument is void* 1390 branchStmt = ast::mutate_field( 1391 branchStmt, &ast::BranchStmt::computedTarget, 1392 findSingleExpression( 1393 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1394 symtab ) ); 1395 } 1396 return branchStmt; 1397 } 1398 1399 const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) { 1400 visit_children = false; 1401 if ( returnStmt->expr ) { 1402 returnStmt = ast::mutate_field( 1403 returnStmt, &ast::ReturnStmt::expr, 1404 findSingleExpression( returnStmt->expr, functionReturn, symtab ) ); 1405 } 1406 return returnStmt; 1407 } 1408 1409 const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) { 1410 visit_children = false; 1411 if ( throwStmt->expr ) { 1412 const ast::StructDecl * exceptionDecl = 1413 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 1414 assert( exceptionDecl ); 1415 ast::ptr< ast::Type > exceptType = 1416 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } }; 1417 throwStmt = ast::mutate_field( 1418 throwStmt, &ast::ThrowStmt::expr, 1419 findSingleExpression( throwStmt->expr, exceptType, symtab ) ); 1420 } 1421 return throwStmt; 1422 } 1423 1424 const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1425 if ( catchStmt->cond ) { 1426 ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool }; 1427 catchStmt = ast::mutate_field( 1428 catchStmt, &ast::CatchStmt::cond, 1429 findSingleExpression( catchStmt->cond, boolType, symtab ) ); 1430 } 1431 return catchStmt; 1302 1432 } 1303 1433 -
src/SynTree/DeclReplacer.h
rc6a1e8a r866545b 33 33 34 34 size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false); 35 35 36 template<typename T> 36 voidreplace( T *& node, const ExprMap & exprMap, bool debug = false ) {37 if ( ! node ) return ;37 size_t replace( T *& node, const ExprMap & exprMap, bool debug = false ) { 38 if ( ! node ) return 0ul; 38 39 BaseSyntaxNode * arg = node; 39 replace( arg, exprMap, debug );40 size_t replaced = replace( arg, exprMap, debug ); 40 41 node = dynamic_cast<T *>( arg ); 41 42 assertf( node, "DeclReplacer fundamentally changed the type of its argument." ); 43 return replaced; 42 44 } 43 45 } -
src/SynTree/Expression.cc
rc6a1e8a r866545b 102 102 SemanticError( this, "Constant expression of non-integral type " ); 103 103 } 104 105 VariableExpr::VariableExpr() : Expression(), var( nullptr ) {} 104 106 105 107 VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) { -
src/SynTree/Expression.h
rc6a1e8a r866545b 299 299 DeclarationWithType * var; 300 300 301 VariableExpr(); 301 302 VariableExpr( DeclarationWithType * var ); 302 303 VariableExpr( const VariableExpr & other );
Note: See TracChangeset
for help on using the changeset viewer.