| 1875 | } |
| 1876 | |
| 1877 | FunctionPtr generateVariantFinalizer ( const LineInfo & at, const TypeDeclPtr & variantType ) { |
| 1878 | DAS_ASSERT(variantType->isVariant() && "can only finalize variant"); |
| 1879 | auto fn = new Function(); |
| 1880 | fn->privateFunction = true; |
| 1881 | fn->generated = true; |
| 1882 | fn->name = "finalize"; |
| 1883 | fn->at = fn->atDecl = at; |
| 1884 | fn->result = new TypeDecl(Type::tVoid); |
| 1885 | auto arg0 = new Variable(); |
| 1886 | arg0->at = at; |
| 1887 | arg0->name = "__this"; |
| 1888 | arg0->type = new TypeDecl(*variantType); |
| 1889 | arg0->type->constant = false; |
| 1890 | arg0->type->ref = false; |
| 1891 | arg0->type->isExplicit = true; |
| 1892 | fn->arguments.push_back(arg0); |
| 1893 | auto block = new ExprBlock(); |
| 1894 | block->at = at; |
| 1895 | ExprIfThenElse * topIf = nullptr; |
| 1896 | ExprIfThenElse * lastIf = nullptr; |
| 1897 | bool needUnsafe = false; |
| 1898 | for ( size_t argi=0, argis=variantType->argTypes.size(); argi!=argis; ++argi ) { |
| 1899 | if ( !variantType->argTypes[argi]->constant && variantType->argTypes[argi]->needDelete() ) { |
| 1900 | if ( variantType->argTypes[argi]->isPointer() && variantType->argTypes[argi]->firstType |
| 1901 | && variantType->argTypes[argi]->firstType->constant ) continue; |
| 1902 | const string & argn = variantType->argNames[argi]; |
| 1903 | auto lv = new ExprVar(at, "__this"); |
| 1904 | auto lf = new ExprField(at, lv, argn); |
| 1905 | lf->alwaysSafe = true; |
| 1906 | auto cl = new ExprDelete(at, lf); |
| 1907 | cl->alwaysSafe = true; |
| 1908 | auto cb = new ExprBlock(); |
| 1909 | cb->at = at; |
| 1910 | cb->list.push_back(cl); |
| 1911 | auto av = new ExprVar(at, "__this"); |
| 1912 | auto isv = new ExprIsVariant(at, av, argn); |
| 1913 | auto thisIf = new ExprIfThenElse(at, isv, cb, nullptr); |
| 1914 | if ( lastIf ) { |
| 1915 | lastIf->if_false = thisIf; |
| 1916 | lastIf = thisIf; |
| 1917 | } else { |
| 1918 | topIf = lastIf = thisIf; |
| 1919 | } |
| 1920 | if ( variantType->argTypes[argi]->isPointer() ) { |
| 1921 | needUnsafe = true; |
| 1922 | } |
| 1923 | } |
| 1924 | } |
| 1925 | if (topIf) block->list.push_back(topIf); |
| 1926 | auto mz = new ExprMemZero(at, "memzero"); |
| 1927 | auto lvar = new ExprVar(at, "__this"); |
| 1928 | mz->arguments.push_back(lvar); |
| 1929 | block->list.push_back(mz); |
| 1930 | fn->body = block; |
| 1931 | if ( needUnsafe ) { |
| 1932 | wrapInUnsafe(fn); |
| 1933 | } |
| 1934 | verifyGenerated(fn->body); |
no test coverage detected