- Timestamp:
- Feb 26, 2024, 3:53:42 AM (19 months ago)
- Branches:
- master
- Children:
- 3f9a8d0
- Parents:
- 0522ebe (diff), 022bce0 (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:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Attribute.hpp
r0522ebe ra4da45e 9 9 // Author : Aaron B. Moss 10 10 // Created On : Fri May 10 10:30:00 2019 11 // Last Modified By : Aaron B. Moss11 // Last Modified By : Peter A. Buhr 12 12 // Created On : Fri May 10 10:30:00 2019 13 // Update Count : 113 // Update Count : 2 14 14 // 15 15 … … 34 34 35 35 Attribute( const std::string & name = "", std::vector<ptr<Expr>> && params = {}) 36 : name( name ), params( params ) {}36 : name( name ), params( params ) {} 37 37 virtual ~Attribute() = default; 38 38 -
src/GenPoly/Box.cpp
r0522ebe ra4da45e 366 366 367 367 /// Passes extra layout arguments for sized polymorphic type parameters. 368 ast::vector<ast::Expr>::iteratorpassTypeVars(368 void passTypeVars( 369 369 ast::ApplicationExpr * expr, 370 ast::vector<ast::Expr> & extraArgs, 370 371 ast::FunctionType const * funcType ); 371 372 /// Wraps a function application with a new temporary for the … … 387 388 /// parameter list. arg should point into expr's argument list. 388 389 void boxParams( 389 ast::ApplicationExpr const* expr,390 ast:: vector<ast::Expr>::iterator arg,390 ast::ApplicationExpr * expr, 391 ast::Type const * polyRetType, 391 392 ast::FunctionType const * function, 392 393 const TypeVarMap & typeVars ); … … 395 396 void addInferredParams( 396 397 ast::ApplicationExpr * expr, 397 ast::vector<ast::Expr> ::iterator arg,398 ast::vector<ast::Expr> & extraArgs, 398 399 ast::FunctionType const * functionType, 399 400 const TypeVarMap & typeVars ); … … 636 637 ast::Expr const * ret = expr; 637 638 638 // TODO: This entire section should probably be refactored to do less639 // pushing to the front/middle of a vector.640 ptrdiff_t initArgCount = mutExpr->args.size();641 642 639 TypeVarMap exprTypeVars; 643 640 makeTypeVarMap( function, exprTypeVars ); … … 662 659 } 663 660 664 assert( typeSubs ); 665 ast::vector<ast::Expr>::iterator argIt = 666 passTypeVars( mutExpr, function ); 667 addInferredParams( mutExpr, argIt, function, exprTypeVars ); 668 669 argIt = mutExpr->args.begin(); 670 std::advance( argIt, ( mutExpr->args.size() - initArgCount ) ); 671 672 boxParams( mutExpr, argIt, function, exprTypeVars ); 661 ast::vector<ast::Expr> prependArgs; 662 passTypeVars( mutExpr, prependArgs, function ); 663 addInferredParams( mutExpr, prependArgs, function, exprTypeVars ); 664 665 boxParams( mutExpr, dynRetType, function, exprTypeVars ); 666 spliceBegin( mutExpr->args, prependArgs ); 673 667 passAdapters( mutExpr, function, exprTypeVars ); 674 668 … … 766 760 } 767 761 768 ast::vector<ast::Expr>::iteratorCallAdapter::passTypeVars(762 void CallAdapter::passTypeVars( 769 763 ast::ApplicationExpr * expr, 764 ast::vector<ast::Expr> & extraArgs, 770 765 ast::FunctionType const * function ) { 771 766 assert( typeSubs ); 772 ast::vector<ast::Expr>::iterator arg = expr->args.begin();773 767 // Pass size/align for type variables. 774 768 for ( ast::ptr<ast::TypeInstType> const & typeVar : function->forall ) { … … 780 774 toString( typeSubs ).c_str(), typeVar->typeString().c_str() ); 781 775 } 782 arg = expr->args.insert( arg,776 extraArgs.emplace_back( 783 777 new ast::SizeofExpr( expr->location, ast::deepCopy( concrete ) ) ); 784 arg++; 785 arg = expr->args.insert( arg, 778 extraArgs.emplace_back( 786 779 new ast::AlignofExpr( expr->location, ast::deepCopy( concrete ) ) ); 787 arg++; 788 } 789 return arg; 780 } 790 781 } 791 782 … … 913 904 914 905 void CallAdapter::boxParams( 915 ast::ApplicationExpr const* expr,916 ast:: vector<ast::Expr>::iterator arg,906 ast::ApplicationExpr * expr, 907 ast::Type const * polyRetType, 917 908 ast::FunctionType const * function, 918 909 const TypeVarMap & typeVars ) { 910 // Start at the beginning, but the return argument may have been added. 911 auto arg = expr->args.begin(); 912 if ( polyRetType ) ++arg; 913 919 914 for ( auto param : function->params ) { 920 915 assertf( arg != expr->args.end(), … … 928 923 void CallAdapter::addInferredParams( 929 924 ast::ApplicationExpr * expr, 930 ast::vector<ast::Expr> ::iterator arg,925 ast::vector<ast::Expr> & extraArgs, 931 926 ast::FunctionType const * functionType, 932 927 TypeVarMap const & typeVars ) { 933 ast::vector<ast::Expr>::iterator cur = arg;934 928 for ( auto assertion : functionType->assertions ) { 935 929 auto inferParam = expr->inferred.inferParams().find( … … 940 934 ast::ptr<ast::Expr> newExpr = ast::deepCopy( inferParam->second.expr ); 941 935 boxParam( newExpr, assertion->result, typeVars ); 942 cur = expr->args.insert( cur, newExpr.release() ); 943 ++cur; 936 extraArgs.emplace_back( newExpr.release() ); 944 937 } 945 938 } … … 1116 1109 ); 1117 1110 1118 for ( auto group : group_iterate( realType->assertions, 1119 adapterType->assertions, adaptee->assertions ) ) { 1120 auto assertArg = std::get<0>( group ); 1121 auto assertParam = std::get<1>( group ); 1122 auto assertReal = std::get<2>( group ); 1111 for ( auto const & [assertArg, assertParam, assertReal] : group_iterate( 1112 realType->assertions, adapterType->assertions, adaptee->assertions ) ) { 1123 1113 adapteeApp->args.push_back( makeAdapterArg( 1124 1114 assertParam->var, assertArg->var->get_type(), … … 1977 1967 bool hasDynamicLayout = false; 1978 1968 1979 for ( auto pair : group_iterate( baseParams, typeParams ) ) { 1980 auto baseParam = std::get<0>( pair ); 1981 auto typeParam = std::get<1>( pair ); 1969 for ( auto const & [baseParam, typeParam] : group_iterate( 1970 baseParams, typeParams ) ) { 1982 1971 if ( !baseParam->isComplete() ) continue; 1983 1972 ast::TypeExpr const * typeExpr = typeParam.as<ast::TypeExpr>(); -
src/InitTweak/FixInit.cpp
r0522ebe ra4da45e 1134 1134 ast::Expr * thisExpr = new ast::CastExpr(funcDecl->location, new ast::VariableExpr(funcDecl->location, thisParam ), thisParam->get_type()->stripReferences()); 1135 1135 ast::Expr * memberDest = new ast::MemberExpr(funcDecl->location, field, thisExpr ); 1136 ast::ptr<ast::Stmt>callStmt = SymTab::genImplicitCall( srcParam, memberDest, loc, function->name, field, static_cast<SymTab::LoopDirection>(isCtor) );1136 const ast::Stmt * callStmt = SymTab::genImplicitCall( srcParam, memberDest, loc, function->name, field, static_cast<SymTab::LoopDirection>(isCtor) ); 1137 1137 1138 1138 if ( callStmt ) { -
src/InitTweak/GenInit.cc
r0522ebe ra4da45e 239 239 if ( varExpr->var == retVal ) return stmt; 240 240 } 241 ast::ptr<ast::Stmt>ctorStmt = genCtorDtor(241 const ast::Stmt * ctorStmt = genCtorDtor( 242 242 retVal->location, "?{}", retVal, stmt->expr ); 243 243 assertf( ctorStmt, … … 327 327 void ManagedTypes::endScope() { managedTypes.endScope(); } 328 328 329 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {329 const ast::Stmt * genCtorDtor( const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg ) { 330 330 assertf(objDecl, "genCtorDtor passed null objDecl"); 331 331 InitExpander srcParam(arg); -
src/InitTweak/GenInit.h
r0522ebe ra4da45e 33 33 34 34 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument 35 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);35 const ast::Stmt * genCtorDtor( const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr ); 36 36 37 37 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer -
src/Parser/DeclarationNode.cc
r0522ebe ra4da45e 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Dec 14 19:05:17 202313 // Update Count : 1 40712 // Last Modified On : Fri Feb 23 18:25:57 2024 13 // Update Count : 1533 14 14 // 15 15 … … 159 159 160 160 if ( ! attributes.empty() ) { 161 os << string( indent + 2, ' ' ) << "with attributes 161 os << string( indent + 2, ' ' ) << "with attributes" << endl; 162 162 for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) { 163 os << string( indent + 4, ' ' ) << attr->name.c_str() << endl; 163 os << string( indent + 4, ' ' ); 164 ast::print( os, attr, indent + 2 ); 164 165 } // for 165 166 } // if … … 537 538 } // DeclarationNode::checkSpecifiers 538 539 539 DeclarationNode * DeclarationNode::copySpecifiers( DeclarationNode * q ) {540 DeclarationNode * DeclarationNode::copySpecifiers( DeclarationNode * q, bool copyattr ) { 540 541 funcSpecs |= q->funcSpecs; 541 542 storageClasses |= q->storageClasses; 542 543 543 std::vector<ast::ptr<ast::Attribute>> tmp; 544 tmp.reserve( q->attributes.size() ); 545 for ( auto const & attr : q->attributes ) { 546 tmp.emplace_back( ast::shallowCopy( attr.get() ) ); 547 } 548 spliceBegin( attributes, tmp ); 544 if ( copyattr ) { 545 std::vector<ast::ptr<ast::Attribute>> tmp; 546 tmp.reserve( q->attributes.size() ); 547 for ( auto const & attr : q->attributes ) { 548 tmp.emplace_back( ast::shallowCopy( attr.get() ) ); 549 } // for 550 spliceBegin( attributes, tmp ); 551 } // if 549 552 550 553 return this; … … 681 684 } 682 685 683 DeclarationNode * DeclarationNode::addType( DeclarationNode * o ) {686 DeclarationNode * DeclarationNode::addType( DeclarationNode * o, bool copyattr ) { 684 687 if ( o ) { 685 688 checkSpecifiers( o ); 686 copySpecifiers( o );689 copySpecifiers( o, copyattr ); 687 690 if ( o->type ) { 688 691 if ( ! type ) { 689 692 if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) { 693 // Hide type information aggregate instances. 690 694 type = new TypeData( TypeData::AggregateInst ); 691 type->aggInst.aggregate = o->type; 695 type->aggInst.aggregate = o->type; // change ownership 696 type->aggInst.aggregate->aggregate.attributes.swap( o->attributes ); // change ownership 692 697 if ( o->type->kind == TypeData::Aggregate ) { 693 698 type->aggInst.hoistType = o->type->aggregate.body; … … 700 705 type = o->type; 701 706 } // if 702 o->type = nullptr; 707 o->type = nullptr; // change ownership 703 708 } else { 704 709 addTypeToType( o->type, type ); … … 953 958 } 954 959 955 DeclarationNode * DeclarationNode::cloneBaseType( DeclarationNode * o ) {960 DeclarationNode * DeclarationNode::cloneBaseType( DeclarationNode * o, bool copyattr ) { 956 961 if ( ! o ) return nullptr; 957 962 958 o->copySpecifiers( this );963 o->copySpecifiers( this, copyattr ); 959 964 if ( type ) { 960 965 TypeData * srcType = type; … … 999 1004 DeclarationNode * newnode = new DeclarationNode; 1000 1005 newnode->type = ret; 1006 if ( ret->kind == TypeData::Aggregate ) { 1007 newnode->attributes.swap( ret->aggregate.attributes ); 1008 } // if 1001 1009 return newnode; 1002 1010 } // if … … 1110 1118 if ( extr->type->kind == TypeData::Aggregate ) { 1111 1119 // typedef struct { int A } B is the only case? 1112 extracted_named = ! extr->type->aggregate.anon;1120 extracted_named = ! extr->type->aggregate.anon; 1113 1121 } else if ( extr->type->kind == TypeData::Enum ) { 1114 1122 // typedef enum { A } B is the only case? 1115 extracted_named = ! extr->type->enumeration.anon;1123 extracted_named = ! extr->type->enumeration.anon; 1116 1124 } else { 1117 1125 extracted_named = true; -
src/Parser/DeclarationNode.h
r0522ebe ra4da45e 9 9 // Author : Andrew Beach 10 10 // Created On : Wed Apr 5 11:38:00 2023 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Apr 5 11:55:00 202313 // Update Count : 011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 09:24:12 2024 13 // Update Count : 4 14 14 // 15 15 … … 83 83 void checkQualifiers( const TypeData *, const TypeData * ); 84 84 void checkSpecifiers( DeclarationNode * ); 85 DeclarationNode * copySpecifiers( DeclarationNode * );86 DeclarationNode * addType( DeclarationNode * );85 DeclarationNode * copySpecifiers( DeclarationNode *, bool = true ); 86 DeclarationNode * addType( DeclarationNode *, bool = true ); 87 87 DeclarationNode * addTypedef(); 88 88 DeclarationNode * addEnumBase( DeclarationNode * ); … … 106 106 107 107 DeclarationNode * cloneType( std::string * newName ); 108 DeclarationNode * cloneBaseType( DeclarationNode * newdecl );108 DeclarationNode * cloneBaseType( DeclarationNode * newdecl, bool = true ); 109 109 110 110 DeclarationNode * appendList( DeclarationNode * node ) { -
src/Parser/TypeData.cc
r0522ebe ra4da45e 10 10 // Created On : Sat May 16 15:12:51 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Dec 14 18:59:12 202313 // Update Count : 68412 // Last Modified On : Fri Feb 23 08:58:30 2024 13 // Update Count : 734 14 14 // 15 15 … … 20 20 21 21 #include "AST/Decl.hpp" // for AggregateDecl, ObjectDecl, TypeDe... 22 #include "AST/Attribute.hpp" // for Attribute 22 23 #include "AST/Init.hpp" // for SingleInit, ListInit 23 24 #include "AST/Print.hpp" // for print 24 25 #include "Common/SemanticError.h" // for SemanticError 25 26 #include "Common/utility.h" // for splice, spliceBegin 27 #include "Common/Iterate.hpp" // for reverseIterate 26 28 #include "Parser/ExpressionNode.h" // for ExpressionNode 27 29 #include "Parser/StatementNode.h" // for StatementNode … … 199 201 newtype->aggregate.kind = aggregate.kind; 200 202 newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr; 203 newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr; 201 204 newtype->aggregate.params = maybeCopy( aggregate.params ); 202 205 newtype->aggregate.actuals = maybeCopy( aggregate.actuals ); 203 206 newtype->aggregate.fields = maybeCopy( aggregate.fields ); 207 newtype->aggregate.attributes = aggregate.attributes; 204 208 newtype->aggregate.body = aggregate.body; 205 209 newtype->aggregate.anon = aggregate.anon; 206 210 newtype->aggregate.tagged = aggregate.tagged; 207 newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;208 211 break; 209 212 case AggregateInst: … … 336 339 } // if 337 340 if ( aggregate.body ) { 338 os << string( indent + 2, ' ' ) << " with body" << endl; 341 os << string( indent + 2, ' ' ) << "with body" << endl; 342 } // if 343 if ( ! aggregate.attributes.empty() ) { 344 os << string( indent + 2, ' ' ) << "with attributes" << endl; 345 for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( aggregate.attributes ) ) { 346 os << string( indent + 4, ' ' ); 347 ast::print( os, attr, indent + 2 ); 348 } // for 339 349 } // if 340 350 break; … … 358 368 } // if 359 369 if ( enumeration.body ) { 360 os << string( indent + 2, ' ' ) << " 370 os << string( indent + 2, ' ' ) << "with body" << endl; 361 371 } // if 362 372 if ( base ) { … … 1088 1098 1089 1099 ast::BaseInstType * buildComAggInst( 1090 const TypeData * t ype,1100 const TypeData * td, 1091 1101 std::vector<ast::ptr<ast::Attribute>> && attributes, 1092 1102 ast::Linkage::Spec linkage ) { 1093 switch ( t ype->kind ) {1103 switch ( td->kind ) { 1094 1104 case TypeData::Enum: 1095 if ( t ype->enumeration.body ) {1105 if ( td->enumeration.body ) { 1096 1106 ast::EnumDecl * typedecl = 1097 buildEnum( t ype, std::move( attributes ), linkage );1107 buildEnum( td, std::move( attributes ), linkage ); 1098 1108 return new ast::EnumInstType( 1099 1109 typedecl, 1100 buildQualifiers( t ype)1110 buildQualifiers( td ) 1101 1111 ); 1102 1112 } else { 1103 1113 return new ast::EnumInstType( 1104 *t ype->enumeration.name,1105 buildQualifiers( t ype)1114 *td->enumeration.name, 1115 buildQualifiers( td ) 1106 1116 ); 1107 1117 } // if 1108 1118 break; 1109 1119 case TypeData::Aggregate: 1110 if ( t ype->aggregate.body ) {1120 if ( td->aggregate.body ) { 1111 1121 ast::AggregateDecl * typedecl = 1112 buildAggregate( t ype, std::move( attributes ), linkage );1113 switch ( t ype->aggregate.kind ) {1122 buildAggregate( td, std::move( attributes ), linkage ); 1123 switch ( td->aggregate.kind ) { 1114 1124 case ast::AggregateDecl::Struct: 1115 1125 case ast::AggregateDecl::Coroutine: … … 1118 1128 return new ast::StructInstType( 1119 1129 strict_dynamic_cast<ast::StructDecl *>( typedecl ), 1120 buildQualifiers( t ype)1130 buildQualifiers( td ) 1121 1131 ); 1122 1132 case ast::AggregateDecl::Union: 1123 1133 return new ast::UnionInstType( 1124 1134 strict_dynamic_cast<ast::UnionDecl *>( typedecl ), 1125 buildQualifiers( t ype)1135 buildQualifiers( td ) 1126 1136 ); 1127 1137 case ast::AggregateDecl::Trait: … … 1132 1142 } // switch 1133 1143 } else { 1134 switch ( t ype->aggregate.kind ) {1144 switch ( td->aggregate.kind ) { 1135 1145 case ast::AggregateDecl::Struct: 1136 1146 case ast::AggregateDecl::Coroutine: … … 1138 1148 case ast::AggregateDecl::Thread: 1139 1149 return new ast::StructInstType( 1140 *t ype->aggregate.name,1141 buildQualifiers( t ype)1150 *td->aggregate.name, 1151 buildQualifiers( td ) 1142 1152 ); 1143 1153 case ast::AggregateDecl::Union: 1144 1154 return new ast::UnionInstType( 1145 *t ype->aggregate.name,1146 buildQualifiers( t ype)1155 *td->aggregate.name, 1156 buildQualifiers( td ) 1147 1157 ); 1148 1158 case ast::AggregateDecl::Trait: 1149 1159 return new ast::TraitInstType( 1150 *t ype->aggregate.name,1151 buildQualifiers( t ype)1160 *td->aggregate.name, 1161 buildQualifiers( td ) 1152 1162 ); 1153 1163 default: -
src/Parser/TypeData.h
r0522ebe ra4da45e 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 15:18:36 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Mar 1 10:44:00 202313 // Update Count : 2 0611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 22 16:30:31 2024 13 // Update Count : 210 14 14 // 15 15 … … 30 30 ast::AggregateDecl::Aggregate kind; 31 31 const std::string * name = nullptr; 32 const std::string * parent = nullptr; 32 33 DeclarationNode * params = nullptr; 33 34 ExpressionNode * actuals = nullptr; // holds actual parameters later applied to AggInst 34 35 DeclarationNode * fields = nullptr; 36 std::vector<ast::ptr<ast::Attribute>> attributes; 35 37 bool body; 36 38 bool anon; 37 39 bool tagged; 38 const std::string * parent = nullptr;39 40 }; 40 41 -
src/Parser/parser.yy
r0522ebe ra4da45e 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Nov 26 13:18:06 202313 // Update Count : 6 39812 // Last Modified On : Fri Feb 23 18:25:46 2024 13 // Update Count : 6484 14 14 // 15 15 … … 102 102 103 103 DeclarationNode * distAttr( DeclarationNode * typeSpec, DeclarationNode * declList ) { 104 // distribute declaration_specifier across all declared variables, e.g., static, const, but not__attribute__.104 // Distribute type specifier across all declared variables, e.g., static, const, __attribute__. 105 105 assert( declList ); 106 // printf( "distAttr1 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout ); 107 DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec ); 108 // printf( "distAttr2 cl %p\n", cl ); cl->type->print( std::cout ); 109 // cl->type->aggregate.name = cl->type->aggInst.aggregate->aggregate.name; 110 106 107 // Do not distribute attributes for aggregates because the attributes surrounding the aggregate belong it not the 108 // variables in the declaration list, e.g., 109 // 110 // struct __attribute__(( aligned(128) )) S { ... 111 // } v1 __attribute__(( aligned(64) )), v2 __attribute__(( aligned(32) )), v3; 112 // struct S v4; 113 // 114 // v1 => 64, v2 =>32, v3 => 128, v2 => 128 115 // 116 // Anonymous aggregates are a special case because there is no aggregate to bind the attribute to; hence it floats 117 // to the declaration list. 118 // 119 // struct __attribute__(( aligned(128) )) /*anonymous */ { ... } v1; 120 // 121 // v1 => 128 122 123 bool copyattr = ! (typeSpec->type && typeSpec->type->kind == TypeData::Aggregate && ! typeSpec->type->aggregate.anon ); 124 125 // addType copies the type information for the aggregate instances from typeSpec into cl's aggInst.aggregate. 126 DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec ); // typeSpec IS DELETED!!! 127 128 // Start at second variable in declaration list and clone the type specifiers for each variable.. 111 129 for ( DeclarationNode * cur = dynamic_cast<DeclarationNode *>( declList->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) { 112 cl->cloneBaseType( cur );130 cl->cloneBaseType( cur, copyattr ); // cur is modified 113 131 } // for 114 declList->addType( cl ); 115 // printf( "distAttr3 declList %p\n", declList ); declList->print( std::cout, 0 ); 132 133 // Add first variable in declaration list with hidden type information in aggInst.aggregate, which is used by 134 // extractType to recover the type for the aggregate instances. 135 declList->addType( cl, copyattr ); // cl IS DELETED!!! 116 136 return declList; 117 137 } // distAttr … … 192 212 fieldList = DeclarationNode::newName( nullptr ); 193 213 } // if 194 // return distAttr( typeSpec, fieldList ); // mark all fields in list195 214 196 215 // printf( "fieldDecl3 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout, 0 ); 197 DeclarationNode * temp = distAttr( typeSpec, fieldList ); 216 DeclarationNode * temp = distAttr( typeSpec, fieldList ); // mark all fields in list 198 217 // printf( "fieldDecl4 temp %p\n", temp ); temp->print( std::cout, 0 ); 199 218 return temp; … … 761 780 | string_literal '`' identifier // CFA, postfix call 762 781 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 782 783 // SKULLDUGGERY: The typedef table used for parsing does not store fields in structures. To parse a qualified 784 // name, it is assumed all name-tokens after the first are identifiers, regardless of how the lexer identifies 785 // them. For example: 786 // 787 // struct S; 788 // forall(T) struct T; 789 // union U; 790 // enum E { S, T, E }; 791 // struct Z { int S, T, Z, E, U; }; 792 // void fred () { 793 // Z z; 794 // z.S; // lexer returns S is TYPEDEFname 795 // z.T; // lexer returns T is TYPEGENname 796 // z.Z; // lexer returns Z is TYPEDEFname 797 // z.U; // lexer returns U is TYPEDEFname 798 // z.E; // lexer returns E is TYPEDEFname 799 // } 763 800 | postfix_expression '.' identifier 764 801 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 802 | postfix_expression '.' TYPEDEFname // CFA, SKULLDUGGERY 803 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 804 | postfix_expression '.' TYPEGENname // CFA, SKULLDUGGERY 805 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 806 765 807 | postfix_expression '.' INTEGERconstant // CFA, tuple index 766 808 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); } … … 1039 1081 | logical_OR_expression '?' comma_expression ':' conditional_expression 1040 1082 { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); } 1041 // FIX ME: computes $1 twice1042 1083 | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand 1043 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1->clone(), $4 ) ); }1084 { $$ = new ExpressionNode( build_cond( yylloc, $1, nullptr, $4 ) ); } 1044 1085 ; 1045 1086 … … 1856 1897 declaration_list: 1857 1898 declaration 1858 | declaration_list declaration 1859 { $$ = $1->appendList( $2 ); } 1899 | declaration_list declaration { $$ = $1->appendList( $2 ); } 1860 1900 ; 1861 1901 … … 1890 1930 declaration: // old & new style declarations 1891 1931 c_declaration ';' 1892 {1893 // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );1894 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {1895 // printf( "\tattr %s\n", attr->name.c_str() );1896 // } // for1897 }1898 1932 | cfa_declaration ';' // CFA 1899 1933 | static_assert // C11 … … 2348 2382 sue_declaration_specifier: // struct, union, enum + storage class + type specifier 2349 2383 sue_type_specifier 2350 {2351 // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2352 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2353 // printf( "\tattr %s\n", attr->name.c_str() );2354 // } // for2355 }2356 2384 | declaration_qualifier_list sue_type_specifier 2357 2385 { $$ = $2->addQualifiers( $1 ); } … … 2364 2392 sue_type_specifier: // struct, union, enum + type specifier 2365 2393 elaborated_type 2366 {2367 // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2368 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2369 // printf( "\tattr %s\n", attr->name.c_str() );2370 // } // for2371 }2372 2394 | type_qualifier_list 2373 2395 { if ( $1->type != nullptr && $1->type->forall ) forall = true; } // remember generic type … … 2442 2464 elaborated_type: // struct, union, enum 2443 2465 aggregate_type 2444 {2445 // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2446 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2447 // printf( "\tattr %s\n", attr->name.c_str() );2448 // } // for2449 }2450 2466 | enum_type 2451 2467 ; … … 2679 2695 { $$ = DeclarationNode::newEnum( nullptr, $4, true, false )->addQualifiers( $2 ); } 2680 2696 | ENUM attribute_list_opt '!' '{' enumerator_list comma_opt '}' // invalid syntax rule 2681 { SemanticError( yylloc, "syntax error, hiding '!'the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }2697 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; } 2682 2698 | ENUM attribute_list_opt identifier 2683 2699 { typedefTable.makeTypedef( *$3, "enum_type 1" ); } … … 2694 2710 } 2695 2711 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '!' '{' enumerator_list comma_opt '}' // unqualified type name 2696 { SemanticError( yylloc, "syntax error, hiding '!'the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }2712 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; } 2697 2713 | ENUM '(' ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2698 2714 { … … 2700 2716 } 2701 2717 | ENUM '(' ')' attribute_list_opt '!' '{' enumerator_list comma_opt '}' // invalid syntax rule 2702 { SemanticError( yylloc, "syntax error, hiding '!'the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }2718 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; } 2703 2719 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt 2704 2720 { … … 3177 3193 // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is 3178 3194 // disallowed at the moment. 3179 if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) { 3195 if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && 3196 $1->type && $1->type->kind == TypeData::AggregateInst ) { 3180 3197 if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) { 3181 3198 SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr; -
src/ResolvExpr/CandidateFinder.cpp
r0522ebe ra4da45e 1018 1018 } 1019 1019 1020 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer); 1020 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer); 1021 1021 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type)); 1022 1022 } … … 1283 1283 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1284 1284 copy( cand->env ), std::move( open ), std::move( need ), cand->cost + thisCost); 1285 // currently assertions are always resolved immediately so this should have no effect. 1285 // currently assertions are always resolved immediately so this should have no effect. 1286 1286 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1287 1287 // we may need to revisit the logic. … … 1618 1618 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1619 1619 // candidates for condition 1620 ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 ); 1620 1621 CandidateFinder finder1( context, tenv ); 1621 ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );1622 1622 finder1.find( arg1, ResolveMode::withAdjustment() ); 1623 1623 if ( finder1.candidates.empty() ) return; 1624 1624 1625 1625 // candidates for true result 1626 // FIX ME: resolves and runs arg1 twice when arg2 is missing. 1627 ast::Expr const * arg2 = conditionalExpr->arg2; 1628 arg2 = arg2 ? arg2 : conditionalExpr->arg1.get(); 1626 1629 CandidateFinder finder2( context, tenv ); 1627 1630 finder2.allowVoid = true; 1628 finder2.find( conditionalExpr->arg2, ResolveMode::withAdjustment() );1631 finder2.find( arg2, ResolveMode::withAdjustment() ); 1629 1632 if ( finder2.candidates.empty() ) return; 1630 1633 … … 1897 1900 CandidateRef newCand = 1898 1901 std::make_shared<Candidate>( 1899 newExpr, copy( tenv ), ast::OpenVarSet{}, 1902 newExpr, copy( tenv ), ast::OpenVarSet{}, 1900 1903 ast::AssertionSet{}, Cost::zero, cost 1901 1904 ); 1902 1905 1903 1906 if (newCand->expr->env) { 1904 1907 newCand->env.add(*newCand->expr->env); -
src/ResolvExpr/ResolveTypeof.cc
r0522ebe ra4da45e 35 35 36 36 struct ResolveTypeof : public ast::WithShortCircuiting { 37 37 const ResolveContext & context; 38 38 39 ResolveTypeof( const ResolveContext & context ) : 40 context( context ) {} 39 ResolveTypeof( const ResolveContext & context ) : context( context ) {} 41 40 42 41 void previsit( const ast::TypeofType * ) { visit_children = false; } 43 42 44 45 46 43 const ast::Type * postvisit( const ast::TypeofType * typeofType ) { 44 // pass on null expression 45 if ( ! typeofType->expr ) return typeofType; 47 46 48 49 50 51 52 53 54 55 56 57 58 59 47 ast::ptr< ast::Type > newType; 48 if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) { 49 // typeof wrapping type 50 newType = tyExpr->type; 51 } else { 52 // typeof wrapping expression 53 ast::TypeEnvironment dummy; 54 ast::ptr< ast::Expr > newExpr = 55 resolveInVoidContext( typeofType->expr, context, dummy ); 56 assert( newExpr->result && ! newExpr->result->isVoid() ); 57 newType = newExpr->result; 58 } 60 59 61 62 63 64 65 newType = new ast::BasicType{66 ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };67 68 69 70 71 72 73 60 // clear qualifiers for base, combine with typeoftype quals regardless 61 if ( typeofType->kind == ast::TypeofType::Basetypeof ) { 62 // replace basetypeof(<enum>) by int 63 if ( newType.as< ast::EnumInstType >() ) { 64 newType = new ast::BasicType( 65 ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) ); 66 } 67 reset_qualifiers( 68 newType, 69 ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers ); 70 } else { 71 add_qualifiers( newType, typeofType->qualifiers ); 72 } 74 73 75 76 74 return newType.release(); 75 } 77 76 }; 78 77 … … 111 110 112 111 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) { 113 if (decl->isTypeFixed) {114 115 112 if ( decl->isTypeFixed ) { 113 return decl; 114 } 116 115 117 118 119 120 121 122 123 116 auto mutDecl = mutate(decl); 117 fixObjectInit(decl, context); 118 { 119 auto resolvedType = resolveTypeof(decl->type, context); 120 resolvedType = fixArrayType(resolvedType, context); 121 mutDecl->type = resolvedType; 122 } 124 123 125 126 if (!mutDecl->name.empty()) {127 128 124 // Do not mangle unnamed variables. 125 if ( !mutDecl->name.empty() ) { 126 mutDecl->mangleName = Mangle::mangle(mutDecl); 127 } 129 128 130 131 132 129 mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID); 130 mutDecl->isTypeFixed = true; 131 return mutDecl; 133 132 } 134 133 135 const ast::ObjectDecl *fixObjectInit( const ast::ObjectDecl *decl,136 137 if (decl->isTypeFixed) {138 139 134 const ast::ObjectDecl *fixObjectInit( 135 const ast::ObjectDecl *decl, const ResolveContext &context) { 136 if ( decl->isTypeFixed ) { 137 return decl; 138 } 140 139 141 auto mutDecl = mutate(decl); 140 if ( auto listInit = decl->init.as<ast::ListInit>() ) { 141 for ( size_t k = 0; k < listInit->designations.size(); k++ ) { 142 const ast::Designation *des = listInit->designations[k].get(); 143 // Desination here 144 ast::Designation * newDesignation = new ast::Designation(des->location); 145 std::deque<ast::ptr<ast::Expr>> newDesignators; 142 146 143 if ( auto mutListInit = mutDecl->init.as<ast::ListInit>() ) { 144 // std::list<ast::Designation *> newDesignations; 145 146 for ( size_t k = 0; k < mutListInit->designations.size(); k++ ) { 147 const ast::Designation *des = mutListInit->designations[k].get(); 148 // Desination here 149 ast::Designation * newDesignation = new ast::Designation(des->location); 150 std::deque<ast::ptr<ast::Expr>> newDesignators; 151 152 for ( ast::ptr<ast::Expr> designator : des->designators ) { 153 // Stupid flag variable for development, to be removed 154 // bool mutated = false; 155 if ( const ast::NameExpr * designatorName = designator.as<ast::NameExpr>() ) { 156 auto candidates = context.symtab.lookupId(designatorName->name); 157 // Does not work for the overloading case currently 158 // assert( candidates.size() == 1 ); 159 if ( candidates.size() != 1 ) return mutDecl; 160 auto candidate = candidates.at(0); 161 if ( const ast::EnumInstType * enumInst = dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type())) { 162 // determine that is an enumInst, swap it with its const value 163 assert( candidates.size() == 1 ); 164 const ast::EnumDecl * baseEnum = enumInst->base; 165 // Need to iterate over all enum value to find the initializer to swap 166 for ( size_t m = 0; m < baseEnum->members.size(); ++m ) { 167 const ast::ObjectDecl * mem = baseEnum->members.at(m).as<const ast::ObjectDecl>(); 168 if ( baseEnum->members.at(m)->name == designatorName->name ) { 169 assert(mem); 170 newDesignators.push_back( ast::ConstantExpr::from_int(designator->location, m) ); 171 // mutated = true; 172 break; 173 } 174 } 175 } else { 176 newDesignators.push_back( des->designators.at(0) ); 177 } 178 } else { 179 newDesignators.push_back( des->designators.at(0) ); 180 } 181 } 182 183 newDesignation->designators = newDesignators; 184 mutListInit = ast::mutate_field_index(mutListInit, &ast::ListInit::designations, k, newDesignation); 185 186 } 187 } 188 return mutDecl; 147 for ( ast::ptr<ast::Expr> designator : des->designators ) { 148 // Stupid flag variable for development, to be removed 149 if ( const ast::NameExpr * designatorName = designator.as<ast::NameExpr>() ) { 150 auto candidates = context.symtab.lookupId(designatorName->name); 151 // Does not work for the overloading case currently 152 // assert( candidates.size() == 1 ); 153 if ( candidates.size() != 1 ) return decl; 154 auto candidate = candidates.at(0); 155 if ( const ast::EnumInstType * enumInst = dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type())) { 156 // determine that is an enumInst, swap it with its const value 157 assert( candidates.size() == 1 ); 158 const ast::EnumDecl * baseEnum = enumInst->base; 159 // Need to iterate over all enum value to find the initializer to swap 160 for ( size_t m = 0; m < baseEnum->members.size(); ++m ) { 161 const ast::ObjectDecl * mem = baseEnum->members.at(m).as<const ast::ObjectDecl>(); 162 if ( baseEnum->members.at(m)->name == designatorName->name ) { 163 assert( mem ); 164 newDesignators.push_back( ast::ConstantExpr::from_int(designator->location, m) ); 165 break; 166 } 167 } 168 } else { 169 newDesignators.push_back( des->designators.at(0) ); 170 } 171 } else { 172 newDesignators.push_back( des->designators.at(0) ); 173 } 174 } 175 newDesignation->designators = newDesignators; 176 listInit = ast::mutate_field_index(listInit, &ast::ListInit::designations, k, newDesignation); 177 } 178 } 179 return decl; 189 180 } 190 181 191 } 182 } // namespace ResolvExpr 192 183 193 184 // Local Variables: // -
src/ResolvExpr/Resolver.cc
r0522ebe ra4da45e 50 50 51 51 namespace ResolvExpr { 52 namespace { 53 /// Finds deleted expressions in an expression tree 54 struct DeleteFinder final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder> { 55 const ast::DeletedExpr * result = nullptr; 56 57 void previsit( const ast::DeletedExpr * expr ) { 58 if ( result ) { visit_children = false; } 59 else { result = expr; } 52 53 namespace { 54 /// Finds deleted expressions in an expression tree 55 struct DeleteFinder final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder> { 56 const ast::DeletedExpr * result = nullptr; 57 58 void previsit( const ast::DeletedExpr * expr ) { 59 if ( result ) { visit_children = false; } 60 else { result = expr; } 61 } 62 63 void previsit( const ast::Expr * expr ) { 64 if ( result ) { visit_children = false; } 65 if (expr->inferred.hasParams()) { 66 for (auto & imp : expr->inferred.inferParams() ) { 67 imp.second.expr->accept(*visitor); 68 } 60 69 } 61 62 void previsit( const ast::Expr * expr ) { 63 if ( result ) { visit_children = false; } 64 if (expr->inferred.hasParams()) { 65 for (auto & imp : expr->inferred.inferParams() ) { 66 imp.second.expr->accept(*visitor); 70 } 71 }; 72 73 struct ResolveDesignators final : public ast::WithShortCircuiting { 74 ResolveContext& context; 75 bool result = false; 76 77 ResolveDesignators( ResolveContext& _context ): context(_context) {}; 78 79 void previsit( const ast::Node * ) { 80 // short circuit if we already know there are designations 81 if ( result ) visit_children = false; 82 } 83 84 void previsit( const ast::Designation * des ) { 85 if ( result ) visit_children = false; 86 else if ( ! des->designators.empty() ) { 87 if ( (des->designators.size() == 1) ) { 88 const ast::Expr * designator = des->designators.at(0); 89 if ( const ast::NameExpr * designatorName = dynamic_cast<const ast::NameExpr *>(designator) ) { 90 auto candidates = context.symtab.lookupId(designatorName->name); 91 for ( auto candidate : candidates ) { 92 if ( dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type()) ) { 93 result = true; 94 break; 95 } 96 } 97 } 98 } 99 visit_children = false; 100 } 101 } 102 }; 103 } // anonymous namespace 104 105 /// Check if this expression is or includes a deleted expression 106 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 107 return ast::Pass<DeleteFinder>::read( expr ); 108 } 109 110 namespace { 111 /// always-accept candidate filter 112 bool anyCandidate( const Candidate & ) { return true; } 113 114 /// Calls the CandidateFinder and finds the single best candidate 115 CandidateRef findUnfinishedKindExpression( 116 const ast::Expr * untyped, const ResolveContext & context, const std::string & kind, 117 std::function<bool(const Candidate &)> pred = anyCandidate, ResolveMode mode = {} 118 ) { 119 if ( ! untyped ) return nullptr; 120 121 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 122 static unsigned recursion_level = 0; 123 124 ++recursion_level; 125 ast::TypeEnvironment env; 126 CandidateFinder finder( context, env ); 127 finder.allowVoid = true; 128 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 129 --recursion_level; 130 131 // produce a filtered list of candidates 132 CandidateList candidates; 133 for ( auto & cand : finder.candidates ) { 134 if ( pred( *cand ) ) { candidates.emplace_back( cand ); } 135 } 136 137 // produce invalid error if no candidates 138 if ( candidates.empty() ) { 139 SemanticError( untyped, 140 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""), 141 "expression: ") ); 142 } 143 144 // search for cheapest candidate 145 CandidateList winners; 146 bool seen_undeleted = false; 147 for ( CandidateRef & cand : candidates ) { 148 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost ); 149 150 if ( c > 0 ) continue; // skip more expensive than winner 151 152 if ( c < 0 ) { 153 // reset on new cheapest 154 seen_undeleted = ! findDeletedExpr( cand->expr ); 155 winners.clear(); 156 } else /* if ( c == 0 ) */ { 157 if ( findDeletedExpr( cand->expr ) ) { 158 // skip deleted expression if already seen one equivalent-cost not 159 if ( seen_undeleted ) continue; 160 } else if ( ! seen_undeleted ) { 161 // replace list of equivalent-cost deleted expressions with one non-deleted 162 winners.clear(); 163 seen_undeleted = true; 164 } 165 } 166 167 winners.emplace_back( std::move( cand ) ); 168 } 169 170 // promote candidate.cvtCost to .cost 171 // promoteCvtCost( winners ); 172 173 // produce ambiguous errors, if applicable 174 if ( winners.size() != 1 ) { 175 std::ostringstream stream; 176 stream << "Cannot choose between " << winners.size() << " alternatives for " 177 << kind << (kind != "" ? " " : "") << "expression\n"; 178 ast::print( stream, untyped ); 179 stream << " Alternatives are:\n"; 180 print( stream, winners, 1 ); 181 SemanticError( untyped->location, stream.str() ); 182 } 183 184 // single selected choice 185 CandidateRef & choice = winners.front(); 186 187 // fail on only expression deleted 188 if ( ! seen_undeleted ) { 189 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative " 190 "includes deleted identifier in " ); 191 } 192 193 return std::move( choice ); 194 } 195 196 /// Strips extraneous casts out of an expression 197 struct StripCasts final { 198 const ast::Expr * postvisit( const ast::CastExpr * castExpr ) { 199 if ( 200 castExpr->isGenerated == ast::GeneratedCast 201 && typesCompatible( castExpr->arg->result, castExpr->result ) 202 ) { 203 // generated cast is the same type as its argument, remove it after keeping env 204 return ast::mutate_field( 205 castExpr->arg.get(), &ast::Expr::env, castExpr->env ); 206 } 207 return castExpr; 208 } 209 210 static void strip( ast::ptr< ast::Expr > & expr ) { 211 ast::Pass< StripCasts > stripper; 212 expr = expr->accept( stripper ); 213 } 214 }; 215 216 /// Swaps argument into expression pointer, saving original environment 217 void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) { 218 ast::ptr< ast::TypeSubstitution > env = expr->env; 219 expr.set_and_mutate( newExpr )->env = env; 220 } 221 222 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 223 void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) { 224 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 225 if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) { 226 // cast is to the same type as its argument, remove it 227 swap_and_save_env( expr, castExpr->arg ); 228 } 229 } 230 } 231 232 } // anonymous namespace 233 234 /// Establish post-resolver invariants for expressions 235 void finishExpr( 236 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, 237 const ast::TypeSubstitution * oldenv = nullptr 238 ) { 239 // set up new type substitution for expression 240 ast::ptr< ast::TypeSubstitution > newenv = 241 oldenv ? oldenv : new ast::TypeSubstitution{}; 242 env.writeToSubstitution( *newenv.get_and_mutate() ); 243 expr.get_and_mutate()->env = std::move( newenv ); 244 // remove unncecessary casts 245 StripCasts::strip( expr ); 246 } 247 248 ast::ptr< ast::Expr > resolveInVoidContext( 249 const ast::Expr * expr, const ResolveContext & context, 250 ast::TypeEnvironment & env 251 ) { 252 assertf( expr, "expected a non-null expression" ); 253 254 // set up and resolve expression cast to void 255 ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr }; 256 CandidateRef choice = findUnfinishedKindExpression( 257 untyped, context, "", anyCandidate, ResolveMode::withAdjustment() ); 258 259 // a cast expression has either 0 or 1 interpretations (by language rules); 260 // if 0, an exception has already been thrown, and this code will not run 261 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 262 env = std::move( choice->env ); 263 264 return castExpr->arg; 265 } 266 267 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 268 /// context. 269 ast::ptr< ast::Expr > findVoidExpression( 270 const ast::Expr * untyped, const ResolveContext & context 271 ) { 272 ast::TypeEnvironment env; 273 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env ); 274 finishExpr( newExpr, env, untyped->env ); 275 return newExpr; 276 } 277 278 namespace { 279 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 280 /// lowest cost, returning the resolved version 281 ast::ptr< ast::Expr > findKindExpression( 282 const ast::Expr * untyped, const ResolveContext & context, 283 std::function<bool(const Candidate &)> pred = anyCandidate, 284 const std::string & kind = "", ResolveMode mode = {} 285 ) { 286 if ( ! untyped ) return {}; 287 CandidateRef choice = 288 findUnfinishedKindExpression( untyped, context, kind, pred, mode ); 289 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env ); 290 return std::move( choice->expr ); 291 } 292 293 /// Resolve `untyped` to the single expression whose candidate is the best match 294 ast::ptr< ast::Expr > findSingleExpression( 295 const ast::Expr * untyped, const ResolveContext & context 296 ) { 297 Stats::ResolveTime::start( untyped ); 298 auto res = findKindExpression( untyped, context ); 299 Stats::ResolveTime::stop(); 300 return res; 301 } 302 } // anonymous namespace 303 304 ast::ptr< ast::Expr > findSingleExpression( 305 const ast::Expr * untyped, const ast::Type * type, 306 const ResolveContext & context 307 ) { 308 assert( untyped && type ); 309 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 310 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context ); 311 removeExtraneousCast( newExpr ); 312 return newExpr; 313 } 314 315 namespace { 316 bool structOrUnion( const Candidate & i ) { 317 const ast::Type * t = i.expr->result->stripReferences(); 318 return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t ); 319 } 320 /// Predicate for "Candidate has integral type" 321 bool hasIntegralType( const Candidate & i ) { 322 const ast::Type * type = i.expr->result; 323 324 if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) { 325 return bt->isInteger(); 326 } else if ( 327 dynamic_cast< const ast::EnumInstType * >( type ) 328 || dynamic_cast< const ast::ZeroType * >( type ) 329 || dynamic_cast< const ast::OneType * >( type ) 330 ) { 331 return true; 332 } else return false; 333 } 334 335 /// Resolve `untyped` as an integral expression, returning the resolved version 336 ast::ptr< ast::Expr > findIntegralExpression( 337 const ast::Expr * untyped, const ResolveContext & context 338 ) { 339 return findKindExpression( untyped, context, hasIntegralType, "condition" ); 340 } 341 342 /// check if a type is a character type 343 bool isCharType( const ast::Type * t ) { 344 if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) { 345 return bt->kind == ast::BasicType::Char 346 || bt->kind == ast::BasicType::SignedChar 347 || bt->kind == ast::BasicType::UnsignedChar; 348 } 349 return false; 350 } 351 352 /// Advance a type itertor to the next mutex parameter 353 template<typename Iter> 354 inline bool nextMutex( Iter & it, const Iter & end ) { 355 while ( it != end && ! (*it)->is_mutex() ) { ++it; } 356 return it != end; 357 } 358 } 359 360 class Resolver final 361 : public ast::WithSymbolTable, public ast::WithGuards, 362 public ast::WithVisitorRef<Resolver>, public ast::WithShortCircuiting, 363 public ast::WithStmtsToAdd<> { 364 365 ast::ptr< ast::Type > functionReturn = nullptr; 366 ast::CurrentObject currentObject; 367 // for work previously in GenInit 368 static InitTweak::ManagedTypes managedTypes; 369 ResolveContext context; 370 371 bool inEnumDecl = false; 372 373 public: 374 static size_t traceId; 375 Resolver( const ast::TranslationGlobal & global ) : 376 ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd), 377 context{ symtab, global } {} 378 Resolver( const ResolveContext & context ) : 379 ast::WithSymbolTable{ context.symtab }, 380 context{ symtab, context.global } {} 381 382 const ast::FunctionDecl * previsit( const ast::FunctionDecl * ); 383 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * ); 384 const ast::ObjectDecl * previsit( const ast::ObjectDecl * ); 385 void previsit( const ast::AggregateDecl * ); 386 void previsit( const ast::StructDecl * ); 387 void previsit( const ast::EnumDecl * ); 388 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * ); 389 390 const ast::ArrayType * previsit( const ast::ArrayType * ); 391 const ast::PointerType * previsit( const ast::PointerType * ); 392 393 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 394 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 395 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 396 const ast::IfStmt * previsit( const ast::IfStmt * ); 397 const ast::WhileDoStmt * previsit( const ast::WhileDoStmt * ); 398 const ast::ForStmt * previsit( const ast::ForStmt * ); 399 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 400 const ast::CaseClause * previsit( const ast::CaseClause * ); 401 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 402 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 403 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 404 const ast::CatchClause * previsit( const ast::CatchClause * ); 405 const ast::CatchClause * postvisit( const ast::CatchClause * ); 406 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 407 const ast::WithStmt * previsit( const ast::WithStmt * ); 408 409 const ast::SingleInit * previsit( const ast::SingleInit * ); 410 const ast::ListInit * previsit( const ast::ListInit * ); 411 const ast::ConstructorInit * previsit( const ast::ConstructorInit * ); 412 413 void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd); 414 415 void beginScope() { managedTypes.beginScope(); } 416 void endScope() { managedTypes.endScope(); } 417 bool on_error(ast::ptr<ast::Decl> & decl); 418 }; 419 // size_t Resolver::traceId = Stats::Heap::new_stacktrace_id("Resolver"); 420 421 InitTweak::ManagedTypes Resolver::managedTypes; 422 423 void resolve( ast::TranslationUnit& translationUnit ) { 424 ast::Pass< Resolver >::run( translationUnit, translationUnit.global ); 425 } 426 427 ast::ptr< ast::Init > resolveCtorInit( 428 const ast::ConstructorInit * ctorInit, const ResolveContext & context 429 ) { 430 assert( ctorInit ); 431 ast::Pass< Resolver > resolver( context ); 432 return ctorInit->accept( resolver ); 433 } 434 435 const ast::Expr * resolveStmtExpr( 436 const ast::StmtExpr * stmtExpr, const ResolveContext & context 437 ) { 438 assert( stmtExpr ); 439 ast::Pass< Resolver > resolver( context ); 440 auto ret = mutate(stmtExpr->accept(resolver)); 441 strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult(); 442 return ret; 443 } 444 445 namespace { 446 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) { 447 std::string name = attr->normalizedName(); 448 if (name == "constructor" || name == "destructor") { 449 if (attr->params.size() == 1) { 450 auto arg = attr->params.front(); 451 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context ); 452 auto result = eval(arg); 453 454 auto mutAttr = mutate(attr); 455 mutAttr->params.front() = resolved; 456 if (! result.hasKnownValue) { 457 SemanticWarning(loc, Warning::GccAttributes, 458 toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) ); 459 } 460 else { 461 auto priority = result.knownValue; 462 if (priority < 101) { 463 SemanticWarning(loc, Warning::GccAttributes, 464 toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) ); 465 } else if (priority < 201 && ! buildingLibrary()) { 466 SemanticWarning(loc, Warning::GccAttributes, 467 toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) ); 468 } 469 } 470 return mutAttr; 471 } else if (attr->params.size() > 1) { 472 SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) ); 473 } else { 474 SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) ); 475 } 476 } 477 return attr; 478 } 479 } 480 481 const ast::FunctionDecl * Resolver::previsit( const ast::FunctionDecl * functionDecl ) { 482 GuardValue( functionReturn ); 483 484 assert (functionDecl->unique()); 485 if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) { 486 SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations"); 487 } 488 489 if (!functionDecl->isTypeFixed) { 490 auto mutDecl = mutate(functionDecl); 491 auto mutType = mutDecl->type.get_and_mutate(); 492 493 for (auto & attr: mutDecl->attributes) { 494 attr = handleAttribute(mutDecl->location, attr, context ); 495 } 496 497 // handle assertions 498 499 symtab.enterScope(); 500 mutType->forall.clear(); 501 mutType->assertions.clear(); 502 for (auto & typeParam : mutDecl->type_params) { 503 symtab.addType(typeParam); 504 mutType->forall.emplace_back(new ast::TypeInstType(typeParam)); 505 } 506 for (auto & asst : mutDecl->assertions) { 507 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context); 508 symtab.addId(asst); 509 mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst)); 510 } 511 512 // temporarily adds params to symbol table. 513 // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl) 514 515 std::vector<ast::ptr<ast::Type>> paramTypes; 516 std::vector<ast::ptr<ast::Type>> returnTypes; 517 518 for (auto & param : mutDecl->params) { 519 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context); 520 symtab.addId(param); 521 paramTypes.emplace_back(param->get_type()); 522 } 523 for (auto & ret : mutDecl->returns) { 524 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context); 525 returnTypes.emplace_back(ret->get_type()); 526 } 527 // since function type in decl is just a view of param types, need to update that as well 528 mutType->params = std::move(paramTypes); 529 mutType->returns = std::move(returnTypes); 530 531 auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID)); 532 533 std::list<ast::ptr<ast::Stmt>> newStmts; 534 resolveWithExprs (mutDecl->withExprs, newStmts); 535 536 if (mutDecl->stmts) { 537 auto mutStmt = mutDecl->stmts.get_and_mutate(); 538 mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts)); 539 mutDecl->stmts = mutStmt; 540 } 541 542 symtab.leaveScope(); 543 544 mutDecl->type = renamedType; 545 mutDecl->mangleName = Mangle::mangle(mutDecl); 546 mutDecl->isTypeFixed = true; 547 functionDecl = mutDecl; 548 } 549 managedTypes.handleDWT(functionDecl); 550 551 functionReturn = extractResultType( functionDecl->type ); 552 return functionDecl; 553 } 554 555 const ast::FunctionDecl * Resolver::postvisit( const ast::FunctionDecl * functionDecl ) { 556 // default value expressions have an environment which shouldn't be there and trips up 557 // later passes. 558 assert( functionDecl->unique() ); 559 ast::FunctionType * mutType = mutate( functionDecl->type.get() ); 560 561 for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) { 562 if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) { 563 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 564 if ( init->value->env == nullptr ) continue; 565 // clone initializer minus the initializer environment 566 auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() ); 567 auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() ); 568 auto mutValue = mutate( mutInit->value.get() ); 569 570 mutValue->env = nullptr; 571 mutInit->value = mutValue; 572 mutParam->init = mutInit; 573 mutType->params[i] = mutParam; 574 575 assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env); 576 } 577 } 578 } 579 mutate_field(functionDecl, &ast::FunctionDecl::type, mutType); 580 return functionDecl; 581 } 582 583 const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) { 584 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 585 // class-variable `initContext` is changed multiple times because the LHS is analyzed 586 // twice. The second analysis changes `initContext` because a function type can contain 587 // object declarations in the return and parameter types. Therefore each value of 588 // `initContext` is retained so the type on the first analysis is preserved and used for 589 // selecting the RHS. 590 GuardValue( currentObject ); 591 592 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) { 593 // enumerator initializers should not use the enum type to initialize, since the 594 // enum type is still incomplete at this point. Use `int` instead. 595 596 if ( auto enumBase = dynamic_cast< const ast::EnumInstType * > 597 ( objectDecl->get_type() )->base->base ) { 598 objectDecl = fixObjectType( objectDecl, context ); 599 currentObject = ast::CurrentObject{ 600 objectDecl->location, 601 enumBase 602 }; 603 } else { 604 objectDecl = fixObjectType( objectDecl, context ); 605 currentObject = ast::CurrentObject{ 606 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } }; 607 } 608 } else { 609 if ( !objectDecl->isTypeFixed ) { 610 auto newDecl = fixObjectType(objectDecl, context); 611 auto mutDecl = mutate(newDecl); 612 613 // generate CtorInit wrapper when necessary. 614 // in certain cases, fixObjectType is called before reaching 615 // this object in visitor pass, thus disabling CtorInit codegen. 616 // this happens on aggregate members and function parameters. 617 if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) { 618 // constructed objects cannot be designated 619 if ( InitTweak::isDesignated( mutDecl->init ) ) { 620 ast::Pass<ResolveDesignators> res( context ); 621 maybe_accept( mutDecl->init.get(), res ); 622 if ( !res.core.result ) { 623 SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object.\n" 624 "If this is really what you want, initialize with @=." ); 625 } 626 } 627 // constructed objects should not have initializers nested too deeply 628 if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " ); 629 630 mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl ); 631 } 632 633 objectDecl = mutDecl; 634 } 635 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() }; 636 } 637 638 return objectDecl; 639 } 640 641 void Resolver::previsit( const ast::AggregateDecl * _aggDecl ) { 642 auto aggDecl = mutate(_aggDecl); 643 assertf(aggDecl == _aggDecl, "type declarations must be unique"); 644 645 for (auto & member: aggDecl->members) { 646 // nested type decls are hoisted already. no need to do anything 647 if (auto obj = member.as<ast::ObjectDecl>()) { 648 member = fixObjectType(obj, context); 649 } 650 } 651 } 652 653 void Resolver::previsit( const ast::StructDecl * structDecl ) { 654 previsit(static_cast<const ast::AggregateDecl *>(structDecl)); 655 managedTypes.handleStruct(structDecl); 656 } 657 658 void Resolver::previsit( const ast::EnumDecl * ) { 659 // in case we decide to allow nested enums 660 GuardValue( inEnumDecl ); 661 inEnumDecl = true; 662 // don't need to fix types for enum fields 663 } 664 665 const ast::StaticAssertDecl * Resolver::previsit( 666 const ast::StaticAssertDecl * assertDecl 667 ) { 668 return ast::mutate_field( 669 assertDecl, &ast::StaticAssertDecl::cond, 670 findIntegralExpression( assertDecl->cond, context ) ); 671 } 672 673 template< typename PtrType > 674 const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) { 675 if ( type->dimension ) { 676 const ast::Type * sizeType = context.global.sizeType.get(); 677 ast::ptr< ast::Expr > dimension = findSingleExpression( type->dimension, sizeType, context ); 678 assertf(dimension->env->empty(), "array dimension expr has nonempty env"); 679 dimension.get_and_mutate()->env = nullptr; 680 ast::mutate_field( type, &PtrType::dimension, dimension ); 681 } 682 return type; 683 } 684 685 const ast::ArrayType * Resolver::previsit( const ast::ArrayType * at ) { 686 return handlePtrType( at, context ); 687 } 688 689 const ast::PointerType * Resolver::previsit( const ast::PointerType * pt ) { 690 return handlePtrType( pt, context ); 691 } 692 693 const ast::ExprStmt * Resolver::previsit( const ast::ExprStmt * exprStmt ) { 694 visit_children = false; 695 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" ); 696 697 return ast::mutate_field( 698 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) ); 699 } 700 701 const ast::AsmExpr * Resolver::previsit( const ast::AsmExpr * asmExpr ) { 702 visit_children = false; 703 704 asmExpr = ast::mutate_field( 705 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) ); 706 707 return asmExpr; 708 } 709 710 const ast::AsmStmt * Resolver::previsit( const ast::AsmStmt * asmStmt ) { 711 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input ); 712 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output ); 713 visit_children = false; 714 return asmStmt; 715 } 716 717 const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) { 718 return ast::mutate_field( 719 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) ); 720 } 721 722 const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) { 723 return ast::mutate_field( 724 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) ); 725 } 726 727 const ast::ForStmt * Resolver::previsit( const ast::ForStmt * forStmt ) { 728 if ( forStmt->cond ) { 729 forStmt = ast::mutate_field( 730 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) ); 731 } 732 733 if ( forStmt->inc ) { 734 forStmt = ast::mutate_field( 735 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) ); 736 } 737 738 return forStmt; 739 } 740 741 const ast::SwitchStmt * Resolver::previsit( const ast::SwitchStmt * switchStmt ) { 742 GuardValue( currentObject ); 743 switchStmt = ast::mutate_field( 744 switchStmt, &ast::SwitchStmt::cond, 745 findIntegralExpression( switchStmt->cond, context ) ); 746 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 747 return switchStmt; 748 } 749 750 const ast::CaseClause * Resolver::previsit( const ast::CaseClause * caseStmt ) { 751 if ( caseStmt->cond ) { 752 std::deque< ast::InitAlternative > initAlts = currentObject.getOptions(); 753 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral " 754 "expression." ); 755 756 ast::ptr< ast::Expr > untyped = 757 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 758 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context ); 759 760 // case condition cannot have a cast in C, so it must be removed here, regardless of 761 // whether it would perform a conversion. 762 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) { 763 swap_and_save_env( newExpr, castExpr->arg ); 764 } 765 766 caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr ); 767 } 768 return caseStmt; 769 } 770 771 const ast::BranchStmt * Resolver::previsit( const ast::BranchStmt * branchStmt ) { 772 visit_children = false; 773 // must resolve the argument of a computed goto 774 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 775 // computed goto argument is void* 776 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} }; 777 branchStmt = ast::mutate_field( 778 branchStmt, &ast::BranchStmt::computedTarget, 779 findSingleExpression( branchStmt->computedTarget, target, context ) ); 780 } 781 return branchStmt; 782 } 783 784 const ast::ReturnStmt * Resolver::previsit( const ast::ReturnStmt * returnStmt ) { 785 visit_children = false; 786 if ( returnStmt->expr ) { 787 returnStmt = ast::mutate_field( 788 returnStmt, &ast::ReturnStmt::expr, 789 findSingleExpression( returnStmt->expr, functionReturn, context ) ); 790 } 791 return returnStmt; 792 } 793 794 const ast::ThrowStmt * Resolver::previsit( const ast::ThrowStmt * throwStmt ) { 795 visit_children = false; 796 if ( throwStmt->expr ) { 797 const ast::StructDecl * exceptionDecl = 798 symtab.lookupStruct( "__cfaehm_base_exception_t" ); 799 assert( exceptionDecl ); 800 ast::ptr< ast::Type > exceptType = 801 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } }; 802 throwStmt = ast::mutate_field( 803 throwStmt, &ast::ThrowStmt::expr, 804 findSingleExpression( throwStmt->expr, exceptType, context ) ); 805 } 806 return throwStmt; 807 } 808 809 const ast::CatchClause * Resolver::previsit( const ast::CatchClause * catchClause ) { 810 // Until we are very sure this invarent (ifs that move between passes have then) 811 // holds, check it. This allows a check for when to decode the mangling. 812 if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) { 813 assert( ifStmt->then ); 814 } 815 // Encode the catchStmt so the condition can see the declaration. 816 if ( catchClause->cond ) { 817 ast::CatchClause * clause = mutate( catchClause ); 818 clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body ); 819 clause->cond = nullptr; 820 return clause; 821 } 822 return catchClause; 823 } 824 825 const ast::CatchClause * Resolver::postvisit( const ast::CatchClause * catchClause ) { 826 // Decode the catchStmt so everything is stored properly. 827 const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>(); 828 if ( nullptr != ifStmt && nullptr == ifStmt->then ) { 829 assert( ifStmt->cond ); 830 assert( ifStmt->else_ ); 831 ast::CatchClause * clause = ast::mutate( catchClause ); 832 clause->cond = ifStmt->cond; 833 clause->body = ifStmt->else_; 834 // ifStmt should be implicately deleted here. 835 return clause; 836 } 837 return catchClause; 838 } 839 840 const ast::WaitForStmt * Resolver::previsit( const ast::WaitForStmt * stmt ) { 841 visit_children = false; 842 843 // Resolve all clauses first 844 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) { 845 const ast::WaitForClause & clause = *stmt->clauses[i]; 846 847 ast::TypeEnvironment env; 848 CandidateFinder funcFinder( context, env ); 849 850 // Find all candidates for a function in canonical form 851 funcFinder.find( clause.target, ResolveMode::withAdjustment() ); 852 853 if ( funcFinder.candidates.empty() ) { 854 stringstream ss; 855 ss << "Use of undeclared indentifier '"; 856 ss << clause.target.strict_as< ast::NameExpr >()->name; 857 ss << "' in call to waitfor"; 858 SemanticError( stmt->location, ss.str() ); 859 } 860 861 if ( clause.target_args.empty() ) { 862 SemanticError( stmt->location, 863 "Waitfor clause must have at least one mutex parameter"); 864 } 865 866 // Find all alternatives for all arguments in canonical form 867 std::vector< CandidateFinder > argFinders = 868 funcFinder.findSubExprs( clause.target_args ); 869 870 // List all combinations of arguments 871 std::vector< CandidateList > possibilities; 872 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) ); 873 874 // For every possible function: 875 // * try matching the arguments to the parameters, not the other way around because 876 // more arguments than parameters 877 CandidateList funcCandidates; 878 std::vector< CandidateList > argsCandidates; 879 SemanticErrorException errors; 880 for ( CandidateRef & func : funcFinder.candidates ) { 881 try { 882 auto pointerType = dynamic_cast< const ast::PointerType * >( 883 func->expr->result->stripReferences() ); 884 if ( ! pointerType ) { 885 SemanticError( stmt->location, func->expr->result.get(), 886 "candidate not viable: not a pointer type\n" ); 887 } 888 889 auto funcType = pointerType->base.as< ast::FunctionType >(); 890 if ( ! funcType ) { 891 SemanticError( stmt->location, func->expr->result.get(), 892 "candidate not viable: not a function type\n" ); 893 } 894 895 { 896 auto param = funcType->params.begin(); 897 auto paramEnd = funcType->params.end(); 898 899 if( ! nextMutex( param, paramEnd ) ) { 900 SemanticError( stmt->location, funcType, 901 "candidate function not viable: no mutex parameters\n"); 902 } 903 } 904 905 CandidateRef func2{ new Candidate{ *func } }; 906 // strip reference from function 907 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 908 909 // Each argument must be matched with a parameter of the current candidate 910 for ( auto & argsList : possibilities ) { 911 try { 912 // Declare data structures needed for resolution 913 ast::OpenVarSet open; 914 ast::AssertionSet need, have; 915 ast::TypeEnvironment resultEnv{ func->env }; 916 // Add all type variables as open so that those not used in the 917 // parameter list are still considered open 918 resultEnv.add( funcType->forall ); 919 920 // load type variables from arguments into one shared space 921 for ( auto & arg : argsList ) { 922 resultEnv.simpleCombine( arg->env ); 923 } 924 925 // Make sure we don't widen any existing bindings 926 resultEnv.forbidWidening(); 927 928 // Find any unbound type variables 929 resultEnv.extractOpenVars( open ); 930 931 auto param = funcType->params.begin(); 932 auto paramEnd = funcType->params.end(); 933 934 unsigned n_mutex_param = 0; 935 936 // For every argument of its set, check if it matches one of the 937 // parameters. The order is important 938 for ( auto & arg : argsList ) { 939 // Ignore non-mutex arguments 940 if ( ! nextMutex( param, paramEnd ) ) { 941 // We ran out of parameters but still have arguments. 942 // This function doesn't match 943 SemanticError( stmt->location, funcType, 944 toString("candidate function not viable: too many mutex " 945 "arguments, expected ", n_mutex_param, "\n" ) ); 946 } 947 948 ++n_mutex_param; 949 950 // Check if the argument matches the parameter type in the current scope. 951 // ast::ptr< ast::Type > paramType = (*param)->get_type(); 952 953 if ( 954 ! unify( 955 arg->expr->result, *param, resultEnv, need, have, open ) 956 ) { 957 // Type doesn't match 958 stringstream ss; 959 ss << "candidate function not viable: no known conversion " 960 "from '"; 961 ast::print( ss, *param ); 962 ss << "' to '"; 963 ast::print( ss, arg->expr->result ); 964 ss << "' with env '"; 965 ast::print( ss, resultEnv ); 966 ss << "'\n"; 967 SemanticError( stmt->location, funcType, ss.str() ); 968 } 969 970 ++param; 971 } 972 973 // All arguments match! 974 975 // Check if parameters are missing 976 if ( nextMutex( param, paramEnd ) ) { 977 do { 978 ++n_mutex_param; 979 ++param; 980 } while ( nextMutex( param, paramEnd ) ); 981 982 // We ran out of arguments but still have parameters left; this 983 // function doesn't match 984 SemanticError( stmt->location, funcType, 985 toString( "candidate function not viable: too few mutex " 986 "arguments, expected ", n_mutex_param, "\n" ) ); 987 } 988 989 // All parameters match! 990 991 // Finish the expressions to tie in proper environments 992 finishExpr( func2->expr, resultEnv ); 993 for ( CandidateRef & arg : argsList ) { 994 finishExpr( arg->expr, resultEnv ); 995 } 996 997 // This is a match, store it and save it for later 998 funcCandidates.emplace_back( std::move( func2 ) ); 999 argsCandidates.emplace_back( std::move( argsList ) ); 1000 1001 } catch ( SemanticErrorException & e ) { 1002 errors.append( e ); 1003 } 1004 } 1005 } catch ( SemanticErrorException & e ) { 1006 errors.append( e ); 1007 } 1008 } 1009 1010 // Make sure correct number of arguments 1011 if( funcCandidates.empty() ) { 1012 SemanticErrorException top( stmt->location, 1013 "No alternatives for function in call to waitfor" ); 1014 top.append( errors ); 1015 throw top; 1016 } 1017 1018 if( argsCandidates.empty() ) { 1019 SemanticErrorException top( stmt->location, 1020 "No alternatives for arguments in call to waitfor" ); 1021 top.append( errors ); 1022 throw top; 1023 } 1024 1025 if( funcCandidates.size() > 1 ) { 1026 SemanticErrorException top( stmt->location, 1027 "Ambiguous function in call to waitfor" ); 1028 top.append( errors ); 1029 throw top; 1030 } 1031 if( argsCandidates.size() > 1 ) { 1032 SemanticErrorException top( stmt->location, 1033 "Ambiguous arguments in call to waitfor" ); 1034 top.append( errors ); 1035 throw top; 1036 } 1037 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 1038 1039 // build new clause 1040 auto clause2 = new ast::WaitForClause( clause.location ); 1041 1042 clause2->target = funcCandidates.front()->expr; 1043 1044 clause2->target_args.reserve( clause.target_args.size() ); 1045 const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" ); 1046 for ( auto arg : argsCandidates.front() ) { 1047 const auto & loc = stmt->location; 1048 1049 ast::Expr * init = new ast::CastExpr( loc, 1050 new ast::UntypedExpr( loc, 1051 new ast::NameExpr( loc, "get_monitor" ), 1052 { arg->expr } 1053 ), 1054 new ast::PointerType( 1055 new ast::StructInstType( 1056 decl_monitor 1057 ) 1058 ) 1059 ); 1060 1061 clause2->target_args.emplace_back( findSingleExpression( init, context ) ); 1062 } 1063 1064 // Resolve the conditions as if it were an IfStmt, statements normally 1065 clause2->when_cond = findSingleExpression( clause.when_cond, context ); 1066 clause2->stmt = clause.stmt->accept( *visitor ); 1067 1068 // set results into stmt 1069 auto n = mutate( stmt ); 1070 n->clauses[i] = clause2; 1071 stmt = n; 1072 } 1073 1074 if ( stmt->timeout_stmt ) { 1075 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally 1076 ast::ptr< ast::Type > target = 1077 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1078 auto timeout_time = findSingleExpression( stmt->timeout_time, target, context ); 1079 auto timeout_cond = findSingleExpression( stmt->timeout_cond, context ); 1080 auto timeout_stmt = stmt->timeout_stmt->accept( *visitor ); 1081 1082 // set results into stmt 1083 auto n = mutate( stmt ); 1084 n->timeout_time = std::move( timeout_time ); 1085 n->timeout_cond = std::move( timeout_cond ); 1086 n->timeout_stmt = std::move( timeout_stmt ); 1087 stmt = n; 1088 } 1089 1090 if ( stmt->else_stmt ) { 1091 // resolve the condition like IfStmt, stmts normally 1092 auto else_cond = findSingleExpression( stmt->else_cond, context ); 1093 auto else_stmt = stmt->else_stmt->accept( *visitor ); 1094 1095 // set results into stmt 1096 auto n = mutate( stmt ); 1097 n->else_cond = std::move( else_cond ); 1098 n->else_stmt = std::move( else_stmt ); 1099 stmt = n; 1100 } 1101 1102 return stmt; 1103 } 1104 1105 const ast::WithStmt * Resolver::previsit( const ast::WithStmt * withStmt ) { 1106 auto mutStmt = mutate(withStmt); 1107 resolveWithExprs(mutStmt->exprs, stmtsToAddBefore); 1108 return mutStmt; 1109 } 1110 1111 void Resolver::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) { 1112 for (auto & expr : exprs) { 1113 // only struct- and union-typed expressions are viable candidates 1114 expr = findKindExpression( expr, context, structOrUnion, "with expression" ); 1115 1116 // if with expression might be impure, create a temporary so that it is evaluated once 1117 if ( Tuples::maybeImpure( expr ) ) { 1118 static UniqueName tmpNamer( "_with_tmp_" ); 1119 const CodeLocation loc = expr->location; 1120 auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) ); 1121 expr = new ast::VariableExpr( loc, tmp ); 1122 stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) ); 1123 if ( InitTweak::isConstructable( tmp->type ) ) { 1124 // generate ctor/dtor and resolve them 1125 tmp->init = InitTweak::genCtorInit( loc, tmp ); 1126 } 1127 // since tmp is freshly created, this should modify tmp in-place 1128 tmp->accept( *visitor ); 1129 } else if (expr->env && expr->env->empty()) { 1130 expr = ast::mutate_field(expr.get(), &ast::Expr::env, nullptr); 1131 } 1132 } 1133 } 1134 1135 const ast::SingleInit * Resolver::previsit( const ast::SingleInit * singleInit ) { 1136 visit_children = false; 1137 // resolve initialization using the possibilities as determined by the `currentObject` 1138 // cursor. 1139 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{ 1140 singleInit->location, singleInit->value, currentObject.getOptions() }; 1141 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context ); 1142 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1143 1144 // move cursor to the object that is actually initialized 1145 currentObject.setNext( initExpr->designation ); 1146 1147 // discard InitExpr wrapper and retain relevant pieces. 1148 // `initExpr` may have inferred params in the case where the expression specialized a 1149 // function pointer, and newExpr may already have inferParams of its own, so a simple 1150 // swap is not sufficient 1151 ast::Expr::InferUnion inferred = initExpr->inferred; 1152 swap_and_save_env( newExpr, initExpr->expr ); 1153 newExpr.get_and_mutate()->inferred.splice( std::move(inferred) ); 1154 1155 // get the actual object's type (may not exactly match what comes back from the resolver 1156 // due to conversions) 1157 const ast::Type * initContext = currentObject.getCurrentType(); 1158 1159 removeExtraneousCast( newExpr ); 1160 1161 // check if actual object's type is char[] 1162 if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) { 1163 if ( isCharType( at->base ) ) { 1164 // check if the resolved type is char* 1165 if ( auto pt = newExpr->result.as< ast::PointerType >() ) { 1166 if ( isCharType( pt->base ) ) { 1167 // strip cast if we're initializing a char[] with a char* 1168 // e.g. char x[] = "hello" 1169 if ( auto ce = newExpr.as< ast::CastExpr >() ) { 1170 swap_and_save_env( newExpr, ce->arg ); 67 1171 } 68 1172 } 69 1173 } 70 }; 71 72 struct ResolveDesignators final : public ast::WithShortCircuiting { 73 ResolveContext& context; 74 bool result = false; 75 76 ResolveDesignators( ResolveContext& _context ): context{_context} {}; 77 78 void previsit( const ast::Node * ) { 79 // short circuit if we already know there are designations 80 if ( result ) visit_children = false; 81 } 82 83 void previsit( const ast::Designation * des ) { 84 if ( result ) visit_children = false; 85 else if ( ! des->designators.empty() ) { 86 if ( (des->designators.size() == 1) ) { 87 const ast::Expr * designator = des->designators.at(0); 88 if ( const ast::NameExpr * designatorName = dynamic_cast<const ast::NameExpr *>(designator) ) { 89 auto candidates = context.symtab.lookupId(designatorName->name); 90 for ( auto candidate : candidates ) { 91 if ( dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type()) ) { 92 result = true; 93 break; 94 } 95 } 96 } 97 } 98 visit_children = false; 99 } 100 } 101 }; 102 } // anonymous namespace 103 /// Check if this expression is or includes a deleted expression 104 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 105 return ast::Pass<DeleteFinder>::read( expr ); 106 } 107 108 namespace { 109 /// always-accept candidate filter 110 bool anyCandidate( const Candidate & ) { return true; } 111 112 /// Calls the CandidateFinder and finds the single best candidate 113 CandidateRef findUnfinishedKindExpression( 114 const ast::Expr * untyped, const ResolveContext & context, const std::string & kind, 115 std::function<bool(const Candidate &)> pred = anyCandidate, ResolveMode mode = {} 116 ) { 117 if ( ! untyped ) return nullptr; 118 119 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 120 static unsigned recursion_level = 0; 121 122 ++recursion_level; 123 ast::TypeEnvironment env; 124 CandidateFinder finder( context, env ); 125 finder.allowVoid = true; 126 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 127 --recursion_level; 128 129 // produce a filtered list of candidates 130 CandidateList candidates; 131 for ( auto & cand : finder.candidates ) { 132 if ( pred( *cand ) ) { candidates.emplace_back( cand ); } 133 } 134 135 // produce invalid error if no candidates 136 if ( candidates.empty() ) { 137 SemanticError( untyped, 138 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""), 139 "expression: ") ); 140 } 141 142 // search for cheapest candidate 143 CandidateList winners; 144 bool seen_undeleted = false; 145 for ( CandidateRef & cand : candidates ) { 146 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost ); 147 148 if ( c > 0 ) continue; // skip more expensive than winner 149 150 if ( c < 0 ) { 151 // reset on new cheapest 152 seen_undeleted = ! findDeletedExpr( cand->expr ); 153 winners.clear(); 154 } else /* if ( c == 0 ) */ { 155 if ( findDeletedExpr( cand->expr ) ) { 156 // skip deleted expression if already seen one equivalent-cost not 157 if ( seen_undeleted ) continue; 158 } else if ( ! seen_undeleted ) { 159 // replace list of equivalent-cost deleted expressions with one non-deleted 160 winners.clear(); 161 seen_undeleted = true; 162 } 163 } 164 165 winners.emplace_back( std::move( cand ) ); 166 } 167 168 // promote candidate.cvtCost to .cost 169 // promoteCvtCost( winners ); 170 171 // produce ambiguous errors, if applicable 172 if ( winners.size() != 1 ) { 173 std::ostringstream stream; 174 stream << "Cannot choose between " << winners.size() << " alternatives for " 175 << kind << (kind != "" ? " " : "") << "expression\n"; 176 ast::print( stream, untyped ); 177 stream << " Alternatives are:\n"; 178 print( stream, winners, 1 ); 179 SemanticError( untyped->location, stream.str() ); 180 } 181 182 // single selected choice 183 CandidateRef & choice = winners.front(); 184 185 // fail on only expression deleted 186 if ( ! seen_undeleted ) { 187 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative " 188 "includes deleted identifier in " ); 189 } 190 191 return std::move( choice ); 192 } 193 194 /// Strips extraneous casts out of an expression 195 struct StripCasts final { 196 const ast::Expr * postvisit( const ast::CastExpr * castExpr ) { 197 if ( 198 castExpr->isGenerated == ast::GeneratedCast 199 && typesCompatible( castExpr->arg->result, castExpr->result ) 200 ) { 201 // generated cast is the same type as its argument, remove it after keeping env 202 return ast::mutate_field( 203 castExpr->arg.get(), &ast::Expr::env, castExpr->env ); 204 } 205 return castExpr; 206 } 207 208 static void strip( ast::ptr< ast::Expr > & expr ) { 209 ast::Pass< StripCasts > stripper; 210 expr = expr->accept( stripper ); 211 } 212 }; 213 214 /// Swaps argument into expression pointer, saving original environment 215 void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) { 216 ast::ptr< ast::TypeSubstitution > env = expr->env; 217 expr.set_and_mutate( newExpr )->env = env; 218 } 219 220 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 221 void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) { 222 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 223 if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) { 224 // cast is to the same type as its argument, remove it 225 swap_and_save_env( expr, castExpr->arg ); 226 } 227 } 228 } 229 230 231 } // anonymous namespace 232 /// Establish post-resolver invariants for expressions 233 void finishExpr( 234 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, 235 const ast::TypeSubstitution * oldenv = nullptr 236 ) { 237 // set up new type substitution for expression 238 ast::ptr< ast::TypeSubstitution > newenv = 239 oldenv ? oldenv : new ast::TypeSubstitution{}; 240 env.writeToSubstitution( *newenv.get_and_mutate() ); 241 expr.get_and_mutate()->env = std::move( newenv ); 242 // remove unncecessary casts 243 StripCasts::strip( expr ); 244 } 245 246 ast::ptr< ast::Expr > resolveInVoidContext( 247 const ast::Expr * expr, const ResolveContext & context, 248 ast::TypeEnvironment & env 249 ) { 250 assertf( expr, "expected a non-null expression" ); 251 252 // set up and resolve expression cast to void 253 ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr }; 254 CandidateRef choice = findUnfinishedKindExpression( 255 untyped, context, "", anyCandidate, ResolveMode::withAdjustment() ); 256 257 // a cast expression has either 0 or 1 interpretations (by language rules); 258 // if 0, an exception has already been thrown, and this code will not run 259 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 260 env = std::move( choice->env ); 261 262 return castExpr->arg; 263 } 264 265 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 266 /// context. 267 ast::ptr< ast::Expr > findVoidExpression( 268 const ast::Expr * untyped, const ResolveContext & context 269 ) { 270 ast::TypeEnvironment env; 271 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env ); 272 finishExpr( newExpr, env, untyped->env ); 273 return newExpr; 274 } 275 276 namespace { 277 278 279 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 280 /// lowest cost, returning the resolved version 281 ast::ptr< ast::Expr > findKindExpression( 282 const ast::Expr * untyped, const ResolveContext & context, 283 std::function<bool(const Candidate &)> pred = anyCandidate, 284 const std::string & kind = "", ResolveMode mode = {} 285 ) { 286 if ( ! untyped ) return {}; 287 CandidateRef choice = 288 findUnfinishedKindExpression( untyped, context, kind, pred, mode ); 289 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env ); 290 return std::move( choice->expr ); 291 } 292 293 /// Resolve `untyped` to the single expression whose candidate is the best match 294 ast::ptr< ast::Expr > findSingleExpression( 295 const ast::Expr * untyped, const ResolveContext & context 296 ) { 297 Stats::ResolveTime::start( untyped ); 298 auto res = findKindExpression( untyped, context ); 299 Stats::ResolveTime::stop(); 300 return res; 301 } 302 } // anonymous namespace 303 304 ast::ptr< ast::Expr > findSingleExpression( 305 const ast::Expr * untyped, const ast::Type * type, 306 const ResolveContext & context 307 ) { 308 assert( untyped && type ); 309 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 310 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context ); 311 removeExtraneousCast( newExpr ); 312 return newExpr; 313 } 314 315 namespace { 316 bool structOrUnion( const Candidate & i ) { 317 const ast::Type * t = i.expr->result->stripReferences(); 318 return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t ); 319 } 320 /// Predicate for "Candidate has integral type" 321 bool hasIntegralType( const Candidate & i ) { 322 const ast::Type * type = i.expr->result; 323 324 if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) { 325 return bt->isInteger(); 326 } else if ( 327 dynamic_cast< const ast::EnumInstType * >( type ) 328 || dynamic_cast< const ast::ZeroType * >( type ) 329 || dynamic_cast< const ast::OneType * >( type ) 330 ) { 331 return true; 332 } else return false; 333 } 334 335 /// Resolve `untyped` as an integral expression, returning the resolved version 336 ast::ptr< ast::Expr > findIntegralExpression( 337 const ast::Expr * untyped, const ResolveContext & context 338 ) { 339 return findKindExpression( untyped, context, hasIntegralType, "condition" ); 340 } 341 342 /// check if a type is a character type 343 bool isCharType( const ast::Type * t ) { 344 if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) { 345 return bt->kind == ast::BasicType::Char 346 || bt->kind == ast::BasicType::SignedChar 347 || bt->kind == ast::BasicType::UnsignedChar; 348 } 1174 } 1175 } 1176 1177 // move cursor to next object in preparation for next initializer 1178 currentObject.increment(); 1179 1180 // set initializer expression to resolved expression 1181 return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) ); 1182 } 1183 1184 const ast::ListInit * Resolver::previsit( const ast::ListInit * listInit ) { 1185 // move cursor into brace-enclosed initializer-list 1186 currentObject.enterListInit( listInit->location ); 1187 1188 assert( listInit->designations.size() == listInit->initializers.size() ); 1189 for ( unsigned i = 0; i < listInit->designations.size(); ++i ) { 1190 // iterate designations and initializers in pairs, moving the cursor to the current 1191 // designated object and resolving the initializer against that object 1192 listInit = ast::mutate_field_index( 1193 listInit, &ast::ListInit::designations, i, 1194 currentObject.findNext( listInit->designations[i] ) ); 1195 listInit = ast::mutate_field_index( 1196 listInit, &ast::ListInit::initializers, i, 1197 listInit->initializers[i]->accept( *visitor ) ); 1198 } 1199 1200 // move cursor out of brace-enclosed initializer-list 1201 currentObject.exitListInit(); 1202 1203 visit_children = false; 1204 return listInit; 1205 } 1206 1207 const ast::ConstructorInit * Resolver::previsit( const ast::ConstructorInit * ctorInit ) { 1208 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor ); 1209 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor ); 1210 1211 // found a constructor - can get rid of C-style initializer 1212 // xxx - Rob suggests this field is dead code 1213 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr ); 1214 1215 // intrinsic single-parameter constructors and destructors do nothing. Since this was 1216 // implicitly generated, there's no way for it to have side effects, so get rid of it to 1217 // clean up generated code 1218 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 1219 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr ); 1220 } 1221 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 1222 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr ); 1223 } 1224 1225 return ctorInit; 1226 } 1227 1228 // suppress error on autogen functions and mark invalid autogen as deleted. 1229 bool Resolver::on_error(ast::ptr<ast::Decl> & decl) { 1230 if (auto functionDecl = decl.as<ast::FunctionDecl>()) { 1231 // xxx - can intrinsic gen ever fail? 1232 if (functionDecl->linkage == ast::Linkage::AutoGen) { 1233 auto mutDecl = mutate(functionDecl); 1234 mutDecl->isDeleted = true; 1235 mutDecl->stmts = nullptr; 1236 decl = mutDecl; 349 1237 return false; 350 1238 } 351 352 /// Advance a type itertor to the next mutex parameter 353 template<typename Iter> 354 inline bool nextMutex( Iter & it, const Iter & end ) { 355 while ( it != end && ! (*it)->is_mutex() ) { ++it; } 356 return it != end; 357 } 358 } 359 360 class Resolver final 361 : public ast::WithSymbolTable, public ast::WithGuards, 362 public ast::WithVisitorRef<Resolver>, public ast::WithShortCircuiting, 363 public ast::WithStmtsToAdd<> { 364 365 ast::ptr< ast::Type > functionReturn = nullptr; 366 ast::CurrentObject currentObject; 367 // for work previously in GenInit 368 static InitTweak::ManagedTypes managedTypes; 369 ResolveContext context; 370 371 bool inEnumDecl = false; 372 373 public: 374 static size_t traceId; 375 Resolver( const ast::TranslationGlobal & global ) : 376 ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd), 377 context{ symtab, global } {} 378 Resolver( const ResolveContext & context ) : 379 ast::WithSymbolTable{ context.symtab }, 380 context{ symtab, context.global } {} 381 382 const ast::FunctionDecl * previsit( const ast::FunctionDecl * ); 383 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * ); 384 const ast::ObjectDecl * previsit( const ast::ObjectDecl * ); 385 void previsit( const ast::AggregateDecl * ); 386 void previsit( const ast::StructDecl * ); 387 void previsit( const ast::EnumDecl * ); 388 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * ); 389 390 const ast::ArrayType * previsit( const ast::ArrayType * ); 391 const ast::PointerType * previsit( const ast::PointerType * ); 392 393 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 394 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 395 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 396 const ast::IfStmt * previsit( const ast::IfStmt * ); 397 const ast::WhileDoStmt * previsit( const ast::WhileDoStmt * ); 398 const ast::ForStmt * previsit( const ast::ForStmt * ); 399 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 400 const ast::CaseClause * previsit( const ast::CaseClause * ); 401 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 402 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 403 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 404 const ast::CatchClause * previsit( const ast::CatchClause * ); 405 const ast::CatchClause * postvisit( const ast::CatchClause * ); 406 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 407 const ast::WithStmt * previsit( const ast::WithStmt * ); 408 409 const ast::SingleInit * previsit( const ast::SingleInit * ); 410 const ast::ListInit * previsit( const ast::ListInit * ); 411 const ast::ConstructorInit * previsit( const ast::ConstructorInit * ); 412 413 void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd); 414 415 void beginScope() { managedTypes.beginScope(); } 416 void endScope() { managedTypes.endScope(); } 417 bool on_error(ast::ptr<ast::Decl> & decl); 418 }; 419 // size_t Resolver::traceId = Stats::Heap::new_stacktrace_id("Resolver"); 420 421 InitTweak::ManagedTypes Resolver::managedTypes; 422 423 void resolve( ast::TranslationUnit& translationUnit ) { 424 ast::Pass< Resolver >::run( translationUnit, translationUnit.global ); 425 } 426 427 ast::ptr< ast::Init > resolveCtorInit( 428 const ast::ConstructorInit * ctorInit, const ResolveContext & context 429 ) { 430 assert( ctorInit ); 431 ast::Pass< Resolver > resolver( context ); 432 return ctorInit->accept( resolver ); 433 } 434 435 const ast::Expr * resolveStmtExpr( 436 const ast::StmtExpr * stmtExpr, const ResolveContext & context 437 ) { 438 assert( stmtExpr ); 439 ast::Pass< Resolver > resolver( context ); 440 auto ret = mutate(stmtExpr->accept(resolver)); 441 strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult(); 442 return ret; 443 } 444 445 namespace { 446 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) { 447 std::string name = attr->normalizedName(); 448 if (name == "constructor" || name == "destructor") { 449 if (attr->params.size() == 1) { 450 auto arg = attr->params.front(); 451 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context ); 452 auto result = eval(arg); 453 454 auto mutAttr = mutate(attr); 455 mutAttr->params.front() = resolved; 456 if (! result.hasKnownValue) { 457 SemanticWarning(loc, Warning::GccAttributes, 458 toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) ); 459 } 460 else { 461 auto priority = result.knownValue; 462 if (priority < 101) { 463 SemanticWarning(loc, Warning::GccAttributes, 464 toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) ); 465 } else if (priority < 201 && ! buildingLibrary()) { 466 SemanticWarning(loc, Warning::GccAttributes, 467 toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) ); 468 } 469 } 470 return mutAttr; 471 } else if (attr->params.size() > 1) { 472 SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) ); 473 } else { 474 SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) ); 475 } 476 } 477 return attr; 478 } 479 } 480 481 const ast::FunctionDecl * Resolver::previsit( const ast::FunctionDecl * functionDecl ) { 482 GuardValue( functionReturn ); 483 484 assert (functionDecl->unique()); 485 if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) { 486 SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations"); 487 } 488 489 if (!functionDecl->isTypeFixed) { 490 auto mutDecl = mutate(functionDecl); 491 auto mutType = mutDecl->type.get_and_mutate(); 492 493 for (auto & attr: mutDecl->attributes) { 494 attr = handleAttribute(mutDecl->location, attr, context ); 495 } 496 497 // handle assertions 498 499 symtab.enterScope(); 500 mutType->forall.clear(); 501 mutType->assertions.clear(); 502 for (auto & typeParam : mutDecl->type_params) { 503 symtab.addType(typeParam); 504 mutType->forall.emplace_back(new ast::TypeInstType(typeParam)); 505 } 506 for (auto & asst : mutDecl->assertions) { 507 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context); 508 symtab.addId(asst); 509 mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst)); 510 } 511 512 // temporarily adds params to symbol table. 513 // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl) 514 515 std::vector<ast::ptr<ast::Type>> paramTypes; 516 std::vector<ast::ptr<ast::Type>> returnTypes; 517 518 for (auto & param : mutDecl->params) { 519 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context); 520 symtab.addId(param); 521 paramTypes.emplace_back(param->get_type()); 522 } 523 for (auto & ret : mutDecl->returns) { 524 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context); 525 returnTypes.emplace_back(ret->get_type()); 526 } 527 // since function type in decl is just a view of param types, need to update that as well 528 mutType->params = std::move(paramTypes); 529 mutType->returns = std::move(returnTypes); 530 531 auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID)); 532 533 std::list<ast::ptr<ast::Stmt>> newStmts; 534 resolveWithExprs (mutDecl->withExprs, newStmts); 535 536 if (mutDecl->stmts) { 537 auto mutStmt = mutDecl->stmts.get_and_mutate(); 538 mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts)); 539 mutDecl->stmts = mutStmt; 540 } 541 542 symtab.leaveScope(); 543 544 mutDecl->type = renamedType; 545 mutDecl->mangleName = Mangle::mangle(mutDecl); 546 mutDecl->isTypeFixed = true; 547 functionDecl = mutDecl; 548 } 549 managedTypes.handleDWT(functionDecl); 550 551 functionReturn = extractResultType( functionDecl->type ); 552 return functionDecl; 553 } 554 555 const ast::FunctionDecl * Resolver::postvisit( const ast::FunctionDecl * functionDecl ) { 556 // default value expressions have an environment which shouldn't be there and trips up 557 // later passes. 558 assert( functionDecl->unique() ); 559 ast::FunctionType * mutType = mutate( functionDecl->type.get() ); 560 561 for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) { 562 if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) { 563 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 564 if ( init->value->env == nullptr ) continue; 565 // clone initializer minus the initializer environment 566 auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() ); 567 auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() ); 568 auto mutValue = mutate( mutInit->value.get() ); 569 570 mutValue->env = nullptr; 571 mutInit->value = mutValue; 572 mutParam->init = mutInit; 573 mutType->params[i] = mutParam; 574 575 assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env); 576 } 577 } 578 } 579 mutate_field(functionDecl, &ast::FunctionDecl::type, mutType); 580 return functionDecl; 581 } 582 583 const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) { 584 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 585 // class-variable `initContext` is changed multiple times because the LHS is analyzed 586 // twice. The second analysis changes `initContext` because a function type can contain 587 // object declarations in the return and parameter types. Therefore each value of 588 // `initContext` is retained so the type on the first analysis is preserved and used for 589 // selecting the RHS. 590 GuardValue( currentObject ); 591 592 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) { 593 // enumerator initializers should not use the enum type to initialize, since the 594 // enum type is still incomplete at this point. Use `int` instead. 595 596 if ( auto enumBase = dynamic_cast< const ast::EnumInstType * > 597 ( objectDecl->get_type() )->base->base ) { 598 objectDecl = fixObjectType( objectDecl, context ); 599 currentObject = ast::CurrentObject{ 600 objectDecl->location, 601 enumBase 602 }; 603 } else { 604 objectDecl = fixObjectType( objectDecl, context ); 605 currentObject = ast::CurrentObject{ 606 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } }; 607 } 608 609 } 610 else { 611 if ( !objectDecl->isTypeFixed ) { 612 auto newDecl = fixObjectType(objectDecl, context); 613 auto mutDecl = mutate(newDecl); 614 615 // generate CtorInit wrapper when necessary. 616 // in certain cases, fixObjectType is called before reaching 617 // this object in visitor pass, thus disabling CtorInit codegen. 618 // this happens on aggregate members and function parameters. 619 if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) { 620 // constructed objects cannot be designated 621 if ( InitTweak::isDesignated( mutDecl->init ) ) { 622 ast::Pass<ResolveDesignators> res( context ); 623 maybe_accept( mutDecl->init.get(), res ); 624 if ( !res.core.result ) { 625 SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object.\n" 626 "If this is really what you want, initialize with @=." ); 627 } 628 } 629 // constructed objects should not have initializers nested too deeply 630 if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " ); 631 632 mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl ); 633 } 634 635 objectDecl = mutDecl; 636 } 637 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() }; 638 } 639 640 return objectDecl; 641 } 642 643 void Resolver::previsit( const ast::AggregateDecl * _aggDecl ) { 644 auto aggDecl = mutate(_aggDecl); 645 assertf(aggDecl == _aggDecl, "type declarations must be unique"); 646 647 for (auto & member: aggDecl->members) { 648 // nested type decls are hoisted already. no need to do anything 649 if (auto obj = member.as<ast::ObjectDecl>()) { 650 member = fixObjectType(obj, context); 651 } 652 } 653 } 654 655 void Resolver::previsit( const ast::StructDecl * structDecl ) { 656 previsit(static_cast<const ast::AggregateDecl *>(structDecl)); 657 managedTypes.handleStruct(structDecl); 658 } 659 660 void Resolver::previsit( const ast::EnumDecl * ) { 661 // in case we decide to allow nested enums 662 GuardValue( inEnumDecl ); 663 inEnumDecl = true; 664 // don't need to fix types for enum fields 665 } 666 667 const ast::StaticAssertDecl * Resolver::previsit( 668 const ast::StaticAssertDecl * assertDecl 669 ) { 670 return ast::mutate_field( 671 assertDecl, &ast::StaticAssertDecl::cond, 672 findIntegralExpression( assertDecl->cond, context ) ); 673 } 674 675 template< typename PtrType > 676 const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) { 677 if ( type->dimension ) { 678 const ast::Type * sizeType = context.global.sizeType.get(); 679 ast::ptr< ast::Expr > dimension = findSingleExpression( type->dimension, sizeType, context ); 680 assertf(dimension->env->empty(), "array dimension expr has nonempty env"); 681 dimension.get_and_mutate()->env = nullptr; 682 ast::mutate_field( type, &PtrType::dimension, dimension ); 683 } 684 return type; 685 } 686 687 const ast::ArrayType * Resolver::previsit( const ast::ArrayType * at ) { 688 return handlePtrType( at, context ); 689 } 690 691 const ast::PointerType * Resolver::previsit( const ast::PointerType * pt ) { 692 return handlePtrType( pt, context ); 693 } 694 695 const ast::ExprStmt * Resolver::previsit( const ast::ExprStmt * exprStmt ) { 696 visit_children = false; 697 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" ); 698 699 return ast::mutate_field( 700 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) ); 701 } 702 703 const ast::AsmExpr * Resolver::previsit( const ast::AsmExpr * asmExpr ) { 704 visit_children = false; 705 706 asmExpr = ast::mutate_field( 707 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) ); 708 709 return asmExpr; 710 } 711 712 const ast::AsmStmt * Resolver::previsit( const ast::AsmStmt * asmStmt ) { 713 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input ); 714 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output ); 715 visit_children = false; 716 return asmStmt; 717 } 718 719 const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) { 720 return ast::mutate_field( 721 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) ); 722 } 723 724 const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) { 725 return ast::mutate_field( 726 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) ); 727 } 728 729 const ast::ForStmt * Resolver::previsit( const ast::ForStmt * forStmt ) { 730 if ( forStmt->cond ) { 731 forStmt = ast::mutate_field( 732 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) ); 733 } 734 735 if ( forStmt->inc ) { 736 forStmt = ast::mutate_field( 737 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) ); 738 } 739 740 return forStmt; 741 } 742 743 const ast::SwitchStmt * Resolver::previsit( const ast::SwitchStmt * switchStmt ) { 744 GuardValue( currentObject ); 745 switchStmt = ast::mutate_field( 746 switchStmt, &ast::SwitchStmt::cond, 747 findIntegralExpression( switchStmt->cond, context ) ); 748 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 749 return switchStmt; 750 } 751 752 const ast::CaseClause * Resolver::previsit( const ast::CaseClause * caseStmt ) { 753 if ( caseStmt->cond ) { 754 std::deque< ast::InitAlternative > initAlts = currentObject.getOptions(); 755 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral " 756 "expression." ); 757 758 ast::ptr< ast::Expr > untyped = 759 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 760 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context ); 761 762 // case condition cannot have a cast in C, so it must be removed here, regardless of 763 // whether it would perform a conversion. 764 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) { 765 swap_and_save_env( newExpr, castExpr->arg ); 766 } 767 768 caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr ); 769 } 770 return caseStmt; 771 } 772 773 const ast::BranchStmt * Resolver::previsit( const ast::BranchStmt * branchStmt ) { 774 visit_children = false; 775 // must resolve the argument of a computed goto 776 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 777 // computed goto argument is void* 778 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} }; 779 branchStmt = ast::mutate_field( 780 branchStmt, &ast::BranchStmt::computedTarget, 781 findSingleExpression( branchStmt->computedTarget, target, context ) ); 782 } 783 return branchStmt; 784 } 785 786 const ast::ReturnStmt * Resolver::previsit( const ast::ReturnStmt * returnStmt ) { 787 visit_children = false; 788 if ( returnStmt->expr ) { 789 returnStmt = ast::mutate_field( 790 returnStmt, &ast::ReturnStmt::expr, 791 findSingleExpression( returnStmt->expr, functionReturn, context ) ); 792 } 793 return returnStmt; 794 } 795 796 const ast::ThrowStmt * Resolver::previsit( const ast::ThrowStmt * throwStmt ) { 797 visit_children = false; 798 if ( throwStmt->expr ) { 799 const ast::StructDecl * exceptionDecl = 800 symtab.lookupStruct( "__cfaehm_base_exception_t" ); 801 assert( exceptionDecl ); 802 ast::ptr< ast::Type > exceptType = 803 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } }; 804 throwStmt = ast::mutate_field( 805 throwStmt, &ast::ThrowStmt::expr, 806 findSingleExpression( throwStmt->expr, exceptType, context ) ); 807 } 808 return throwStmt; 809 } 810 811 const ast::CatchClause * Resolver::previsit( const ast::CatchClause * catchClause ) { 812 // Until we are very sure this invarent (ifs that move between passes have then) 813 // holds, check it. This allows a check for when to decode the mangling. 814 if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) { 815 assert( ifStmt->then ); 816 } 817 // Encode the catchStmt so the condition can see the declaration. 818 if ( catchClause->cond ) { 819 ast::CatchClause * clause = mutate( catchClause ); 820 clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body ); 821 clause->cond = nullptr; 822 return clause; 823 } 824 return catchClause; 825 } 826 827 const ast::CatchClause * Resolver::postvisit( const ast::CatchClause * catchClause ) { 828 // Decode the catchStmt so everything is stored properly. 829 const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>(); 830 if ( nullptr != ifStmt && nullptr == ifStmt->then ) { 831 assert( ifStmt->cond ); 832 assert( ifStmt->else_ ); 833 ast::CatchClause * clause = ast::mutate( catchClause ); 834 clause->cond = ifStmt->cond; 835 clause->body = ifStmt->else_; 836 // ifStmt should be implicately deleted here. 837 return clause; 838 } 839 return catchClause; 840 } 841 842 const ast::WaitForStmt * Resolver::previsit( const ast::WaitForStmt * stmt ) { 843 visit_children = false; 844 845 // Resolve all clauses first 846 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) { 847 const ast::WaitForClause & clause = *stmt->clauses[i]; 848 849 ast::TypeEnvironment env; 850 CandidateFinder funcFinder( context, env ); 851 852 // Find all candidates for a function in canonical form 853 funcFinder.find( clause.target, ResolveMode::withAdjustment() ); 854 855 if ( funcFinder.candidates.empty() ) { 856 stringstream ss; 857 ss << "Use of undeclared indentifier '"; 858 ss << clause.target.strict_as< ast::NameExpr >()->name; 859 ss << "' in call to waitfor"; 860 SemanticError( stmt->location, ss.str() ); 861 } 862 863 if ( clause.target_args.empty() ) { 864 SemanticError( stmt->location, 865 "Waitfor clause must have at least one mutex parameter"); 866 } 867 868 // Find all alternatives for all arguments in canonical form 869 std::vector< CandidateFinder > argFinders = 870 funcFinder.findSubExprs( clause.target_args ); 871 872 // List all combinations of arguments 873 std::vector< CandidateList > possibilities; 874 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) ); 875 876 // For every possible function: 877 // * try matching the arguments to the parameters, not the other way around because 878 // more arguments than parameters 879 CandidateList funcCandidates; 880 std::vector< CandidateList > argsCandidates; 881 SemanticErrorException errors; 882 for ( CandidateRef & func : funcFinder.candidates ) { 883 try { 884 auto pointerType = dynamic_cast< const ast::PointerType * >( 885 func->expr->result->stripReferences() ); 886 if ( ! pointerType ) { 887 SemanticError( stmt->location, func->expr->result.get(), 888 "candidate not viable: not a pointer type\n" ); 889 } 890 891 auto funcType = pointerType->base.as< ast::FunctionType >(); 892 if ( ! funcType ) { 893 SemanticError( stmt->location, func->expr->result.get(), 894 "candidate not viable: not a function type\n" ); 895 } 896 897 { 898 auto param = funcType->params.begin(); 899 auto paramEnd = funcType->params.end(); 900 901 if( ! nextMutex( param, paramEnd ) ) { 902 SemanticError( stmt->location, funcType, 903 "candidate function not viable: no mutex parameters\n"); 904 } 905 } 906 907 CandidateRef func2{ new Candidate{ *func } }; 908 // strip reference from function 909 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 910 911 // Each argument must be matched with a parameter of the current candidate 912 for ( auto & argsList : possibilities ) { 913 try { 914 // Declare data structures needed for resolution 915 ast::OpenVarSet open; 916 ast::AssertionSet need, have; 917 ast::TypeEnvironment resultEnv{ func->env }; 918 // Add all type variables as open so that those not used in the 919 // parameter list are still considered open 920 resultEnv.add( funcType->forall ); 921 922 // load type variables from arguments into one shared space 923 for ( auto & arg : argsList ) { 924 resultEnv.simpleCombine( arg->env ); 925 } 926 927 // Make sure we don't widen any existing bindings 928 resultEnv.forbidWidening(); 929 930 // Find any unbound type variables 931 resultEnv.extractOpenVars( open ); 932 933 auto param = funcType->params.begin(); 934 auto paramEnd = funcType->params.end(); 935 936 unsigned n_mutex_param = 0; 937 938 // For every argument of its set, check if it matches one of the 939 // parameters. The order is important 940 for ( auto & arg : argsList ) { 941 // Ignore non-mutex arguments 942 if ( ! nextMutex( param, paramEnd ) ) { 943 // We ran out of parameters but still have arguments. 944 // This function doesn't match 945 SemanticError( stmt->location, funcType, 946 toString("candidate function not viable: too many mutex " 947 "arguments, expected ", n_mutex_param, "\n" ) ); 948 } 949 950 ++n_mutex_param; 951 952 // Check if the argument matches the parameter type in the current scope. 953 // ast::ptr< ast::Type > paramType = (*param)->get_type(); 954 955 if ( 956 ! unify( 957 arg->expr->result, *param, resultEnv, need, have, open ) 958 ) { 959 // Type doesn't match 960 stringstream ss; 961 ss << "candidate function not viable: no known conversion " 962 "from '"; 963 ast::print( ss, *param ); 964 ss << "' to '"; 965 ast::print( ss, arg->expr->result ); 966 ss << "' with env '"; 967 ast::print( ss, resultEnv ); 968 ss << "'\n"; 969 SemanticError( stmt->location, funcType, ss.str() ); 970 } 971 972 ++param; 973 } 974 975 // All arguments match! 976 977 // Check if parameters are missing 978 if ( nextMutex( param, paramEnd ) ) { 979 do { 980 ++n_mutex_param; 981 ++param; 982 } while ( nextMutex( param, paramEnd ) ); 983 984 // We ran out of arguments but still have parameters left; this 985 // function doesn't match 986 SemanticError( stmt->location, funcType, 987 toString( "candidate function not viable: too few mutex " 988 "arguments, expected ", n_mutex_param, "\n" ) ); 989 } 990 991 // All parameters match! 992 993 // Finish the expressions to tie in proper environments 994 finishExpr( func2->expr, resultEnv ); 995 for ( CandidateRef & arg : argsList ) { 996 finishExpr( arg->expr, resultEnv ); 997 } 998 999 // This is a match, store it and save it for later 1000 funcCandidates.emplace_back( std::move( func2 ) ); 1001 argsCandidates.emplace_back( std::move( argsList ) ); 1002 1003 } catch ( SemanticErrorException & e ) { 1004 errors.append( e ); 1005 } 1006 } 1007 } catch ( SemanticErrorException & e ) { 1008 errors.append( e ); 1009 } 1010 } 1011 1012 // Make sure correct number of arguments 1013 if( funcCandidates.empty() ) { 1014 SemanticErrorException top( stmt->location, 1015 "No alternatives for function in call to waitfor" ); 1016 top.append( errors ); 1017 throw top; 1018 } 1019 1020 if( argsCandidates.empty() ) { 1021 SemanticErrorException top( stmt->location, 1022 "No alternatives for arguments in call to waitfor" ); 1023 top.append( errors ); 1024 throw top; 1025 } 1026 1027 if( funcCandidates.size() > 1 ) { 1028 SemanticErrorException top( stmt->location, 1029 "Ambiguous function in call to waitfor" ); 1030 top.append( errors ); 1031 throw top; 1032 } 1033 if( argsCandidates.size() > 1 ) { 1034 SemanticErrorException top( stmt->location, 1035 "Ambiguous arguments in call to waitfor" ); 1036 top.append( errors ); 1037 throw top; 1038 } 1039 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 1040 1041 // build new clause 1042 auto clause2 = new ast::WaitForClause( clause.location ); 1043 1044 clause2->target = funcCandidates.front()->expr; 1045 1046 clause2->target_args.reserve( clause.target_args.size() ); 1047 const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" ); 1048 for ( auto arg : argsCandidates.front() ) { 1049 const auto & loc = stmt->location; 1050 1051 ast::Expr * init = new ast::CastExpr( loc, 1052 new ast::UntypedExpr( loc, 1053 new ast::NameExpr( loc, "get_monitor" ), 1054 { arg->expr } 1055 ), 1056 new ast::PointerType( 1057 new ast::StructInstType( 1058 decl_monitor 1059 ) 1060 ) 1061 ); 1062 1063 clause2->target_args.emplace_back( findSingleExpression( init, context ) ); 1064 } 1065 1066 // Resolve the conditions as if it were an IfStmt, statements normally 1067 clause2->when_cond = findSingleExpression( clause.when_cond, context ); 1068 clause2->stmt = clause.stmt->accept( *visitor ); 1069 1070 // set results into stmt 1071 auto n = mutate( stmt ); 1072 n->clauses[i] = clause2; 1073 stmt = n; 1074 } 1075 1076 if ( stmt->timeout_stmt ) { 1077 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally 1078 ast::ptr< ast::Type > target = 1079 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1080 auto timeout_time = findSingleExpression( stmt->timeout_time, target, context ); 1081 auto timeout_cond = findSingleExpression( stmt->timeout_cond, context ); 1082 auto timeout_stmt = stmt->timeout_stmt->accept( *visitor ); 1083 1084 // set results into stmt 1085 auto n = mutate( stmt ); 1086 n->timeout_time = std::move( timeout_time ); 1087 n->timeout_cond = std::move( timeout_cond ); 1088 n->timeout_stmt = std::move( timeout_stmt ); 1089 stmt = n; 1090 } 1091 1092 if ( stmt->else_stmt ) { 1093 // resolve the condition like IfStmt, stmts normally 1094 auto else_cond = findSingleExpression( stmt->else_cond, context ); 1095 auto else_stmt = stmt->else_stmt->accept( *visitor ); 1096 1097 // set results into stmt 1098 auto n = mutate( stmt ); 1099 n->else_cond = std::move( else_cond ); 1100 n->else_stmt = std::move( else_stmt ); 1101 stmt = n; 1102 } 1103 1104 return stmt; 1105 } 1106 1107 const ast::WithStmt * Resolver::previsit( const ast::WithStmt * withStmt ) { 1108 auto mutStmt = mutate(withStmt); 1109 resolveWithExprs(mutStmt->exprs, stmtsToAddBefore); 1110 return mutStmt; 1111 } 1112 1113 void Resolver::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) { 1114 for (auto & expr : exprs) { 1115 // only struct- and union-typed expressions are viable candidates 1116 expr = findKindExpression( expr, context, structOrUnion, "with expression" ); 1117 1118 // if with expression might be impure, create a temporary so that it is evaluated once 1119 if ( Tuples::maybeImpure( expr ) ) { 1120 static UniqueName tmpNamer( "_with_tmp_" ); 1121 const CodeLocation loc = expr->location; 1122 auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) ); 1123 expr = new ast::VariableExpr( loc, tmp ); 1124 stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) ); 1125 if ( InitTweak::isConstructable( tmp->type ) ) { 1126 // generate ctor/dtor and resolve them 1127 tmp->init = InitTweak::genCtorInit( loc, tmp ); 1128 } 1129 // since tmp is freshly created, this should modify tmp in-place 1130 tmp->accept( *visitor ); 1131 } 1132 else if (expr->env && expr->env->empty()) { 1133 expr = ast::mutate_field(expr.get(), &ast::Expr::env, nullptr); 1134 } 1135 } 1136 } 1137 1138 1139 const ast::SingleInit * Resolver::previsit( const ast::SingleInit * singleInit ) { 1140 visit_children = false; 1141 // resolve initialization using the possibilities as determined by the `currentObject` 1142 // cursor. 1143 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{ 1144 singleInit->location, singleInit->value, currentObject.getOptions() }; 1145 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context ); 1146 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1147 1148 // move cursor to the object that is actually initialized 1149 currentObject.setNext( initExpr->designation ); 1150 1151 // discard InitExpr wrapper and retain relevant pieces. 1152 // `initExpr` may have inferred params in the case where the expression specialized a 1153 // function pointer, and newExpr may already have inferParams of its own, so a simple 1154 // swap is not sufficient 1155 ast::Expr::InferUnion inferred = initExpr->inferred; 1156 swap_and_save_env( newExpr, initExpr->expr ); 1157 newExpr.get_and_mutate()->inferred.splice( std::move(inferred) ); 1158 1159 // get the actual object's type (may not exactly match what comes back from the resolver 1160 // due to conversions) 1161 const ast::Type * initContext = currentObject.getCurrentType(); 1162 1163 removeExtraneousCast( newExpr ); 1164 1165 // check if actual object's type is char[] 1166 if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) { 1167 if ( isCharType( at->base ) ) { 1168 // check if the resolved type is char* 1169 if ( auto pt = newExpr->result.as< ast::PointerType >() ) { 1170 if ( isCharType( pt->base ) ) { 1171 // strip cast if we're initializing a char[] with a char* 1172 // e.g. char x[] = "hello" 1173 if ( auto ce = newExpr.as< ast::CastExpr >() ) { 1174 swap_and_save_env( newExpr, ce->arg ); 1175 } 1176 } 1177 } 1178 } 1179 } 1180 1181 // move cursor to next object in preparation for next initializer 1182 currentObject.increment(); 1183 1184 // set initializer expression to resolved expression 1185 return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) ); 1186 } 1187 1188 const ast::ListInit * Resolver::previsit( const ast::ListInit * listInit ) { 1189 // move cursor into brace-enclosed initializer-list 1190 currentObject.enterListInit( listInit->location ); 1191 1192 assert( listInit->designations.size() == listInit->initializers.size() ); 1193 for ( unsigned i = 0; i < listInit->designations.size(); ++i ) { 1194 // iterate designations and initializers in pairs, moving the cursor to the current 1195 // designated object and resolving the initializer against that object 1196 listInit = ast::mutate_field_index( 1197 listInit, &ast::ListInit::designations, i, 1198 currentObject.findNext( listInit->designations[i] ) ); 1199 listInit = ast::mutate_field_index( 1200 listInit, &ast::ListInit::initializers, i, 1201 listInit->initializers[i]->accept( *visitor ) ); 1202 } 1203 1204 // move cursor out of brace-enclosed initializer-list 1205 currentObject.exitListInit(); 1206 1207 visit_children = false; 1208 return listInit; 1209 } 1210 1211 const ast::ConstructorInit * Resolver::previsit( const ast::ConstructorInit * ctorInit ) { 1212 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor ); 1213 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor ); 1214 1215 // found a constructor - can get rid of C-style initializer 1216 // xxx - Rob suggests this field is dead code 1217 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr ); 1218 1219 // intrinsic single-parameter constructors and destructors do nothing. Since this was 1220 // implicitly generated, there's no way for it to have side effects, so get rid of it to 1221 // clean up generated code 1222 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 1223 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr ); 1224 } 1225 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 1226 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr ); 1227 } 1228 1229 return ctorInit; 1230 } 1231 1232 // suppress error on autogen functions and mark invalid autogen as deleted. 1233 bool Resolver::on_error(ast::ptr<ast::Decl> & decl) { 1234 if (auto functionDecl = decl.as<ast::FunctionDecl>()) { 1235 // xxx - can intrinsic gen ever fail? 1236 if (functionDecl->linkage == ast::Linkage::AutoGen) { 1237 auto mutDecl = mutate(functionDecl); 1238 mutDecl->isDeleted = true; 1239 mutDecl->stmts = nullptr; 1240 decl = mutDecl; 1241 return false; 1242 } 1243 } 1244 return true; 1245 } 1239 } 1240 return true; 1241 } 1246 1242 1247 1243 } // namespace ResolvExpr -
src/SymTab/GenImplicitCall.cpp
r0522ebe ra4da45e 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // GenImplicitCall. hpp --7 // GenImplicitCall.cpp -- Generate code for implicit operator calls. 8 8 // 9 9 // Author : Andrew Beach … … 31 31 namespace { 32 32 33 template< typename OutIter > 33 using Inserter = std::back_insert_iterator<std::list<ast::ptr<ast::Stmt>>>; 34 34 35 ast::ptr< ast::Stmt > genCall( 35 36 InitTweak::InitExpander & srcParam, const ast::Expr * dstParam, 36 const CodeLocation & loc, const std::string & fname, OutIter && out,37 const CodeLocation & loc, const std::string & fname, Inserter && out, 37 38 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward ); 38 39 … … 41 42 /// optionally returns a statement which must be inserted prior to the containing loop, if 42 43 /// there is one 43 template< typename OutIter >44 44 ast::ptr< ast::Stmt > genScalarCall( 45 45 InitTweak::InitExpander & srcParam, const ast::Expr * dstParam, 46 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,46 const CodeLocation & loc, std::string fname, Inserter && out, const ast::Type * type, 47 47 const ast::Type * addCast = nullptr 48 48 ) { … … 97 97 /// Store in out a loop which calls fname on each element of the array with srcParam and 98 98 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0 99 template< typename OutIter >100 99 void genArrayCall( 101 100 InitTweak::InitExpander & srcParam, const ast::Expr * dstParam, 102 const CodeLocation & loc, const std::string & fname, OutIter && out,101 const CodeLocation & loc, const std::string & fname, Inserter && out, 103 102 const ast::ArrayType * array, const ast::Type * addCast = nullptr, 104 103 LoopDirection forward = LoopForward … … 166 165 } 167 166 168 template< typename OutIter >169 167 ast::ptr< ast::Stmt > genCall( 170 168 InitTweak::InitExpander & srcParam, const ast::Expr * dstParam, 171 const CodeLocation & loc, const std::string & fname, OutIter && out,169 const CodeLocation & loc, const std::string & fname, Inserter && out, 172 170 const ast::Type * type, const ast::Type * addCast, LoopDirection forward 173 171 ) { 174 172 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { 175 173 genArrayCall( 176 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,174 srcParam, dstParam, loc, fname, std::forward< Inserter&& >( out ), at, addCast, 177 175 forward ); 178 176 return {}; 179 177 } else { 180 178 return genScalarCall( 181 srcParam, dstParam, loc, fname, std::forward< OutIter>( out ), type, addCast );179 srcParam, dstParam, loc, fname, std::forward< Inserter&& >( out ), type, addCast ); 182 180 } 183 181 } … … 185 183 } // namespace 186 184 187 ast::ptr< ast::Stmt >genImplicitCall(185 const ast::Stmt * genImplicitCall( 188 186 InitTweak::InitExpander & srcParam, const ast::Expr * dstParam, 189 187 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj, … … 191 189 ) { 192 190 // unnamed bit fields are not copied as they cannot be accessed 193 if ( isUnnamedBitfield( obj ) ) return {};191 if ( isUnnamedBitfield( obj ) ) return nullptr; 194 192 195 193 ast::ptr< ast::Type > addCast; … … 199 197 } 200 198 201 std:: vector< ast::ptr< ast::Stmt > > stmts;199 std::list< ast::ptr< ast::Stmt > > stmts; 202 200 genCall( 203 201 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward ); 204 202 205 if ( stmts.empty() ) { 206 return {}; 207 } else if ( stmts.size() == 1 ) { 208 const ast::Stmt * callStmt = stmts.front(); 209 if ( addCast ) { 210 // implicitly generated ctor/dtor calls should be wrapped so that later passes are 211 // aware they were generated. 212 callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt ); 213 } 214 return callStmt; 215 } else { 216 assert( false ); 217 return {}; 218 } 203 if ( stmts.empty() ) return nullptr; 204 assert( stmts.size() == 1 ); 205 206 const ast::Stmt * callStmt = stmts.front().release(); 207 // Implicitly generated ctor/dtor calls should be wrapped so that 208 // later passes are aware they were generated. 209 if ( addCast ) { 210 callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt ); 211 } 212 return callStmt; 219 213 } 220 214 … … 226 220 // compile-command: "make install" // 227 221 // End: // 228 229 -
src/SymTab/GenImplicitCall.hpp
r0522ebe ra4da45e 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // GenImplicitCall.hpp -- 7 // GenImplicitCall.hpp -- Generate code for implicit operator calls. 8 8 // 9 9 // Author : Andrew Beach … … 25 25 /// Returns a generated call expression to function fname with srcParam and 26 26 /// dstParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 27 ast::ptr<ast::Stmt>genImplicitCall(27 const ast::Stmt * genImplicitCall( 28 28 InitTweak::InitExpander & srcParam, const ast::Expr * dstParam, 29 29 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj, -
src/Validate/Autogen.cpp
r0522ebe ra4da45e 133 133 /// Generates a single struct member operation. 134 134 /// (constructor call, destructor call, assignment call) 135 // This is managed because it uses another helper that returns a ast::ptr. 136 ast::ptr<ast::Stmt> makeMemberOp( 135 const ast::Stmt * makeMemberOp( 137 136 const CodeLocation& location, 138 137 const ast::ObjectDecl * dstParam, const ast::Expr * src, … … 525 524 } 526 525 527 ast::ptr<ast::Stmt>StructFuncGenerator::makeMemberOp(526 const ast::Stmt * StructFuncGenerator::makeMemberOp( 528 527 const CodeLocation& location, const ast::ObjectDecl * dstParam, 529 528 const ast::Expr * src, const ast::ObjectDecl * field, … … 540 539 ) 541 540 ); 542 autostmt = genImplicitCall(541 const ast::Stmt * stmt = genImplicitCall( 543 542 srcParam, dstSelect, location, func->name, 544 543 field, direction … … 598 597 location, field, new ast::VariableExpr( location, srcParam ) 599 598 ) : nullptr; 600 ast::ptr<ast::Stmt>stmt =599 const ast::Stmt * stmt = 601 600 makeMemberOp( location, dstParam, srcSelect, field, func, direction ); 602 601 603 602 if ( nullptr != stmt ) { 604 stmts->kids. push_back( stmt );603 stmts->kids.emplace_back( stmt ); 605 604 } 606 605 } … … 623 622 for ( auto param = params.begin() + 1 ; current != end ; ++current ) { 624 623 const ast::ptr<ast::Decl> & member = *current; 625 ast::ptr<ast::Stmt>stmt = nullptr;624 const ast::Stmt * stmt = nullptr; 626 625 auto field = member.as<ast::ObjectDecl>(); 627 626 // Not sure why it could be null. … … 641 640 642 641 if ( nullptr != stmt ) { 643 stmts->kids. push_back( stmt );642 stmts->kids.emplace_back( stmt ); 644 643 } 645 644 } -
src/main.cc
r0522ebe ra4da45e 181 181 182 182 static void _Signal(struct sigaction & act, int sig, int flags ) { 183 sigemptyset( &act.sa_mask ); 183 184 act.sa_flags = flags; 184 185
Note:
See TracChangeset
for help on using the changeset viewer.