diff --git a/libcfa/prelude/prelude-gen.cc b/libcfa/prelude/prelude-gen.cc
index 2fe54ca11..90ffeb8a2 100644
a
|
b
|
int main() {
|
205 | 205 | cout << "/////////////////////////////" << endl; |
206 | 206 | cout << endl; |
207 | 207 | |
208 | | auto otype = [](const std::string & type, bool do_volatile = false) { |
| 208 | // The general pattern for arithmetic types. |
| 209 | auto arithmetic = [](const std::string & type, |
| 210 | bool do_zero_one = true, bool do_volatile = false) { |
209 | 211 | cout << "void ?{} (" << type << " &);" << endl; |
210 | | cout << "void ?{} (" << type << " &, " << type << ");" << endl; |
211 | | cout << type << " ?=? (" << type << " &, " << type << ")"; |
| 212 | cout << "void ?{} (" << type << " &, " << type << " const &);" << endl; |
| 213 | cout << type << " & ?=? (" << type << " &, " << type << " const &)"; |
212 | 214 | if ( do_volatile ) { |
213 | | cout << ", ?=?(volatile " << type << " &, " << type << ")"; |
| 215 | cout << ", ?=?(volatile " << type << " &, " << type << " const &)"; |
214 | 216 | } |
215 | 217 | cout << ";" << endl; |
216 | | cout << "void ^?{}( " << type << " & );" << endl; |
| 218 | if ( do_zero_one ) { |
| 219 | cout << "void ?{}(" << type << " &, zero_t);" << endl; |
| 220 | cout << "void ?{}(" << type << " &, one_t);" << endl; |
| 221 | } |
| 222 | cout << "void ^?{}(" << type << " &);" << endl; |
217 | 223 | }; |
218 | 224 | |
219 | | otype("zero_t"); |
| 225 | arithmetic("zero_t", false); |
220 | 226 | cout << endl; |
221 | | otype("one_t"); |
| 227 | arithmetic("one_t", false); |
222 | 228 | cout << endl; |
223 | | otype("_Bool", true); |
| 229 | arithmetic("_Bool", false, true); |
224 | 230 | cout << endl; |
225 | 231 | |
226 | 232 | for (auto type : basicTypes) { |
227 | | cout << "void ?{}(" << type.name << " &);" << endl; |
228 | | cout << "void ?{}(" << type.name << " &, " << type.name << ");" << endl; |
229 | | cout << "void ?{}(" << type.name << " &, zero_t);" << endl; |
230 | | cout << "void ?{}(" << type.name << " &, one_t);" << endl; |
231 | | cout << "void ^?{}(" << type.name << " &);" << endl; |
| 233 | arithmetic(type.name); |
232 | 234 | cout << endl; |
233 | 235 | } |
234 | 236 | cout << endl; |
… |
… |
int main() {
|
238 | 240 | cout << "//////////////////////////" << endl; |
239 | 241 | cout << endl; |
240 | 242 | |
241 | | cout << "forall(ftype FT) void ?{}( FT *&, FT * );" << endl; |
242 | | cout << "forall(ftype FT) void ?{}( FT * volatile &, FT * );" << endl; |
| 243 | cout << "forall(ftype FT) void ?{}( FT *&, FT * const & );" << endl; |
| 244 | cout << "forall(ftype FT) void ?{}( FT * volatile &, FT * const & );" << endl; |
243 | 245 | |
244 | 246 | // generate qualifiers |
245 | 247 | vector<string> qualifiersSingle; |
… |
… |
int main() {
|
263 | 265 | for (auto type : { " DT", "void" }) { |
264 | 266 | for (auto cvq : qualifiersPair) { |
265 | 267 | for (auto is_vol : { " ", "volatile" }) { |
266 | | cout << "forall(DT &) void ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl; |
| 268 | cout << "forall(DT &) void ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT * const &);" << endl; |
267 | 269 | } |
268 | 270 | } |
269 | 271 | } |
… |
… |
int main() {
|
297 | 299 | cout << endl; |
298 | 300 | |
299 | 301 | cout << "forall(ftype FT) void ?{}( FT * &, zero_t );" << endl; |
300 | | cout << "forall(ftype FT) FT * ?=?( FT * &, zero_t );" << endl; |
301 | | cout << "forall(ftype FT) FT * ?=?( FT * volatile &, zero_t );" << endl; |
| 302 | cout << "forall(ftype FT) FT *& ?=?( FT * &, zero_t const & );" << endl; |
| 303 | cout << "forall(ftype FT) FT *& ?=?( FT * volatile &, zero_t const & );" << endl; |
302 | 304 | cout << "forall(ftype FT) void ?{}( FT * & );" << endl; |
303 | 305 | cout << "forall(ftype FT) void ^?{}( FT * & );" << endl; |
304 | 306 | cout << endl; |
… |
… |
int main() {
|
307 | 309 | cout << "// Pointer Operators //" << endl; |
308 | 310 | cout << "///////////////////////" << endl; |
309 | 311 | |
310 | | cout << "forall(ftype FT) FT * ?=?( FT *&, FT * );" << endl; |
311 | | cout << "forall(ftype FT) FT * ?=?( FT * volatile &, FT * );" << endl; |
| 312 | cout << "forall(ftype FT) FT *& ?=?( FT *&, FT * const &);" << endl; |
| 313 | cout << "forall(ftype FT) FT *& ?=?( FT * volatile &, FT * const &);" << endl; |
312 | 314 | cout << "forall(ftype FT) int !?( FT * );" << endl; |
313 | 315 | cout << "forall(ftype FT) signed int ?==?( FT *, FT * );" << endl; |
314 | 316 | cout << "forall(ftype FT) signed int ?!=?( FT *, FT * );" << endl; |
… |
… |
int main() {
|
328 | 330 | for (auto q : qualifiersSingle){ |
329 | 331 | for (auto q2 : { " ", "volatile" }) { |
330 | 332 | forall(); |
331 | | cout << q << type << " * " << op.name << "("; |
| 333 | cout << q << type << " * &" << op.name << "("; |
332 | 334 | cout << q << type << " * " << q2 << " &"; |
333 | 335 | cout << ");" << endl; |
334 | 336 | } |
… |
… |
int main() {
|
337 | 339 | for (auto q : qualifiersPair){ |
338 | 340 | for (auto q2 : { " ", "volatile" }) { |
339 | 341 | forall(); |
340 | | cout << q.first << type << " * " << op.name << "("; |
| 342 | cout << q.first << type << " * &" << op.name << "("; |
341 | 343 | cout << q.first << type << " * " << q2 << " &"; |
342 | 344 | |
343 | 345 | for (int i = 1; i < operands; ++i) { |
344 | | cout << ", " << q.second << type << " *"; |
| 346 | cout << ", " << q.second << type << " * " << q2 << " const &"; |
345 | 347 | } |
346 | 348 | cout << ");" << endl; |
347 | 349 | } |
… |
… |
int main() {
|
407 | 409 | |
408 | 410 | for (auto is_vol : { " ", "volatile" }) { |
409 | 411 | for (auto cvq : qualifiersPair) { |
410 | | cout << "forall(DT &) " << cvq.first << "void * ?=?( " << cvq.first << "void * " << is_vol << " &, " << cvq.second << "DT *);" << endl; |
| 412 | cout << "forall(DT &) " << cvq.first << "void *& ?=?( " << cvq.first << "void * " << is_vol << " &, " << cvq.second << "DT *);" << endl; |
411 | 413 | } |
412 | 414 | for (auto cvq : qualifiersSingle) { |
413 | | cout << "forall(DT &) " << cvq << " DT * ?=?( " << cvq << " DT * " << is_vol << " &, zero_t);" << endl; |
| 415 | cout << "forall(DT &) " << cvq << " DT *& ?=?( " << cvq << " DT * " << is_vol << " &, zero_t);" << endl; |
414 | 416 | } |
415 | 417 | } |
416 | 418 | cout << endl; |
diff --git a/src/GenPoly/Lvalue.cpp b/src/GenPoly/Lvalue.cpp
index a2e83f512..f2c09b326 100644
a
|
b
|
struct CollapseAddressDeref final {
|
103 | 103 | ast::Expr const * postvisit( ast::ApplicationExpr const * expr ); |
104 | 104 | }; |
105 | 105 | |
| 106 | struct RValueCastAdjustment final { |
| 107 | ast::Expr const * postvisit( ast::AddressExpr const * expr ); |
| 108 | }; |
| 109 | |
106 | 110 | /// GCC-like Generalized Lvalues (which have since been removed from GCC). |
107 | 111 | /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues |
108 | 112 | /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c) |
… |
… |
ast::Expr const * CollapseAddressDeref::postvisit(
|
533 | 537 | ret->env = expr->env; |
534 | 538 | return ret; |
535 | 539 | } |
536 | | } else { |
537 | | return moveAddressUnderCast( expr ); |
538 | 540 | } |
539 | 541 | return expr; |
540 | 542 | } |
… |
… |
ast::Expr const * CollapseAddressDeref::postvisit(
|
560 | 562 | return expr; |
561 | 563 | } |
562 | 564 | |
| 565 | ast::Expr const * RValueCastAdjustment::postvisit( |
| 566 | ast::AddressExpr const * expr ) { |
| 567 | return moveAddressUnderCast( expr ); |
| 568 | } |
| 569 | |
563 | 570 | ast::Expr const * GeneralizedLvalue::postvisit( |
564 | 571 | ast::AddressExpr const * expr ) { |
565 | 572 | return applyTransformation( expr, &ast::AddressExpr::arg, |
… |
… |
void convertLvalue( ast::TranslationUnit & translationUnit ) {
|
639 | 646 | ast::Pass<ReferenceConversions>::run( translationUnit ); |
640 | 647 | ast::Pass<FixIntrinsicArgs>::run( translationUnit ); |
641 | 648 | ast::Pass<CollapseAddressDeref>::run( translationUnit ); |
| 649 | ast::Pass<RValueCastAdjustment>::run( translationUnit ); |
642 | 650 | ast::Pass<GeneralizedLvalue>::run( translationUnit ); |
643 | 651 | // Last because other passes need reference types to work. |
644 | 652 | ast::Pass<ReferenceTypeElimination>::run( translationUnit ); |
diff --git a/src/InitTweak/FixInit.cpp b/src/InitTweak/FixInit.cpp
index 5304dcda6..6657b3668 100644
a
|
b
|
const ast::DeclWithType * FixInit::postvisit( const ast::ObjectDecl *_objDecl )
|
912 | 912 | // ctorCall should be gone afterwards |
913 | 913 | auto mutArg = mutate(ctorArg); |
914 | 914 | mutArg->env = ctorCall->env; |
| 915 | // TODO: Get rid of layer of reference. |
| 916 | if ( auto cast = dynamic_cast<ast::CastExpr *>( mutArg ) ) { |
| 917 | if ( auto refType = cast->result.as<ast::ReferenceType>() ) { |
| 918 | cast->result = refType->base; |
| 919 | mutArg = cast; |
| 920 | } |
| 921 | } |
915 | 922 | objDecl->init = new ast::SingleInit(loc, mutArg ); |
916 | 923 | } else { |
917 | 924 | stmtsToAddAfter.push_back( ctor ); |
diff --git a/src/InitTweak/InitTweak.cpp b/src/InitTweak/InitTweak.cpp
index b0c932ecd..a1ae61dab 100644
a
|
b
|
bool isCopyFunction( const ast::FunctionDecl * decl ) {
|
319 | 319 | |
320 | 320 | const ast::Type * t1 = ast::getPointerBase( ftype->params.front() ); |
321 | 321 | if ( ! t1 ) return false; |
322 | | const ast::Type * t2 = ftype->params.back(); |
| 322 | const ast::Type * t2 = ast::getPointerBase( ftype->params.back() ); |
| 323 | if ( ! t2 ) return false; |
323 | 324 | |
324 | 325 | return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 ); |
325 | 326 | } |
diff --git a/src/Parser/TypeData.cpp b/src/Parser/TypeData.cpp
index 135a0331d..5d7d3077c 100644
a
|
b
|
void buildForall(
|
731 | 731 | const CodeLocation & location = mutTypeDecl->location; |
732 | 732 | *i = mutTypeDecl; |
733 | 733 | |
734 | | // add assertion parameters to `type' tyvars in reverse order |
735 | | // add assignment operator: T * ?=?(T *, T) |
| 734 | // TODO: Helper functions! |
| 735 | |
| 736 | ast::TypeInstType * mut0 = ast::shallowCopy( i->get() ); |
| 737 | mut0->set_const( true ); |
| 738 | |
| 739 | // Add assertion parameters to `type' tyvars in reverse order: |
| 740 | // Add assignment operator: T & ?=?(T &, T const &) |
736 | 741 | newAssertions.push_back( new ast::FunctionDecl( |
737 | 742 | location, |
738 | 743 | "?=?", |
… |
… |
void buildForall(
|
749 | 754 | new ast::ObjectDecl( |
750 | 755 | location, |
751 | 756 | "", |
752 | | i->get(), |
| 757 | new ast::ReferenceType( mut0 ), |
753 | 758 | (ast::Init *)nullptr, |
754 | 759 | ast::Storage::Classes(), |
755 | 760 | ast::Linkage::Cforall, |
… |
… |
void buildForall(
|
760 | 765 | new ast::ObjectDecl( |
761 | 766 | location, |
762 | 767 | "", |
763 | | i->get(), |
| 768 | new ast::ReferenceType( i->get() ), |
764 | 769 | (ast::Init *)nullptr, |
765 | 770 | ast::Storage::Classes(), |
766 | 771 | ast::Linkage::Cforall, |
… |
… |
void buildForall(
|
772 | 777 | ast::Linkage::Cforall |
773 | 778 | ) ); |
774 | 779 | |
775 | | // add default ctor: void ?{}(T *) |
| 780 | // Add default ctor: void ?{}(T &) |
776 | 781 | newAssertions.push_back( new ast::FunctionDecl( |
777 | 782 | location, |
778 | 783 | "?{}", |
… |
… |
void buildForall(
|
793 | 798 | ast::Linkage::Cforall |
794 | 799 | ) ); |
795 | 800 | |
796 | | // add copy ctor: void ?{}(T *, T) |
| 801 | // Add copy ctor: void ?{}(T &, T const &) |
797 | 802 | newAssertions.push_back( new ast::FunctionDecl( |
798 | 803 | location, |
799 | 804 | "?{}", |
… |
… |
void buildForall(
|
810 | 815 | new ast::ObjectDecl( |
811 | 816 | location, |
812 | 817 | "", |
813 | | i->get(), |
| 818 | new ast::ReferenceType( mut0 ), |
814 | 819 | (ast::Init *)nullptr, |
815 | 820 | ast::Storage::Classes(), |
816 | 821 | ast::Linkage::Cforall, |
… |
… |
void buildForall(
|
823 | 828 | ast::Linkage::Cforall |
824 | 829 | ) ); |
825 | 830 | |
826 | | // add dtor: void ^?{}(T *) |
| 831 | // Add dtor: void ^?{}(T &) |
827 | 832 | newAssertions.push_back( new ast::FunctionDecl( |
828 | 833 | location, |
829 | 834 | "^?{}", |
… |
… |
void buildForall(
|
868 | 873 | const CodeLocation & location = mutTypeDecl->location; |
869 | 874 | *i = mutTypeDecl; |
870 | 875 | |
871 | | // add assertion parameters to `type' tyvars in reverse order |
872 | | // add assignment operator: T * ?=?(T *, T) |
| 876 | // TODO: Helper functions! |
| 877 | |
| 878 | // Add assertion parameters to `type' tyvars in reverse order: |
| 879 | // Add assignment operator: T & ?=?(T &, T const &) |
873 | 880 | newAssertions.push_back( new ast::FunctionDecl( |
874 | 881 | location, |
875 | 882 | "?=?", |
… |
… |
void buildForall(
|
886 | 893 | new ast::ObjectDecl( |
887 | 894 | location, |
888 | 895 | "", |
889 | | new ast::TypeInstType( td->name, *i ), |
| 896 | new ast::ReferenceType( |
| 897 | new ast::TypeInstType( td->name, *i, ast::CV::Const ) ), |
890 | 898 | (ast::Init *)nullptr, |
891 | 899 | ast::Storage::Classes(), |
892 | 900 | ast::Linkage::Cforall, |
… |
… |
void buildForall(
|
897 | 905 | new ast::ObjectDecl( |
898 | 906 | location, |
899 | 907 | "", |
900 | | new ast::TypeInstType( td->name, *i ), |
| 908 | new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ), |
901 | 909 | (ast::Init *)nullptr, |
902 | 910 | ast::Storage::Classes(), |
903 | 911 | ast::Linkage::Cforall, |
… |
… |
void buildForall(
|
909 | 917 | ast::Linkage::Cforall |
910 | 918 | ) ); |
911 | 919 | |
912 | | // add default ctor: void ?{}(T *) |
| 920 | // add default ctor: void ?{}(T &) |
913 | 921 | newAssertions.push_back( new ast::FunctionDecl( |
914 | 922 | location, |
915 | 923 | "?{}", |
… |
… |
void buildForall(
|
931 | 939 | ast::Linkage::Cforall |
932 | 940 | ) ); |
933 | 941 | |
934 | | // add copy ctor: void ?{}(T *, T) |
| 942 | // Add copy ctor: void ?{}(T &, T const &) |
935 | 943 | newAssertions.push_back( new ast::FunctionDecl( |
936 | 944 | location, |
937 | 945 | "?{}", |
… |
… |
void buildForall(
|
949 | 957 | new ast::ObjectDecl( |
950 | 958 | location, |
951 | 959 | "", |
952 | | new ast::TypeInstType( td->name, *i ), |
| 960 | new ast::ReferenceType( |
| 961 | new ast::TypeInstType( td->name, *i, ast::CV::Const ) ), |
953 | 962 | (ast::Init *)nullptr, |
954 | 963 | ast::Storage::Classes(), |
955 | 964 | ast::Linkage::Cforall, |
… |
… |
void buildForall(
|
962 | 971 | ast::Linkage::Cforall |
963 | 972 | ) ); |
964 | 973 | |
965 | | // add dtor: void ^?{}(T *) |
| 974 | // Add dtor: void ^?{}(T &) |
966 | 975 | newAssertions.push_back( new ast::FunctionDecl( |
967 | 976 | location, |
968 | 977 | "^?{}", |
diff --git a/src/Validate/Autogen.cpp b/src/Validate/Autogen.cpp
index 4f753fed5..ce0a5a701 100644
a
|
b
|
ast::ObjectDecl * FuncGenerator::dstParam() const {
|
378 | 378 | } |
379 | 379 | |
380 | 380 | ast::ObjectDecl * FuncGenerator::srcParam() const { |
| 381 | ast::ptr<ast::Type> srcType = ast::deepCopy( type ); |
| 382 | add_qualifiers( srcType, { ast::CV::Const } ); |
381 | 383 | return addUnusedAttribute( |
382 | 384 | new ast::ObjectDecl( getLocation(), "_src", |
383 | | ast::deepCopy( type ) ) ); |
| 385 | new ast::ReferenceType( srcType.release() ) ) ); |
384 | 386 | } |
385 | 387 | |
386 | 388 | /// Use the current type T to create `void ?{}(T & _dst)`. |
… |
… |
ast::FunctionDecl * FuncGenerator::genCtorProto() const {
|
388 | 390 | return genProto( "?{}", { dstParam() }, {} ); |
389 | 391 | } |
390 | 392 | |
391 | | /// Use the current type T to create `void ?{}(T & _dst, T _src)`. |
| 393 | /// Use the current type T to create `void ?{}(T & _dst, T const & _src)`. |
392 | 394 | ast::FunctionDecl * FuncGenerator::genCopyProto() const { |
393 | 395 | return genProto( "?{}", { dstParam(), srcParam() }, {} ); |
394 | 396 | } |
… |
… |
ast::FunctionDecl * FuncGenerator::genDtorProto() const {
|
403 | 405 | return genProto( "^?{}", { dst }, {} ); |
404 | 406 | } |
405 | 407 | |
406 | | /// Use the current type T to create `T ?=?(T & _dst, T _src)`. |
| 408 | /// Use the current type T to create `T & ?=?(T & _dst, T const & _src)`. |
407 | 409 | ast::FunctionDecl * FuncGenerator::genAssignProto() const { |
408 | 410 | // Only the name is different, so just reuse the generation function. |
409 | | auto retval = srcParam(); |
| 411 | auto retval = dstParam(); |
410 | 412 | retval->name = "_ret"; |
411 | 413 | return genProto( "?=?", { dstParam(), srcParam() }, { retval } ); |
412 | 414 | } |
… |
… |
void StructFuncGenerator::makeFunctionBody( Iterator current, Iterator end,
|
549 | 551 | |
550 | 552 | ast::CompoundStmt * stmts = new ast::CompoundStmt( location ); |
551 | 553 | |
| 554 | assert( !func->params.empty() ); |
| 555 | const ast::ObjectDecl * dstParam = |
| 556 | func->params.front().strict_as<ast::ObjectDecl>(); |
| 557 | const ast::ObjectDecl * srcParam = nullptr; |
| 558 | if ( 2 == func->params.size() ) { |
| 559 | srcParam = func->params.back().strict_as<ast::ObjectDecl>(); |
| 560 | } |
| 561 | |
552 | 562 | for ( ; current != end ; ++current ) { |
553 | 563 | const ast::ptr<ast::Decl> & member = *current; |
554 | 564 | auto field = member.as<ast::ObjectDecl>(); |
… |
… |
void StructFuncGenerator::makeFunctionBody( Iterator current, Iterator end,
|
568 | 578 | } |
569 | 579 | } |
570 | 580 | |
571 | | assert( !func->params.empty() ); |
572 | | const ast::ObjectDecl * dstParam = |
573 | | func->params.front().strict_as<ast::ObjectDecl>(); |
574 | | const ast::ObjectDecl * srcParam = nullptr; |
575 | | if ( 2 == func->params.size() ) { |
576 | | srcParam = func->params.back().strict_as<ast::ObjectDecl>(); |
577 | | } |
| 581 | ast::MemberExpr * srcSelect = (!srcParam) ? nullptr : |
| 582 | new ast::MemberExpr( |
| 583 | location, |
| 584 | field, |
| 585 | new ast::CastExpr( |
| 586 | location, |
| 587 | new ast::VariableExpr( location, srcParam ), |
| 588 | srcParam->type.strict_as<ast::ReferenceType>()->base |
| 589 | ) |
| 590 | ); |
578 | 591 | |
579 | | ast::MemberExpr * srcSelect = (srcParam) ? new ast::MemberExpr( |
580 | | location, field, new ast::VariableExpr( location, srcParam ) |
581 | | ) : nullptr; |
582 | 592 | const ast::Stmt * stmt = |
583 | 593 | makeMemberOp( location, dstParam, srcSelect, field, func, direction ); |
584 | 594 | |