sem.c (3845B)
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 const Type* lu; 48 const Type* ru; 49 if (!lhs || !rhs) return sem_ok(); 50 lu = type_unqual(p, lhs); 51 ru = type_unqual(p, rhs); 52 if (lu->kind == TY_VOID) 53 return sem_bad("assignment to an object with void type"); 54 if (lu->kind == TY_ARRAY) return sem_bad("assignment to array type"); 55 if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok(); 56 if ((lu->kind == TY_STRUCT || lu->kind == TY_UNION) && 57 type_compatible(lu, ru)) { 58 return sem_ok(); 59 } 60 if (type_is_ptr(lu)) { 61 if (type_is_ptr(ru)) { 62 if (pointer_pointees_assignable(p, lu, ru)) { 63 return sem_ok(); 64 } 65 return sem_bad("assignment between incompatible pointer types"); 66 } 67 if (type_is_int(ru)) return sem_ok(); 68 return sem_bad("incompatible assignment to pointer"); 69 } 70 if (type_is_ptr(ru) && type_is_arith(lu)) 71 return sem_bad("incompatible assignment from pointer to integer"); 72 return sem_bad("incompatible assignment"); 73 } 74 75 CSemCheck c_sem_check_compound_assignment(Pool* p, const Type* lhs, 76 const Type* rhs, int op) { 77 const Type* lu; 78 const Type* ru; 79 if (!lhs || !rhs) return sem_ok(); 80 lu = type_unqual(p, lhs); 81 ru = type_unqual(p, rhs); 82 switch (op) { 83 case '+': 84 case '-': 85 if (type_is_ptr(lu)) { 86 if (type_is_int(ru)) return sem_ok(); 87 return sem_bad("pointer compound assignment requires integer rhs"); 88 } 89 if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok(); 90 return sem_bad("compound assignment requires arithmetic operands"); 91 case '*': 92 case '/': 93 if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok(); 94 return sem_bad("compound assignment requires arithmetic operands"); 95 case '%': 96 case '&': 97 case '|': 98 case '^': 99 case '<': 100 case '>': 101 if (type_is_int(lu) && type_is_int(ru)) return sem_ok(); 102 return sem_bad("compound assignment requires integer operands"); 103 default: 104 return sem_bad("unsupported compound assignment"); 105 } 106 } 107 108 CSemCheck c_sem_check_redeclaration(Pool* p, const Type* old_type, 109 const Type* new_type, 110 const Type** composite_out) { 111 const Type* composite; 112 if (composite_out) *composite_out = old_type; 113 if (!old_type || !new_type) return sem_ok(); 114 composite = type_composite(p, old_type, new_type); 115 if (!composite) return sem_bad("conflicting types for declaration"); 116 if (composite_out) *composite_out = composite; 117 return sem_ok(); 118 }