- Timestamp:
- Jun 4, 2019, 6:39:23 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- c6a1e8a
- Parents:
- 7564e10 (diff), 1346914 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 4 added
- 38 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r7564e10 r67130fe 47 47 namespace { 48 48 49 // This is to preserve the SymTab::dereferenceOperatorhack. It does not (and perhaps should not)49 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not) 50 50 // allow us to use the same stratagy in the new ast. 51 51 ast::FunctionDecl * dereferenceOperator = nullptr; 52 ast::StructDecl * dtorStruct = nullptr; 53 ast::FunctionDecl * dtorStructDestroy = nullptr; 52 54 53 55 } … … 75 77 std::list< T * > acceptL( const U & container ) { 76 78 std::list< T * > ret; 77 for ( auto ptr : container ) {79 for ( auto ptr : container ) { 78 80 ret.emplace_back( accept1( ptr ) ); 79 81 } … … 176 178 Validate::dereferenceOperator = decl; 177 179 } 180 if ( dtorStructDestroy == node ) { 181 Validate::dtorStructDestroy = decl; 182 } 178 183 return declWithTypePostamble( decl, node ); 179 184 } … … 231 236 LinkageSpec::Spec( node->linkage.val ) 232 237 ); 238 239 if ( dtorStruct == node ) { 240 Validate::dtorStruct = decl; 241 } 242 233 243 return aggregatePostamble( decl, node ); 234 244 } … … 1445 1455 }; 1446 1456 cache.emplace( old, decl ); 1457 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1447 1458 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); 1448 1459 decl->scopeLevel = old->scopeLevel; … … 1456 1467 if ( Validate::dereferenceOperator == old ) { 1457 1468 dereferenceOperator = decl; 1469 } 1470 1471 if ( Validate::dtorStructDestroy == old ) { 1472 dtorStructDestroy = decl; 1458 1473 } 1459 1474 } … … 1478 1493 1479 1494 this->node = decl; 1495 1496 if ( Validate::dtorStruct == old ) { 1497 dtorStruct = decl; 1498 } 1480 1499 } 1481 1500 -
src/AST/Decl.cpp
r7564e10 r67130fe 17 17 18 18 #include <cassert> // for assert, strict_dynamic_cast 19 #include <iostream> 19 20 #include <string> 20 21 #include <unordered_map> … … 70 71 } 71 72 73 std::ostream & operator<< ( std::ostream & out, const TypeDecl::Data & data ) { 74 return out << data.kind << ", " << data.isComplete; 75 } 76 72 77 // --- EnumDecl 73 78 -
src/AST/Decl.hpp
r7564e10 r67130fe 16 16 #pragma once 17 17 18 #include <iosfwd> 18 19 #include <string> // for string, to_string 19 20 #include <unordered_map> … … 101 102 ptr<Expr> bitfieldWidth; 102 103 103 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, Init * init = nullptr, 104 Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, Expr * bitWd = nullptr, 105 std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {}) 104 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, 105 Init * init = nullptr, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 106 Expr * bitWd = nullptr, std::vector< ptr<Attribute> > && attrs = {}, 107 Function::Specs fs = {} ) 106 108 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ), 107 109 init( init ), bitfieldWidth( bitWd ) {} … … 121 123 ptr<FunctionType> type; 122 124 ptr<CompoundStmt> stmts; 123 std:: list< ptr<Expr> > withExprs;125 std::vector< ptr<Expr> > withExprs; 124 126 125 127 FunctionDecl( const CodeLocation & loc, const std::string &name, FunctionType * type, … … 172 174 173 175 Data() : kind( (TypeVar::Kind)-1 ), isComplete( false ) {} 174 Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {}176 Data( const TypeDecl * d ) : kind( d->kind ), isComplete( d->sized ) {} 175 177 Data( TypeVar::Kind k, bool c ) : kind( k ), isComplete( c ) {} 176 Data( const Data & d1, const Data& d2 )178 Data( const Data & d1, const Data & d2 ) 177 179 : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {} 178 180 179 bool operator== ( const Data & o ) const {181 bool operator== ( const Data & o ) const { 180 182 return kind == o.kind && isComplete == o.isComplete; 181 183 } 182 bool operator!= ( const Data & o ) const { return !(*this == o); }184 bool operator!= ( const Data & o ) const { return !(*this == o); } 183 185 }; 184 186 … … 200 202 MUTATE_FRIEND 201 203 }; 204 205 std::ostream & operator<< ( std::ostream &, const TypeDecl::Data & ); 202 206 203 207 /// C-style typedef `typedef Foo Bar` -
src/AST/Expr.cpp
r7564e10 r67130fe 64 64 // references have been removed, in which case dereference returns an lvalue of the 65 65 // base type 66 ret->result.set_and_mutate( base )->set_lvalue( true ); 66 ret->result = base; 67 add_qualifiers( ret->result, CV::Lvalue ); 67 68 } 68 69 } … … 164 165 genericSubsitution( aggregate->result ).apply( result ); 165 166 // ensure lvalue and appropriate restrictions from aggregate type 166 result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;167 add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue ); 167 168 } 168 169 … … 173 174 assert( var ); 174 175 assert( var->get_type() ); 175 result.set_and_mutate( var->get_type() )->set_lvalue( true ); 176 result = var->get_type(); 177 add_qualifiers( result, CV::Lvalue ); 176 178 } 177 179 … … 306 308 : Expr( loc ), init( i ) { 307 309 assert( t && i ); 308 result.set_and_mutate( t )->set_lvalue( true ); 310 result = t; 311 add_qualifiers( result, CV::Lvalue ); 309 312 } 310 313 … … 322 325 "index %d in expr %s", type->size(), index, toString( tuple ).c_str() ); 323 326 // like MemberExpr, TupleIndexExpr is always an lvalue 324 result.set_and_mutate( type->types[ index ] )->set_lvalue( true ); 327 result = type->types[ index ]; 328 add_qualifiers( result, CV::Lvalue ); 325 329 } 326 330 -
src/AST/Node.hpp
r7564e10 r67130fe 10 10 // Created On : Wed May 8 10:27:04 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu May 23 16:00:00 201913 // Update Count : 412 // Last Modified On : Mon Jun 3 13:26:00 2019 13 // Update Count : 5 14 14 // 15 15 … … 18 18 #include <cassert> 19 19 #include <iosfwd> 20 21 #include "Common/ErrorObjects.h" // for SemanticErrorException 20 22 21 23 namespace ast { … … 100 102 } 101 103 104 /// Call a visitor on a collection of nodes, throwing any exceptions when completed 105 template< typename Container > 106 void accept_each( const Container & c, Visitor & v ) { 107 SemanticErrorException errors; 108 for ( const auto & i : c ) { 109 try { 110 if ( i ) { 111 i->accept( v ); 112 } 113 } catch ( SemanticErrorException & e ) { 114 errors.append( e ); 115 } 116 } 117 if ( ! errors.isEmpty() ) { 118 throw errors; 119 } 120 } 121 102 122 /// Base class for the smart pointer types 103 123 /// should never really be used. … … 107 127 ptr_base() : node(nullptr) {} 108 128 ptr_base( const node_t * n ) : node(n) { if( node ) _inc(node); } 109 ~ptr_base() { if( node ) _dec(node);}129 ~ptr_base() { if( node ) { auto tmp = node; node = nullptr; _dec(tmp); } } 110 130 111 131 ptr_base( const ptr_base & o ) : node(o.node) { … … 113 133 } 114 134 115 ptr_base( ptr_base && o ) : node(o.node) { 116 if( node ) _inc(node); 117 } 135 ptr_base( ptr_base && o ) : node(o.node) { o.node = nullptr; } 118 136 119 137 template< enum Node::ref_type o_ref_t > … … 129 147 template<typename o_node_t> 130 148 ptr_base & operator=( const o_node_t * node ) { 131 assign( node ? strict_dynamic_cast<const node_t *>(node) : nullptr);149 assign( strict_dynamic_cast<const node_t *, nullptr>(node) ); 132 150 return *this; 133 151 } … … 139 157 140 158 ptr_base & operator=( ptr_base && o ) { 141 assign(o.node); 159 if ( node == o.node ) return *this; 160 if ( node ) _dec(node); 161 node = o.node; 162 o.node = nullptr; 142 163 return *this; 143 164 } … … 165 186 const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); } 166 187 188 /// wrapper for convenient access to strict_dynamic_cast 189 template<typename o_node_t> 190 const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); } 191 167 192 /// Returns a mutable version of the pointer in this node. 168 193 node_t * get_and_mutate(); -
src/AST/Pass.hpp
r7564e10 r67130fe 179 179 180 180 template<typename pass_type> 181 friend void accept All( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );181 friend void accept_all( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor ); 182 182 private: 183 183 -
src/AST/Pass.proto.hpp
r7564e10 r67130fe 312 312 INDEXER_FUNC1( addTrait , const TraitDecl * ); 313 313 INDEXER_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Node * ); 314 INDEXER_FUNC2( addWith , const std::list < ptr<Expr> > &, const Node * );315 314 316 315 // A few extra functions have more complicated behaviour, they are hand written -
src/AST/Print.hpp
r7564e10 r67130fe 17 17 18 18 #include <iosfwd> 19 #include <utility> // for forward 19 20 20 21 #include "AST/Node.hpp" … … 28 29 void print( std::ostream & os, const ast::Node * node, Indenter indent = {} ); 29 30 30 inline void print( std::ostream & os, const ast::Node * node, unsigned int indent ) { 31 print( os, node, Indenter{ Indenter::tabsize, indent }); 31 /// Wrap any standard format printer (matching above) with integer Indenter constructor 32 template<typename T> 33 inline void print( std::ostream & os, T && x, unsigned int indent ) { 34 print( os, std::forward<T>(x), Indenter{ Indenter::tabsize, indent }); 32 35 } 33 36 -
src/AST/Type.cpp
r7564e10 r67130fe 27 27 namespace ast { 28 28 29 const Type * Type::getComponent( unsigned i ) {29 const Type * Type::getComponent( unsigned i ) const { 30 30 assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); 31 31 return this; 32 32 } 33 33 34 const Type * Type::stripDeclarator() {34 const Type * Type::stripDeclarator() const { 35 35 const Type * t; 36 36 const Type * a; … … 39 39 } 40 40 41 const Type * Type::stripReferences() {41 const Type * Type::stripReferences() const { 42 42 const Type * t; 43 43 const ReferenceType * r; -
src/AST/Type.hpp
r7564e10 r67130fe 25 25 #include "Decl.hpp" // for AggregateDecl subclasses 26 26 #include "Fwd.hpp" 27 #include "Node.hpp" // for Node, ptr 27 #include "Node.hpp" // for Node, ptr, ptr_base 28 28 #include "TypeVar.hpp" 29 29 #include "Visitor.hpp" … … 48 48 49 49 Type * set_const( bool v ) { qualifiers.is_const = v; return this; } 50 Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; } 50 51 Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; } 51 52 Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; } … … 58 59 virtual bool isVoid() const { return size() == 0; } 59 60 /// Get the i'th component of this type 60 virtual const Type * getComponent( unsigned i ) ;61 virtual const Type * getComponent( unsigned i ) const; 61 62 62 63 /// type without outer pointers and arrays 63 const Type * stripDeclarator() ;64 const Type * stripDeclarator() const; 64 65 /// type without outer references 65 const Type * stripReferences() ;66 const Type * stripReferences() const; 66 67 /// number of reference occuring consecutively on the outermost layer of this type 67 68 /// (i.e. do not count references nested within other types) … … 75 76 MUTATE_FRIEND 76 77 }; 78 79 /// Clear/reset the qualifiers on this type, cloning only if necessary 80 template< enum Node::ref_type ref_t > 81 void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) { 82 if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q; 83 } 84 85 /// Add the specified qualifiers to this type, cloning only if necessary 86 template< enum Node::ref_type ref_t > 87 void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) { 88 if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q; 89 } 90 91 /// Remove the specified qualifiers from this type, cloning only if necessary 92 template< enum Node::ref_type ref_t > 93 void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) { 94 if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q; 95 } 77 96 78 97 /// `void` … … 437 456 unsigned size() const override { return types.size(); } 438 457 439 const Type * getComponent( unsigned i ) override {458 const Type * getComponent( unsigned i ) const override { 440 459 assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", 441 460 i, size() ); -
src/AST/TypeSubstitution.cpp
r7564e10 r67130fe 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Mar 16 15:54:35201713 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 3 13:26:00 2017 13 // Update Count : 5 14 14 // 15 15 … … 26 26 } 27 27 28 TypeSubstitution::~TypeSubstitution() { 29 for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) { 30 delete( i->second ); 31 } 32 for ( VarEnvType::iterator i = varEnv.begin(); i != varEnv.end(); ++i ) { 33 delete( i->second ); 34 } 35 } 28 TypeSubstitution::~TypeSubstitution() {} 36 29 37 30 TypeSubstitution &TypeSubstitution::operator=( const TypeSubstitution &other ) { -
src/AST/module.mk
r7564e10 r67130fe 28 28 AST/Print.cpp \ 29 29 AST/Stmt.cpp \ 30 AST/SymbolTable.cpp \ 30 31 AST/Type.cpp \ 32 AST/TypeEnvironment.cpp \ 31 33 AST/TypeSubstitution.cpp 32 34 -
src/AST/porting.md
r7564e10 r67130fe 104 104 * `LinkageSpec::isMangled(Spec)` etc. => `Spec.is_mangled` etc. 105 105 * `LinkageSpec::Intrinsic` etc. => `ast::Linkage::Intrinsic` etc. 106 * Boolean flags to `SymTab::Mangler::mangle` are now a `SymTab::Mangle::Mode` struct 107 * uses `bitfield` 108 * Because `Indexer` isn't a terribly evocative name: 109 * `SymTab::Indexer` => `ast::SymbolTable` 110 * `SymTab/Indexer.{h,cc}` => `AST/SymbolTable.{hpp,cpp}` 111 * **TODO** `WithIndexer` => `WithSymbolTable` 112 * `indexer` => `symTab` 113 * `IdData::deleteStmt` => `IdData::deleter` 114 * `lookupId()` now returns a vector rather than an out-param list 115 * To avoid name collisions: 116 * `SymTab::Mangler` => `Mangle` 117 * `ResolvExpr::TypeEnvironment` => `ast::TypeEnvironment` 118 * in `AST/TypeEnvironment.hpp` 106 119 * Boolean constructor parameters get replaced with a dedicated flag enum: 107 120 * e.g. `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen };` `LengthFlag isVarLen;` … … 261 274 * feature is `type@thing` e.g. `int@MAX` 262 275 276 `referenceToRvalueConversion` 277 * now returns `const Expr *` rather than mutating argument 278 279 `printAssertionSet`, `printOpenVarSet` 280 * `ostream &` now first argument, for consistency 281 282 `EqvClass` 283 * `type` => `bound` 284 285 `TypeEnvironment` 286 * `makeSubstitution()` => `writeToSubstitution()` 287 * `isEmpty()` => `empty()` 288 * removed `clone()` in favour of explicit copies 289 290 `occurs` 291 * moved to be helper function in `TypeEnvironment.cpp` (its only use) 292 293 `WidenMode` 294 * changed `widenFirst`, `widenSecond` => `first`, `second` 295 * changed `WidenMode widenMode` => `WidenMode widen` 296 263 297 [1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes 264 298 -
src/GenPoly/GenPoly.cc
r7564e10 r67130fe 24 24 #include <vector> // for vector 25 25 26 #include "AST/Type.hpp" 26 27 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_it... 27 28 #include "ResolvExpr/typeops.h" // for flatten … … 262 263 } else { 263 264 return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise 265 } 266 } 267 268 const ast::FunctionType * getFunctionType( const ast::Type * ty ) { 269 if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) { 270 return pty->base.as< ast::FunctionType >(); 271 } else { 272 return dynamic_cast< const ast::FunctionType * >( ty ); 264 273 } 265 274 } -
src/GenPoly/GenPoly.h
r7564e10 r67130fe 20 20 21 21 #include "ErasableScopedMap.h" // for ErasableScopedMap 22 #include "AST/Fwd.hpp" 22 23 #include "SymTab/Mangler.h" // for Mangler 23 24 #include "SynTree/Declaration.h" // for TypeDecl::Data, AggregateDecl, Type... … … 72 73 /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise 73 74 FunctionType *getFunctionType( Type *ty ); 75 const ast::FunctionType * getFunctionType( const ast::Type * ty ); 74 76 75 77 /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise; -
src/InitTweak/FixInit.cc
r7564e10 r67130fe 72 72 }; 73 73 74 struct StmtExprResult { 75 static void link( std::list< Declaration * > & translationUnit ); 76 77 void previsit( StmtExpr * stmtExpr ); 78 }; 79 74 80 struct InsertImplicitCalls : public WithConstTypeSubstitution { 75 81 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which … … 226 232 acceptAll( translationUnit, checker ); 227 233 234 // fixes StmtExpr to properly link to their resulting expression 235 StmtExprResult::link( translationUnit ); 236 228 237 // fixes ConstructorInit for global variables. should happen before fixInitializers. 229 238 InitTweak::fixGlobalInit( translationUnit, inLibrary ); … … 299 308 300 309 return dtorFunc; 310 } 311 312 void StmtExprResult::link( std::list< Declaration * > & translationUnit ) { 313 PassVisitor<StmtExprResult> linker; 314 acceptAll( translationUnit, linker ); 301 315 } 302 316 … … 349 363 PassVisitor<FixCtorExprs> fixer; 350 364 mutateAll( translationUnit, fixer ); 365 } 366 367 void StmtExprResult::previsit( StmtExpr * stmtExpr ) { 368 // we might loose the result expression here so add a pointer to trace back 369 assert( stmtExpr->result ); 370 Type * result = stmtExpr->result; 371 if ( ! result->isVoid() ) { 372 CompoundStmt * body = stmtExpr->statements; 373 assert( ! body->kids.empty() ); 374 stmtExpr->resultExpr = strict_dynamic_cast< ExprStmt * >( body->kids.back() ); 375 } 351 376 } 352 377 … … 655 680 // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression, 656 681 // since temporaries can be shared across sub-expressions, e.g. 657 // [A, A] f(); 658 // g([A] x, [A] y); 659 // g(f()); 682 // [A, A] f(); // decl 683 // g([A] x, [A] y); // decl 684 // g(f()); // call 660 685 // f is executed once, so the return temporary is shared across the tuple constructors for x and y. 661 686 // Explicitly mutating children instead of mutating the inner compound statement forces the temporaries to be added … … 665 690 assert( env ); 666 691 692 indexer.enterScope(); 667 693 // visit all statements 668 694 std::list< Statement * > & stmts = stmtExpr->statements->get_kids(); … … 670 696 stmt = stmt->acceptMutator( *visitor ); 671 697 } // for 698 indexer.leaveScope(); 672 699 673 700 assert( stmtExpr->result ); … … 688 715 stmtsToAddBefore.push_back( new DeclStmt( ret ) ); 689 716 690 // must have a non-empty body, otherwise it wouldn't have a result 691 CompoundStmt * body = stmtExpr->statements; 692 assert( ! body->kids.empty() ); 693 // must be an ExprStmt, otherwise it wouldn't have a result 694 ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->kids.back() ); 695 last->expr = makeCtorDtor( "?{}", ret, last->expr ); 717 if(!stmtExpr->resultExpr) { 718 SemanticError(stmtExpr, "Statment-Expression should have a resulting expression"); 719 } 720 ExprStmt * last = stmtExpr->resultExpr; 721 try { 722 last->expr = makeCtorDtor( "?{}", ret, last->expr ); 723 } catch(...) { 724 std::cerr << "=======================" << std::endl; 725 std::cerr << "ERROR, can't resolve" << std::endl; 726 ret->print(std::cerr); 727 std::cerr << std::endl << "---" << std::endl; 728 last->expr->print(std::cerr); 729 730 abort(); 731 } 696 732 697 733 // add destructors after current statement -
src/InitTweak/InitTweak.cc
r7564e10 r67130fe 756 756 } 757 757 758 bool isCopyFunction( const ast::FunctionDecl * decl ) { 759 const ast::FunctionType * ftype = decl->type; 760 if ( ftype->params.size() != 2 ) return false; 761 762 const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() ); 763 if ( ! t1 ) return false; 764 const ast::Type * t2 = ftype->params.back()->get_type(); 765 766 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} ); 767 } 768 758 769 FunctionDecl * isAssignment( Declaration * decl ) { 759 770 return isCopyFunction( decl, "?=?" ); -
src/InitTweak/InitTweak.h
r7564e10 r67130fe 30 30 FunctionDecl * isCopyConstructor( Declaration * decl ); 31 31 FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ); 32 bool isCopyFunction( const ast::FunctionDecl * decl ); 32 33 33 34 /// returns the base type of the first parameter to a constructor/destructor/assignment function -
src/Makefile.in
r7564e10 r67130fe 170 170 AST/Init.$(OBJEXT) AST/LinkageSpec.$(OBJEXT) \ 171 171 AST/Node.$(OBJEXT) AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) \ 172 AST/Stmt.$(OBJEXT) AST/Type.$(OBJEXT) \ 172 AST/Stmt.$(OBJEXT) AST/SymbolTable.$(OBJEXT) \ 173 AST/Type.$(OBJEXT) AST/TypeEnvironment.$(OBJEXT) \ 173 174 AST/TypeSubstitution.$(OBJEXT) 174 175 am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \ … … 586 587 AST/Print.cpp \ 587 588 AST/Stmt.cpp \ 589 AST/SymbolTable.cpp \ 588 590 AST/Type.cpp \ 591 AST/TypeEnvironment.cpp \ 589 592 AST/TypeSubstitution.cpp 590 593 … … 754 757 AST/Print.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp) 755 758 AST/Stmt.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp) 759 AST/SymbolTable.$(OBJEXT): AST/$(am__dirstamp) \ 760 AST/$(DEPDIR)/$(am__dirstamp) 756 761 AST/Type.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp) 762 AST/TypeEnvironment.$(OBJEXT): AST/$(am__dirstamp) \ 763 AST/$(DEPDIR)/$(am__dirstamp) 757 764 AST/TypeSubstitution.$(OBJEXT): AST/$(am__dirstamp) \ 758 765 AST/$(DEPDIR)/$(am__dirstamp) … … 1190 1197 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Print.Po@am__quote@ 1191 1198 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Stmt.Po@am__quote@ 1199 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/SymbolTable.Po@am__quote@ 1192 1200 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Type.Po@am__quote@ 1201 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeEnvironment.Po@am__quote@ 1193 1202 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeSubstitution.Po@am__quote@ 1194 1203 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/CodeGenerator.Po@am__quote@ -
src/ResolvExpr/AlternativeFinder.cc
r7564e10 r67130fe 28 28 #include "Alternative.h" // for AltList, Alternative 29 29 #include "AlternativeFinder.h" 30 #include "AST/Expr.hpp" 31 #include "AST/Type.hpp" 30 32 #include "Common/SemanticError.h" // for SemanticError 31 33 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation … … 222 224 cost.incReference(); 223 225 } 226 } 227 228 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) { 229 if ( expr->result.as< ast::ReferenceType >() ) { 230 // cast away reference from expr 231 cost.incReference(); 232 return new ast::CastExpr{ expr->location, expr, expr->result->stripReferences() }; 233 } 234 235 return expr; 224 236 } 225 237 -
src/ResolvExpr/CommonType.cc
r7564e10 r67130fe 18 18 #include <utility> // for pair 19 19 20 #include "AST/Decl.hpp" 21 #include "AST/Type.hpp" 20 22 #include "Common/PassVisitor.h" 21 23 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet … … 35 37 36 38 namespace ResolvExpr { 37 struct CommonType : public WithShortCircuiting {38 CommonType ( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );39 struct CommonType_old : public WithShortCircuiting { 40 CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 39 41 Type *get_result() const { return result; } 40 42 … … 94 96 95 97 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 96 PassVisitor<CommonType > visitor( type2, widenFirst, widenSecond, indexer, env, openVars );98 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 97 99 98 100 int depth1 = type1->referenceDepth(); … … 483 485 ); 484 486 485 CommonType ::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )487 CommonType_old::CommonType_old( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) 486 488 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) { 487 489 } 488 490 489 void CommonType ::postvisit( VoidType * ) {}490 491 void CommonType ::postvisit( BasicType *basicType ) {491 void CommonType_old::postvisit( VoidType * ) {} 492 493 void CommonType_old::postvisit( BasicType *basicType ) { 492 494 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 493 495 BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 505 507 506 508 template< typename Pointer > 507 void CommonType ::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {509 void CommonType_old::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 508 510 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 509 511 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 518 520 } 519 521 520 void CommonType ::postvisit( PointerType *pointerType ) {522 void CommonType_old::postvisit( PointerType *pointerType ) { 521 523 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 522 524 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 553 555 } 554 556 555 void CommonType ::postvisit( ArrayType * ) {}556 557 void CommonType ::postvisit( ReferenceType *refType ) {557 void CommonType_old::postvisit( ArrayType * ) {} 558 559 void CommonType_old::postvisit( ReferenceType *refType ) { 558 560 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 559 561 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 590 592 } 591 593 592 void CommonType ::postvisit( FunctionType * ) {}593 void CommonType ::postvisit( StructInstType * ) {}594 void CommonType ::postvisit( UnionInstType * ) {}595 596 void CommonType ::postvisit( EnumInstType *enumInstType ) {594 void CommonType_old::postvisit( FunctionType * ) {} 595 void CommonType_old::postvisit( StructInstType * ) {} 596 void CommonType_old::postvisit( UnionInstType * ) {} 597 598 void CommonType_old::postvisit( EnumInstType *enumInstType ) { 597 599 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 598 600 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType … … 601 603 } 602 604 603 void CommonType ::postvisit( TraitInstType * ) {604 } 605 606 void CommonType ::postvisit( TypeInstType *inst ) {605 void CommonType_old::postvisit( TraitInstType * ) { 606 } 607 608 void CommonType_old::postvisit( TypeInstType *inst ) { 607 609 if ( widenFirst ) { 608 610 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 626 628 } 627 629 628 void CommonType ::postvisit( TupleType * ) {}629 void CommonType ::postvisit( VarArgsType * ) {}630 631 void CommonType ::postvisit( ZeroType *zeroType ) {630 void CommonType_old::postvisit( TupleType * ) {} 631 void CommonType_old::postvisit( VarArgsType * ) {} 632 633 void CommonType_old::postvisit( ZeroType *zeroType ) { 632 634 if ( widenFirst ) { 633 635 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 643 645 } 644 646 645 void CommonType ::postvisit( OneType *oneType ) {647 void CommonType_old::postvisit( OneType *oneType ) { 646 648 if ( widenFirst ) { 647 649 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 656 658 } 657 659 } 660 661 class CommonType_new final : public ast::WithShortCircuiting { 662 const ast::Type * type2; 663 WidenMode widen; 664 const ast::SymbolTable & symtab; 665 ast::TypeEnvironment & tenv; 666 const ast::OpenVarSet & open; 667 public: 668 ast::ptr< ast::Type > result; 669 670 CommonType_new( 671 const ast::Type * t2, WidenMode w, const ast::SymbolTable & st, 672 ast::TypeEnvironment & env, const ast::OpenVarSet & o ) 673 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {} 674 675 void previsit( const ast::Node * ) { visit_children = false; } 676 677 void postvisit( const ast::VoidType * ) {} 678 679 void postvisit( const ast::BasicType * basic ) { 680 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 681 #warning remove casts when `commonTypes` moved to new AST 682 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 683 if ( 684 ( ( kind == basic->kind && basic->qualifiers >= basic2->qualifiers ) 685 || widen.first ) 686 && ( ( kind == basic2->kind && basic->qualifiers <= basic2->qualifiers ) 687 || widen.second ) 688 ) { 689 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 690 } 691 } else if ( 692 dynamic_cast< const ast::EnumInstType * >( type2 ) 693 || dynamic_cast< const ast::ZeroType * >( type2 ) 694 || dynamic_cast< const ast::OneType * >( type2 ) 695 ) { 696 #warning remove casts when `commonTypes` moved to new AST 697 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ]; 698 if ( 699 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 700 || widen.first ) 701 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 702 || widen.second ) 703 ) { 704 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 705 } 706 } 707 } 708 709 private: 710 template< typename Pointer > 711 void getCommonWithVoidPointer( const Pointer * voidPtr, const Pointer * oPtr ) { 712 const ast::Type * base = oPtr->base; 713 if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) { 714 auto entry = open.find( var->name ); 715 if ( entry != open.end() ) { 716 ast::AssertionSet need, have; 717 if ( ! tenv.bindVar( 718 var, voidPtr->base, entry->second, need, have, open, widen, symtab ) 719 ) return; 720 } 721 } 722 result = voidPtr; 723 add_qualifiers( result, oPtr->qualifiers ); 724 } 725 726 public: 727 void postvisit( const ast::PointerType * pointer ) { 728 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 729 if ( 730 widen.first 731 && pointer2->base.as< ast::VoidType >() 732 && ! ast::isFtype( pointer->base ) 733 ) { 734 getCommonWithVoidPointer( pointer2, pointer ); 735 } else if ( 736 widen.second 737 && pointer->base.as< ast::VoidType >() 738 && ! ast::isFtype( pointer2->base ) 739 ) { 740 getCommonWithVoidPointer( pointer, pointer2 ); 741 } else if ( 742 ( pointer->base->qualifiers >= pointer2->base->qualifiers || widen.first ) 743 && ( pointer->base->qualifiers <= pointer2->base->qualifiers || widen.second ) 744 ) { 745 ast::CV::Qualifiers q1 = pointer->base->qualifiers; 746 ast::CV::Qualifiers q2 = pointer2->base->qualifiers; 747 748 // force t{1,2} to be cloned if their qualifiers must be stripped, so that 749 // pointer{,2}->base are unchanged 750 ast::ptr< ast::Type > t1{ pointer->base }, t2{ pointer2->base }; 751 reset_qualifiers( t1 ); 752 reset_qualifiers( t2 ); 753 754 ast::AssertionSet have, need; 755 ast::OpenVarSet newOpen{ open }; 756 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 757 result = pointer; 758 if ( q1.val != q2.val ) { 759 // reset result->base->qualifiers to be union of two base qualifiers 760 strict_dynamic_cast< ast::PointerType * >( 761 result.get_and_mutate() 762 )->base.get_and_mutate()->qualifiers = q1 | q2; 763 } 764 } 765 } 766 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 767 result = pointer; 768 add_qualifiers( result, type2->qualifiers ); 769 } 770 } 771 772 void postvisit( const ast::ArrayType * ) {} 773 774 void postvisit( const ast::ReferenceType * ref ) { 775 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 776 if ( 777 widen.first && ref2->base.as< ast::VoidType >() && ! ast::isFtype( ref->base ) 778 ) { 779 getCommonWithVoidPointer( ref2, ref ); 780 } else if ( 781 widen.second && ref->base.as< ast::VoidType>() && ! ast::isFtype( ref2->base ) 782 ) { 783 getCommonWithVoidPointer( ref, ref2 ); 784 } else if ( 785 ( ref->base->qualifiers >= ref2->base->qualifiers || widen.first ) 786 && ( ref->base->qualifiers <= ref2->base->qualifiers || widen.second ) 787 ) { 788 ast::CV::Qualifiers q1 = ref->base->qualifiers, q2 = ref2->base->qualifiers; 789 790 // force t{1,2} to be cloned if their qualifiers must be stripped, so that 791 // ref{,2}->base are unchanged 792 ast::ptr< ast::Type > t1{ ref->base }, t2{ ref2->base }; 793 reset_qualifiers( t1 ); 794 reset_qualifiers( t2 ); 795 796 ast::AssertionSet have, need; 797 ast::OpenVarSet newOpen{ open }; 798 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 799 result = ref; 800 if ( q1.val != q2.val ) { 801 // reset result->base->qualifiers to be union of two base qualifiers 802 strict_dynamic_cast< ast::ReferenceType * >( 803 result.get_and_mutate() 804 )->base.get_and_mutate()->qualifiers = q1 | q2; 805 } 806 } 807 } 808 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 809 result = ref; 810 add_qualifiers( result, type2->qualifiers ); 811 } 812 } 813 814 void postvisit( const ast::FunctionType * ) {} 815 816 void postvisit( const ast::StructInstType * ) {} 817 818 void postvisit( const ast::UnionInstType * ) {} 819 820 void postvisit( const ast::EnumInstType * enumInst ) { 821 if ( 822 dynamic_cast< const ast::BasicType * >( type2 ) 823 || dynamic_cast< const ast::ZeroType * >( type2 ) 824 || dynamic_cast< const ast::OneType * >( type2 ) 825 ) { 826 // reuse BasicType/EnumInstType common type by swapping 827 result = commonType( type2, enumInst, widen, symtab, tenv, open ); 828 } 829 } 830 831 void postvisit( const ast::TraitInstType * ) {} 832 833 void postvisit( const ast::TypeInstType * inst ) { 834 if ( ! widen.first ) return; 835 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 836 if ( const ast::Type * base = 837 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base 838 ) { 839 ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers; 840 841 // force t{1,2} to be cloned if their qualifiers must be mutated 842 ast::ptr< ast::Type > t1{ base }, t2{ type2 }; 843 reset_qualifiers( t1, q1 ); 844 reset_qualifiers( t2 ); 845 846 ast::AssertionSet have, need; 847 ast::OpenVarSet newOpen{ open }; 848 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 849 result = type2; 850 reset_qualifiers( result, q1 | q2 ); 851 } 852 } 853 } 854 } 855 856 void postvisit( const ast::TupleType * ) {} 857 858 void postvisit( const ast::VarArgsType * ) {} 859 860 void postvisit( const ast::ZeroType * zero ) { 861 if ( ! widen.first ) return; 862 if ( 863 dynamic_cast< const ast::BasicType * >( type2 ) 864 || dynamic_cast< const ast::PointerType * >( type2 ) 865 || dynamic_cast< const ast::EnumInstType * >( type2 ) 866 ) { 867 if ( widen.second || zero->qualifiers <= type2->qualifiers ) { 868 result = type2; 869 add_qualifiers( result, zero->qualifiers ); 870 } 871 } else if ( widen.second && dynamic_cast< const ast::OneType * >( type2 ) ) { 872 result = new ast::BasicType{ 873 ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers }; 874 } 875 } 876 877 void postvisit( const ast::OneType * one ) { 878 if ( ! widen.first ) return; 879 if ( 880 dynamic_cast< const ast::BasicType * >( type2 ) 881 || dynamic_cast< const ast::EnumInstType * >( type2 ) 882 ) { 883 if ( widen.second || one->qualifiers <= type2->qualifiers ) { 884 result = type2; 885 add_qualifiers( result, one->qualifiers ); 886 } 887 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 888 result = new ast::BasicType{ 889 ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers }; 890 } 891 } 892 893 }; 894 895 namespace { 896 ast::ptr< ast::Type > handleReference( 897 const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen, 898 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, 899 const ast::OpenVarSet & open 900 ) { 901 ast::ptr<ast::Type> common; 902 ast::AssertionSet have, need; 903 ast::OpenVarSet newOpen{ open }; 904 905 // need unify to bind type variables 906 if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) { 907 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers; 908 PRINT( 909 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl; 910 ) 911 if ( ( widen.first || q2 <= q1 ) && ( widen.second || q1 <= q2 ) ) { 912 PRINT( 913 std::cerr << "widen okay" << std::endl; 914 ) 915 add_qualifiers( common, q1 | q2 ); 916 return common; 917 } 918 } 919 920 PRINT( 921 std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl; 922 ) 923 return { nullptr }; 924 } 925 } 926 927 ast::ptr< ast::Type > commonType( 928 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 929 WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env, 930 const ast::OpenVarSet & open 931 ) { 932 unsigned depth1 = type1->referenceDepth(); 933 unsigned depth2 = type2->referenceDepth(); 934 935 if ( depth1 != depth2 ) { // implies depth1 > 0 || depth2 > 0 936 PRINT( 937 std::cerr << "reference depth diff: " << (depth1-depth2) << std::endl; 938 ) 939 ast::ptr< ast::Type > result; 940 const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >(); 941 const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >(); 942 943 if ( depth1 > depth2 ) { 944 assert( ref1 ); 945 result = handleReference( ref1->base, type2, widen, symtab, env, open ); 946 } else { // implies depth1 < depth2 947 assert( ref2 ); 948 result = handleReference( type1, ref2->base, widen, symtab, env, open ); 949 } 950 951 if ( result && ref1 ) { 952 // formal is reference, so result should be reference 953 PRINT( 954 std::cerr << "formal is reference; result should be reference" << std::endl; 955 ) 956 result = new ast::ReferenceType{ result, ref1->qualifiers }; 957 } 958 959 PRINT( 960 std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is " 961 "[" << result << "]" << std::endl; 962 ) 963 return result; 964 } 965 // otherwise both are reference types of the same depth and this is handled by the visitor 966 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open }; 967 type1->accept( visitor ); 968 ast::ptr< ast::Type > result = visitor.pass.result; 969 970 // handling for opaque type declarations (?) 971 if ( ! result && widen.second ) { 972 if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) { 973 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 974 auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt ); 975 if ( type->base ) { 976 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 977 ast::AssertionSet have, need; 978 ast::OpenVarSet newOpen{ open }; 979 980 // force t{1,2} to be cloned if its qualifiers must be stripped, so that 981 // type1 and type->base are left unchanged; calling convention forces 982 // {type1,type->base}->strong_ref >= 1 983 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base }; 984 reset_qualifiers( t1 ); 985 reset_qualifiers( t2, q1 ); 986 987 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) { 988 result = t1; 989 reset_qualifiers( result, q1 | q2 ); 990 } 991 } 992 } 993 } 994 } 995 996 return result; 997 } 998 658 999 } // namespace ResolvExpr 659 1000 -
src/ResolvExpr/FindOpenVars.cc
r7564e10 r67130fe 19 19 #include <map> // for map<>::mapped_type 20 20 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 21 23 #include "Common/PassVisitor.h" 22 24 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... … … 24 26 25 27 namespace ResolvExpr { 26 struct FindOpenVars : public WithGuards {27 FindOpenVars ( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );28 struct FindOpenVars_old : public WithGuards { 29 FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 28 30 29 31 void previsit( PointerType * pointerType ); … … 40 42 41 43 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) { 42 PassVisitor<FindOpenVars > finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );44 PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen ); 43 45 type->accept( finder ); 44 46 } 45 47 46 FindOpenVars ::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )48 FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) 47 49 : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) { 48 50 } 49 51 50 void FindOpenVars ::common_action( Type *type ) {52 void FindOpenVars_old::common_action( Type *type ) { 51 53 if ( nextIsOpen ) { 52 54 for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) { … … 76 78 } 77 79 78 void FindOpenVars ::previsit(PointerType *pointerType) {80 void FindOpenVars_old::previsit(PointerType *pointerType) { 79 81 common_action( pointerType ); 80 82 } 81 83 82 void FindOpenVars ::previsit(ArrayType *arrayType) {84 void FindOpenVars_old::previsit(ArrayType *arrayType) { 83 85 common_action( arrayType ); 84 86 } 85 87 86 void FindOpenVars ::previsit(FunctionType *functionType) {88 void FindOpenVars_old::previsit(FunctionType *functionType) { 87 89 common_action( functionType ); 88 90 nextIsOpen = ! nextIsOpen; … … 90 92 } 91 93 92 void FindOpenVars ::previsit(TupleType *tupleType) {94 void FindOpenVars_old::previsit(TupleType *tupleType) { 93 95 common_action( tupleType ); 96 } 97 98 namespace { 99 struct FindOpenVars_new final : public ast::WithGuards { 100 ast::OpenVarSet & open; 101 ast::OpenVarSet & closed; 102 ast::AssertionSet & need; 103 ast::AssertionSet & have; 104 bool nextIsOpen; 105 106 FindOpenVars_new( 107 ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n, 108 ast::AssertionSet & h, FirstMode firstIsOpen ) 109 : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {} 110 111 void previsit( const ast::FunctionType * type ) { 112 // mark open/closed variables 113 if ( nextIsOpen ) { 114 for ( const ast::TypeDecl * decl : type->forall ) { 115 open[ decl->name ] = ast::TypeDecl::Data{ decl }; 116 for ( const ast::DeclWithType * assert : decl->assertions ) { 117 need[ assert ].isUsed = false; 118 } 119 } 120 } else { 121 for ( const ast::TypeDecl * decl : type->forall ) { 122 closed[ decl->name ] = ast::TypeDecl::Data{ decl }; 123 for ( const ast::DeclWithType * assert : decl->assertions ) { 124 have[ assert ].isUsed = false; 125 } 126 } 127 } 128 129 // flip open variables for contained function types 130 nextIsOpen = ! nextIsOpen; 131 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } ); 132 } 133 134 }; 135 } 136 137 void findOpenVars( 138 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 139 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) { 140 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen }; 141 type->accept( finder ); 94 142 } 95 143 } // namespace ResolvExpr -
src/ResolvExpr/FindOpenVars.h
r7564e10 r67130fe 16 16 #pragma once 17 17 18 #include "AST/TypeEnvironment.hpp" // for AssertionSet, OpenVarSet 18 19 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 19 20 20 21 class Type; 22 namespace ast { 23 class Type; 24 } 21 25 22 26 namespace ResolvExpr { 23 27 // Updates open and closed variables and their associated assertions 24 28 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 29 30 enum FirstMode { FirstClosed, FirstOpen }; 31 32 // Updates open and closed variables and their associated assertions 33 void findOpenVars( 34 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 35 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ); 25 36 } // namespace ResolvExpr 26 37 -
src/ResolvExpr/ResolveAssertions.cc
r7564e10 r67130fe 30 30 #include "Common/Indenter.h" // for Indenter 31 31 #include "Common/utility.h" // for sort_mins 32 #include "GenPoly/GenPoly.h" // for getFunctionType 32 33 #include "ResolvExpr/RenameVars.h" // for renameTyVars 33 34 #include "SymTab/Indexer.h" // for Indexer … … 154 155 Cost k = Cost::zero; 155 156 for ( const auto& assn : x.assns ) { 157 // compute conversion cost from satisfying decl to assertion 156 158 k += computeConversionCost( 157 159 assn.match.adjType, assn.decl->get_type(), indexer, x.env ); 158 160 159 161 // mark vars+specialization cost on function-type assertions 160 Type* assnType = assn.match.cdata.id->get_type(); 161 FunctionType* func; 162 if ( PointerType* ptr = dynamic_cast< PointerType* >( assnType ) ) { 163 func = dynamic_cast< FunctionType* >( ptr->base ); 164 } else { 165 func = dynamic_cast< FunctionType* >( assnType ); 166 } 162 FunctionType* func = GenPoly::getFunctionType( assn.match.cdata.id->get_type() ); 167 163 if ( ! func ) continue; 168 164 -
src/ResolvExpr/Resolver.cc
r7564e10 r67130fe 7 7 // Resolver.cc -- 8 8 // 9 // Author : Richard C. Bilson9 // Author : Aaron B. Moss 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 19 18:09:56201913 // Update Count : 24 011 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Wed May 29 11:00:00 2019 13 // Update Count : 241 14 14 // 15 15 … … 21 21 #include "Alternative.h" // for Alternative, AltList 22 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "CurrentObject.h" // for CurrentObject 24 #include "RenameVars.h" // for RenameVars, global_renamer 25 #include "Resolver.h" 26 #include "ResolvMode.h" // for ResolvMode 27 #include "typeops.h" // for extractResultType 28 #include "Unify.h" // for unify 29 #include "AST/Pass.hpp" 30 #include "AST/SymbolTable.hpp" 23 31 #include "Common/PassVisitor.h" // for PassVisitor 24 32 #include "Common/SemanticError.h" // for SemanticError 25 33 #include "Common/utility.h" // for ValueGuard, group_iterate 26 #include "CurrentObject.h" // for CurrentObject27 34 #include "InitTweak/GenInit.h" 28 35 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt 29 #include "RenameVars.h" // for RenameVars, global_renamer30 36 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 31 #include "Resolver.h"32 #include "ResolvMode.h" // for ResolvMode33 37 #include "SymTab/Autogen.h" // for SizeType 34 38 #include "SymTab/Indexer.h" // for Indexer … … 41 45 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 42 46 #include "Tuples/Tuples.h" 43 #include "typeops.h" // for extractResultType44 #include "Unify.h" // for unify45 47 #include "Validate/FindSpecialDecls.h" // for SizeType 46 48 … … 48 50 49 51 namespace ResolvExpr { 50 struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {51 Resolver () {}52 Resolver ( const SymTab::Indexer & other ) {52 struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd { 53 Resolver_old() {} 54 Resolver_old( const SymTab::Indexer & other ) { 53 55 indexer = other; 54 56 } … … 101 103 102 104 void resolve( std::list< Declaration * > translationUnit ) { 103 PassVisitor<Resolver > resolver;105 PassVisitor<Resolver_old> resolver; 104 106 acceptAll( translationUnit, resolver ); 105 107 } 106 108 107 109 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) { 108 PassVisitor<Resolver > resolver( indexer );110 PassVisitor<Resolver_old> resolver( indexer ); 109 111 maybeAccept( decl, resolver ); 110 112 } … … 402 404 } 403 405 404 void Resolver ::previsit( ObjectDecl * objectDecl ) {405 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 406 // class-variable initContext is changed multiple time because the LHS is analysed twice. 407 // The second analysis changes initContext because of a function type can contain object 408 // declarations in the return and parameter types. So each value of initContext is 406 void Resolver_old::previsit( ObjectDecl * objectDecl ) { 407 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 408 // class-variable initContext is changed multiple time because the LHS is analysed twice. 409 // The second analysis changes initContext because of a function type can contain object 410 // declarations in the return and parameter types. So each value of initContext is 409 411 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 410 412 GuardValue( currentObject ); … … 418 420 419 421 template< typename PtrType > 420 void Resolver ::handlePtrType( PtrType * type ) {422 void Resolver_old::handlePtrType( PtrType * type ) { 421 423 if ( type->get_dimension() ) { 422 424 findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer ); … … 424 426 } 425 427 426 void Resolver ::previsit( ArrayType * at ) {428 void Resolver_old::previsit( ArrayType * at ) { 427 429 handlePtrType( at ); 428 430 } 429 431 430 void Resolver ::previsit( PointerType * pt ) {432 void Resolver_old::previsit( PointerType * pt ) { 431 433 handlePtrType( pt ); 432 434 } 433 435 434 void Resolver ::previsit( FunctionDecl * functionDecl ) {436 void Resolver_old::previsit( FunctionDecl * functionDecl ) { 435 437 #if 0 436 438 std::cerr << "resolver visiting functiondecl "; … … 442 444 } 443 445 444 void Resolver ::postvisit( FunctionDecl * functionDecl ) {445 // default value expressions have an environment which shouldn't be there and trips up 446 void Resolver_old::postvisit( FunctionDecl * functionDecl ) { 447 // default value expressions have an environment which shouldn't be there and trips up 446 448 // later passes. 447 449 // xxx - it might be necessary to somehow keep the information from this environment, but I … … 457 459 } 458 460 459 void Resolver ::previsit( EnumDecl * ) {461 void Resolver_old::previsit( EnumDecl * ) { 460 462 // in case we decide to allow nested enums 461 463 GuardValue( inEnumDecl ); … … 463 465 } 464 466 465 void Resolver ::previsit( StaticAssertDecl * assertDecl ) {467 void Resolver_old::previsit( StaticAssertDecl * assertDecl ) { 466 468 findIntegralExpression( assertDecl->condition, indexer ); 467 469 } 468 470 469 void Resolver ::previsit( ExprStmt * exprStmt ) {471 void Resolver_old::previsit( ExprStmt * exprStmt ) { 470 472 visit_children = false; 471 473 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" ); … … 473 475 } 474 476 475 void Resolver ::previsit( AsmExpr * asmExpr ) {477 void Resolver_old::previsit( AsmExpr * asmExpr ) { 476 478 visit_children = false; 477 479 findVoidExpression( asmExpr->operand, indexer ); … … 481 483 } 482 484 483 void Resolver ::previsit( AsmStmt * asmStmt ) {485 void Resolver_old::previsit( AsmStmt * asmStmt ) { 484 486 visit_children = false; 485 487 acceptAll( asmStmt->get_input(), *visitor ); … … 487 489 } 488 490 489 void Resolver ::previsit( IfStmt * ifStmt ) {491 void Resolver_old::previsit( IfStmt * ifStmt ) { 490 492 findIntegralExpression( ifStmt->condition, indexer ); 491 493 } 492 494 493 void Resolver ::previsit( WhileStmt * whileStmt ) {495 void Resolver_old::previsit( WhileStmt * whileStmt ) { 494 496 findIntegralExpression( whileStmt->condition, indexer ); 495 497 } 496 498 497 void Resolver ::previsit( ForStmt * forStmt ) {499 void Resolver_old::previsit( ForStmt * forStmt ) { 498 500 if ( forStmt->condition ) { 499 501 findIntegralExpression( forStmt->condition, indexer ); … … 505 507 } 506 508 507 void Resolver ::previsit( SwitchStmt * switchStmt ) {509 void Resolver_old::previsit( SwitchStmt * switchStmt ) { 508 510 GuardValue( currentObject ); 509 511 findIntegralExpression( switchStmt->condition, indexer ); … … 512 514 } 513 515 514 void Resolver ::previsit( CaseStmt * caseStmt ) {516 void Resolver_old::previsit( CaseStmt * caseStmt ) { 515 517 if ( caseStmt->condition ) { 516 518 std::list< InitAlternative > initAlts = currentObject.getOptions(); … … 531 533 } 532 534 533 void Resolver ::previsit( BranchStmt * branchStmt ) {535 void Resolver_old::previsit( BranchStmt * branchStmt ) { 534 536 visit_children = false; 535 537 // must resolve the argument for a computed goto … … 542 544 } 543 545 544 void Resolver ::previsit( ReturnStmt * returnStmt ) {546 void Resolver_old::previsit( ReturnStmt * returnStmt ) { 545 547 visit_children = false; 546 548 if ( returnStmt->expr ) { … … 549 551 } 550 552 551 void Resolver ::previsit( ThrowStmt * throwStmt ) {553 void Resolver_old::previsit( ThrowStmt * throwStmt ) { 552 554 visit_children = false; 553 555 // TODO: Replace *exception type with &exception type. … … 561 563 } 562 564 563 void Resolver ::previsit( CatchStmt * catchStmt ) {565 void Resolver_old::previsit( CatchStmt * catchStmt ) { 564 566 if ( catchStmt->cond ) { 565 567 findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer ); … … 576 578 } 577 579 578 void Resolver ::previsit( WaitForStmt * stmt ) {580 void Resolver_old::previsit( WaitForStmt * stmt ) { 579 581 visit_children = false; 580 582 … … 782 784 } 783 785 784 void Resolver ::previsit( SingleInit * singleInit ) {786 void Resolver_old::previsit( SingleInit * singleInit ) { 785 787 visit_children = false; 786 788 // resolve initialization using the possibilities as determined by the currentObject cursor … … 834 836 } 835 837 836 void Resolver ::previsit( ListInit * listInit ) {838 void Resolver_old::previsit( ListInit * listInit ) { 837 839 visit_children = false; 838 840 // move cursor into brace-enclosed initializer-list … … 869 871 870 872 // ConstructorInit - fall back on C-style initializer 871 void Resolver ::fallbackInit( ConstructorInit * ctorInit ) {873 void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) { 872 874 // could not find valid constructor, or found an intrinsic constructor 873 875 // fall back on C-style initializer … … 882 884 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) { 883 885 assert( ctorInit ); 884 PassVisitor<Resolver > resolver( indexer );886 PassVisitor<Resolver_old> resolver( indexer ); 885 887 ctorInit->accept( resolver ); 886 888 } … … 888 890 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) { 889 891 assert( stmtExpr ); 890 PassVisitor<Resolver > resolver( indexer );892 PassVisitor<Resolver_old> resolver( indexer ); 891 893 stmtExpr->accept( resolver ); 892 894 stmtExpr->computeResult(); … … 894 896 } 895 897 896 void Resolver ::previsit( ConstructorInit * ctorInit ) {898 void Resolver_old::previsit( ConstructorInit * ctorInit ) { 897 899 visit_children = false; 898 900 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit … … 928 930 // } 929 931 } 932 933 /////////////////////////////////////////////////////////////////////////// 934 // 935 // *** NEW RESOLVER *** 936 // 937 /////////////////////////////////////////////////////////////////////////// 938 939 class Resolver_new final 940 : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>, 941 public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> { 942 943 public: 944 Resolver_new() = default; 945 Resolver_new( const ast::SymbolTable & syms ) { /*symtab = syms;*/ } 946 947 void previsit( ast::FunctionDecl * functionDecl ); 948 ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl ); 949 void previsit( ast::ObjectDecl * objectDecl ); 950 void previsit( ast::EnumDecl * enumDecl ); 951 void previsit( ast::StaticAssertDecl * assertDecl ); 952 953 void previsit( ast::ArrayType * at ); 954 void previsit( ast::PointerType * pt ); 955 956 void previsit( ast::ExprStmt * exprStmt ); 957 void previsit( ast::AsmExpr * asmExpr ); 958 void previsit( ast::AsmStmt * asmStmt ); 959 void previsit( ast::IfStmt * ifStmt ); 960 void previsit( ast::WhileStmt * whileStmt ); 961 void previsit( ast::ForStmt * forStmt ); 962 void previsit( ast::SwitchStmt * switchStmt ); 963 void previsit( ast::CaseStmt * caseStmt ); 964 void previsit( ast::BranchStmt * branchStmt ); 965 void previsit( ast::ReturnStmt * returnStmt ); 966 void previsit( ast::ThrowStmt * throwStmt ); 967 void previsit( ast::CatchStmt * catchStmt ); 968 void previsit( ast::WaitForStmt * stmt ); 969 970 void previsit( ast::SingleInit * singleInit ); 971 void previsit( ast::ListInit * listInit ); 972 void previsit( ast::ConstructorInit * ctorInit ); 973 }; 974 975 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) { 976 ast::Pass<Resolver_new> resolver; 977 accept_all( translationUnit, resolver ); 978 } 979 980 void previsit( ast::FunctionDecl * functionDecl ) { 981 #warning unimplemented; Resolver port in progress 982 (void)functionDecl; 983 assert(false); 984 } 985 986 ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl ) { 987 #warning unimplemented; Resolver port in progress 988 (void)functionDecl; 989 assert(false); 990 return nullptr; 991 } 992 993 void previsit( ast::ObjectDecl * objectDecl ) { 994 #warning unimplemented; Resolver port in progress 995 (void)objectDecl; 996 assert(false); 997 } 998 999 void previsit( ast::EnumDecl * enumDecl ) { 1000 #warning unimplemented; Resolver port in progress 1001 (void)enumDecl; 1002 assert(false); 1003 } 1004 1005 void previsit( ast::StaticAssertDecl * assertDecl ) { 1006 #warning unimplemented; Resolver port in progress 1007 (void)assertDecl; 1008 assert(false); 1009 } 1010 1011 void previsit( ast::ArrayType * at ) { 1012 #warning unimplemented; Resolver port in progress 1013 (void)at; 1014 assert(false); 1015 } 1016 1017 void previsit( ast::PointerType * pt ) { 1018 #warning unimplemented; Resolver port in progress 1019 (void)pt; 1020 assert(false); 1021 } 1022 1023 void previsit( ast::ExprStmt * exprStmt ) { 1024 #warning unimplemented; Resolver port in progress 1025 (void)exprStmt; 1026 assert(false); 1027 } 1028 1029 void previsit( ast::AsmExpr * asmExpr ) { 1030 #warning unimplemented; Resolver port in progress 1031 (void)asmExpr; 1032 assert(false); 1033 } 1034 1035 void previsit( ast::AsmStmt * asmStmt ) { 1036 #warning unimplemented; Resolver port in progress 1037 (void)asmStmt; 1038 assert(false); 1039 } 1040 1041 void previsit( ast::IfStmt * ifStmt ) { 1042 #warning unimplemented; Resolver port in progress 1043 (void)ifStmt; 1044 assert(false); 1045 } 1046 1047 void previsit( ast::WhileStmt * whileStmt ) { 1048 #warning unimplemented; Resolver port in progress 1049 (void)whileStmt; 1050 assert(false); 1051 } 1052 1053 void previsit( ast::ForStmt * forStmt ) { 1054 #warning unimplemented; Resolver port in progress 1055 (void)forStmt; 1056 assert(false); 1057 } 1058 1059 void previsit( ast::SwitchStmt * switchStmt ) { 1060 #warning unimplemented; Resolver port in progress 1061 (void)switchStmt; 1062 assert(false); 1063 } 1064 1065 void previsit( ast::CaseStmt * caseStmt ) { 1066 #warning unimplemented; Resolver port in progress 1067 (void)caseStmt; 1068 assert(false); 1069 } 1070 1071 void previsit( ast::BranchStmt * branchStmt ) { 1072 #warning unimplemented; Resolver port in progress 1073 (void)branchStmt; 1074 assert(false); 1075 } 1076 1077 void previsit( ast::ReturnStmt * returnStmt ) { 1078 #warning unimplemented; Resolver port in progress 1079 (void)returnStmt; 1080 assert(false); 1081 } 1082 1083 void previsit( ast::ThrowStmt * throwStmt ) { 1084 #warning unimplemented; Resolver port in progress 1085 (void)throwStmt; 1086 assert(false); 1087 } 1088 1089 void previsit( ast::CatchStmt * catchStmt ) { 1090 #warning unimplemented; Resolver port in progress 1091 (void)catchStmt; 1092 assert(false); 1093 } 1094 1095 void previsit( ast::WaitForStmt * stmt ) { 1096 #warning unimplemented; Resolver port in progress 1097 (void)stmt; 1098 assert(false); 1099 } 1100 1101 void previsit( ast::SingleInit * singleInit ) { 1102 #warning unimplemented; Resolver port in progress 1103 (void)singleInit; 1104 assert(false); 1105 } 1106 1107 void previsit( ast::ListInit * listInit ) { 1108 #warning unimplemented; Resolver port in progress 1109 (void)listInit; 1110 assert(false); 1111 } 1112 1113 void previsit( ast::ConstructorInit * ctorInit ) { 1114 #warning unimplemented; Resolver port in progress 1115 (void)ctorInit; 1116 assert(false); 1117 } 1118 930 1119 } // namespace ResolvExpr 931 1120 -
src/ResolvExpr/Resolver.h
r7564e10 r67130fe 16 16 #pragma once 17 17 18 #include <list> // for list 18 #include <list> // for list 19 #include <AST/Node.hpp> // for ptr 19 20 20 21 class ConstructorInit; … … 23 24 class StmtExpr; 24 25 namespace SymTab { 25 class Indexer; 26 } // namespace SymTab 26 class Indexer; 27 } // namespace SymTab 28 29 namespace ast { 30 class Decl; 31 } // namespace ast 27 32 28 33 namespace ResolvExpr { … … 40 45 /// Resolves with-stmts and with-clauses on functions 41 46 void resolveWithExprs( std::list< Declaration * > & translationUnit ); 47 48 /// Checks types and binds syntactic constructs to typed representations 49 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ); 42 50 } // namespace ResolvExpr 43 51 -
src/ResolvExpr/TypeEnvironment.cc
r7564e10 r67130fe 205 205 // attempt to unify bound types 206 206 std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() }; 207 WidenMode widen Mode{ to.allowWidening, from.allowWidening };207 WidenMode widen{ to.allowWidening, from.allowWidening }; 208 208 Type* common = nullptr; 209 209 AssertionSet need, have; 210 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen Mode, indexer, common ) ) {210 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen, indexer, common ) ) { 211 211 // unifies, set common type if necessary 212 212 if ( common ) { … … 343 343 } 344 344 345 bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer ) {345 bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 346 346 347 347 // remove references from other, so that type variables can only bind to value types … … 362 362 std::unique_ptr< Type > newType( curClass->type->clone() ); 363 363 newType->get_qualifiers() = typeInst->get_qualifiers(); 364 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen Mode& WidenMode( curClass->allowWidening, true ), indexer, common ) ) {364 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) { 365 365 if ( common ) { 366 366 common->get_qualifiers() = Type::Qualifiers{}; … … 372 372 newType->get_qualifiers() = Type::Qualifiers{}; 373 373 curClass->set_type( newType ); 374 curClass->allowWidening = widen Mode.widenFirst && widenMode.widenSecond;374 curClass->allowWidening = widen.first && widen.second; 375 375 } // if 376 376 } else { … … 379 379 newClass.type = bindTo->clone(); 380 380 newClass.type->get_qualifiers() = Type::Qualifiers(); 381 newClass.allowWidening = widen Mode.widenFirst && widenMode.widenSecond;381 newClass.allowWidening = widen.first && widen.second; 382 382 newClass.data = data; 383 383 env.push_back( std::move(newClass) ); … … 388 388 bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2, 389 389 TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, 390 const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer ) {390 const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 391 391 392 392 auto class1 = internal_lookup( var1->get_name() ); … … 395 395 // exit early if variables already bound together 396 396 if ( class1 != env.end() && class1 == class2 ) { 397 class1->allowWidening &= widen Mode;397 class1->allowWidening &= widen; 398 398 return true; 399 399 } … … 408 408 type1 = class1->type; 409 409 } // if 410 widen1 = widen Mode.widenFirst && class1->allowWidening;410 widen1 = widen.first && class1->allowWidening; 411 411 } // if 412 412 if ( class2 != env.end() ) { … … 415 415 type2 = class2->type; 416 416 } // if 417 widen2 = widen Mode.widenSecond && class2->allowWidening;417 widen2 = widen.second && class2->allowWidening; 418 418 } // if 419 419 -
src/ResolvExpr/TypeEnvironment.h
r7564e10 r67130fe 136 136 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add 137 137 /// the class if needed. Returns false on failure. 138 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer );138 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 139 139 140 140 /// Binds the type classes represented by `var1` and `var2` together; will add 141 141 /// one or both classes if needed. Returns false on failure. 142 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer );142 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 143 143 144 144 /// Disallows widening for all bindings in the environment -
src/ResolvExpr/Unify.cc
r7564e10 r67130fe 14 14 // 15 15 16 #include <cassert> // for assertf, assert 17 #include <iterator> // for back_insert_iterator, back_inserter 18 #include <map> // for _Rb_tree_const_iterator, _Rb_tree_i... 19 #include <memory> // for unique_ptr 20 #include <set> // for set 21 #include <string> // for string, operator==, operator!=, bas... 22 #include <utility> // for pair, move 16 #include "Unify.h" 17 18 #include <cassert> // for assertf, assert 19 #include <iterator> // for back_insert_iterator, back_inserter 20 #include <map> // for _Rb_tree_const_iterator, _Rb_tree_i... 21 #include <memory> // for unique_ptr 22 #include <set> // for set 23 #include <string> // for string, operator==, operator!=, bas... 24 #include <utility> // for pair, move 23 25 #include <vector> 24 26 27 #include "AST/Decl.hpp" 25 28 #include "AST/Node.hpp" 29 #include "AST/Pass.hpp" 26 30 #include "AST/Type.hpp" 27 #include "Common/PassVisitor.h" // for PassVisitor 28 #include "FindOpenVars.h" // for findOpenVars 29 #include "Parser/LinkageSpec.h" // for C 30 #include "SynTree/Constant.h" // for Constant 31 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Declarati... 32 #include "SynTree/Expression.h" // for TypeExpr, Expression, ConstantExpr 33 #include "SynTree/Mutator.h" // for Mutator 34 #include "SynTree/Type.h" // for Type, TypeInstType, FunctionType 35 #include "SynTree/Visitor.h" // for Visitor 36 #include "Tuples/Tuples.h" // for isTtype 37 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet 38 #include "Unify.h" 39 #include "typeops.h" // for flatten, occurs, commonType 31 #include "AST/TypeEnvironment.hpp" 32 #include "Common/PassVisitor.h" // for PassVisitor 33 #include "FindOpenVars.h" // for findOpenVars 34 #include "Parser/LinkageSpec.h" // for C 35 #include "SynTree/Constant.h" // for Constant 36 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Declarati... 37 #include "SynTree/Expression.h" // for TypeExpr, Expression, ConstantExpr 38 #include "SynTree/Mutator.h" // for Mutator 39 #include "SynTree/Type.h" // for Type, TypeInstType, FunctionType 40 #include "SynTree/Visitor.h" // for Visitor 41 #include "Tuples/Tuples.h" // for isTtype 42 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet 43 #include "typeops.h" // for flatten, occurs, commonType 44 45 namespace ast { 46 class SymbolTable; 47 } 40 48 41 49 namespace SymTab { … … 47 55 namespace ResolvExpr { 48 56 49 struct Unify : public WithShortCircuiting {50 Unify ( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );57 struct Unify_old : public WithShortCircuiting { 58 Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 51 59 52 60 bool get_result() const { return result; } … … 80 88 AssertionSet &haveAssertions; 81 89 const OpenVarSet &openVars; 82 WidenMode widen Mode;90 WidenMode widen; 83 91 const SymTab::Indexer &indexer; 84 92 }; … … 86 94 /// Attempts an inexact unification of type1 and type2. 87 95 /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers) 88 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ); 89 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 96 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 97 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 98 99 bool unifyExact( 100 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 101 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 102 WidenMode widen, const ast::SymbolTable & symtab ); 90 103 91 104 bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { … … 106 119 delete newSecond; 107 120 return result; 121 } 122 123 bool typesCompatible( 124 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 125 const ast::TypeEnvironment & env ) { 126 ast::TypeEnvironment newEnv; 127 ast::OpenVarSet open, closed; 128 ast::AssertionSet need, have; 129 130 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 131 env.apply( newFirst ); 132 env.apply( newSecond ); 133 134 findOpenVars( newFirst, open, closed, need, have, FirstClosed ); 135 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 136 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 108 139 } 109 140 … … 132 163 } 133 164 165 bool typesCompatibleIgnoreQualifiers( 166 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 167 const ast::TypeEnvironment & env ) { 168 ast::TypeEnvironment newEnv; 169 ast::OpenVarSet open; 170 ast::AssertionSet need, have; 171 172 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 173 env.apply( newFirst ); 174 env.apply( newSecond ); 175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 177 178 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 180 } 181 134 182 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 135 183 OpenVarSet closedVars; … … 154 202 } 155 203 156 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer ) {204 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 157 205 #ifdef DEBUG 158 206 TypeEnvironment debugEnv( env ); … … 181 229 result = env.bindVarToVar( 182 230 var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions, 183 haveAssertions, openVars, widen Mode, indexer );231 haveAssertions, openVars, widen, indexer ); 184 232 } 185 233 } else if ( isopen1 ) { 186 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen Mode, indexer );187 } else if ( isopen2 ) { // TODO: swap widen Modevalues in call, since type positions are flipped?188 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen Mode, indexer );234 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer ); 235 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped? 236 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer ); 189 237 } else { 190 PassVisitor<Unify > comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );238 PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer ); 191 239 type1->accept( comparator ); 192 240 result = comparator.pass.get_result(); … … 213 261 } 214 262 215 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer, Type *&common ) {263 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) { 216 264 Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers(); 217 265 type1->get_qualifiers() = Type::Qualifiers(); … … 225 273 std::cerr << std::endl; 226 274 #endif 227 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen Mode, indexer ) ) {275 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) { 228 276 #ifdef DEBUG 229 277 std::cerr << "unifyInexact: no exact unification found" << std::endl; 230 278 #endif 231 if ( ( common = commonType( type1, type2, widen Mode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {279 if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) { 232 280 common->get_qualifiers() = tq1 | tq2; 233 281 #ifdef DEBUG … … 245 293 } else { 246 294 if ( tq1 != tq2 ) { 247 if ( ( tq1 > tq2 || widen Mode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {295 if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) { 248 296 common = type1->clone(); 249 297 common->get_qualifiers() = tq1 | tq2; … … 263 311 } 264 312 265 Unify ::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )266 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen Mode( widenMode), indexer( indexer ) {267 } 268 269 void Unify ::postvisit( __attribute__((unused)) VoidType *voidType) {313 Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) 314 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) { 315 } 316 317 void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) { 270 318 result = dynamic_cast< VoidType* >( type2 ); 271 319 } 272 320 273 void Unify ::postvisit(BasicType *basicType) {321 void Unify_old::postvisit(BasicType *basicType) { 274 322 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 275 323 result = basicType->get_kind() == otherBasic->get_kind(); … … 299 347 } 300 348 301 void Unify ::postvisit(PointerType *pointerType) {349 void Unify_old::postvisit(PointerType *pointerType) { 302 350 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 303 351 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 307 355 } 308 356 309 void Unify ::postvisit(ReferenceType *refType) {357 void Unify_old::postvisit(ReferenceType *refType) { 310 358 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 311 359 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 315 363 } 316 364 317 void Unify ::postvisit(ArrayType *arrayType) {365 void Unify_old::postvisit(ArrayType *arrayType) { 318 366 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 319 367 // to unify, array types must both be VLA or both not VLA … … 395 443 /// If this isn't done then argument lists can have wildly different 396 444 /// size and structure, when they should be compatible. 397 struct TtypeExpander : public WithShortCircuiting {445 struct TtypeExpander_old : public WithShortCircuiting { 398 446 TypeEnvironment & tenv; 399 TtypeExpander ( TypeEnvironment & tenv ) : tenv( tenv ) {}447 TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {} 400 448 void premutate( TypeInstType * ) { visit_children = false; } 401 449 Type * postmutate( TypeInstType * typeInst ) { … … 416 464 dst.clear(); 417 465 for ( DeclarationWithType * dcl : src ) { 418 PassVisitor<TtypeExpander > expander( env );466 PassVisitor<TtypeExpander_old> expander( env ); 419 467 dcl->acceptMutator( expander ); 420 468 std::list< Type * > types; … … 431 479 } 432 480 433 void Unify ::postvisit(FunctionType *functionType) {481 void Unify_old::postvisit(FunctionType *functionType) { 434 482 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 435 483 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { … … 442 490 443 491 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 444 if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) { 492 if ( 493 (flatFunc->parameters.size() == flatOther->parameters.size() && 494 flatFunc->returnVals.size() == flatOther->returnVals.size()) 495 || flatFunc->isTtype() 496 || flatOther->isTtype() 497 ) { 445 498 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 446 499 if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { … … 458 511 459 512 template< typename RefType > 460 void Unify ::handleRefType( RefType *inst, Type *other ) {513 void Unify_old::handleRefType( RefType *inst, Type *other ) { 461 514 // check that other type is compatible and named the same 462 515 RefType *otherStruct = dynamic_cast< RefType* >( other ); … … 465 518 466 519 template< typename RefType > 467 void Unify ::handleGenericRefType( RefType *inst, Type *other ) {520 void Unify_old::handleGenericRefType( RefType *inst, Type *other ) { 468 521 // Check that other type is compatible and named the same 469 522 handleRefType( inst, other ); … … 533 586 } 534 587 535 void Unify ::postvisit(StructInstType *structInst) {588 void Unify_old::postvisit(StructInstType *structInst) { 536 589 handleGenericRefType( structInst, type2 ); 537 590 } 538 591 539 void Unify ::postvisit(UnionInstType *unionInst) {592 void Unify_old::postvisit(UnionInstType *unionInst) { 540 593 handleGenericRefType( unionInst, type2 ); 541 594 } 542 595 543 void Unify ::postvisit(EnumInstType *enumInst) {596 void Unify_old::postvisit(EnumInstType *enumInst) { 544 597 handleRefType( enumInst, type2 ); 545 598 } 546 599 547 void Unify ::postvisit(TraitInstType *contextInst) {600 void Unify_old::postvisit(TraitInstType *contextInst) { 548 601 handleRefType( contextInst, type2 ); 549 602 } 550 603 551 void Unify ::postvisit(TypeInstType *typeInst) {604 void Unify_old::postvisit(TypeInstType *typeInst) { 552 605 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 553 606 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); … … 604 657 } 605 658 606 void Unify ::postvisit(TupleType *tupleType) {659 void Unify_old::postvisit(TupleType *tupleType) { 607 660 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 608 661 std::unique_ptr<TupleType> flat1( tupleType->clone() ); … … 610 663 std::list<Type *> types1, types2; 611 664 612 PassVisitor<TtypeExpander > expander( env );665 PassVisitor<TtypeExpander_old> expander( env ); 613 666 flat1->acceptMutator( expander ); 614 667 flat2->acceptMutator( expander ); … … 621 674 } 622 675 623 void Unify ::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {676 void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 624 677 result = dynamic_cast< VarArgsType* >( type2 ); 625 678 } 626 679 627 void Unify ::postvisit( __attribute__((unused)) ZeroType *zeroType ) {680 void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 628 681 result = dynamic_cast< ZeroType* >( type2 ); 629 682 } 630 683 631 void Unify ::postvisit( __attribute__((unused)) OneType *oneType ) {684 void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) { 632 685 result = dynamic_cast< OneType* >( type2 ); 633 686 } … … 647 700 } 648 701 702 class Unify_new final : public ast::WithShortCircuiting { 703 const ast::Type * type2; 704 ast::TypeEnvironment & tenv; 705 ast::AssertionSet & need; 706 ast::AssertionSet & have; 707 const ast::OpenVarSet & open; 708 WidenMode widen; 709 const ast::SymbolTable & symtab; 710 public: 711 bool result; 712 713 Unify_new( 714 const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need, 715 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen, 716 const ast::SymbolTable & symtab ) 717 : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen), 718 symtab(symtab), result(false) {} 719 720 void previsit( const ast::Node * ) { visit_children = false; } 721 722 void postvisit( const ast::VoidType * ) { 723 result = dynamic_cast< const ast::VoidType * >( type2 ); 724 } 725 726 void postvisit( const ast::BasicType * basic ) { 727 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 728 result = basic->kind == basic2->kind; 729 } 730 } 731 732 void postvisit( const ast::PointerType * pointer ) { 733 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 734 result = unifyExact( 735 pointer->base, pointer2->base, tenv, need, have, open, 736 noWiden(), symtab ); 737 } 738 } 739 740 void postvisit( const ast::ArrayType * array ) { 741 auto array2 = dynamic_cast< const ast::ArrayType * >( type2 ); 742 if ( ! array2 ) return; 743 744 // to unify, array types must both be VLA or both not VLA and both must have a 745 // dimension expression or not have a dimension 746 if ( array->isVarLen != array2->isVarLen ) return; 747 if ( ! array->isVarLen && ! array2->isVarLen 748 && array->dimension && array2->dimension ) { 749 auto ce1 = array->dimension.as< ast::ConstantExpr >(); 750 auto ce2 = array2->dimension.as< ast::ConstantExpr >(); 751 752 // see C11 Reference Manual 6.7.6.2.6 753 // two array types with size specifiers that are integer constant expressions are 754 // compatible if both size specifiers have the same constant value 755 if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return; 756 } 757 758 result = unifyExact( 759 array->base, array2->base, tenv, need, have, open, noWiden(), 760 symtab ); 761 } 762 763 void postvisit( const ast::ReferenceType * ref ) { 764 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 765 result = unifyExact( 766 ref->base, ref2->base, tenv, need, have, open, noWiden(), 767 symtab ); 768 } 769 } 770 771 private: 772 /// Replaces ttype variables with their bound types. 773 /// If this isn't done when satifying ttype assertions, then argument lists can have 774 /// different size and structure when they should be compatible. 775 struct TtypeExpander_new : public ast::WithShortCircuiting { 776 ast::TypeEnvironment & tenv; 777 778 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 779 780 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 781 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) { 782 // expand ttype parameter into its actual type 783 if ( clz->data.kind == ast::TypeVar::Ttype && clz->bound ) { 784 return clz->bound; 785 } 786 } 787 return typeInst; 788 } 789 }; 790 791 /// returns flattened version of `src` 792 static std::vector< ast::ptr< ast::DeclWithType > > flattenList( 793 const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env 794 ) { 795 std::vector< ast::ptr< ast::DeclWithType > > dst; 796 dst.reserve( src.size() ); 797 for ( const ast::DeclWithType * d : src ) { 798 ast::Pass<TtypeExpander_new> expander{ env }; 799 d = d->accept( expander ); 800 auto types = flatten( d->get_type() ); 801 for ( ast::ptr< ast::Type > & t : types ) { 802 // outermost const, volatile, _Atomic qualifiers in parameters should not play 803 // a role in the unification of function types, since they do not determine 804 // whether a function is callable. 805 // NOTE: **must** consider at least mutex qualifier, since functions can be 806 // overloaded on outermost mutex and a mutex function has different 807 // requirements than a non-mutex function 808 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 809 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } ); 810 } 811 } 812 return dst; 813 } 814 815 /// Creates a tuple type based on a list of DeclWithType 816 template< typename Iter > 817 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) { 818 std::vector< ast::ptr< ast::Type > > types; 819 while ( crnt != end ) { 820 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 821 // that this results in a flat tuple 822 flatten( (*crnt)->get_type(), types ); 823 824 ++crnt; 825 } 826 827 return { new ast::TupleType{ std::move(types) } }; 828 } 829 830 template< typename Iter > 831 static bool unifyDeclList( 832 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 833 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 834 const ast::SymbolTable & symtab 835 ) { 836 while ( crnt1 != end1 && crnt2 != end2 ) { 837 const ast::Type * t1 = (*crnt1)->get_type(); 838 const ast::Type * t2 = (*crnt2)->get_type(); 839 bool isTuple1 = Tuples::isTtype( t1 ); 840 bool isTuple2 = Tuples::isTtype( t2 ); 841 842 // assumes here that ttype *must* be last parameter 843 if ( isTuple1 && ! isTuple2 ) { 844 // combine remainder of list2, then unify 845 return unifyExact( 846 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 847 noWiden(), symtab ); 848 } else if ( ! isTuple1 && isTuple2 ) { 849 // combine remainder of list1, then unify 850 return unifyExact( 851 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 852 noWiden(), symtab ); 853 } 854 855 if ( ! unifyExact( 856 t1, t2, env, need, have, open, noWiden(), symtab ) 857 ) return false; 858 859 ++crnt1; ++crnt2; 860 } 861 862 // May get to the end of one argument list before the other. This is only okay if the 863 // other is a ttype 864 if ( crnt1 != end1 ) { 865 // try unifying empty tuple with ttype 866 const ast::Type * t1 = (*crnt1)->get_type(); 867 if ( ! Tuples::isTtype( t1 ) ) return false; 868 return unifyExact( 869 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 870 noWiden(), symtab ); 871 } else if ( crnt2 != end2 ) { 872 // try unifying empty tuple with ttype 873 const ast::Type * t2 = (*crnt2)->get_type(); 874 if ( ! Tuples::isTtype( t2 ) ) return false; 875 return unifyExact( 876 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 877 noWiden(), symtab ); 878 } 879 880 return true; 881 } 882 883 static bool unifyDeclList( 884 const std::vector< ast::ptr< ast::DeclWithType > > & list1, 885 const std::vector< ast::ptr< ast::DeclWithType > > & list2, 886 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 887 const ast::OpenVarSet & open, const ast::SymbolTable & symtab 888 ) { 889 return unifyDeclList( 890 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 891 symtab ); 892 } 893 894 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) { 895 auto i = assns.find( assn ); 896 if ( i != assns.end() ) { 897 i->second.isUsed = true; 898 } 899 } 900 901 /// mark all assertions in `type` used in both `assn1` and `assn2` 902 static void markAssertions( 903 ast::AssertionSet & assn1, ast::AssertionSet & assn2, 904 const ast::ParameterizedType * type 905 ) { 906 for ( const auto & tyvar : type->forall ) { 907 for ( const ast::DeclWithType * assert : tyvar->assertions ) { 908 markAssertionSet( assn1, assert ); 909 markAssertionSet( assn2, assert ); 910 } 911 } 912 } 913 914 public: 915 void postvisit( const ast::FunctionType * func ) { 916 auto func2 = dynamic_cast< const ast::FunctionType * >( type2 ); 917 if ( ! func2 ) return; 918 919 if ( func->isVarArgs != func2->isVarArgs ) return; 920 921 // Flatten the parameter lists for both functions so that tuple structure does not 922 // affect unification. Does not actually mutate function parameters. 923 auto params = flattenList( func->params, tenv ); 924 auto params2 = flattenList( func2->params, tenv ); 925 926 // sizes don't have to match if ttypes are involved; need to be more precise w.r.t. 927 // where the ttype is to prevent errors 928 if ( 929 ( params.size() != params2.size() || func->returns.size() != func2->returns.size() ) 930 && ! func->isTtype() 931 && ! func2->isTtype() 932 ) return; 933 934 if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return; 935 if ( ! unifyDeclList( 936 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return; 937 938 markAssertions( have, need, func ); 939 markAssertions( have, need, func2 ); 940 941 result = true; 942 } 943 944 private: 945 template< typename RefType > 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 947 // check that the other type is compatible and named the same 948 auto otherInst = dynamic_cast< const RefType * >( other ); 949 result = otherInst && inst->name == otherInst->name; 950 return otherInst; 951 } 952 953 /// Creates a tuple type based on a list of TypeExpr 954 template< typename Iter > 955 static const ast::Type * tupleFromExprs( 956 const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs 957 ) { 958 std::vector< ast::ptr< ast::Type > > types; 959 do { 960 types.emplace_back( param->type ); 961 962 ++crnt; 963 if ( crnt == end ) break; 964 param = strict_dynamic_cast< const ast::TypeExpr * >( crnt->get() ); 965 } while(true); 966 967 return new ast::TupleType{ std::move(types), qs }; 968 } 969 970 template< typename RefType > 971 void handleGenericRefType( const RefType * inst, const ast::Type * other ) { 972 // check that other type is compatible and named the same 973 const RefType * inst2 = handleRefType( inst, other ); 974 if ( ! inst2 ) return; 975 976 // check that parameters of types unify, if any 977 const std::vector< ast::ptr< ast::Expr > > & params = inst->params; 978 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params; 979 980 auto it = params.begin(); 981 auto jt = params2.begin(); 982 for ( ; it != params.end() && jt != params2.end(); ++it, ++jt ) { 983 auto param = strict_dynamic_cast< const ast::TypeExpr * >( it->get() ); 984 auto param2 = strict_dynamic_cast< const ast::TypeExpr * >( jt->get() ); 985 986 ast::ptr< ast::Type > pty = param->type; 987 ast::ptr< ast::Type > pty2 = param2->type; 988 989 bool isTuple = Tuples::isTtype( pty ); 990 bool isTuple2 = Tuples::isTtype( pty2 ); 991 992 if ( isTuple && isTuple2 ) { 993 ++it; ++jt; // skip ttype parameters before break 994 } else if ( isTuple ) { 995 // bundle remaining params into tuple 996 pty2 = tupleFromExprs( param2, jt, params2.end(), pty->qualifiers ); 997 ++it; // skip ttype parameter for break 998 } else if ( isTuple2 ) { 999 // bundle remaining params into tuple 1000 pty = tupleFromExprs( param, it, params.end(), pty2->qualifiers ); 1001 ++jt; // skip ttype parameter for break 1002 } 1003 1004 if ( ! unifyExact( 1005 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) { 1006 result = false; 1007 return; 1008 } 1009 1010 // ttype parameter should be last 1011 if ( isTuple || isTuple2 ) break; 1012 } 1013 result = it == params.end() && jt == params2.end(); 1014 } 1015 1016 public: 1017 void postvisit( const ast::StructInstType * aggrType ) { 1018 handleGenericRefType( aggrType, type2 ); 1019 } 1020 1021 void postvisit( const ast::UnionInstType * aggrType ) { 1022 handleGenericRefType( aggrType, type2 ); 1023 } 1024 1025 void postvisit( const ast::EnumInstType * aggrType ) { 1026 handleRefType( aggrType, type2 ); 1027 } 1028 1029 void postvisit( const ast::TraitInstType * aggrType ) { 1030 handleRefType( aggrType, type2 ); 1031 } 1032 1033 void postvisit( const ast::TypeInstType * typeInst ) { 1034 assert( open.find( typeInst->name ) == open.end() ); 1035 handleRefType( typeInst, type2 ); 1036 } 1037 1038 private: 1039 /// Creates a tuple type based on a list of Type 1040 static ast::ptr< ast::Type > tupleFromTypes( 1041 const std::vector< ast::ptr< ast::Type > > & tys 1042 ) { 1043 std::vector< ast::ptr< ast::Type > > out; 1044 for ( const ast::Type * ty : tys ) { 1045 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 1046 // that this results in a flat tuple 1047 flatten( ty, out ); 1048 } 1049 1050 return { new ast::TupleType{ std::move(out) } }; 1051 } 1052 1053 static bool unifyList( 1054 const std::vector< ast::ptr< ast::Type > > & list1, 1055 const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env, 1056 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1057 const ast::SymbolTable & symtab 1058 ) { 1059 auto crnt1 = list1.begin(); 1060 auto crnt2 = list2.begin(); 1061 while ( crnt1 != list1.end() && crnt2 != list2.end() ) { 1062 const ast::Type * t1 = *crnt1; 1063 const ast::Type * t2 = *crnt2; 1064 bool isTuple1 = Tuples::isTtype( t1 ); 1065 bool isTuple2 = Tuples::isTtype( t2 ); 1066 1067 // assumes ttype must be last parameter 1068 if ( isTuple1 && ! isTuple2 ) { 1069 // combine entirety of list2, then unify 1070 return unifyExact( 1071 t1, tupleFromTypes( list2 ), env, need, have, open, 1072 noWiden(), symtab ); 1073 } else if ( ! isTuple1 && isTuple2 ) { 1074 // combine entirety of list1, then unify 1075 return unifyExact( 1076 tupleFromTypes( list1 ), t2, env, need, have, open, 1077 noWiden(), symtab ); 1078 } 1079 1080 if ( ! unifyExact( 1081 t1, t2, env, need, have, open, noWiden(), symtab ) 1082 ) return false; 1083 1084 ++crnt1; ++crnt2; 1085 } 1086 1087 if ( crnt1 != list1.end() ) { 1088 // try unifying empty tuple type with ttype 1089 const ast::Type * t1 = *crnt1; 1090 if ( ! Tuples::isTtype( t1 ) ) return false; 1091 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported 1092 // from Rob's code 1093 return unifyExact( 1094 t1, tupleFromTypes( list2 ), env, need, have, open, 1095 noWiden(), symtab ); 1096 } else if ( crnt2 != list2.end() ) { 1097 // try unifying empty tuple with ttype 1098 const ast::Type * t2 = *crnt2; 1099 if ( ! Tuples::isTtype( t2 ) ) return false; 1100 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported 1101 // from Rob's code 1102 return unifyExact( 1103 tupleFromTypes( list1 ), t2, env, need, have, open, 1104 noWiden(), symtab ); 1105 } 1106 1107 return true; 1108 } 1109 1110 public: 1111 void postvisit( const ast::TupleType * tuple ) { 1112 auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 ); 1113 if ( ! tuple2 ) return; 1114 1115 ast::Pass<TtypeExpander_new> expander{ tenv }; 1116 const ast::Type * flat = tuple->accept( expander ); 1117 const ast::Type * flat2 = tuple2->accept( expander ); 1118 1119 auto types = flatten( flat ); 1120 auto types2 = flatten( flat2 ); 1121 1122 result = unifyList( types, types2, tenv, need, have, open, symtab ); 1123 } 1124 1125 void postvisit( const ast::VarArgsType * ) { 1126 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 1127 } 1128 1129 void postvisit( const ast::ZeroType * ) { 1130 result = dynamic_cast< const ast::ZeroType * >( type2 ); 1131 } 1132 1133 void postvisit( const ast::OneType * ) { 1134 result = dynamic_cast< const ast::OneType * >( type2 ); 1135 } 1136 1137 private: 1138 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 1139 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); 1140 }; 1141 1142 bool unify( 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1144 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1145 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1146 ) { 1147 ast::OpenVarSet closed; 1148 findOpenVars( type1, open, closed, need, have, FirstClosed ); 1149 findOpenVars( type2, open, closed, need, have, FirstOpen ); 1150 return unifyInexact( 1151 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common ); 1152 } 1153 1154 bool unifyExact( 1155 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 1156 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1157 WidenMode widen, const ast::SymbolTable & symtab 1158 ) { 1159 if ( type1->qualifiers != type2->qualifiers ) return false; 1160 1161 auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 ); 1162 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 ); 1163 ast::OpenVarSet::const_iterator 1164 entry1 = var1 ? open.find( var1->name ) : open.end(), 1165 entry2 = var2 ? open.find( var2->name ) : open.end(); 1166 bool isopen1 = entry1 != open.end(); 1167 bool isopen2 = entry2 != open.end(); 1168 1169 if ( isopen1 && isopen2 ) { 1170 if ( entry1->second.kind != entry2->second.kind ) return false; 1171 return env.bindVarToVar( 1172 var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have, 1173 open, widen, symtab ); 1174 } else if ( isopen1 ) { 1175 return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab ); 1176 } else if ( isopen2 ) { 1177 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab ); 1178 } else { 1179 ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab }; 1180 type1->accept( comparator ); 1181 return comparator.pass.result; 1182 } 1183 } 1184 1185 bool unifyInexact( 1186 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1187 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1188 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 1189 ast::ptr<ast::Type> & common 1190 ) { 1191 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 1192 1193 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 1194 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1195 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1196 reset_qualifiers( t1 ); 1197 reset_qualifiers( t2 ); 1198 1199 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { 1200 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1201 1202 // if exact unification on unqualified types, try to merge qualifiers 1203 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1204 common = type1; 1205 reset_qualifiers( common, q1 | q2 ); 1206 return true; 1207 } else { 1208 return false; 1209 } 1210 1211 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) { 1212 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1213 1214 // no exact unification, but common type 1215 reset_qualifiers( common, q1 | q2 ); 1216 return true; 1217 } else { 1218 return false; 1219 } 1220 } 1221 649 1222 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) { 650 1223 if ( func->returns.empty() ) return new ast::VoidType{}; -
src/ResolvExpr/Unify.h
r7564e10 r67130fe 18 18 #include <list> // for list 19 19 20 #include "AST/Node.hpp" // for ptr 21 #include "AST/TypeEnvironment.hpp" // for TypeEnvironment, AssertionSet, OpenVarSet 20 22 #include "Common/utility.h" // for deleteAll 21 23 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data 22 24 #include "TypeEnvironment.h" // for AssertionSet, OpenVarSet 23 #include "WidenMode.h" // for WidenMode25 #include "WidenMode.h" // for WidenMode 24 26 25 27 class Type; 26 28 class TypeInstType; 27 29 namespace SymTab { 28 class Indexer; 29 } // namespace SymTab 30 class Indexer; 31 } 32 33 namespace ast { 34 class SymbolTable; 35 class Type; 36 } 30 37 31 38 namespace ResolvExpr { … … 33 40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ); 34 41 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 35 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer, Type *&common );42 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 36 43 37 44 template< typename Iterator1, typename Iterator2 > … … 62 69 } 63 70 71 bool unify( 72 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 73 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 74 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 75 76 bool unifyExact( 77 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 78 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 79 WidenMode widen, const ast::SymbolTable & symtab ); 80 81 bool unifyInexact( 82 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 83 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 84 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 85 ast::ptr<ast::Type> & common ); 86 64 87 } // namespace ResolvExpr 65 88 -
src/ResolvExpr/WidenMode.h
r7564e10 r67130fe 18 18 namespace ResolvExpr { 19 19 struct WidenMode { 20 WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {} 21 WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; } 22 WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; } 23 WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; } 24 WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; } 25 operator bool() { return widenFirst && widenSecond; } 20 WidenMode( bool first, bool second ): first( first ), second( second ) {} 21 22 WidenMode &operator|=( const WidenMode &other ) { 23 first |= other.first; second |= other.second; return *this; 24 } 26 25 27 bool widenFirst : 1, widenSecond : 1; 26 WidenMode &operator&=( const WidenMode &other ) { 27 first &= other.first; second &= other.second; return *this; 28 } 29 30 WidenMode operator|( const WidenMode &other ) { 31 WidenMode newWM( *this ); newWM |= other; return newWM; 32 } 33 34 WidenMode operator&( const WidenMode &other ) { 35 WidenMode newWM( *this ); newWM &= other; return newWM; 36 } 37 38 operator bool() { return first && second; } 39 40 bool first : 1, second : 1; 28 41 }; 42 43 static inline WidenMode noWiden() { return { false, false }; } 29 44 } // namespace ResolvExpr 30 45 -
src/ResolvExpr/typeops.h
r7564e10 r67130fe 18 18 #include <vector> 19 19 20 #include "Cost.h" 21 #include "TypeEnvironment.h" 22 #include "WidenMode.h" 23 #include "AST/Fwd.hpp" 20 24 #include "AST/Node.hpp" 25 #include "AST/SymbolTable.hpp" 21 26 #include "AST/Type.hpp" 27 #include "AST/TypeEnvironment.hpp" 22 28 #include "SynTree/SynTree.h" 23 29 #include "SynTree/Type.h" 24 30 #include "SymTab/Indexer.h" 25 #include "Cost.h"26 #include "TypeEnvironment.h"27 31 28 32 namespace ResolvExpr { … … 85 89 86 90 // in Unify.cc 87 bool isFtype( Type *type );88 91 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 89 92 bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 99 102 } 100 103 104 bool typesCompatible( 105 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 106 const ast::TypeEnvironment & env = {} ); 107 108 bool typesCompatibleIgnoreQualifiers( 109 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 110 const ast::TypeEnvironment & env = {} ); 111 101 112 /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value. 102 113 Type * extractResultType( FunctionType * functionType ); … … 106 117 // in CommonType.cc 107 118 Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 119 ast::ptr< ast::Type > commonType( 120 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen, 121 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open ); 108 122 109 123 // in PolyCost.cc … … 115 129 // in Occurs.cc 116 130 bool occurs( Type *type, std::string varName, const TypeEnvironment &env ); 131 // new AST version in TypeEnvironment.cpp (only place it was used in old AST) 117 132 118 133 template<typename Iter> … … 127 142 // in AlternativeFinder.cc 128 143 void referenceToRvalueConversion( Expression *& expr, Cost & cost ); 144 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ); 129 145 130 // flatten tuple type into list of types146 /// flatten tuple type into list of types 131 147 template< typename OutputIterator > 132 148 void flatten( Type * type, OutputIterator out ) { … … 139 155 } 140 156 } 157 158 /// flatten tuple type into existing list of types 159 static inline void flatten( 160 const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out 161 ) { 162 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) { 163 for ( const ast::Type * t : tupleType->types ) { 164 flatten( t, out ); 165 } 166 } else { 167 out.emplace_back( type ); 168 } 169 } 170 171 /// flatten tuple type into list of types 172 static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) { 173 std::vector< ast::ptr< ast::Type > > out; 174 out.reserve( type->size() ); 175 flatten( type, out ); 176 return out; 177 } 178 179 // in TypeEnvironment.cc 180 bool isFtype( Type *type ); 141 181 } // namespace ResolvExpr 182 183 namespace ast { 184 // in TypeEnvironment.cpp 185 bool isFtype( const ast::Type * type ); 186 } // namespace ast 142 187 143 188 // Local Variables: // -
src/SymTab/Mangler.cc
r7564e10 r67130fe 32 32 #include "SynTree/Type.h" // for Type, ReferenceToType, Type::Fora... 33 33 34 #include "AST/Pass.hpp" 35 34 36 namespace SymTab { 35 37 namespace Mangler { 36 38 namespace { 37 39 /// Mangles names to a unique C identifier 38 struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {39 Mangler ( bool mangleOverridable, bool typeMode, bool mangleGenericParams );40 Mangler ( const Mangler& ) = delete;40 struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards { 41 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); 42 Mangler_old( const Mangler_old & ) = delete; 41 43 42 44 void previsit( BaseSyntaxNode * ) { visit_children = false; } … … 77 79 78 80 public: 79 Mangler ( bool mangleOverridable, bool typeMode, bool mangleGenericParams,81 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 80 82 int nextVarNum, const VarMapType& varNums ); 81 83 … … 85 87 86 88 void printQualifiers( Type *type ); 87 }; // Mangler 89 }; // Mangler_old 88 90 } // namespace 89 91 90 92 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) { 91 PassVisitor<Mangler > mangler( mangleOverridable, typeMode, mangleGenericParams );93 PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams ); 92 94 maybeAccept( decl, mangler ); 93 95 return mangler.pass.get_mangleName(); … … 95 97 96 98 std::string mangleType( Type * ty ) { 97 PassVisitor<Mangler > mangler( false, true, true );99 PassVisitor<Mangler_old> mangler( false, true, true ); 98 100 maybeAccept( ty, mangler ); 99 101 return mangler.pass.get_mangleName(); … … 101 103 102 104 std::string mangleConcrete( Type * ty ) { 103 PassVisitor<Mangler > mangler( false, false, false );105 PassVisitor<Mangler_old> mangler( false, false, false ); 104 106 maybeAccept( ty, mangler ); 105 107 return mangler.pass.get_mangleName(); … … 107 109 108 110 namespace { 109 Mangler ::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )111 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 110 112 : nextVarNum( 0 ), isTopLevel( true ), 111 113 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 112 114 mangleGenericParams( mangleGenericParams ) {} 113 115 114 Mangler ::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,116 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 115 117 int nextVarNum, const VarMapType& varNums ) 116 118 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), … … 118 120 mangleGenericParams( mangleGenericParams ) {} 119 121 120 void Mangler ::mangleDecl( DeclarationWithType * declaration ) {122 void Mangler_old::mangleDecl( DeclarationWithType * declaration ) { 121 123 bool wasTopLevel = isTopLevel; 122 124 if ( isTopLevel ) { … … 148 150 } 149 151 150 void Mangler ::postvisit( ObjectDecl * declaration ) {152 void Mangler_old::postvisit( ObjectDecl * declaration ) { 151 153 mangleDecl( declaration ); 152 154 } 153 155 154 void Mangler ::postvisit( FunctionDecl * declaration ) {156 void Mangler_old::postvisit( FunctionDecl * declaration ) { 155 157 mangleDecl( declaration ); 156 158 } 157 159 158 void Mangler ::postvisit( VoidType * voidType ) {160 void Mangler_old::postvisit( VoidType * voidType ) { 159 161 printQualifiers( voidType ); 160 162 mangleName << Encoding::void_t; 161 163 } 162 164 163 void Mangler ::postvisit( BasicType * basicType ) {165 void Mangler_old::postvisit( BasicType * basicType ) { 164 166 printQualifiers( basicType ); 165 167 assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() ); … … 167 169 } 168 170 169 void Mangler ::postvisit( PointerType * pointerType ) {171 void Mangler_old::postvisit( PointerType * pointerType ) { 170 172 printQualifiers( pointerType ); 171 173 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers … … 174 176 } 175 177 176 void Mangler ::postvisit( ArrayType * arrayType ) {178 void Mangler_old::postvisit( ArrayType * arrayType ) { 177 179 // TODO: encode dimension 178 180 printQualifiers( arrayType ); … … 181 183 } 182 184 183 void Mangler ::postvisit( ReferenceType * refType ) {185 void Mangler_old::postvisit( ReferenceType * refType ) { 184 186 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 185 187 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), … … 200 202 } 201 203 202 void Mangler ::postvisit( FunctionType * functionType ) {204 void Mangler_old::postvisit( FunctionType * functionType ) { 203 205 printQualifiers( functionType ); 204 206 mangleName << Encoding::function; … … 217 219 } 218 220 219 void Mangler ::mangleRef( ReferenceToType * refType, std::string prefix ) {221 void Mangler_old::mangleRef( ReferenceToType * refType, std::string prefix ) { 220 222 printQualifiers( refType ); 221 223 … … 236 238 } 237 239 238 void Mangler ::postvisit( StructInstType * aggregateUseType ) {240 void Mangler_old::postvisit( StructInstType * aggregateUseType ) { 239 241 mangleRef( aggregateUseType, Encoding::struct_t ); 240 242 } 241 243 242 void Mangler ::postvisit( UnionInstType * aggregateUseType ) {244 void Mangler_old::postvisit( UnionInstType * aggregateUseType ) { 243 245 mangleRef( aggregateUseType, Encoding::union_t ); 244 246 } 245 247 246 void Mangler ::postvisit( EnumInstType * aggregateUseType ) {248 void Mangler_old::postvisit( EnumInstType * aggregateUseType ) { 247 249 mangleRef( aggregateUseType, Encoding::enum_t ); 248 250 } 249 251 250 void Mangler ::postvisit( TypeInstType * typeInst ) {252 void Mangler_old::postvisit( TypeInstType * typeInst ) { 251 253 VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); 252 254 if ( varNum == varNums.end() ) { … … 264 266 } 265 267 266 void Mangler ::postvisit( TraitInstType * inst ) {268 void Mangler_old::postvisit( TraitInstType * inst ) { 267 269 printQualifiers( inst ); 268 270 mangleName << inst->name.size() << inst->name; 269 271 } 270 272 271 void Mangler ::postvisit( TupleType * tupleType ) {273 void Mangler_old::postvisit( TupleType * tupleType ) { 272 274 printQualifiers( tupleType ); 273 275 mangleName << Encoding::tuple << tupleType->types.size(); … … 275 277 } 276 278 277 void Mangler ::postvisit( VarArgsType * varArgsType ) {279 void Mangler_old::postvisit( VarArgsType * varArgsType ) { 278 280 printQualifiers( varArgsType ); 279 281 static const std::string vargs = "__builtin_va_list"; … … 281 283 } 282 284 283 void Mangler ::postvisit( ZeroType * ) {285 void Mangler_old::postvisit( ZeroType * ) { 284 286 mangleName << Encoding::zero; 285 287 } 286 288 287 void Mangler ::postvisit( OneType * ) {289 void Mangler_old::postvisit( OneType * ) { 288 290 mangleName << Encoding::one; 289 291 } 290 292 291 void Mangler ::postvisit( QualifiedType * qualType ) {293 void Mangler_old::postvisit( QualifiedType * qualType ) { 292 294 bool inqual = inQualifiedType; 293 295 if (! inqual ) { … … 305 307 } 306 308 307 void Mangler ::postvisit( TypeDecl * decl ) {309 void Mangler_old::postvisit( TypeDecl * decl ) { 308 310 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 309 311 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. … … 311 313 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed 312 314 // aside from the assert false. 313 assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));315 assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl)); 314 316 assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() ); 315 317 mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name; … … 322 324 } 323 325 324 void Mangler ::printQualifiers( Type * type ) {326 void Mangler_old::printQualifiers( Type * type ) { 325 327 // skip if not including qualifiers 326 328 if ( typeMode ) return; … … 345 347 varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind() ); 346 348 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { 347 PassVisitor<Mangler > sub_mangler(349 PassVisitor<Mangler_old> sub_mangler( 348 350 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 349 351 (*assert)->accept( sub_mangler ); … … 390 392 } // namespace SymTab 391 393 394 namespace Mangle { 395 namespace { 396 /// Mangles names to a unique C identifier 397 struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards { 398 Mangler_new( Mangle::Mode mode ); 399 Mangler_new( const Mangler_new & ) = delete; 400 401 void previsit( const ast::Node * ) { visit_children = false; } 402 403 void postvisit( const ast::ObjectDecl * declaration ); 404 void postvisit( const ast::FunctionDecl * declaration ); 405 void postvisit( const ast::TypeDecl * declaration ); 406 407 void postvisit( const ast::VoidType * voidType ); 408 void postvisit( const ast::BasicType * basicType ); 409 void postvisit( const ast::PointerType * pointerType ); 410 void postvisit( const ast::ArrayType * arrayType ); 411 void postvisit( const ast::ReferenceType * refType ); 412 void postvisit( const ast::FunctionType * functionType ); 413 void postvisit( const ast::StructInstType * aggregateUseType ); 414 void postvisit( const ast::UnionInstType * aggregateUseType ); 415 void postvisit( const ast::EnumInstType * aggregateUseType ); 416 void postvisit( const ast::TypeInstType * aggregateUseType ); 417 void postvisit( const ast::TraitInstType * inst ); 418 void postvisit( const ast::TupleType * tupleType ); 419 void postvisit( const ast::VarArgsType * varArgsType ); 420 void postvisit( const ast::ZeroType * zeroType ); 421 void postvisit( const ast::OneType * oneType ); 422 void postvisit( const ast::QualifiedType * qualType ); 423 424 std::string get_mangleName() { return mangleName.str(); } 425 private: 426 std::ostringstream mangleName; ///< Mangled name being constructed 427 typedef std::map< std::string, std::pair< int, int > > VarMapType; 428 VarMapType varNums; ///< Map of type variables to indices 429 int nextVarNum; ///< Next type variable index 430 bool isTopLevel; ///< Is the Mangler at the top level 431 bool mangleOverridable; ///< Specially mangle overridable built-in methods 432 bool typeMode; ///< Produce a unique mangled name for a type 433 bool mangleGenericParams; ///< Include generic parameters in name mangling if true 434 bool inFunctionType = false; ///< Include type qualifiers if false. 435 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type 436 437 private: 438 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 439 int nextVarNum, const VarMapType& varNums ); 440 friend class ast::Pass<Mangler_new>; 441 442 private: 443 void mangleDecl( const ast::DeclWithType *declaration ); 444 void mangleRef( const ast::ReferenceToType *refType, std::string prefix ); 445 446 void printQualifiers( const ast::Type *type ); 447 }; // Mangler_new 448 } // namespace 449 450 451 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) { 452 ast::Pass<Mangler_new> mangler( mode ); 453 maybeAccept( decl, mangler ); 454 return mangler.pass.get_mangleName(); 455 } 456 457 namespace { 458 Mangler_new::Mangler_new( Mangle::Mode mode ) 459 : nextVarNum( 0 ), isTopLevel( true ), 460 mangleOverridable ( ! mode.no_overrideable ), 461 typeMode ( mode.type ), 462 mangleGenericParams( ! mode.no_generic_params ) {} 463 464 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 465 int nextVarNum, const VarMapType& varNums ) 466 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 467 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 468 mangleGenericParams( mangleGenericParams ) {} 469 470 void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) { 471 bool wasTopLevel = isTopLevel; 472 if ( isTopLevel ) { 473 varNums.clear(); 474 nextVarNum = 0; 475 isTopLevel = false; 476 } // if 477 mangleName << Encoding::manglePrefix; 478 CodeGen::OperatorInfo opInfo; 479 if ( operatorLookup( decl->name, opInfo ) ) { 480 mangleName << opInfo.outputName.size() << opInfo.outputName; 481 } else { 482 mangleName << decl->name.size() << decl->name; 483 } // if 484 maybeAccept( decl->get_type(), *visitor ); 485 if ( mangleOverridable && decl->linkage.is_overrideable ) { 486 // want to be able to override autogenerated and intrinsic routines, 487 // so they need a different name mangling 488 if ( decl->linkage == ast::Linkage::AutoGen ) { 489 mangleName << Encoding::autogen; 490 } else if ( decl->linkage == ast::Linkage::Intrinsic ) { 491 mangleName << Encoding::intrinsic; 492 } else { 493 // if we add another kind of overridable function, this has to change 494 assert( false && "unknown overrideable linkage" ); 495 } // if 496 } 497 isTopLevel = wasTopLevel; 498 } 499 500 void Mangler_new::postvisit( const ast::ObjectDecl * decl ) { 501 mangleDecl( decl ); 502 } 503 504 void Mangler_new::postvisit( const ast::FunctionDecl * decl ) { 505 mangleDecl( decl ); 506 } 507 508 void Mangler_new::postvisit( const ast::VoidType * voidType ) { 509 printQualifiers( voidType ); 510 mangleName << Encoding::void_t; 511 } 512 513 void Mangler_new::postvisit( const ast::BasicType * basicType ) { 514 printQualifiers( basicType ); 515 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind ); 516 mangleName << Encoding::basicTypes[ basicType->kind ]; 517 } 518 519 void Mangler_new::postvisit( const ast::PointerType * pointerType ) { 520 printQualifiers( pointerType ); 521 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers 522 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer; 523 maybe_accept( pointerType->base.get(), *visitor ); 524 } 525 526 void Mangler_new::postvisit( const ast::ArrayType * arrayType ) { 527 // TODO: encode dimension 528 printQualifiers( arrayType ); 529 mangleName << Encoding::array << "0"; 530 maybeAccept( arrayType->base.get(), *visitor ); 531 } 532 533 void Mangler_new::postvisit( const ast::ReferenceType * refType ) { 534 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 535 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), 536 // by pretending every reference type is a function parameter. 537 GuardValue( inFunctionType ); 538 inFunctionType = true; 539 printQualifiers( refType ); 540 maybeAccept( refType->base.get(), *visitor ); 541 } 542 543 inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) { 544 std::vector< ast::ptr< ast::Type > > ret; 545 std::transform( decls.begin(), decls.end(), std::back_inserter( ret ), 546 std::mem_fun( &ast::DeclWithType::get_type ) ); 547 return ret; 548 } 549 550 void Mangler_new::postvisit( const ast::FunctionType * functionType ) { 551 printQualifiers( functionType ); 552 mangleName << Encoding::function; 553 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters, 554 // since qualifiers on outermost parameter type do not differentiate function types, e.g., 555 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different 556 GuardValue( inFunctionType ); 557 inFunctionType = true; 558 std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns ); 559 if (returnTypes.empty()) mangleName << Encoding::void_t; 560 else accept_each( returnTypes, *visitor ); 561 mangleName << "_"; 562 std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params ); 563 accept_each( paramTypes, *visitor ); 564 mangleName << "_"; 565 } 566 567 void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) { 568 printQualifiers( refType ); 569 570 mangleName << prefix << refType->name.length() << refType->name; 571 572 if ( mangleGenericParams ) { 573 if ( ! refType->params.empty() ) { 574 mangleName << "_"; 575 for ( const ast::Expr * param : refType->params ) { 576 auto paramType = dynamic_cast< const ast::TypeExpr * >( param ); 577 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 578 maybeAccept( paramType->type.get(), *visitor ); 579 } 580 mangleName << "_"; 581 } 582 } 583 } 584 585 void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) { 586 mangleRef( aggregateUseType, Encoding::struct_t ); 587 } 588 589 void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) { 590 mangleRef( aggregateUseType, Encoding::union_t ); 591 } 592 593 void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) { 594 mangleRef( aggregateUseType, Encoding::enum_t ); 595 } 596 597 void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) { 598 VarMapType::iterator varNum = varNums.find( typeInst->name ); 599 if ( varNum == varNums.end() ) { 600 mangleRef( typeInst, Encoding::type ); 601 } else { 602 printQualifiers( typeInst ); 603 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g. 604 // forall(dtype T) void f(T); 605 // forall(dtype S) void f(S); 606 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they 607 // are first found and prefixing with the appropriate encoding for the type class. 608 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second ); 609 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first; 610 } // if 611 } 612 613 void Mangler_new::postvisit( const ast::TraitInstType * inst ) { 614 printQualifiers( inst ); 615 mangleName << inst->name.size() << inst->name; 616 } 617 618 void Mangler_new::postvisit( const ast::TupleType * tupleType ) { 619 printQualifiers( tupleType ); 620 mangleName << Encoding::tuple << tupleType->types.size(); 621 accept_each( tupleType->types, *visitor ); 622 } 623 624 void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) { 625 printQualifiers( varArgsType ); 626 static const std::string vargs = "__builtin_va_list"; 627 mangleName << Encoding::type << vargs.size() << vargs; 628 } 629 630 void Mangler_new::postvisit( const ast::ZeroType * ) { 631 mangleName << Encoding::zero; 632 } 633 634 void Mangler_new::postvisit( const ast::OneType * ) { 635 mangleName << Encoding::one; 636 } 637 638 void Mangler_new::postvisit( const ast::QualifiedType * qualType ) { 639 bool inqual = inQualifiedType; 640 if (! inqual ) { 641 // N marks the start of a qualified type 642 inQualifiedType = true; 643 mangleName << Encoding::qualifiedTypeStart; 644 } 645 maybeAccept( qualType->parent.get(), *visitor ); 646 maybeAccept( qualType->child.get(), *visitor ); 647 if ( ! inqual ) { 648 // E marks the end of a qualified type 649 inQualifiedType = false; 650 mangleName << Encoding::qualifiedTypeEnd; 651 } 652 } 653 654 void Mangler_new::postvisit( const ast::TypeDecl * decl ) { 655 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 656 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. 657 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply 658 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed 659 // aside from the assert false. 660 assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl)); 661 assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 662 mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name; 663 } 664 665 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) { 666 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) { 667 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl; 668 } // for 669 } 670 671 void Mangler_new::printQualifiers( const ast::Type * type ) { 672 // skip if not including qualifiers 673 if ( typeMode ) return; 674 if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) { 675 if ( ! ptype->forall.empty() ) { 676 std::list< std::string > assertionNames; 677 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 678 mangleName << Encoding::forall; 679 for ( const ast::TypeDecl * decl : ptype->forall ) { 680 switch ( decl->kind ) { 681 case ast::TypeVar::Kind::Dtype: 682 dcount++; 683 break; 684 case ast::TypeVar::Kind::Ftype: 685 fcount++; 686 break; 687 case ast::TypeVar::Kind::Ttype: 688 vcount++; 689 break; 690 default: 691 assert( false ); 692 } // switch 693 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 694 for ( const ast::DeclWithType * assert : decl->assertions ) { 695 ast::Pass<Mangler_new> sub_mangler( 696 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 697 assert->accept( sub_mangler ); 698 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); 699 acount++; 700 } // for 701 } // for 702 mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_"; 703 std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); 704 mangleName << "_"; 705 } // if 706 } // if 707 if ( ! inFunctionType ) { 708 // these qualifiers do not distinguish the outermost type of a function parameter 709 if ( type->is_const() ) { 710 mangleName << Encoding::qualifiers.at(Type::Const); 711 } // if 712 if ( type->is_volatile() ) { 713 mangleName << Encoding::qualifiers.at(Type::Volatile); 714 } // if 715 // Removed due to restrict not affecting function compatibility in GCC 716 // if ( type->get_isRestrict() ) { 717 // mangleName << "E"; 718 // } // if 719 if ( type->is_atomic() ) { 720 mangleName << Encoding::qualifiers.at(Type::Atomic); 721 } // if 722 } 723 if ( type->is_mutex() ) { 724 mangleName << Encoding::qualifiers.at(Type::Mutex); 725 } // if 726 if ( type->is_lvalue() ) { 727 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues 728 mangleName << Encoding::qualifiers.at(Type::Lvalue); 729 } 730 731 if ( inFunctionType ) { 732 // turn off inFunctionType so that types can be differentiated for nested qualifiers 733 GuardValue( inFunctionType ); 734 inFunctionType = false; 735 } 736 } 737 } // namespace 738 } // namespace Mangle 739 392 740 // Local Variables: // 393 741 // tab-width: 4 // -
src/SymTab/Mangler.h
r7564e10 r67130fe 21 21 #include <utility> // for pair 22 22 23 #include "AST/Bitfield.hpp" 24 #include "AST/Fwd.hpp" 23 25 #include "SynTree/SynTree.h" // for Types 24 26 #include "SynTree/Visitor.h" // for Visitor, maybeAccept … … 75 77 } // SymTab 76 78 79 namespace Mangle { 80 /// Bitflags for mangle modes 81 enum { 82 NoOverrideable = 1 << 0, 83 Type = 1 << 1, 84 NoGenericParams = 1 << 2 85 }; 86 87 /// Bitflag type for mangler modes 88 struct mangle_flags { 89 union { 90 unsigned int val; 91 struct { 92 bool no_overrideable : 1; 93 bool type : 1; 94 bool no_generic_params : 1; 95 }; 96 }; 97 98 constexpr mangle_flags( unsigned int val ) : val(val) {} 99 }; 100 101 using Mode = bitfield<mangle_flags>; 102 103 /// Mangle declaration name 104 std::string mangle( const ast::Node * decl, Mode mode = {} ); 105 106 namespace Encoding { 107 using namespace SymTab::Mangler::Encoding; 108 }; 109 } 110 77 111 extern "C" { 78 112 char * cforall_demangle(const char *, int); -
src/SynTree/Expression.cc
r7564e10 r67130fe 610 610 computeResult(); 611 611 } 612 StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ) {612 StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ), resultExpr( other.resultExpr ) { 613 613 cloneAll( other.returnDecls, returnDecls ); 614 614 cloneAll( other.dtors, dtors ); -
src/SynTree/Expression.h
r7564e10 r67130fe 62 62 InferredParams inferParams; ///< Post-resolution inferred parameter slots 63 63 std::vector<UniqueId> resnSlots; ///< Pre-resolution inferred parameter slots 64 64 65 65 // xxx - should turn inferParams+resnSlots into a union to save some memory 66 66 … … 744 744 std::list< Expression * > dtors; // destructor(s) for return variable(s) 745 745 746 // readonly 747 ExprStmt * resultExpr = nullptr; 748 746 749 StmtExpr( CompoundStmt * statements ); 747 750 StmtExpr( const StmtExpr & other ); -
src/Validate/FindSpecialDecls.cc
r7564e10 r67130fe 26 26 namespace Validate { 27 27 Type * SizeType = nullptr; 28 29 30 28 FunctionDecl * dereferenceOperator = nullptr; 29 StructDecl * dtorStruct = nullptr; 30 FunctionDecl * dtorStructDestroy = nullptr; 31 31 32 32 namespace { -
src/include/cassert
r7564e10 r67130fe 10 10 // Created On : Thu Aug 18 13:19:26 2016 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu May 23 15:30:00 201713 // Update Count : 1 712 // Last Modified On : Mon Jun 3 13:11:00 2017 13 // Update Count : 18 14 14 // 15 15 … … 43 43 #endif 44 44 45 enum StrictAllowNull {NonNull, AllowNull}; 46 47 template<typename T, StrictAllowNull nullable = NonNull, typename U> 45 template<typename T, typename U> 48 46 static inline T strict_dynamic_cast( const U & src ) { 49 if (nullable == AllowNull && src == nullptr) {50 return nullptr;51 }52 47 assert(src); 53 48 T ret = dynamic_cast<T>(src); 54 49 assertf(ret, "%s", toString(src).c_str()); 55 50 return ret; 51 } 52 53 template<typename T, decltype(nullptr) null, typename U> 54 static inline T strict_dynamic_cast( const U & src ) { 55 return src ? strict_dynamic_cast<T, U>( src ) : nullptr; 56 56 } 57 57
Note: See TracChangeset
for help on using the changeset viewer.