Changeset 276a55b2 for src/ResolvExpr/Resolver.cc
- Timestamp:
- Jan 14, 2019, 3:38:28 PM (5 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- fd73248
- Parents:
- 07ec1a2 (diff), 52ffa30 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r07ec1a2 r276a55b2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Feb 17 11:19:40 201813 // Update Count : 21 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Oct 05 09:43:00 2018 13 // Update Count : 214 14 14 // 15 15 16 #include <stddef.h> // for NULL17 16 #include <cassert> // for strict_dynamic_cast, assert 18 17 #include <memory> // for allocator, allocator_traits<... 19 18 #include <tuple> // for get 20 #include <vector> 19 #include <vector> // for vector 21 20 22 21 #include "Alternative.h" // for Alternative, AltList … … 31 30 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 31 #include "Resolver.h" 32 #include "ResolvMode.h" // for ResolvMode 33 33 #include "SymTab/Autogen.h" // for SizeType 34 34 #include "SymTab/Indexer.h" // for Indexer … … 168 168 169 169 namespace { 170 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {170 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) { 171 171 assertf( untyped, "expected a non-null expression." ); 172 173 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 174 static unsigned recursion_level = 0; 175 176 ++recursion_level; 172 177 TypeEnvironment env; 173 178 AlternativeFinder finder( indexer, env ); 174 finder.find( untyped, adjust, prune, failFast ); 179 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 180 --recursion_level; 175 181 176 182 #if 0 … … 185 191 #endif 186 192 193 // produce filtered list of alternatives 187 194 AltList candidates; 188 195 for ( Alternative & alt : finder.get_alternatives() ) { … … 192 199 } 193 200 194 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 195 // choose the lowest cost expression among the candidates 201 // produce invalid error if no candidates 202 if ( candidates.empty() ) { 203 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 204 } 205 206 // search for cheapest candidate 196 207 AltList winners; 197 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 198 if ( winners.size() == 0 ) { 199 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 200 } else if ( winners.size() != 1 ) { 208 bool seen_undeleted = false; 209 for ( unsigned i = 0; i < candidates.size(); ++i ) { 210 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost ); 211 212 if ( c > 0 ) continue; // skip more expensive than winner 213 214 if ( c < 0 ) { 215 // reset on new cheapest 216 seen_undeleted = ! findDeletedExpr( candidates[i].expr ); 217 winners.clear(); 218 } else /* if ( c == 0 ) */ { 219 if ( findDeletedExpr( candidates[i].expr ) ) { 220 // skip deleted expression if already seen one equivalent-cost not 221 if ( seen_undeleted ) continue; 222 } else if ( ! seen_undeleted ) { 223 // replace list of equivalent-cost deleted expressions with one non-deleted 224 winners.clear(); 225 seen_undeleted = true; 226 } 227 } 228 229 winners.emplace_back( std::move( candidates[i] ) ); 230 } 231 232 // promote alternative.cvtCost to .cost 233 // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost 234 for ( Alternative& winner : winners ) { 235 winner.cost = winner.cvtCost; 236 } 237 238 // produce ambiguous errors, if applicable 239 if ( winners.size() != 1 ) { 201 240 std::ostringstream stream; 202 241 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 207 246 } 208 247 209 // there is one unambiguous interpretation - move the expression into the with statement 210 Alternative & choice = winners.front(); 211 if ( findDeletedExpr( choice.expr ) ) { 248 // single selected choice 249 Alternative& choice = winners.front(); 250 251 // fail on only expression deleted 252 if ( ! seen_undeleted ) { 212 253 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 213 254 } 255 256 // xxx - check for ambiguous expressions 257 258 // output selected choice 214 259 alt = std::move( choice ); 215 260 } 216 261 217 262 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 218 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {263 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) { 219 264 if ( ! untyped ) return; 220 265 Alternative choice; 221 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast);266 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode ); 222 267 finishExpr( choice.expr, choice.env, untyped->env ); 223 268 delete untyped; … … 250 295 untyped.arg = expr; 251 296 Alternative choice; 252 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true);297 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() ); 253 298 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 254 299 env = std::move( choice.env ); … … 357 402 358 403 void Resolver::previsit( ObjectDecl *objectDecl ) { 359 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable360 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes361 // initContext because of a function type can contain object declarations in the return and parameter types. So362 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting363 // the RHS.404 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 405 // class-variable initContext is changed multiple time because the LHS is analysed twice. 406 // The second analysis changes initContext because of a function type can contain object 407 // declarations in the return and parameter types. So each value of initContext is 408 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 364 409 GuardValue( currentObject ); 365 410 currentObject = CurrentObject( objectDecl->get_type() ); … … 397 442 398 443 void Resolver::postvisit( FunctionDecl *functionDecl ) { 399 // default value expressions have an environment which shouldn't be there and trips up later passes. 400 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 401 // see how it's useful. 444 // default value expressions have an environment which shouldn't be there and trips up 445 // later passes. 446 // xxx - it might be necessary to somehow keep the information from this environment, but I 447 // can't currently see how it's useful. 402 448 for ( Declaration * d : functionDecl->type->parameters ) { 403 449 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 749 795 initExpr->expr = nullptr; 750 796 std::swap( initExpr->env, newExpr->env ); 751 // InitExpr may have inferParams in the case where the expression specializes a function pointer, 752 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient. 797 // InitExpr may have inferParams in the case where the expression specializes a function 798 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 799 // sufficient. 753 800 newExpr->spliceInferParams( initExpr ); 754 801 delete initExpr; 755 802 756 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 803 // get the actual object's type (may not exactly match what comes back from the resolver 804 // due to conversions) 757 805 Type * initContext = currentObject.getCurrentType(); 758 806 … … 766 814 if ( isCharType( pt->get_base() ) ) { 767 815 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 768 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 816 // strip cast if we're initializing a char[] with a char *, 817 // e.g. char x[] = "hello"; 769 818 newExpr = ce->get_arg(); 770 819 ce->set_arg( nullptr ); … … 788 837 // move cursor into brace-enclosed initializer-list 789 838 currentObject.enterListInit(); 790 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 839 // xxx - fix this so that the list isn't copied, iterator should be used to change current 840 // element 791 841 std::list<Designation *> newDesignations; 792 842 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 793 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving794 // the initializer against that object.843 // iterate designations and initializers in pairs, moving the cursor to the current 844 // designated object and resolving the initializer against that object. 795 845 Designation * des = std::get<0>(p); 796 846 Initializer * init = std::get<1>(p); … … 822 872 // fall back on C-style initializer 823 873 delete ctorInit->get_ctor(); 824 ctorInit->set_ctor( NULL);874 ctorInit->set_ctor( nullptr ); 825 875 delete ctorInit->get_dtor(); 826 ctorInit->set_dtor( NULL);876 ctorInit->set_dtor( nullptr ); 827 877 maybeAccept( ctorInit->get_init(), *visitor ); 828 878 } … … 867 917 868 918 // xxx - todo -- what about arrays? 869 // if ( dtor == NULL&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {919 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 870 920 // // can reduce the constructor down to a SingleInit using the 871 921 // // second argument from the ctor call, since 872 922 // delete ctorInit->get_ctor(); 873 // ctorInit->set_ctor( NULL);923 // ctorInit->set_ctor( nullptr ); 874 924 875 925 // Expression * arg =
Note: See TracChangeset
for help on using the changeset viewer.