sem.c (3914B)
1 #include "sem/sem.h" 2 3 static int is_void_pointer(const Type* t) { 4 return t && t->kind == TY_PTR && t->ptr.pointee && 5 t->ptr.pointee->kind == TY_VOID; 6 } 7 8 static int is_builtin_va_list_record(Pool* p, const Type* t) { 9 KitSlice s; 10 if (!t || t->kind != TY_STRUCT || !t->rec.tag) return 0; 11 s = kit_sym_str(p->c, t->rec.tag); 12 if (!s.s) return 0; 13 return kit_slice_eq_cstr(s, "__va_list") || 14 kit_slice_eq_cstr(s, "__va_list_tag"); 15 } 16 17 static int pointer_pointees_assignable(Pool* p, const Type* lhs, 18 const Type* rhs) { 19 const Type* lp; 20 const Type* rp; 21 if (!lhs || !rhs || lhs->kind != TY_PTR || rhs->kind != TY_PTR) return 0; 22 lp = lhs->ptr.pointee; 23 rp = rhs->ptr.pointee; 24 if (!lp || !rp) return 0; 25 if (is_void_pointer(lhs) || is_void_pointer(rhs)) return 1; 26 if (is_builtin_va_list_record(p, lp) && is_builtin_va_list_record(p, rp)) 27 return 1; 28 if ((rp->qual & (u16)~lp->qual) != 0) return 0; 29 return type_compatible(type_unqual(p, lp), type_unqual(p, rp)); 30 } 31 32 static CSemCheck sem_ok(void) { 33 CSemCheck c; 34 c.ok = 1; 35 c.message = NULL; 36 return c; 37 } 38 39 static CSemCheck sem_bad(const char* msg) { 40 CSemCheck c; 41 c.ok = 0; 42 c.message = msg; 43 return c; 44 } 45 46 CSemCheck c_sem_check_assignment(Pool* p, const Type* lhs, const Type* rhs, 47 CSemAssignContext ctx) { 48 const Type* lu; 49 const Type* ru; 50 (void)ctx; 51 if (!lhs || !rhs) return sem_ok(); 52 lu = type_unqual(p, lhs); 53 ru = type_unqual(p, rhs); 54 if (lu->kind == TY_VOID) 55 return sem_bad("assignment to an object with void type"); 56 if (lu->kind == TY_ARRAY) return sem_bad("assignment to array type"); 57 if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok(); 58 if ((lu->kind == TY_STRUCT || lu->kind == TY_UNION) && 59 type_compatible(lu, ru)) { 60 return sem_ok(); 61 } 62 if (type_is_ptr(lu)) { 63 if (type_is_ptr(ru)) { 64 if (pointer_pointees_assignable(p, lu, ru)) { 65 return sem_ok(); 66 } 67 return sem_bad("assignment between incompatible pointer types"); 68 } 69 if (type_is_int(ru)) return sem_ok(); 70 return sem_bad("incompatible assignment to pointer"); 71 } 72 if (type_is_ptr(ru) && type_is_arith(lu)) 73 return sem_bad("incompatible assignment from pointer to integer"); 74 return sem_bad("incompatible assignment"); 75 } 76 77 CSemCheck c_sem_check_compound_assignment(Pool* p, const Type* lhs, 78 const Type* rhs, int op) { 79 const Type* lu; 80 const Type* ru; 81 if (!lhs || !rhs) return sem_ok(); 82 lu = type_unqual(p, lhs); 83 ru = type_unqual(p, rhs); 84 switch (op) { 85 case '+': 86 case '-': 87 if (type_is_ptr(lu)) { 88 if (type_is_int(ru)) return sem_ok(); 89 return sem_bad("pointer compound assignment requires integer rhs"); 90 } 91 if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok(); 92 return sem_bad("compound assignment requires arithmetic operands"); 93 case '*': 94 case '/': 95 if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok(); 96 return sem_bad("compound assignment requires arithmetic operands"); 97 case '%': 98 case '&': 99 case '|': 100 case '^': 101 case '<': 102 case '>': 103 if (type_is_int(lu) && type_is_int(ru)) return sem_ok(); 104 return sem_bad("compound assignment requires integer operands"); 105 default: 106 return sem_bad("unsupported compound assignment"); 107 } 108 } 109 110 CSemCheck c_sem_check_redeclaration(Pool* p, const Type* old_type, 111 const Type* new_type, 112 const Type** composite_out) { 113 const Type* composite; 114 if (composite_out) *composite_out = old_type; 115 if (!old_type || !new_type) return sem_ok(); 116 composite = type_composite(p, old_type, new_type); 117 if (!composite) return sem_bad("conflicting types for declaration"); 118 if (composite_out) *composite_out = composite; 119 return sem_ok(); 120 }