Changes in src/AST/Expr.cpp [c36298d:ae265b55]
- File:
-
- 1 edited
-
src/AST/Expr.cpp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.cpp
rc36298d rae265b55 20 20 #include <vector> 21 21 22 #include "Copy.hpp" // for shallowCopy 23 #include "Eval.hpp" // for call 22 24 #include "GenericSubstitution.hpp" 23 25 #include "Stmt.hpp" … … 51 53 assert( arg ); 52 54 53 UntypedExpr * ret = new UntypedExpr{ 54 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } } 55 }; 55 UntypedExpr * ret = call( loc, "*?", arg ); 56 56 if ( const Type * ty = arg->result ) { 57 57 const Type * base = InitTweak::getPointerBase( ty ); … … 74 74 assert( lhs && rhs ); 75 75 76 UntypedExpr * ret = new UntypedExpr{ 77 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } } 78 }; 76 UntypedExpr * ret = call( loc, "?=?", lhs, rhs ); 79 77 if ( lhs->result && rhs->result ) { 80 78 // if both expressions are typed, assumes that this assignment is a C bitwise assignment, … … 160 158 assert( aggregate->result ); 161 159 162 // take ownership of member type 163 result = mem->get_type(); 160 // Deep copy on result type avoids mutation on transitively multiply referenced object. 161 // 162 // Example, adapted from parts of builtins and bootloader: 163 // 164 // forall(dtype T) 165 // struct __Destructor { 166 // T * object; 167 // void (*dtor)(T *); 168 // }; 169 // 170 // forall(dtype S) 171 // void foo(__Destructor(S) &d) { 172 // if (d.dtor) { // here 173 // } 174 // } 175 // 176 // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve. Let d be the 177 // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level 178 // declaration of __Destructor. Consider the types e.result and d.type. In the old AST, one 179 // is a clone of the other. Ordinary new-AST use would set them up as a multiply-referenced 180 // object. 181 // 182 // e.result: PointerType 183 // .base: FunctionType 184 // .params.front(): ObjectDecl, the anonymous parameter of type T* 185 // .type: PointerType 186 // .base: TypeInstType 187 // let x = that 188 // let y = similar, except start from d.type 189 // 190 // Consider two code lines down, genericSubstitution(...).apply(result). 191 // 192 // Applying this chosen-candidate's type substitution means modifying x, substituting 193 // S for T. This mutation should affect x and not y. 194 195 result = deepCopy(mem->get_type()); 196 164 197 // substitute aggregate generic parameters into member type 165 198 genericSubstitution( aggregate->result ).apply( result ); … … 168 201 } 169 202 203 MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg, 204 MemberExpr::NoOpConstruction overloadSelector ) 205 : Expr( loc ), member( mem ), aggregate( agg ) { 206 assert( member ); 207 assert( aggregate ); 208 assert( aggregate->result ); 209 (void) overloadSelector; 210 } 211 170 212 // --- VariableExpr 171 213 … … 177 219 assert( var ); 178 220 assert( var->get_type() ); 179 result = var->get_type(); 180 add_qualifiers( result, CV::Lvalue ); 221 auto r = shallowCopy( var->get_type() ); 222 r->qualifiers |= CV::Lvalue; 223 result = r; 181 224 } 182 225
Note:
See TracChangeset
for help on using the changeset viewer.