Changes in / [f5478c8:50abab9]
- Location:
- src
- Files:
-
- 3 deleted
- 41 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
rf5478c8 r50abab9 167 167 Expression *postmutate( OffsetofExpr *offsetofExpr ); 168 168 Expression *postmutate( OffsetPackExpr *offsetPackExpr ); 169 void premutate( StructDecl * );170 void premutate( UnionDecl * );171 169 172 170 void beginScope(); … … 180 178 /// adds type parameters to the layout call; will generate the appropriate parameters if needed 181 179 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ); 182 /// change the type of generic aggregate members to char[]183 void mutateMembers( AggregateDecl * aggrDecl );184 180 185 181 /// Enters a new scope for type-variables, adding the type variables from ty … … 1418 1414 1419 1415 void PolyGenericCalculator::premutate( TypedefDecl *typedefDecl ) { 1420 assert(false);1421 1416 beginTypeScope( typedefDecl->get_base() ); 1422 1417 } … … 1465 1460 } 1466 1461 1467 /// converts polymorphic type T into a suitable monomorphic representation, currently: __attribute__((aligned(8)) char[size_T]1468 Type * polyToMonoType( Type * declType ) {1469 Type * charType = new BasicType( Type::Qualifiers(), BasicType::Kind::Char);1470 Expression * size = new NameExpr( sizeofName( mangleType(declType) ) );1471 Attribute * aligned = new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } );1472 return new ArrayType( Type::Qualifiers(), charType, size,1473 true, false, std::list<Attribute *>{ aligned } );1474 }1475 1476 void PolyGenericCalculator::mutateMembers( AggregateDecl * aggrDecl ) {1477 std::set< std::string > genericParams;1478 for ( TypeDecl * td : aggrDecl->parameters ) {1479 genericParams.insert( td->name );1480 }1481 for ( Declaration * decl : aggrDecl->members ) {1482 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( decl ) ) {1483 Type * ty = replaceTypeInst( field->type, env );1484 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {1485 // do not try to monomorphize generic parameters1486 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {1487 // polymorphic aggregate members should be converted into monomorphic members.1488 // Using char[size_T] here respects the expected sizing rules of an aggregate type.1489 Type * newType = polyToMonoType( field->type );1490 delete field->type;1491 field->type = newType;1492 }1493 }1494 }1495 }1496 }1497 1498 void PolyGenericCalculator::premutate( StructDecl * structDecl ) {1499 mutateMembers( structDecl );1500 }1501 1502 void PolyGenericCalculator::premutate( UnionDecl * unionDecl ) {1503 mutateMembers( unionDecl );1504 }1505 1506 1462 void PolyGenericCalculator::premutate( DeclStmt *declStmt ) { 1507 1463 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { … … 1509 1465 // change initialization of a polymorphic value object to allocate via a VLA 1510 1466 // (alloca was previously used, but can't be safely used in loops) 1511 ObjectDecl *newBuf = ObjectDecl::newObject( bufNamer.newName(), polyToMonoType( objectDecl->type ), nullptr ); 1467 Type *declType = objectDecl->get_type(); 1468 ObjectDecl *newBuf = new ObjectDecl( bufNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, 1469 new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Kind::Char), new NameExpr( sizeofName( mangleType(declType) ) ), 1470 true, false, std::list<Attribute*>{ new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 ); 1512 1471 stmtsToAddBefore.push_back( new DeclStmt( noLabels, newBuf ) ); 1513 1472 -
src/GenPoly/InstantiateGeneric.cc
rf5478c8 r50abab9 27 27 #include "Common/utility.h" // for deleteAll, cloneAll 28 28 #include "GenPoly.h" // for isPolyType, typesPolyCompatible 29 #include "ResolvExpr/typeops.h"30 29 #include "ScopedSet.h" // for ScopedSet, ScopedSet<>::iterator 31 30 #include "ScrubTyVars.h" // for ScrubTyVars … … 152 151 return gt; 153 152 } 154 155 /// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator156 struct FixDtypeStatic final {157 Expression * postmutate( MemberExpr * memberExpr );158 159 template<typename AggrInst>160 Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );161 };162 153 163 154 /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately … … 207 198 208 199 void instantiateGeneric( std::list< Declaration* > &translationUnit ) { 209 PassVisitor<FixDtypeStatic> fixer;210 200 PassVisitor<GenericInstantiator> instantiator; 211 212 mutateAll( translationUnit, fixer );213 201 mutateAll( translationUnit, instantiator ); 214 }215 216 bool isDtypeStatic( const std::list< TypeDecl* >& baseParams ) {217 return std::all_of( baseParams.begin(), baseParams.end(), []( TypeDecl * td ) { return ! td->isComplete(); } );218 202 } 219 203 … … 495 479 } 496 480 497 template< typename AggrInst >498 Expression * FixDtypeStatic::fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr ) {499 // need to cast dtype-static member expressions to their actual type before that type is erased.500 auto & baseParams = *inst->get_baseParameters();501 if ( isDtypeStatic( baseParams ) ) {502 if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {503 // type of member and type of expression differ, so add cast to actual type504 return new CastExpr( memberExpr, memberExpr->result->clone() );505 }506 }507 return memberExpr;508 }509 510 Expression * FixDtypeStatic::postmutate( MemberExpr * memberExpr ) {511 Type * aggrType = memberExpr->aggregate->result;512 if ( isGenericType( aggrType ) ) {513 if ( StructInstType * inst = dynamic_cast< StructInstType * >( aggrType ) ) {514 return fixMemberExpr( inst, memberExpr );515 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( aggrType ) ) {516 return fixMemberExpr( inst, memberExpr );517 }518 }519 return memberExpr;520 }521 522 481 } // namespace GenPoly 523 482 -
src/InitTweak/FixInit.cc
rf5478c8 r50abab9 393 393 if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types 394 394 395 // type may involve type variables, so apply type substitution to get temporary variable's actual type, 396 // since result type may not be substituted (e.g., if the type does not appear in the parameter list) 395 // type may involve type variables, so apply type substitution to get temporary variable's actual type. 397 396 // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T). 397 result = result->clone(); 398 398 env->applyFree( result ); 399 399 ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr ); … … 570 570 571 571 if ( returnDecl ) { 572 ApplicationExpr * assign = createBitwiseAssignment( new VariableExpr( returnDecl ), callExpr ); 572 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 573 assign->get_args().push_back( new VariableExpr( returnDecl ) ); 574 assign->get_args().push_back( callExpr ); 575 // know the result type of the assignment is the type of the LHS (minus the pointer), so 576 // add that onto the assignment expression so that later steps have the necessary information 577 assign->set_result( returnDecl->get_type()->clone() ); 578 573 579 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 574 580 // move env from callExpr to retExpr … … 937 943 } 938 944 945 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) { 946 for ( auto d : decls ) { 947 indexer.addId( d ); 948 } 949 } 950 951 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) { 952 for ( auto td : tds ) { 953 indexer.addType( td ); 954 addIds( indexer, td->assertions ); 955 } 956 } 957 939 958 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) { 940 959 GuardValue( function ); … … 993 1012 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors 994 1013 auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this]() { indexer.leaveScope(); } ); 995 indexer.addFunctionType( function->type ); 1014 addTypes( indexer, function->type->forall ); 1015 addIds( indexer, function->type->returnVals ); 1016 addIds( indexer, function->type->parameters ); 996 1017 997 1018 // need to iterate through members in reverse in order for … … 1008 1029 // insert and resolve default/copy constructor call for each field that's unhandled 1009 1030 std::list< Statement * > stmt; 1010 Expression * arg2 = nullptr;1031 Expression * arg2 = 0; 1011 1032 if ( isCopyConstructor( function ) ) { 1012 1033 // if copy ctor, need to pass second-param-of-this-function.field … … 1140 1161 assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 ); 1141 1162 1163 // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary. 1164 ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr ); 1165 declsToAddBefore.push_back( tmp ); 1166 1142 1167 // xxx - this can be TupleAssignExpr now. Need to properly handle this case. 1143 1168 ApplicationExpr * callExpr = strict_dynamic_cast< ApplicationExpr * > ( ctorExpr->get_callExpr() ); … … 1145 1170 ctorExpr->set_callExpr( nullptr ); 1146 1171 ctorExpr->set_env( nullptr ); 1147 1148 // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.1149 ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), callExpr->args.front()->result->clone(), nullptr );1150 declsToAddBefore.push_back( tmp );1151 1172 delete ctorExpr; 1152 1173 -
src/InitTweak/InitTweak.cc
rf5478c8 r50abab9 12 12 #include "Parser/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 13 13 #include "ResolvExpr/typeops.h" // for typesCompatibleIgnoreQualifiers 14 #include "SymTab/Autogen.h"15 14 #include "SymTab/Indexer.h" // for Indexer 16 15 #include "SynTree/Attribute.h" // for Attribute … … 525 524 } 526 525 527 ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ) {528 static FunctionDecl * assign = nullptr;529 if ( ! assign ) {530 // temporary? Generate a fake assignment operator to represent bitwise assignments.531 // This operator could easily exist as a real function, but it's tricky because nothing should resolve to this function.532 TypeDecl * td = new TypeDecl( "T", noStorageClasses, nullptr, TypeDecl::Dtype, true );533 assign = new FunctionDecl( "?=?", noStorageClasses, LinkageSpec::Intrinsic, SymTab::genAssignType( new TypeInstType( noQualifiers, td->name, td ) ), nullptr );534 }535 if ( dynamic_cast< ReferenceType * >( dst->result ) ) {536 dst = new AddressExpr( dst );537 } else {538 dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) );539 }540 if ( dynamic_cast< ReferenceType * >( src->result ) ) {541 src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) );542 }543 return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } );544 }545 546 526 class ConstExprChecker : public Visitor { 547 527 public: -
src/InitTweak/InitTweak.h
rf5478c8 r50abab9 35 35 /// returns the first parameter of a constructor/destructor/assignment function 36 36 ObjectDecl * getParamThis( FunctionType * ftype ); 37 38 /// generate a bitwise assignment operation.39 ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src );40 37 41 38 /// transform Initializer into an argument list that can be passed to a call expression -
src/Makefile.in
rf5478c8 r50abab9 210 210 ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) \ 211 211 ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT) \ 212 ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT) \213 212 SymTab/driver_cfa_cpp-Indexer.$(OBJEXT) \ 214 213 SymTab/driver_cfa_cpp-Mangler.$(OBJEXT) \ … … 512 511 ResolvExpr/FindOpenVars.cc ResolvExpr/PolyCost.cc \ 513 512 ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \ 514 ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \ 515 SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \ 516 SymTab/FixFunction.cc SymTab/ImplementationType.cc \ 517 SymTab/TypeEquality.cc SymTab/Autogen.cc SynTree/Type.cc \ 518 SynTree/VoidType.cc SynTree/BasicType.cc \ 519 SynTree/PointerType.cc SynTree/ArrayType.cc \ 520 SynTree/ReferenceType.cc SynTree/FunctionType.cc \ 521 SynTree/ReferenceToType.cc SynTree/TupleType.cc \ 522 SynTree/TypeofType.cc SynTree/AttrType.cc \ 513 ResolvExpr/CurrentObject.cc SymTab/Indexer.cc \ 514 SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \ 515 SymTab/ImplementationType.cc SymTab/TypeEquality.cc \ 516 SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \ 517 SynTree/BasicType.cc SynTree/PointerType.cc \ 518 SynTree/ArrayType.cc SynTree/ReferenceType.cc \ 519 SynTree/FunctionType.cc SynTree/ReferenceToType.cc \ 520 SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \ 523 521 SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \ 524 522 SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \ … … 827 825 ResolvExpr/$(am__dirstamp) \ 828 826 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 829 ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT): \830 ResolvExpr/$(am__dirstamp) \831 ResolvExpr/$(DEPDIR)/$(am__dirstamp)832 827 SymTab/$(am__dirstamp): 833 828 @$(MKDIR_P) SymTab … … 1027 1022 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Po@am__quote@ 1028 1023 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po@am__quote@ 1029 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po@am__quote@1030 1024 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Po@am__quote@ 1031 1025 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Po@am__quote@ … … 1970 1964 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.obj `if test -f 'ResolvExpr/CurrentObject.cc'; then $(CYGPATH_W) 'ResolvExpr/CurrentObject.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CurrentObject.cc'; fi` 1971 1965 1972 ResolvExpr/driver_cfa_cpp-ExplodedActual.o: ResolvExpr/ExplodedActual.cc1973 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ExplodedActual.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.o `test -f 'ResolvExpr/ExplodedActual.cc' || echo '$(srcdir)/'`ResolvExpr/ExplodedActual.cc1974 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po1975 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ResolvExpr/ExplodedActual.cc' object='ResolvExpr/driver_cfa_cpp-ExplodedActual.o' libtool=no @AMDEPBACKSLASH@1976 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1977 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.o `test -f 'ResolvExpr/ExplodedActual.cc' || echo '$(srcdir)/'`ResolvExpr/ExplodedActual.cc1978 1979 ResolvExpr/driver_cfa_cpp-ExplodedActual.obj: ResolvExpr/ExplodedActual.cc1980 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ExplodedActual.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.obj `if test -f 'ResolvExpr/ExplodedActual.cc'; then $(CYGPATH_W) 'ResolvExpr/ExplodedActual.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ExplodedActual.cc'; fi`1981 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po1982 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ResolvExpr/ExplodedActual.cc' object='ResolvExpr/driver_cfa_cpp-ExplodedActual.obj' libtool=no @AMDEPBACKSLASH@1983 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1984 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.obj `if test -f 'ResolvExpr/ExplodedActual.cc'; then $(CYGPATH_W) 'ResolvExpr/ExplodedActual.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ExplodedActual.cc'; fi`1985 1986 1966 SymTab/driver_cfa_cpp-Indexer.o: SymTab/Indexer.cc 1987 1967 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Indexer.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Tpo -c -o SymTab/driver_cfa_cpp-Indexer.o `test -f 'SymTab/Indexer.cc' || echo '$(srcdir)/'`SymTab/Indexer.cc -
src/ResolvExpr/Alternative.cc
rf5478c8 r50abab9 18 18 #include <ostream> // for operator<<, ostream, basic_o... 19 19 #include <string> // for operator<<, char_traits, string 20 #include <utility> // for move21 20 22 21 #include "Common/utility.h" // for maybeClone … … 82 81 os << std::endl; 83 82 } 84 85 void splice( AltList& dst, AltList& src ) {86 dst.reserve( dst.size() + src.size() );87 for ( Alternative& alt : src ) {88 dst.push_back( std::move(alt) );89 }90 src.clear();91 }92 93 void spliceBegin( AltList& dst, AltList& src ) {94 splice( src, dst );95 dst.swap( src );96 }97 98 83 } // namespace ResolvExpr 99 84 -
src/ResolvExpr/Alternative.h
rf5478c8 r50abab9 17 17 18 18 #include <iosfwd> // for ostream 19 #include < vector> // for vector19 #include <list> // for list 20 20 21 21 #include "Cost.h" // for Cost … … 25 25 26 26 namespace ResolvExpr { 27 struct Alternative; 28 29 typedef std::list< Alternative > AltList; 30 27 31 struct Alternative { 28 32 Alternative(); … … 37 41 void print( std::ostream &os, Indenter indent = {} ) const; 38 42 39 /// Returns the stored expression, but released from management of this Alternative40 Expression* release_expr() {41 Expression* tmp = expr;42 expr = nullptr;43 return tmp;44 }45 46 43 Cost cost; 47 44 Cost cvtCost; … … 49 46 TypeEnvironment env; 50 47 }; 51 52 typedef std::vector< Alternative > AltList;53 54 /// Moves all elements from src to the end of dst55 void splice( AltList& dst, AltList& src );56 57 /// Moves all elements from src to the beginning of dst58 void spliceBegin( AltList& dst, AltList& src );59 48 } // namespace ResolvExpr 60 49 -
src/ResolvExpr/AlternativeFinder.cc
rf5478c8 r50abab9 16 16 #include <algorithm> // for copy 17 17 #include <cassert> // for strict_dynamic_cast, assert, assertf 18 #include <cstddef> // for size_t19 18 #include <iostream> // for operator<<, cerr, ostream, endl 20 19 #include <iterator> // for back_insert_iterator, back_inserter 21 20 #include <list> // for _List_iterator, list, _List_const_... 22 21 #include <map> // for _Rb_tree_iterator, map, _Rb_tree_c... 23 #include <memory> // for allocator_traits<>::value_type , unique_ptr22 #include <memory> // for allocator_traits<>::value_type 24 23 #include <utility> // for pair 25 24 #include <vector> // for vector … … 30 29 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation 31 30 #include "Cost.h" // for Cost, Cost::zero, operator<<, Cost... 32 #include "ExplodedActual.h" // for ExplodedActual33 31 #include "InitTweak/InitTweak.h" // for getFunctionName 34 32 #include "RenameVars.h" // for RenameVars, global_renamer … … 52 50 #define PRINT( text ) if ( resolvep ) { text } 53 51 //#define DEBUG_COST 54 55 using std::move;56 57 /// copies any copyable type58 template<typename T>59 T copy(const T& x) { return x; }60 52 61 53 namespace ResolvExpr { … … 187 179 expr->accept( *this ); 188 180 if ( failFast && alternatives.empty() ) { 189 PRINT(190 std::cerr << "No reasonable alternatives for expression " << expr << std::endl;191 )192 181 throw SemanticError( "No reasonable alternatives for expression ", expr ); 193 182 } … … 198 187 printAlts( alternatives, std::cerr ); 199 188 ) 200 AltList pruned;201 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned) );202 if ( failFast && pruned.empty()) {189 AltList::iterator oldBegin = alternatives.begin(); 190 pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) ); 191 if ( failFast && alternatives.begin() == oldBegin ) { 203 192 std::ostringstream stream; 204 193 AltList winners; … … 210 199 throw SemanticError( stream.str() ); 211 200 } 212 alternatives = move(pruned);201 alternatives.erase( oldBegin, alternatives.end() ); 213 202 PRINT( 214 203 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; … … 582 571 /// State to iteratively build a match of parameter expressions to arguments 583 572 struct ArgPack { 584 std::size_t parent; ///< Index of parent pack 585 std::unique_ptr<Expression> expr; ///< The argument stored here 586 Cost cost; ///< The cost of this argument 587 TypeEnvironment env; ///< Environment for this pack 588 AssertionSet need; ///< Assertions outstanding for this pack 589 AssertionSet have; ///< Assertions found for this pack 590 OpenVarSet openVars; ///< Open variables for this pack 591 unsigned nextArg; ///< Index of next argument in arguments list 592 unsigned tupleStart; ///< Number of tuples that start at this index 593 unsigned nextExpl; ///< Index of next exploded element 594 unsigned explAlt; ///< Index of alternative for nextExpl > 0 595 596 ArgPack() 597 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 599 tupleStart(0), nextExpl(0), explAlt(0) {} 573 AltList actuals; ///< Arguments included in this pack 574 TypeEnvironment env; ///< Environment for this pack 575 AssertionSet need; ///< Assertions outstanding for this pack 576 AssertionSet have; ///< Assertions found for this pack 577 OpenVarSet openVars; ///< Open variables for this pack 578 unsigned nextArg; ///< Index of next argument in arguments list 579 std::vector<Alternative> expls; ///< Exploded actuals left over from last match 580 unsigned nextExpl; ///< Index of next exploded alternative to use 581 std::vector<unsigned> tupleEls; /// Number of elements in current tuple element(s) 600 582 601 583 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 602 584 const OpenVarSet& openVars) 603 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 604 openVars(openVars), nextArg(0), tupleStart(0), nextExpl(0), explAlt(0) {} 605 606 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 607 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 608 unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0, 609 unsigned explAlt = 0 ) 610 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 611 have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart), 612 nextExpl(nextExpl), explAlt(explAlt) {} 613 614 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 615 OpenVarSet&& openVars, unsigned nextArg, Cost added ) 616 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 617 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 618 nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {} 619 620 /// true iff this pack is in the middle of an exploded argument 621 bool hasExpl() const { return nextExpl > 0; } 622 623 /// Gets the list of exploded alternatives for this pack 624 const ExplodedActual& getExpl( const ExplodedArgs& args ) const { 625 return args[nextArg-1][explAlt]; 585 : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0), 586 expls(), nextExpl(0), tupleEls() {} 587 588 /// Starts a new tuple expression 589 void beginTuple() { 590 if ( ! tupleEls.empty() ) ++tupleEls.back(); 591 tupleEls.push_back(0); 626 592 } 627 593 628 594 /// Ends a tuple expression, consolidating the appropriate actuals 629 void endTuple( const std::vector<ArgPack>& packs) {630 // add all expressions in tuple to list, summing cost595 void endTuple() { 596 // set up new Tuple alternative 631 597 std::list<Expression*> exprs; 632 const ArgPack* pack = this; 633 if ( expr ) { exprs.push_front( expr.release() ); } 634 while ( pack->tupleStart == 0 ) { 635 pack = &packs[pack->parent]; 636 exprs.push_front( pack->expr->clone() ); 637 cost += pack->cost; 638 } 639 // reset pack to appropriate tuple 640 expr.reset( new TupleExpr( exprs ) ); 641 tupleStart = pack->tupleStart - 1; 642 parent = pack->parent; 598 Cost cost = Cost::zero; 599 600 // transfer elements into alternative 601 for (unsigned i = 0; i < tupleEls.back(); ++i) { 602 exprs.push_front( actuals.back().expr ); 603 actuals.back().expr = nullptr; 604 cost += actuals.back().cost; 605 actuals.pop_back(); 606 } 607 tupleEls.pop_back(); 608 609 // build new alternative 610 actuals.emplace_back( new TupleExpr( exprs ), this->env, cost ); 611 } 612 613 /// Clones and adds an actual, returns this 614 ArgPack& withArg( Expression* expr, Cost cost = Cost::zero ) { 615 actuals.emplace_back( expr->clone(), this->env, cost ); 616 if ( ! tupleEls.empty() ) ++tupleEls.back(); 617 return *this; 643 618 } 644 619 }; … … 646 621 /// Instantiates an argument to match a formal, returns false if no results left 647 622 bool instantiateArgument( Type* formalType, Initializer* initializer, 648 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 649 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 623 const std::vector< AlternativeFinder >& args, 624 std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 625 const SymTab::Indexer& indexer ) { 650 626 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { 651 627 // formalType is a TupleType - group actuals into a TupleExpr 652 ++nTuples;628 for ( ArgPack& result : results ) { result.beginTuple(); } 653 629 for ( Type* type : *tupleType ) { 654 630 // xxx - dropping initializer changes behaviour from previous, but seems correct 655 if ( ! instantiateArgument( 656 type, nullptr, args, results, genStart, indexer, nTuples ) ) 631 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 657 632 return false; 658 nTuples = 0; 659 } 660 // re-consititute tuples for final generation 661 for ( auto i = genStart; i < results.size(); ++i ) { 662 results[i].endTuple( results ); 663 } 633 } 634 for ( ArgPack& result : results ) { result.endTuple(); } 664 635 return true; 665 636 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) { 666 637 // formalType is a ttype, consumes all remaining arguments 667 638 // xxx - mixing default arguments with variadic?? 668 669 // completed tuples; will be spliced to end of results to finish 670 std::vector<ArgPack> finalResults{}; 671 639 std::vector<ArgPack> finalResults{}; /// list of completed tuples 640 // start tuples 641 for ( ArgPack& result : results ) { 642 result.beginTuple(); 643 644 // use rest of exploded tuple if present 645 while ( result.nextExpl < result.expls.size() ) { 646 const Alternative& actual = result.expls[result.nextExpl]; 647 result.env.addActual( actual.env, result.openVars ); 648 result.withArg( actual.expr ); 649 ++result.nextExpl; 650 } 651 } 672 652 // iterate until all results completed 673 std::size_t genEnd; 674 ++nTuples; 675 do { 676 genEnd = results.size(); 677 653 while ( ! results.empty() ) { 678 654 // add another argument to results 679 for ( std::size_t i = genStart; i < genEnd; ++i ) { 680 auto nextArg = results[i].nextArg; 681 682 // use next element of exploded tuple if present 683 if ( results[i].hasExpl() ) { 684 const ExplodedActual& expl = results[i].getExpl( args ); 685 686 unsigned nextExpl = results[i].nextExpl + 1; 687 if ( nextExpl == expl.exprs.size() ) { 688 nextExpl = 0; 655 for ( ArgPack& result : results ) { 656 // finish result when out of arguments 657 if ( result.nextArg >= args.size() ) { 658 Type* argType = result.actuals.back().expr->get_result(); 659 if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) { 660 // the case where a ttype value is passed directly is special, e.g. for 661 // argument forwarding purposes 662 // xxx - what if passing multiple arguments, last of which is ttype? 663 // xxx - what would happen if unify was changed so that unifying tuple 664 // types flattened both before unifying lists? then pass in TupleType 665 // (ttype) below. 666 result.tupleEls.pop_back(); 667 } else { 668 // collapse leftover arguments into tuple 669 result.endTuple(); 670 argType = result.actuals.back().expr->get_result(); 689 671 } 690 691 results.emplace_back( 692 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 693 copy(results[i].need), copy(results[i].have), 694 copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl, 695 results[i].explAlt ); 696 672 // check unification for ttype before adding to final 673 if ( unify( ttype, argType, result.env, result.need, result.have, 674 result.openVars, indexer ) ) { 675 finalResults.push_back( std::move(result) ); 676 } 697 677 continue; 698 678 } 699 679 700 // finish result when out of arguments 701 if ( nextArg >= args.size() ) { 702 ArgPack newResult{ 703 results[i].env, results[i].need, results[i].have, 704 results[i].openVars }; 705 newResult.nextArg = nextArg; 706 Type* argType; 707 708 if ( nTuples > 0 ) { 709 // first iteration, push empty tuple expression 710 newResult.parent = i; 711 std::list<Expression*> emptyList; 712 newResult.expr.reset( new TupleExpr( emptyList ) ); 713 argType = newResult.expr->get_result(); 714 } else { 715 // clone result to collect tuple 716 newResult.parent = results[i].parent; 717 newResult.cost = results[i].cost; 718 newResult.tupleStart = results[i].tupleStart; 719 newResult.expr.reset( results[i].expr->clone() ); 720 argType = newResult.expr->get_result(); 721 722 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 723 // the case where a ttype value is passed directly is special, 724 // e.g. for argument forwarding purposes 725 // xxx - what if passing multiple arguments, last of which is 726 // ttype? 727 // xxx - what would happen if unify was changed so that unifying 728 // tuple 729 // types flattened both before unifying lists? then pass in 730 // TupleType (ttype) below. 731 --newResult.tupleStart; 732 } else { 733 // collapse leftover arguments into tuple 734 newResult.endTuple( results ); 735 argType = newResult.expr->get_result(); 736 } 680 // add each possible next argument 681 for ( const Alternative& actual : args[result.nextArg] ) { 682 ArgPack aResult = result; // copy to clone everything 683 // add details of actual to result 684 aResult.env.addActual( actual.env, aResult.openVars ); 685 Cost cost = actual.cost; 686 687 // explode argument 688 std::vector<Alternative> exploded; 689 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 690 691 // add exploded argument to tuple 692 for ( Alternative& aActual : exploded ) { 693 aResult.withArg( aActual.expr, cost ); 694 cost = Cost::zero; 737 695 } 738 739 // check unification for ttype before adding to final 740 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 741 newResult.openVars, indexer ) ) { 742 finalResults.push_back( move(newResult) ); 743 } 744 745 continue; 696 ++aResult.nextArg; 697 nextResults.push_back( std::move(aResult) ); 746 698 } 747 748 // add each possible next argument749 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {750 const ExplodedActual& expl = args[nextArg][j];751 752 // fresh copies of parent parameters for this iteration753 TypeEnvironment env = results[i].env;754 OpenVarSet openVars = results[i].openVars;755 756 env.addActual( expl.env, openVars );757 758 // skip empty tuple arguments by (near-)cloning parent into next gen759 if ( expl.exprs.empty() ) {760 results.emplace_back(761 results[i], move(env), copy(results[i].need),762 copy(results[i].have), move(openVars), nextArg + 1, expl.cost );763 764 continue;765 }766 767 // add new result768 results.emplace_back(769 i, expl.exprs.front().get(), move(env), copy(results[i].need),770 copy(results[i].have), move(openVars), nextArg + 1,771 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );772 }773 699 } 774 700 775 701 // reset for next round 776 genStart = genEnd; 777 nTuples = 0; 778 } while ( genEnd != results.size() ); 779 780 // splice final results onto results 781 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 782 results.push_back( move(finalResults[i]) ); 783 } 784 return ! finalResults.empty(); 702 results.swap( nextResults ); 703 nextResults.clear(); 704 } 705 results.swap( finalResults ); 706 return ! results.empty(); 785 707 } 786 708 787 709 // iterate each current subresult 788 std::size_t genEnd = results.size(); 789 for ( std::size_t i = genStart; i < genEnd; ++i ) { 790 auto nextArg = results[i].nextArg; 791 792 // use remainder of exploded tuple if present 793 if ( results[i].hasExpl() ) { 794 const ExplodedActual& expl = results[i].getExpl( args ); 795 Expression* expr = expl.exprs[results[i].nextExpl].get(); 796 797 TypeEnvironment env = results[i].env; 798 AssertionSet need = results[i].need, have = results[i].have; 799 OpenVarSet openVars = results[i].openVars; 800 801 Type* actualType = expr->get_result(); 710 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) { 711 ArgPack& result = results[iResult]; 712 713 if ( result.nextExpl < result.expls.size() ) { 714 // use remainder of exploded tuple if present 715 const Alternative& actual = result.expls[result.nextExpl]; 716 result.env.addActual( actual.env, result.openVars ); 717 Type* actualType = actual.expr->get_result(); 802 718 803 719 PRINT( … … 809 725 ) 810 726 811 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 812 unsigned nextExpl = results[i].nextExpl + 1; 813 if ( nextExpl == expl.exprs.size() ) { 814 nextExpl = 0; 815 } 816 817 results.emplace_back( 818 i, expr, move(env), move(need), move(have), move(openVars), nextArg, 819 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 727 if ( unify( formalType, actualType, result.env, result.need, result.have, 728 result.openVars, indexer ) ) { 729 ++result.nextExpl; 730 nextResults.push_back( std::move(result.withArg( actual.expr )) ); 820 731 } 821 732 822 733 continue; 823 } 824 825 // use default initializers if out of arguments 826 if ( nextArg >= args.size() ) { 734 } else if ( result.nextArg >= args.size() ) { 735 // use default initializers if out of arguments 827 736 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 828 737 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 829 TypeEnvironment env = results[i].env; 830 AssertionSet need = results[i].need, have = results[i].have; 831 OpenVarSet openVars = results[i].openVars; 832 833 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 834 indexer ) ) { 835 results.emplace_back( 836 i, cnstExpr, move(env), move(need), move(have), 837 move(openVars), nextArg, nTuples ); 738 if ( unify( formalType, cnst->get_type(), result.env, result.need, 739 result.have, result.openVars, indexer ) ) { 740 nextResults.push_back( std::move(result.withArg( cnstExpr )) ); 838 741 } 839 742 } 840 743 } 841 842 744 continue; 843 745 } 844 746 845 747 // Check each possible next argument 846 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 847 const ExplodedActual& expl = args[nextArg][j]; 848 849 // fresh copies of parent parameters for this iteration 850 TypeEnvironment env = results[i].env; 851 AssertionSet need = results[i].need, have = results[i].have; 852 OpenVarSet openVars = results[i].openVars; 853 854 env.addActual( expl.env, openVars ); 855 856 // skip empty tuple arguments by (near-)cloning parent into next gen 857 if ( expl.exprs.empty() ) { 858 results.emplace_back( 859 results[i], move(env), move(need), move(have), move(openVars), 860 nextArg + 1, expl.cost ); 861 748 for ( const Alternative& actual : args[result.nextArg] ) { 749 ArgPack aResult = result; // copy to clone everything 750 // add details of actual to result 751 aResult.env.addActual( actual.env, aResult.openVars ); 752 753 // explode argument 754 std::vector<Alternative> exploded; 755 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 756 if ( exploded.empty() ) { 757 // skip empty tuple arguments 758 ++aResult.nextArg; 759 results.push_back( std::move(aResult) ); 862 760 continue; 863 761 } 864 762 865 763 // consider only first exploded actual 866 Expression* expr = expl.exprs.front().get();867 Type* actualType = expr->get_result()->clone();764 const Alternative& aActual = exploded.front(); 765 Type* actualType = aActual.expr->get_result()->clone(); 868 766 869 767 PRINT( … … 876 774 877 775 // attempt to unify types 878 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 879 // add new result 880 results.emplace_back( 881 i, expr, move(env), move(need), move(have), move(openVars), nextArg + 1, 882 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 776 if ( unify( formalType, actualType, aResult.env, aResult.need, aResult.have, aResult.openVars, indexer ) ) { 777 // add argument 778 aResult.withArg( aActual.expr, actual.cost ); 779 ++aResult.nextArg; 780 if ( exploded.size() > 1 ) { 781 // other parts of tuple left over 782 aResult.expls = std::move( exploded ); 783 aResult.nextExpl = 1; 784 } 785 nextResults.push_back( std::move(aResult) ); 883 786 } 884 787 } … … 886 789 887 790 // reset for next parameter 888 genStart = genEnd; 889 890 return genEnd != results.size(); 891 } 892 893 template<typename OutputIterator> 894 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 895 const std::vector<ArgPack>& results, OutputIterator out ) { 896 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 897 // sum cost and accumulate actuals 898 std::list<Expression*>& args = appExpr->get_args(); 899 Cost cost = Cost::zero; 900 const ArgPack* pack = &result; 901 while ( pack->expr ) { 902 args.push_front( pack->expr->clone() ); 903 cost += pack->cost; 904 pack = &results[pack->parent]; 905 } 906 // build and validate new alternative 907 Alternative newAlt( appExpr, result.env, cost ); 908 PRINT( 909 std::cerr << "instantiate function success: " << appExpr << std::endl; 910 std::cerr << "need assertions:" << std::endl; 911 printAssertionSet( result.need, std::cerr, 8 ); 912 ) 913 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 791 results.swap( nextResults ); 792 nextResults.clear(); 793 794 return ! results.empty(); 914 795 } 915 796 916 797 template<typename OutputIterator> 917 798 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 918 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 799 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 800 OutputIterator out ) { 919 801 OpenVarSet funcOpenVars; 920 802 AssertionSet funcNeed, funcHave; … … 936 818 937 819 // iteratively build matches, one parameter at a time 938 std::vector<ArgPack> results; 939 results.push_back( ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } ); 940 std::size_t genStart = 0; 941 820 std::vector<ArgPack> results{ ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } }; 821 std::vector<ArgPack> nextResults{}; 942 822 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 943 823 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 944 824 if ( ! instantiateArgument( 945 obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )825 obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) ) 946 826 return; 947 827 } 948 828 829 // filter out results that don't use all the arguments, and aren't variadic 830 std::vector<ArgPack> finalResults{}; 949 831 if ( funcType->get_isVarArgs() ) { 950 // append any unused arguments to vararg pack 951 std::size_t genEnd; 952 do { 953 genEnd = results.size(); 954 955 // iterate results 956 for ( std::size_t i = genStart; i < genEnd; ++i ) { 957 auto nextArg = results[i].nextArg; 958 959 // use remainder of exploded tuple if present 960 if ( results[i].hasExpl() ) { 961 const ExplodedActual& expl = results[i].getExpl( args ); 962 963 unsigned nextExpl = results[i].nextExpl + 1; 964 if ( nextExpl == expl.exprs.size() ) { 965 nextExpl = 0; 966 } 967 968 results.emplace_back( 969 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 970 copy(results[i].need), copy(results[i].have), 971 copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl, 972 results[i].explAlt ); 973 832 for ( ArgPack& result : results ) { 833 // use rest of exploded tuple if present 834 while ( result.nextExpl < result.expls.size() ) { 835 const Alternative& actual = result.expls[result.nextExpl]; 836 result.env.addActual( actual.env, result.openVars ); 837 result.withArg( actual.expr ); 838 ++result.nextExpl; 839 } 840 } 841 842 while ( ! results.empty() ) { 843 // build combinations for all remaining arguments 844 for ( ArgPack& result : results ) { 845 // keep if used all arguments 846 if ( result.nextArg >= args.size() ) { 847 finalResults.push_back( std::move(result) ); 974 848 continue; 975 849 } 976 850 977 // finish result when out of arguments 978 if ( nextArg >= args.size() ) { 979 validateFunctionAlternative( func, results[i], results, out ); 980 981 continue; 851 // add each possible next argument 852 for ( const Alternative& actual : args[result.nextArg] ) { 853 ArgPack aResult = result; // copy to clone everything 854 // add details of actual to result 855 aResult.env.addActual( actual.env, aResult.openVars ); 856 Cost cost = actual.cost; 857 858 // explode argument 859 std::vector<Alternative> exploded; 860 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 861 862 // add exploded argument to arg list 863 for ( Alternative& aActual : exploded ) { 864 aResult.withArg( aActual.expr, cost ); 865 cost = Cost::zero; 866 } 867 ++aResult.nextArg; 868 nextResults.push_back( std::move(aResult) ); 982 869 } 983 984 // add each possible next argument 985 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 986 const ExplodedActual& expl = args[nextArg][j]; 987 988 // fresh copies of parent parameters for this iteration 989 TypeEnvironment env = results[i].env; 990 OpenVarSet openVars = results[i].openVars; 991 992 env.addActual( expl.env, openVars ); 993 994 // skip empty tuple arguments by (near-)cloning parent into next gen 995 if ( expl.exprs.empty() ) { 996 results.emplace_back( 997 results[i], move(env), copy(results[i].need), 998 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 999 1000 continue; 1001 } 1002 1003 // add new result 1004 results.emplace_back( 1005 i, expl.exprs.front().get(), move(env), copy(results[i].need), 1006 copy(results[i].have), move(openVars), nextArg + 1, 0, 1007 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 1008 } 1009 } 1010 1011 genStart = genEnd; 1012 } while ( genEnd != results.size() ); 870 } 871 872 // reset for next round 873 results.swap( nextResults ); 874 nextResults.clear(); 875 } 1013 876 } else { 1014 877 // filter out results that don't use all the arguments 1015 for ( std::size_t i = genStart; i < results.size(); ++i ) { 1016 ArgPack& result = results[i]; 1017 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 1018 validateFunctionAlternative( func, result, results, out ); 1019 } 1020 } 878 for ( ArgPack& result : results ) { 879 if ( result.nextExpl >= result.expls.size() && result.nextArg >= args.size() ) { 880 finalResults.push_back( std::move(result) ); 881 } 882 } 883 } 884 885 // validate matching combos, add to final result list 886 for ( ArgPack& result : finalResults ) { 887 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 888 Alternative newAlt( appExpr, result.env, sumCost( result.actuals ) ); 889 makeExprList( result.actuals, appExpr->get_args() ); 890 PRINT( 891 std::cerr << "instantiate function success: " << appExpr << std::endl; 892 std::cerr << "need assertions:" << std::endl; 893 printAssertionSet( result.need, std::cerr, 8 ); 894 ) 895 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 1021 896 } 1022 897 } … … 1045 920 printAlts( funcOpFinder.alternatives, std::cerr, 1 ); 1046 921 ) 1047 1048 // pre-explode arguments1049 ExplodedArgs argExpansions;1050 argExpansions.reserve( argAlternatives.size() );1051 1052 for ( const AlternativeFinder& arg : argAlternatives ) {1053 argExpansions.emplace_back();1054 auto& argE = argExpansions.back();1055 argE.reserve( arg.alternatives.size() );1056 1057 for ( const Alternative& actual : arg ) {1058 argE.emplace_back( actual, indexer );1059 }1060 }1061 922 1062 923 AltList candidates; … … 1073 934 Alternative newFunc( *func ); 1074 935 referenceToRvalueConversion( newFunc.expr ); 1075 makeFunctionAlternatives( newFunc, function, arg Expansions,936 makeFunctionAlternatives( newFunc, function, argAlternatives, 1076 937 std::back_inserter( candidates ) ); 1077 938 } … … 1082 943 Alternative newFunc( *func ); 1083 944 referenceToRvalueConversion( newFunc.expr ); 1084 makeFunctionAlternatives( newFunc, function, arg Expansions,945 makeFunctionAlternatives( newFunc, function, argAlternatives, 1085 946 std::back_inserter( candidates ) ); 1086 947 } // if … … 1094 955 // try each function operator ?() with each function alternative 1095 956 if ( ! funcOpFinder.alternatives.empty() ) { 1096 // add exploded function alternatives to front of argument list 1097 std::vector<ExplodedActual> funcE; 1098 funcE.reserve( funcFinder.alternatives.size() ); 1099 for ( const Alternative& actual : funcFinder ) { 1100 funcE.emplace_back( actual, indexer ); 1101 } 1102 argExpansions.insert( argExpansions.begin(), move(funcE) ); 957 // add function alternatives to front of argument list 958 argAlternatives.insert( argAlternatives.begin(), std::move(funcFinder) ); 1103 959 1104 960 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); … … 1112 968 Alternative newFunc( *funcOp ); 1113 969 referenceToRvalueConversion( newFunc.expr ); 1114 makeFunctionAlternatives( newFunc, function, arg Expansions,970 makeFunctionAlternatives( newFunc, function, argAlternatives, 1115 971 std::back_inserter( candidates ) ); 1116 972 } … … 1126 982 1127 983 // compute conversionsion costs 1128 for ( Alt ernative& withFunc : candidates) {1129 Cost cvtCost = computeApplicationConversionCost( withFunc, indexer );984 for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) { 985 Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer ); 1130 986 1131 987 PRINT( 1132 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc .expr );988 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc->expr ); 1133 989 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 1134 990 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); … … 1139 995 printAll( appExpr->get_args(), std::cerr, 8 ); 1140 996 std::cerr << "bindings are:" << std::endl; 1141 withFunc .env.print( std::cerr, 8 );997 withFunc->env.print( std::cerr, 8 ); 1142 998 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1143 999 ) 1144 1000 if ( cvtCost != Cost::infinity ) { 1145 withFunc .cvtCost = cvtCost;1146 alternatives.push_back( withFunc );1001 withFunc->cvtCost = cvtCost; 1002 alternatives.push_back( *withFunc ); 1147 1003 } // if 1148 1004 } // for 1149 1005 1150 candidates = move(alternatives); 1006 candidates.clear(); 1007 candidates.splice( candidates.end(), alternatives ); 1151 1008 1152 1009 // use a new list so that alternatives are not examined by addAnonConversions twice. … … 1154 1011 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1155 1012 1156 // function may return struct or union value, in which case we need to add alternatives 1157 // for implicitconversions to each of the anonymous members, must happen after findMinCost1158 // since anon conversionsare never the cheapest expression1013 // function may return struct or union value, in which case we need to add alternatives for implicit 1014 // conversions to each of the anonymous members, must happen after findMinCost since anon conversions 1015 // are never the cheapest expression 1159 1016 for ( const Alternative & alt : winners ) { 1160 1017 addAnonConversions( alt ); 1161 1018 } 1162 spliceBegin( alternatives, winners );1019 alternatives.splice( alternatives.begin(), winners ); 1163 1020 1164 1021 if ( alternatives.empty() && targetType && ! targetType->isVoid() ) { … … 1184 1041 AlternativeFinder finder( indexer, env ); 1185 1042 finder.find( addressExpr->get_arg() ); 1186 for ( Alternative& alt : finder.alternatives ) { 1187 if ( isLvalue( alt.expr ) ) { 1188 alternatives.push_back( 1189 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1043 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 1044 if ( isLvalue( i->expr ) ) { 1045 alternatives.push_back( Alternative( new AddressExpr( i->expr->clone() ), i->env, i->cost ) ); 1190 1046 } // if 1191 1047 } // for … … 1193 1049 1194 1050 void AlternativeFinder::visit( LabelAddressExpr * expr ) { 1195 alternatives.push_back( Alternative { expr->clone(), env, Cost::zero });1051 alternatives.push_back( Alternative( expr->clone(), env, Cost::zero) ); 1196 1052 } 1197 1053 … … 1235 1091 1236 1092 AltList candidates; 1237 for ( Alternative & alt : finder.alternatives) {1093 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 1238 1094 AssertionSet needAssertions, haveAssertions; 1239 1095 OpenVarSet openVars; … … 1243 1099 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1244 1100 // to. 1245 int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size();1101 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 1246 1102 if ( discardedValues < 0 ) continue; 1247 1103 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1248 1104 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1249 1105 // unification run for side-effects 1250 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1251 haveAssertions, openVars, indexer ); 1252 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1253 alt.env ); 1254 PRINT( 1255 std::cerr << "working on cast with result: " << castExpr->result << std::endl; 1256 std::cerr << "and expr type: " << alt.expr->result << std::endl; 1257 std::cerr << "env: " << alt.env << std::endl; 1258 ) 1106 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 1107 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 1259 1108 if ( thisCost != Cost::infinity ) { 1260 PRINT(1261 std::cerr << "has finite cost." << std::endl;1262 )1263 1109 // count one safe conversion for each value that is thrown away 1264 1110 thisCost.incSafe( discardedValues ); 1265 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1266 alt.cost, thisCost ); 1267 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1268 back_inserter( candidates ) ); 1111 Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ); 1112 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1269 1113 } // if 1270 1114 } // for … … 1553 1397 1554 1398 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1555 std::vector< AlternativeFinder > subExprAlternatives; 1556 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1557 back_inserter( subExprAlternatives ) ); 1558 std::vector< AltList > possibilities; 1559 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1560 back_inserter( possibilities ) ); 1561 for ( const AltList& alts : possibilities ) { 1399 std::list< AlternativeFinder > subExprAlternatives; 1400 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) ); 1401 std::list< AltList > possibilities; 1402 combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) ); 1403 for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) { 1562 1404 std::list< Expression * > exprs; 1563 makeExprList( alts, exprs );1405 makeExprList( *i, exprs ); 1564 1406 1565 1407 TypeEnvironment compositeEnv; 1566 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1567 alternatives.push_back( 1568 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1408 simpleCombineEnvironments( i->begin(), i->end(), compositeEnv ); 1409 alternatives.push_back( Alternative( new TupleExpr( exprs ) , compositeEnv, sumCost( *i ) ) ); 1569 1410 } // for 1570 1411 } -
src/ResolvExpr/AlternativeFinder.h
rf5478c8 r50abab9 21 21 22 22 #include "Alternative.h" // for AltList, Alternative 23 #include "ExplodedActual.h" // for ExplodedActual24 23 #include "ResolvExpr/Cost.h" // for Cost, Cost::infinity 25 24 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet … … 32 31 33 32 namespace ResolvExpr { 34 struct ArgPack;35 36 /// First index is which argument, second index is which alternative for that argument,37 /// third index is which exploded element of that alternative38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;39 40 33 class AlternativeFinder : public Visitor { 41 34 public: … … 43 36 44 37 AlternativeFinder( const AlternativeFinder& o ) 45 : indexer(o.indexer), alternatives(o.alternatives), env(o.env), 38 : indexer(o.indexer), alternatives(o.alternatives), env(o.env), 46 39 targetType(o.targetType) {} 47 40 48 41 AlternativeFinder( AlternativeFinder&& o ) 49 : indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env), 42 : indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env), 50 43 targetType(o.targetType) {} 51 44 52 45 AlternativeFinder& operator= ( const AlternativeFinder& o ) { 53 46 if (&o == this) return *this; 54 47 55 48 // horrific nasty hack to rebind references... 56 49 alternatives.~AltList(); … … 61 54 AlternativeFinder& operator= ( AlternativeFinder&& o ) { 62 55 if (&o == this) return *this; 63 56 64 57 // horrific nasty hack to rebind references... 65 58 alternatives.~AltList(); … … 133 126 /// Adds alternatives for offsetof expressions, given the base type and name of the member 134 127 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 135 /// Takes a final result and checks if its assertions can be satisfied136 128 template<typename OutputIterator> 137 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 138 /// Finds matching alternatives for a function, given a set of arguments 139 template<typename OutputIterator> 140 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 141 /// Checks if assertion parameters match for a new alternative 129 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const std::vector< AlternativeFinder >& args, OutputIterator out ); 142 130 template< typename OutputIterator > 143 131 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); -
src/ResolvExpr/PtrsAssignable.cc
rf5478c8 r50abab9 68 68 69 69 void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) { 70 // T * = void * is disallowed - this is a change from C, where any 71 // void * can be assigned or passed to a non-void pointer without a cast. 70 if ( ! dynamic_cast< FunctionType* >( dest ) ) { 71 // T * = void * is safe for any T that is not a function type. 72 // xxx - this should be unsafe... 73 result = 1; 74 } // if 72 75 } 73 76 -
src/ResolvExpr/Resolver.cc
rf5478c8 r50abab9 18 18 #include <memory> // for allocator, allocator_traits<... 19 19 #include <tuple> // for get 20 #include <vector>21 20 22 21 #include "Alternative.h" // for Alternative, AltList … … 412 411 413 412 // Find all alternatives for all arguments in canonical form 414 std:: vector< AlternativeFinder > argAlternatives;413 std::list< AlternativeFinder > argAlternatives; 415 414 funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) ); 416 415 417 416 // List all combinations of arguments 418 std:: vector< AltList > possibilities;417 std::list< AltList > possibilities; 419 418 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 420 419 -
src/ResolvExpr/TypeEnvironment.cc
rf5478c8 r50abab9 212 212 } 213 213 214 std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {215 env.print( out );216 return out;217 }218 214 } // namespace ResolvExpr 219 215 -
src/ResolvExpr/TypeEnvironment.h
rf5478c8 r50abab9 86 86 TypeEnvironment *clone() const { return new TypeEnvironment( *this ); } 87 87 88 /// Iteratively adds the environment of a new actual (with allowWidening = false), 88 /// Iteratively adds the environment of a new actual (with allowWidening = false), 89 89 /// and extracts open variables. 90 90 void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ); … … 114 114 return sub.applyFree( type ); 115 115 } 116 117 std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env );118 116 } // namespace ResolvExpr 119 117 -
src/ResolvExpr/module.mk
rf5478c8 r50abab9 32 32 ResolvExpr/Occurs.cc \ 33 33 ResolvExpr/TypeEnvironment.cc \ 34 ResolvExpr/CurrentObject.cc \ 35 ResolvExpr/ExplodedActual.cc 34 ResolvExpr/CurrentObject.cc -
src/ResolvExpr/typeops.h
rf5478c8 r50abab9 16 16 #pragma once 17 17 18 #include <vector>19 20 18 #include "SynTree/SynTree.h" 21 19 #include "SynTree/Type.h" … … 30 28 void combos( InputIterator begin, InputIterator end, OutputIterator out ) { 31 29 typedef typename InputIterator::value_type SetType; 32 typedef typename std:: vector< typename SetType::value_type > ListType;30 typedef typename std::list< typename SetType::value_type > ListType; 33 31 34 32 if ( begin == end ) { … … 40 38 begin++; 41 39 42 std:: vector< ListType > recursiveResult;40 std::list< ListType > recursiveResult; 43 41 combos( begin, end, back_inserter( recursiveResult ) ); 44 42 45 for ( const auto& i : recursiveResult ) for ( const auto& j : *current ) { 46 ListType result; 47 std::back_insert_iterator< ListType > inserter = back_inserter( result ); 48 *inserter++ = j; 49 std::copy( i.begin(), i.end(), inserter ); 50 *out++ = result; 51 } 43 for ( typename std::list< ListType >::const_iterator i = recursiveResult.begin(); i != recursiveResult.end(); ++i ) { 44 for ( typename ListType::const_iterator j = current->begin(); j != current->end(); ++j ) { 45 ListType result; 46 std::back_insert_iterator< ListType > inserter = back_inserter( result ); 47 *inserter++ = *j; 48 std::copy( i->begin(), i->end(), inserter ); 49 *out++ = result; 50 } // for 51 } // for 52 52 } 53 53 -
src/SymTab/Autogen.cc
rf5478c8 r50abab9 62 62 void previsit( FunctionDecl * functionDecl ); 63 63 64 void previsit( FunctionType * ftype ); 65 void previsit( PointerType * ptype ); 66 64 67 void previsit( CompoundStmt * compoundStmt ); 65 68 … … 69 72 unsigned int functionNesting = 0; // current level of nested functions 70 73 74 InitTweak::ManagedTypes managedTypes; 71 75 std::vector< FuncData > data; 72 76 }; … … 618 622 // generate ctor/dtors/assign for typedecls, e.g., otype T = int *; 619 623 void AutogenerateRoutines::previsit( TypeDecl * typeDecl ) { 624 visit_children = false; 620 625 if ( ! typeDecl->base ) return; 621 626 … … 623 628 TypeFuncGenerator gen( typeDecl, &refType, data, functionNesting, indexer ); 624 629 generateFunctions( gen, declsToAddAfter ); 625 630 } 631 632 void AutogenerateRoutines::previsit( FunctionType *) { 633 // ensure that we don't add assignment ops for types defined as part of the function 634 visit_children = false; 635 } 636 637 void AutogenerateRoutines::previsit( PointerType *) { 638 // ensure that we don't add assignment ops for types defined as part of the pointer 639 visit_children = false; 626 640 } 627 641 … … 631 645 } 632 646 633 void AutogenerateRoutines::previsit( FunctionDecl * ) { 634 // Track whether we're currently in a function. 635 // Can ignore function type idiosyncrasies, because function type can never 636 // declare a new type. 647 void AutogenerateRoutines::previsit( FunctionDecl * functionDecl ) { 648 visit_children = false; 649 // record the existence of this function as appropriate 650 managedTypes.handleDWT( functionDecl ); 651 652 maybeAccept( functionDecl->type, *visitor ); 637 653 functionNesting += 1; 638 GuardAction( [this]() { functionNesting -= 1; } ); 654 maybeAccept( functionDecl->statements, *visitor ); 655 functionNesting -= 1; 639 656 } 640 657 641 658 void AutogenerateRoutines::previsit( CompoundStmt * ) { 659 GuardScope( managedTypes ); 642 660 GuardScope( structsDone ); 643 661 } -
src/SymTab/Autogen.h
rf5478c8 r50abab9 56 56 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 57 57 template< typename OutputIterator > 58 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );58 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true ); 59 59 60 60 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. 61 61 /// optionally returns a statement which must be inserted prior to the containing loop, if there is one 62 62 template< typename OutputIterator > 63 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr) {63 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, bool addCast = false ) { 64 64 bool isReferenceCtorDtor = false; 65 65 if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) { … … 68 68 fname = "?=?"; 69 69 dstParam = new AddressExpr( dstParam ); 70 addCast = nullptr;70 addCast = false; 71 71 isReferenceCtorDtor = true; 72 72 } … … 83 83 // remove lvalue as a qualifier, this can change to 84 84 // type->get_qualifiers() = Type::Qualifiers(); 85 Type * castType = addCast->clone(); 85 assert( type ); 86 Type * castType = type->clone(); 86 87 castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 87 88 // castType->set_lvalue( true ); // xxx - might not need this … … 114 115 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0 115 116 template< typename OutputIterator > 116 void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {117 void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) { 117 118 static UniqueName indexName( "_index" ); 118 119 119 120 // for a flexible array member nothing is done -- user must define own assignment 120 if ( ! array->get_dimension() ) return; 121 122 if ( addCast ) { 123 // peel off array layer from cast 124 ArrayType * at = strict_dynamic_cast< ArrayType * >( addCast ); 125 addCast = at->base; 126 } 121 if ( ! array->get_dimension() ) return ; 127 122 128 123 Expression * begin, * end, * update, * cmp; … … 176 171 177 172 template< typename OutputIterator > 178 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type *addCast, bool forward ) {173 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) { 179 174 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 180 175 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward ); … … 196 191 if ( isUnnamedBitfield( obj ) ) return; 197 192 198 Type * addCast = nullptr; 199 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ) ) { 200 assert( dstParam->result ); 201 addCast = dstParam->result; 202 } 193 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ); 203 194 std::list< Statement * > stmts; 204 195 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward ); -
src/SymTab/Indexer.cc
rf5478c8 r50abab9 567 567 } 568 568 569 void Indexer::addIds( const std::list< DeclarationWithType * > & decls ) {570 for ( auto d : decls ) {571 addId( d );572 }573 }574 575 void Indexer::addTypes( const std::list< TypeDecl * > & tds ) {576 for ( auto td : tds ) {577 addType( td );578 addIds( td->assertions );579 }580 }581 582 void Indexer::addFunctionType( FunctionType * ftype ) {583 addTypes( ftype->forall );584 addIds( ftype->returnVals );585 addIds( ftype->parameters );586 }587 588 569 void Indexer::enterScope() { 589 570 ++scope; -
src/SymTab/Indexer.h
rf5478c8 r50abab9 76 76 void addTrait( TraitDecl *decl ); 77 77 78 /// convenience function for adding a list of Ids to the indexer79 void addIds( const std::list< DeclarationWithType * > & decls );80 81 /// convenience function for adding a list of forall parameters to the indexer82 void addTypes( const std::list< TypeDecl * > & tds );83 84 /// convenience function for adding all of the declarations in a function type to the indexer85 void addFunctionType( FunctionType * ftype );86 87 78 bool doDebug = false; ///< Display debugging trace? 88 79 private: -
src/SymTab/Validate.cc
rf5478c8 r50abab9 124 124 125 125 /// Associates forward declarations of aggregates with their definitions 126 struct LinkReferenceToTypes final : public WithIndexer , public WithGuards{126 struct LinkReferenceToTypes final : public WithIndexer { 127 127 LinkReferenceToTypes( const Indexer *indexer ); 128 128 void postvisit( TypeInstType *typeInst ); … … 137 137 void postvisit( UnionDecl *unionDecl ); 138 138 void postvisit( TraitDecl * traitDecl ); 139 140 void previsit( StructDecl *structDecl );141 void previsit( UnionDecl *unionDecl );142 143 void renameGenericParams( std::list< TypeDecl * > & params );144 139 145 140 private: … … 152 147 ForwardStructsType forwardStructs; 153 148 ForwardUnionsType forwardUnions; 154 /// true if currently in a generic type body, so that type parameter instances can be renamed appropriately155 bool inGeneric = false;156 149 }; 157 150 … … 568 561 } 569 562 570 void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {571 // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.572 // forall(otype T)573 // struct Box {574 // T x;575 // };576 // forall(otype T)577 // void f(Box(T) b) {578 // ...579 // }580 // The T in Box and the T in f are different, so internally the naming must reflect that.581 GuardValue( inGeneric );582 inGeneric = ! params.empty();583 for ( TypeDecl * td : params ) {584 td->name = "__" + td->name + "_generic_";585 }586 }587 588 void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {589 renameGenericParams( structDecl->parameters );590 }591 592 void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {593 renameGenericParams( unionDecl->parameters );594 }595 596 563 void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) { 597 564 // visit struct members first so that the types of self-referencing members are updated properly … … 621 588 622 589 void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) { 623 // ensure generic parameter instances are renamed like the base type624 if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;625 590 if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) { 626 591 if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) { -
src/SynTree/Expression.cc
rf5478c8 r50abab9 88 88 Type * type = var->get_type()->clone(); 89 89 type->set_lvalue( true ); 90 91 // xxx - doesn't quite work yet - get different alternatives with the same cost92 93 // // enumerators are not lvalues94 // if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( var->get_type() ) ) {95 // assert( inst->baseEnum );96 // EnumDecl * decl = inst->baseEnum;97 // for ( Declaration * member : decl->members ) {98 // if ( member == _var ) {99 // type->set_lvalue( false );100 // }101 // }102 // }103 104 90 set_result( type ); 105 91 } … … 338 324 return makeSub( refType->get_base() ); 339 325 } else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) { 340 return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst-> parameters.begin() );326 return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() ); 341 327 } else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) { 342 return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst-> parameters.begin() );328 return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() ); 343 329 } else { 344 330 assertf( false, "makeSub expects struct or union type for aggregate, but got: %s", toString( t ).c_str() ); -
src/Tuples/Explode.h
rf5478c8 r50abab9 16 16 #pragma once 17 17 18 #include <iterator> // for back_inserter, back_insert_iterator 19 #include <utility> // for forward 18 #include <iterator> // for back_inserter, back_insert_iterator 20 19 21 #include "ResolvExpr/Alternative.h" // for Alternative, AltList 22 #include "ResolvExpr/ExplodedActual.h" // for ExplodedActual 23 #include "SynTree/Expression.h" // for Expression, UniqueExpr, AddressExpr 24 #include "SynTree/Type.h" // for TupleType, Type 25 #include "Tuples.h" // for maybeImpure 20 #include "ResolvExpr/Alternative.h" // for Alternative, AltList 21 #include "SynTree/Expression.h" // for Expression, UniqueExpr, AddressExpr 22 #include "SynTree/Type.h" // for TupleType, Type 23 #include "Tuples.h" // for maybeImpure 26 24 27 25 namespace SymTab { … … 41 39 } 42 40 43 /// Append alternative to an OutputIterator of Alternatives44 template<typename OutputIterator>45 void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,46 const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {47 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };48 }49 50 /// Append alternative to an ExplodedActual51 static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,52 const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {53 ea.exprs.emplace_back( expr );54 /// xxx -- merge environment, cost?55 }56 57 41 /// helper function used by explode 58 template< typename Output > 59 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, 60 const SymTab::Indexer & indexer, Output&& out, bool isTupleAssign ) { 42 template< typename OutputIterator > 43 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign ) { 61 44 if ( isTupleAssign ) { 62 45 // tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components 63 46 if ( CastExpr * castExpr = isReferenceCast( expr ) ) { 64 47 ResolvExpr::AltList alts; 65 explodeUnique( 66 castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign ); 48 explodeUnique( castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign ); 67 49 for ( ResolvExpr::Alternative & alt : alts ) { 68 50 // distribute reference cast over all components 69 a ppend( std::forward<Output>(out), distributeReference( alt.release_expr() ),70 alt.env, alt.cost, alt.cvtCost );51 alt.expr = distributeReference( alt.expr ); 52 *out++ = alt; 71 53 } 72 54 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives) … … 79 61 // can open tuple expr and dump its exploded components 80 62 for ( Expression * expr : tupleExpr->get_exprs() ) { 81 explodeUnique( expr, alt, indexer, std::forward<Output>(out), isTupleAssign );63 explodeUnique( expr, alt, indexer, out, isTupleAssign ); 82 64 } 83 65 } else { … … 95 77 for ( unsigned int i = 0; i < tupleType->size(); i++ ) { 96 78 TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i ); 97 explodeUnique( idx, alt, indexer, std::forward<Output>(out), isTupleAssign );79 explodeUnique( idx, alt, indexer, out, isTupleAssign ); 98 80 delete idx; 99 81 } … … 102 84 } else { 103 85 // atomic (non-tuple) type - output a clone of the expression in a new alternative 104 append( std::forward<Output>(out),expr->clone(), alt.env, alt.cost, alt.cvtCost );86 *out++ = ResolvExpr::Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost ); 105 87 } 106 88 } 107 89 108 90 /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type 109 template< typename Output > 110 void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, 111 Output&& out, bool isTupleAssign = false ) { 112 explodeUnique( alt.expr, alt, indexer, std::forward<Output>(out), isTupleAssign ); 91 template< typename OutputIterator > 92 void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign = false ) { 93 explodeUnique( alt.expr, alt, indexer, out, isTupleAssign ); 113 94 } 114 95 115 96 // explode list of alternatives 116 template< typename AltIterator, typename Output > 117 void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, 118 Output&& out, bool isTupleAssign = false ) { 97 template< typename AltIterator, typename OutputIterator > 98 void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign = false ) { 119 99 for ( ; altBegin != altEnd; ++altBegin ) { 120 explode( *altBegin, indexer, std::forward<Output>(out), isTupleAssign );100 explode( *altBegin, indexer, out, isTupleAssign ); 121 101 } 122 102 } 123 103 124 template< typename Output > 125 void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out, 126 bool isTupleAssign = false ) { 127 explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign ); 104 template< typename OutputIterator > 105 void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign = false ) { 106 explode( alts.begin(), alts.end(), indexer, out, isTupleAssign ); 128 107 } 129 108 } // namespace Tuples -
src/Tuples/TupleAssignment.cc
rf5478c8 r50abab9 251 251 // combine assignment environments into combined expression environment 252 252 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv ); 253 // xxx -- was push_front 254 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative( 253 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative( 255 254 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 256 255 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); -
src/libcfa/concurrency/kernel
rf5478c8 r50abab9 108 108 #ifdef __CFA_DEBUG__ 109 109 // Last function to enable preemption on this processor 110 c onst char * last_enable;110 char * last_enable; 111 111 #endif 112 112 }; -
src/libcfa/concurrency/monitor.c
rf5478c8 r50abab9 823 823 this.monitor_count = thrd->monitors.size; 824 824 825 this.monitors = (monitor_desc **)malloc( this.monitor_count * sizeof( *this.monitors ) );825 this.monitors = malloc( this.monitor_count * sizeof( *this.monitors ) ); 826 826 for( int i = 0; i < this.monitor_count; i++ ) { 827 827 this.monitors[i] = thrd->monitors[i]; -
src/libcfa/stdhdr/stddef.h
rf5478c8 r50abab9 4 4 // The contents of this file are covered under the licence agreement in the 5 5 // file "LICENCE" distributed with Cforall. 6 // 7 // stddef.h -- 8 // 6 // 7 // stddef.h -- 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Mon Jul 4 23:25:26 2016 … … 12 12 // Last Modified On : Tue Jul 5 20:40:01 2016 13 13 // Update Count : 12 14 // 14 // 15 15 16 16 extern "C" { 17 #include_next <stddef.h> // has internal check for multiple expansion 18 #undef NULL 19 #define NULL 0 // define NULL as 0 rather than (void*)0 to take advantage of zero_t 17 #include_next <stddef.h> // has internal check for multiple expansion 20 18 } // extern "C" 21 19 -
src/libcfa/stdlib
rf5478c8 r50abab9 77 77 //printf( "X8\n" ); 78 78 T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 79 return (T *)memset( ptr, (int)fill, sizeof(T) ); // initial with fill value79 return memset( ptr, (int)fill, sizeof(T) ); // initial with fill value 80 80 } // alloc 81 81 … … 87 87 //printf( "X10\n" ); 88 88 T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc 89 return (T *)memset( ptr, (int)fill, dim * sizeof(T) );89 return memset( ptr, (int)fill, dim * sizeof(T) ); 90 90 } // alloc 91 91 92 92 static inline forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim ) { 93 93 //printf( "X11\n" ); 94 return ( T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc94 return (void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc 95 95 } // alloc 96 96 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill ); … … 103 103 //printf( "X14\n" ); 104 104 T * ptr = (T *)memalign( align, sizeof(T) ); 105 return (T *)memset( ptr, (int)fill, sizeof(T) );105 return memset( ptr, (int)fill, sizeof(T) ); 106 106 } // align_alloc 107 107 … … 113 113 //printf( "X16\n" ); 114 114 T * ptr = (T *)memalign( align, dim * sizeof(T) ); 115 return (T *)memset( ptr, (int)fill, dim * sizeof(T) );115 return memset( ptr, (int)fill, dim * sizeof(T) ); 116 116 } // align_alloc 117 117 … … 120 120 static inline forall( dtype T | sized(T) ) T * memset( T * dest, char c ) { 121 121 //printf( "X17\n" ); 122 return (T *)memset( dest, c, sizeof(T) );122 return memset( dest, c, sizeof(T) ); 123 123 } // memset 124 124 extern "C" { void * memcpy( void * dest, const void * src, size_t size ); } // use default C routine for void * 125 125 static inline forall( dtype T | sized(T) ) T * memcpy( T * dest, const T * src ) { 126 126 //printf( "X18\n" ); 127 return (T *)memcpy( dest, src, sizeof(T) );127 return memcpy( dest, src, sizeof(T) ); 128 128 } // memcpy 129 129 … … 131 131 static inline forall( dtype T | sized(T) ) T * memset( T dest[], size_t dim, char c ) { 132 132 //printf( "X19\n" ); 133 return ( T *)(void *)memset( dest, c, dim * sizeof(T) ); // C memset133 return (void *)memset( dest, c, dim * sizeof(T) ); // C memset 134 134 } // memset 135 135 static inline forall( dtype T | sized(T) ) T * memcpy( T dest[], const T src[], size_t dim ) { 136 136 //printf( "X20\n" ); 137 return ( T *)(void *)memcpy( dest, src, dim * sizeof(T) ); // C memcpy137 return (void *)memcpy( dest, src, dim * sizeof(T) ); // C memcpy 138 138 } // memcpy 139 139 -
src/prelude/prelude.cf
rf5478c8 r50abab9 403 403 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * volatile &, const volatile DT * ); 404 404 405 forall( dtype DT ) DT * ?=?( DT * &, void * ); 406 forall( dtype DT ) DT * ?=?( DT * volatile &, void * ); 407 forall( dtype DT ) const DT * ?=?( const DT * &, void * ); 408 forall( dtype DT ) const DT * ?=?( const DT * volatile &, void * ); 409 forall( dtype DT ) const DT * ?=?( const DT * &, const void * ); 410 forall( dtype DT ) const DT * ?=?( const DT * volatile &, const void * ); 411 forall( dtype DT ) volatile DT * ?=?( volatile DT * &, void * ); 412 forall( dtype DT ) volatile DT * ?=?( volatile DT * volatile &, void * ); 413 forall( dtype DT ) volatile DT * ?=?( volatile DT * &, volatile void * ); 414 forall( dtype DT ) volatile DT * ?=?( volatile DT * volatile &, volatile void * ); 415 416 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * &, void * ); 417 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * volatile &, void * ); 418 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * &, const void * ); 419 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * volatile &, const void * ); 420 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * &, volatile void * ); 421 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * volatile &, volatile void * ); 422 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * &, const volatile void * ); 423 forall( dtype DT ) const volatile DT * ?=?( const volatile DT * volatile &, const volatile void * ); 424 405 425 forall( dtype DT ) void * ?=?( void * &, DT * ); 406 426 forall( dtype DT ) void * ?=?( void * volatile &, DT * ); … … 421 441 forall( dtype DT ) const volatile void * ?=?( const volatile void * &, const volatile DT * ); 422 442 forall( dtype DT ) const volatile void * ?=?( const volatile void * volatile &, const volatile DT * ); 443 444 void * ?=?( void * &, void * ); 445 void * ?=?( void * volatile &, void * ); 446 const void * ?=?( const void * &, void * ); 447 const void * ?=?( const void * volatile &, void * ); 448 const void * ?=?( const void * &, const void * ); 449 const void * ?=?( const void * volatile &, const void * ); 450 volatile void * ?=?( volatile void * &, void * ); 451 volatile void * ?=?( volatile void * volatile &, void * ); 452 volatile void * ?=?( volatile void * &, volatile void * ); 453 volatile void * ?=?( volatile void * volatile &, volatile void * ); 454 const volatile void * ?=?( const volatile void * &, void * ); 455 const volatile void * ?=?( const volatile void * volatile &, void * ); 456 const volatile void * ?=?( const volatile void * &, const void * ); 457 const volatile void * ?=?( const volatile void * volatile &, const void * ); 458 const volatile void * ?=?( const volatile void * &, volatile void * ); 459 const volatile void * ?=?( const volatile void * volatile &, volatile void * ); 460 const volatile void * ?=?( const volatile void * &, const volatile void * ); 461 const volatile void * ?=?( const volatile void * volatile &, const volatile void * ); 423 462 424 463 //forall( dtype DT ) DT * ?=?( DT * &, zero_t ); … … 742 781 forall( dtype DT ) void ?{}( const volatile DT * &, const volatile DT * ); 743 782 783 forall( dtype DT ) void ?{}( DT * &, void * ); 784 forall( dtype DT ) void ?{}( const DT * &, void * ); 785 forall( dtype DT ) void ?{}( const DT * &, const void * ); 786 forall( dtype DT ) void ?{}( volatile DT * &, void * ); 787 forall( dtype DT ) void ?{}( volatile DT * &, volatile void * ); 788 789 forall( dtype DT ) void ?{}( const volatile DT * &, void * ); 790 forall( dtype DT ) void ?{}( const volatile DT * &, const void * ); 791 forall( dtype DT ) void ?{}( const volatile DT * &, volatile void * ); 792 forall( dtype DT ) void ?{}( const volatile DT * &, const volatile void * ); 793 744 794 forall( dtype DT ) void ?{}( void * &, DT * ); 745 795 forall( dtype DT ) void ?{}( const void * &, DT * ); … … 752 802 forall( dtype DT ) void ?{}( const volatile void * &, const volatile DT * ); 753 803 804 void ?{}( void * &, void * ); 805 void ?{}( const void * &, void * ); 806 void ?{}( const void * &, const void * ); 807 void ?{}( volatile void * &, void * ); 808 void ?{}( volatile void * &, volatile void * ); 809 void ?{}( const volatile void * &, void * ); 810 void ?{}( const volatile void * &, const void * ); 811 void ?{}( const volatile void * &, volatile void * ); 812 void ?{}( const volatile void * &, const volatile void * ); 813 754 814 //forall( dtype DT ) void ?{}( DT * &, zero_t ); 755 815 //forall( dtype DT ) void ?{}( DT * volatile &, zero_t ); -
src/tests/.expect/castError.txt
rf5478c8 r50abab9 5 5 charAlternatives are: 6 6 Cost ( 1, 0, 0, 0 ): Cast of: 7 Variable Expression: f: function 8 accepting unspecified arguments 9 ... returning nothing 10 7 Variable Expression: f: signed int 11 8 ... to: 12 9 char … … 26 23 27 24 Cost ( 1, 0, 0, 0 ): Cast of: 28 Variable Expression: f: signed int 25 Variable Expression: f: function 26 accepting unspecified arguments 27 ... returning nothing 28 29 29 ... to: 30 30 char -
src/tests/.expect/completeTypeError.txt
rf5478c8 r50abab9 1 completeTypeError.c:3 3:1 error: No reasonable alternatives for expression Applying untyped:1 completeTypeError.c:34:1 error: No reasonable alternatives for expression Applying untyped: 2 2 Name: *? 3 3 ...to: 4 4 Name: v 5 5 6 completeTypeError.c:34:1 error: No reasonable alternatives for expression Applying untyped:7 Name: *?8 ...to:9 Name: y10 11 completeTypeError.c:35:1 error: No reasonable alternatives for expression Applying untyped:12 Name: foo13 ...to:14 Name: v15 6 16 7 completeTypeError.c:36:1 error: No reasonable alternatives for expression Applying untyped: … … 19 10 Name: v 20 11 12 21 13 completeTypeError.c:37:1 error: No reasonable alternatives for expression Applying untyped: 22 14 Name: quux 23 15 ...to: 24 16 Name: v 17 25 18 26 19 completeTypeError.c:58:1 error: No reasonable alternatives for expression Applying untyped: … … 29 22 Name: y 30 23 24 31 25 completeTypeError.c:59:1 error: No reasonable alternatives for expression Applying untyped: 32 26 Name: quux 33 27 ...to: 34 28 Name: y 29 35 30 36 31 completeTypeError.c:60:1 error: No reasonable alternatives for expression Applying untyped: … … 39 34 Name: y 40 35 36 41 37 completeTypeError.c:72:1 error: No reasonable alternatives for expression Applying untyped: 42 38 Name: baz … … 44 40 Name: z 45 41 42 -
src/tests/Makefile.am
rf5478c8 r50abab9 141 141 typedefRedef-ERR1: typedefRedef.c @CFA_BINDIR@/@CFA_NAME@ 142 142 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 143 144 alloc-ERROR: alloc.c @CFA_BINDIR@/@CFA_NAME@145 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} -
src/tests/Makefile.in
rf5478c8 r50abab9 895 895 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 896 896 897 alloc-ERROR: alloc.c @CFA_BINDIR@/@CFA_NAME@898 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}899 900 897 # Tell versions [3.59,3.63) of GNU make to not export all variables. 901 898 # Otherwise a system limit (for SysV at least) may be exceeded. -
src/tests/alloc.c
rf5478c8 r50abab9 32 32 // allocation, non-array types 33 33 34 p = ( int *)(void *)malloc( sizeof(*p) ); // C malloc, type unsafe34 p = (void *)malloc( sizeof(*p) ); // C malloc, type unsafe 35 35 *p = 0xdeadbeef; 36 36 printf( "C malloc %#x\n", *p ); … … 54 54 printf( "\n" ); 55 55 56 p = (int *)calloc( dim, sizeof( *p ) ); // C array calloc, type unsafe56 p = calloc( dim, sizeof( *p ) ); // C array calloc, type unsafe 57 57 printf( "C array calloc, fill 0\n" ); 58 58 for ( int i = 0; i < dim; i += 1 ) { printf( "%#x ", p[i] ); } … … 83 83 printf( "\n" ); 84 84 85 p = ( int *)(void *)realloc( p, dim * sizeof(*p) ); // C realloc85 p = (void *)realloc( p, dim * sizeof(*p) ); // C realloc 86 86 for ( int i = 0; i < dim; i += 1 ) { p[i] = 0xdeadbeef; } 87 87 printf( "C realloc\n" ); … … 256 256 stp = malloc(); 257 257 printf( "\nSHOULD FAIL\n" ); 258 #ifdef ERR1259 258 p = alloc( stp, dim * sizeof(*stp) ); 260 259 p = memset( stp, 10 ); 261 260 p = memcpy( &st1, &st ); 262 #endif263 261 } // main 264 262 -
src/tests/completeTypeError.c
rf5478c8 r50abab9 12 12 void *v; 13 13 14 A * x;15 A * y;16 B * x;17 B * z;14 // A * x; 15 // A * y; 16 // B * x; 17 // B * z; 18 18 19 19 // okay 20 20 *i; 21 *x; // picks B22 *z;21 // *x; // picks B 22 // *z; 23 23 foo(i); 24 24 bar(i); … … 29 29 bar(v); 30 30 qux(v); 31 foo(v); // questionable, but works at the moment for C compatibility 31 32 32 33 // bad 33 34 *v; 34 *y; 35 foo(v); 35 // *y; 36 36 baz(v); 37 37 quux(v); -
src/tests/dtor-early-exit.c
rf5478c8 r50abab9 22 22 23 23 struct A { 24 c onst char * name;24 char * name; 25 25 int * x; 26 26 }; -
src/tests/init_once.c
rf5478c8 r50abab9 72 72 insert( &constructed, &x ); 73 73 74 x.x = (int *)malloc(sizeof(int));74 x.x = malloc(sizeof(int)); 75 75 } 76 76 -
src/tests/multiDimension.c
rf5478c8 r50abab9 7 7 printf("default constructing\n"); 8 8 (this.a){ 123 }; 9 this.ptr = (int *)malloc(sizeof(int));9 this.ptr = malloc(sizeof(int)); 10 10 } 11 11 … … 13 13 printf("copy constructing\n"); 14 14 (this.a){ other.a }; 15 this.ptr = (int *)malloc(sizeof(int));15 this.ptr = malloc(sizeof(int)); 16 16 } 17 17 … … 19 19 printf("constructing with %d\n", a); 20 20 (this.a){ a }; 21 this.ptr = (int *)malloc(sizeof(int));21 this.ptr = malloc(sizeof(int)); 22 22 } 23 23 -
src/tests/polymorphism.c
rf5478c8 r50abab9 14 14 // 15 15 16 #include <assert.h>17 #include <inttypes.h>18 19 16 forall(otype T) 20 17 T f(T x, T y) { … … 27 24 } 28 25 29 forall( otype T, otype U ) 30 size_t struct_size( T i, U j ) { 31 struct S { T i; U j; }; 32 return sizeof(S); 33 } 26 int main() { 27 // ensure that x is not changed by the invocation of a polymorphic function 28 int x = 123; 29 int y = 456; 30 int z = f(x, y); 31 printf("%d %d %d\n", x, y, z); 34 32 35 forall( otype T, otype U ) 36 size_t union_size( T i, U j ) { 37 union B { T i; U j; }; 38 return sizeof(B); 39 } 40 41 // perform some simple operations on aggregates of T and U 42 forall( otype T | { void print(T); int ?==?(T, T); }, otype U | { void print(U); U ?=?(U&, zero_t); } ) 43 U foo(T i, U j) { 44 struct S { T i; U j; }; 45 union B { T i; U j; }; 46 47 S s; 48 s.i = i; 49 assert(s.i == i); 50 51 B b; 52 b.j = 0; 53 b.i = s.i; 54 return b.j; 55 } 56 57 int main() { 58 { 59 // ensure that x is not changed by the invocation of a polymorphic function 60 int x = 123; 61 int y = 456; 62 int z = f(x, y); 63 printf("%d %d %d\n", x, y, z); 64 } 65 66 { 67 // explicitly specialize function 68 int (*f)(int) = ident; 69 ((int(*)(int))ident); 70 printf("%d %d\n", f(5), ((int(*)(int))ident)(5)); 71 } 72 73 { 74 // test aggregates with polymorphic members 75 typedef uint32_t x_type; 76 typedef uint64_t y_type; 77 78 x_type x = 3; 79 y_type y = 3; 80 81 struct S { 82 x_type f1; 83 y_type f2; 84 }; 85 union U { 86 x_type f1; 87 y_type f2; 88 }; 89 // ensure that the size of aggregates with polymorphic members 90 // matches the size of the aggregates in a monomorphic context 91 assert( struct_size(x, y) == sizeof(S) ); 92 assert( union_size(x, y) == sizeof(U) ); 93 94 y_type ?=?(y_type & this, zero_t) { 95 this = (int)0; 96 return this; 97 } 98 99 void print(x_type x) { 100 printf("%"PRIu32"\n", x); 101 } 102 103 void print(y_type y) { 104 printf("%"PRIu64"\n", y); 105 } 106 107 y_type ret = foo(x, y); 108 109 // duplicate logic from inside of foo to ensure the same results 110 U u; 111 u.f2 = 0; 112 u.f1 = x; 113 assert(ret == u.f2); 114 } 33 // explicitly specialize function 34 int (*f)(int) = ident; 35 ((int(*)(int))ident); 36 printf("%d %d\n", f(5), ((int(*)(int))ident)(5)); 115 37 } 116 38 -
src/tests/tupleVariadic.c
rf5478c8 r50abab9 73 73 [a0, a1, a2, a3] = args; 74 74 a.size = 4; 75 a.data = (int *)malloc(sizeof(int)*a.size);75 a.data = malloc(sizeof(int)*a.size); 76 76 a.data[0] = a0; 77 77 a.data[1] = a1; -
src/tests/vector/vector_int.c
rf5478c8 r50abab9 27 27 vec.last = -1; 28 28 vec.capacity = reserve; 29 vec.data = (int *)malloc( sizeof( int ) * reserve );29 vec.data = malloc( sizeof( int ) * reserve ); 30 30 } 31 31 … … 33 33 vec.last = other.last; 34 34 vec.capacity = other.capacity; 35 vec.data = (int *)malloc( sizeof( int ) * other.capacity );35 vec.data = malloc( sizeof( int ) * other.capacity ); 36 36 for (int i = 0; i < vec.last; i++) { 37 37 vec.data[i] = other.data[i]; … … 45 45 void reserve( vector_int *vec, int reserve ) { 46 46 if ( reserve > vec->capacity ) { 47 vec->data = (int *)realloc( vec->data, sizeof( int ) * reserve );47 vec->data = realloc( vec->data, sizeof( int ) * reserve ); 48 48 vec->capacity = reserve; 49 49 } … … 54 54 if ( vec->last == vec->capacity ) { 55 55 vec->capacity *= 2; 56 vec->data = (int *)realloc( vec->data, sizeof( int ) * vec->capacity );56 vec->data = realloc( vec->data, sizeof( int ) * vec->capacity ); 57 57 } 58 58 vec->data[ vec->last ] = element;
Note: See TracChangeset
for help on using the changeset viewer.