Changes in src/ResolvExpr/Resolver.cc [2fd9f24:2a6292d]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r2fd9f24 r2a6292d 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Fri Oct 05 09:43:00 201813 // Update Count : 21 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 11:19:40 2018 13 // Update Count : 213 14 14 // 15 15 16 #include <stddef.h> // for NULL 16 17 #include <cassert> // for strict_dynamic_cast, assert 17 18 #include <memory> // for allocator, allocator_traits<... 18 19 #include <tuple> // for get 19 #include <vector> // for vector20 #include <vector> 20 21 21 22 #include "Alternative.h" // for Alternative, AltList … … 30 31 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 31 32 #include "Resolver.h" 32 #include "ResolvMode.h" // for ResolvMode33 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, ResolvMode mode = ResolvMode{}) {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) { 171 171 assertf( untyped, "expected a non-null expression." ); 172 173 // xxx - this isn't thread-safe, but should work until we parallelize the resolver174 static unsigned recursion_level = 0;175 176 ++recursion_level;177 172 TypeEnvironment env; 178 173 AlternativeFinder finder( indexer, env ); 179 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 180 --recursion_level; 174 finder.find( untyped, adjust, prune, failFast ); 181 175 182 176 #if 0 … … 191 185 #endif 192 186 193 // produce filtered list of alternatives194 187 AltList candidates; 195 188 for ( Alternative & alt : finder.get_alternatives() ) { … … 199 192 } 200 193 201 // produce invalid error if no candidates 202 if ( candidates.empty() ) { 194 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 195 // choose the lowest cost expression among the candidates 196 AltList winners; 197 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 198 if ( winners.size() == 0 ) { 203 199 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 204 } 205 206 // search for cheapest candidate 207 AltList winners; 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 ) { 200 } else if ( winners.size() != 1 ) { 240 201 std::ostringstream stream; 241 202 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 246 207 } 247 208 248 // single selected choice 249 Alternative& choice = winners.front(); 250 251 // fail on only expression deleted 252 if ( ! seen_undeleted ) { 209 // there is one unambiguous interpretation - move the expression into the with statement 210 Alternative & choice = winners.front(); 211 if ( findDeletedExpr( choice.expr ) ) { 253 212 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 254 213 } 255 256 // xxx - check for ambiguous expressions257 258 // output selected choice259 214 alt = std::move( choice ); 260 215 } 261 216 262 217 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 263 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {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) { 264 219 if ( ! untyped ) return; 265 220 Alternative choice; 266 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode);221 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast ); 267 222 finishExpr( choice.expr, choice.env, untyped->env ); 268 223 delete untyped; … … 295 250 untyped.arg = expr; 296 251 Alternative choice; 297 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment());252 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true ); 298 253 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 299 254 env = std::move( choice.env ); … … 402 357 403 358 void Resolver::previsit( ObjectDecl *objectDecl ) { 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 object407 // declarations in the return and parameter types. So each value of initContext is408 // retained, so the type on the first analysis is preserved and used for selectingthe RHS.359 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable 360 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes 361 // initContext because of a function type can contain object declarations in the return and parameter types. So 362 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting 363 // the RHS. 409 364 GuardValue( currentObject ); 410 365 currentObject = CurrentObject( objectDecl->get_type() ); … … 442 397 443 398 void Resolver::postvisit( FunctionDecl *functionDecl ) { 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. 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. 448 402 for ( Declaration * d : functionDecl->type->parameters ) { 449 403 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 795 749 initExpr->expr = nullptr; 796 750 std::swap( initExpr->env, newExpr->env ); 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. 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. 800 753 newExpr->spliceInferParams( initExpr ); 801 754 delete initExpr; 802 755 803 // get the actual object's type (may not exactly match what comes back from the resolver 804 // due to conversions) 756 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 805 757 Type * initContext = currentObject.getCurrentType(); 806 758 … … 814 766 if ( isCharType( pt->get_base() ) ) { 815 767 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 816 // strip cast if we're initializing a char[] with a char *, 817 // e.g. char x[] = "hello"; 768 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 818 769 newExpr = ce->get_arg(); 819 770 ce->set_arg( nullptr ); … … 837 788 // move cursor into brace-enclosed initializer-list 838 789 currentObject.enterListInit(); 839 // xxx - fix this so that the list isn't copied, iterator should be used to change current 840 // element 790 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 841 791 std::list<Designation *> newDesignations; 842 792 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 843 // iterate designations and initializers in pairs, moving the cursor to the current 844 // designated object and resolvingthe initializer against that object.793 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving 794 // the initializer against that object. 845 795 Designation * des = std::get<0>(p); 846 796 Initializer * init = std::get<1>(p); … … 872 822 // fall back on C-style initializer 873 823 delete ctorInit->get_ctor(); 874 ctorInit->set_ctor( nullptr);824 ctorInit->set_ctor( NULL ); 875 825 delete ctorInit->get_dtor(); 876 ctorInit->set_dtor( nullptr);826 ctorInit->set_dtor( NULL ); 877 827 maybeAccept( ctorInit->get_init(), *visitor ); 878 828 } … … 917 867 918 868 // xxx - todo -- what about arrays? 919 // if ( dtor == nullptr&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {869 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 920 870 // // can reduce the constructor down to a SingleInit using the 921 871 // // second argument from the ctor call, since 922 872 // delete ctorInit->get_ctor(); 923 // ctorInit->set_ctor( nullptr);873 // ctorInit->set_ctor( NULL ); 924 874 925 875 // Expression * arg =
Note:
See TracChangeset
for help on using the changeset viewer.