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