//TODO int define_array(struct token *token) { printf("Hello from define_array!\n");//DEBUG //needs to be a constant value, since assignments have not been made if ( (token->type >= C_NUM) && (token->type <= C_F)){ struct identifier *nid = malloc(sizeof(struct identifier)); nid->lexeme = token->lexeme; type_const(nid->type); nid->op_type = 0; nid->kw_name = 0; hash_insert(symboltable, nid); tree_mknode(DEFINE_ARRAY); stack_pop(); input_consume(); tree_add_attr(nid, 4); free(token); struct token *t = input_consume(); if (t->op_type == CLOSEBRACKET){ return 0; } else{ log_error(DEFINE_ARRAY); printf("Incorrect token \"%s\", expecting \"]\".\n", t->lexeme); return -1; } } else{ return -1; } }
static void ptrconversion_warnings(type ttl, type ttr, expression rhs, const char *context, const char *funname, int parmnum, bool pedantic) { if (pedantic && ((type_void(ttl) && type_function(ttr)) || (type_function(ttl) && type_void(ttr) && !(rhs && definite_null(rhs))))) warn_for_assignment("ANSI forbids %s between function pointer and `void *'", context, funname, parmnum); /* Const and volatile mean something different for function types, so the usual warnings are not appropriate. */ else if (type_function(ttl) && type_function(ttr)) { /* Because const and volatile on functions are restrictions that say the function will not do certain things, it is okay to use a const or volatile function where an ordinary one is wanted, but not vice-versa. */ if (type_const(ttl) && !type_const(ttr)) warn_for_assignment("%s makes `const *' function pointer from non-const", context, funname, parmnum); if (type_volatile(ttl) && !type_volatile(ttr)) warn_for_assignment("%s makes `volatile *' function pointer from non-volatile", context, funname, parmnum); } else if (!type_function(ttl) && !type_function(ttr)) { if (!type_const(ttl) && type_const(ttr)) warn_for_assignment("%s discards `const' from pointer target type", context, funname, parmnum); if (!type_volatile(ttl) && type_volatile(ttr)) warn_for_assignment("%s discards `volatile' from pointer target type", context, funname, parmnum); /* If this is not a case of ignoring a mismatch in signedness, no warning. */ if (!assignable_pointer_targets(ttl, ttr, FALSE) && pedantic) warn_for_assignment("pointer targets in %s differ in signedness", context, funname, parmnum); } }
int postfix_expression(struct token *token) { if ((token->type >= ID_KW) && (token->type <= S_C)){ if(token->type == ID_KW){ struct hashentry *ifkw = hash_retrieve(kwtable, token->lexeme); if (ifkw != NULL){ //is a keyword log_error(POSTFIX_EXPRESSION); return -1; } } //if identifier if (token->type == ID_KW){ //already checked if kw struct hashentry *entry = hash_retrieve(symboltable, token->lexeme); if (entry == NULL){ //not defined log_error(POSTFIX_EXPRESSION); printf("%s has not been defined!\n", token->lexeme); return -1; } else{ tree_mknode(POSTFIX_EXPRESSION); tree_add_attr(entry->data, 1); input_consume(); free_token(token); stack_pop(); stack_push(PRIMARY_EXPRESSION_MODS); return 0; } } else{ //should be some sort of constant struct identifier *c = malloc(sizeof(struct identifier)); type_const(c->type); c->lexeme = token->lexeme; tree_mknode(POSTFIX_EXPRESSION); tree_add_attr(c, 1); input_consume(); free(token); stack_pop(); return 0; } } else{ log_error(POSTFIX_EXPRESSION); return -1; } }
int primary_expression_mods(struct token *token) { printf("Hello from primary_expression_mods\n"); if (token->op_type == OPENPAREN){ tree_mknode(-1); //TODO implement '(' input_consume(); free_token(token); stack_pop(); stack_push(TOKEN_CLOSEPAREN); //')' stack_push(PRIMARY_EXPRESSION_LIST); return -1; } else if (token->op_type == OPENBRACKET){ tree_mknode(PRIMARY_EXPRESSION_MODS); input_consume(); //get the [ free_token(token); stack_pop(); struct token *t = input_consume(); //the inner part of the [x] struct identifier *nid = malloc(sizeof(struct identifier)); nid->lexeme = t->lexeme; if (t->type == ID_KW){ struct hashentry *he = hash_retrieve(kwtable, nid->lexeme); if (he != NULL){ //is a keyword (an error) log_error(PRIMARY_EXPRESSION_MODS); return -1; } else{ he = hash_retrieve(symboltable, nid->lexeme); if (he == NULL){ //symbol not defined log_error(PRIMARY_EXPRESSION_MODS); printf("%s has not been initialized\n", nid->lexeme); return -1; } else{ tree_add_attr(he->data, 4); free_token(t); input_consume(); //the last ] return 0; } } } else if (t->type >= C_NUM && t->type <= C_F){ struct identifier *id = malloc(sizeof(struct identifier)); id->lexeme = t->lexeme; type_const(id->type); tree_add_attr(id, 4); //add it as attribute free(t); input_consume(); // the last ] return 0; } else{ log_error(PRIMARY_EXPRESSION_MODS); printf("%s has not been initialized\n", nid->lexeme); return -1; } } else if (token->op_type == VALUEAT){ input_consume(); // throw away '.' struct token *tmp = input_consume(); //get the identifier struct hashentry *ifkw = hash_retrieve(kwtable, tmp->lexeme); if (ifkw != NULL){ //error is a keyword log_error(PRIMARY_EXPRESSION_MODS); return -1; } else{ tree_mknode(-1); //TODO implement '.' free_token(token); stack_pop(); stack_push(PRIMARY_EXPRESSION); return -1; } } else{ //not a mod of a primary expression stack_pop(); return 0; } }
expression make_cast(location loc, asttype t, expression e) { expression result = CAST(expression, new_cast(parse_region, loc, e, t)); type castto = t->type; if (castto == error_type || type_void(castto)) ; /* Do nothing */ else if (type_array(castto)) { error("cast specifies array type"); castto = error_type; } else if (type_function(castto)) { error("cast specifies function type"); castto = error_type; } else if (type_equal_unqualified(castto, e->type)) { if (pedantic && type_aggregate(castto)) pedwarn("ANSI C forbids casting nonscalar to the same type"); } else { type etype = e->type; /* Convert functions and arrays to pointers, but don't convert any other types. */ if (type_function(etype) || type_array(etype)) etype = default_conversion(e); if (type_union(castto)) { tag_declaration utag = type_tag(castto); field_declaration ufield; /* Look for etype as a field of the union */ for (ufield = utag->fieldlist; ufield; ufield = ufield->next) if (ufield->name && type_equal_unqualified(ufield->type, etype)) { if (pedantic) pedwarn("ANSI C forbids casts to union type"); break; } if (!ufield) error("cast to union type from type not present in union"); } else { /* Optionally warn about potentially worrisome casts. */ if (warn_cast_qual && type_pointer(etype) && type_pointer(castto)) { type ep = type_points_to(etype), cp = type_points_to(castto); if (type_volatile(ep) && !type_volatile(cp)) pedwarn("cast discards `volatile' from pointer target type"); if (type_const(ep) && !type_const(cp)) pedwarn("cast discards `const' from pointer target type"); } /* This warning is weird */ if (warn_bad_function_cast && is_function_call(e) && !type_equal_unqualified(castto, etype)) warning ("cast does not match function type"); #if 0 /* Warn about possible alignment problems. */ if (STRICT_ALIGNMENT && warn_cast_align && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE /* Don't warn about opaque types, where the actual alignment restriction is unknown. */ && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) warning ("cast increases required alignment of target type"); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) && !TREE_CONSTANT (value)) warning ("cast from pointer to integer of different size"); if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) #if 0 /* Don't warn about converting 0 to pointer, provided the 0 was explicit--not cast or made by folding. */ && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)) #endif /* Don't warn about converting any constant. */ && !TREE_CONSTANT (value)) warning ("cast to pointer from integer of different size"); #endif check_conversion(castto, etype); } } result->lvalue = !pedantic && e->lvalue; result->isregister = e->isregister; result->bitfield = e->bitfield; result->static_address = e->static_address; result->type = castto; result->cst = fold_cast(result); return result; }
/* Return TRUE if no error and lhstype and rhstype are not error_type */ bool check_assignment(type lhstype, type rhstype, expression rhs, const char *context, data_declaration fundecl, const char *funname, int parmnum) { bool zerorhs = rhs && definite_zero(rhs); if (lhstype == error_type || rhstype == error_type) return FALSE; if (type_void(rhstype)) { error("void value not ignored as it ought to be"); return FALSE; } if (type_equal_unqualified(lhstype, rhstype)) return TRUE; if (type_arithmetic(lhstype) && type_arithmetic(rhstype)) { if (rhs) constant_overflow_warning(rhs->cst); return check_conversion(lhstype, rhstype); } if (parmnum && (type_qualifiers(lhstype) & transparent_qualifier)) { /* See if we can match any field of lhstype */ tag_declaration tag = type_tag(lhstype); field_declaration fields, marginal_field = NULL; /* I blame gcc for this horrible mess (and it's minor inconsistencies with the regular rules) */ /* pedantic warnings are skipped in here because we're already issuing a warning for the use of this construct */ for (fields = tag->fieldlist; fields; fields = fields->next) { type ft = fields->type; if (type_compatible(ft, rhstype)) break; if (!type_pointer(ft)) continue; if (type_pointer(rhstype)) { type ttl = type_points_to(ft), ttr = type_points_to(rhstype); bool goodmatch = assignable_pointer_targets(ttl, ttr, FALSE); /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (goodmatch) { /* If this type won't generate any warnings, use it. */ if ((type_function(ttr) && type_function(ttl)) ? (((!type_const(ttl)) | type_const(ttr)) & ((!type_volatile(ttl)) | type_volatile(ttr))) : (((type_const(ttl)) | (!type_const(ttr))) & (type_volatile(ttl) | (!type_volatile(ttr))))) break; /* Keep looking for a better type, but remember this one. */ if (!marginal_field) marginal_field = fields; } } /* Can convert integer zero to any pointer type. */ /* Note that this allows passing *any* null pointer (gcc bug?) */ if (zerorhs) break; } if (fields || marginal_field) { if (!fields) { /* We have only a marginally acceptable member type; it needs a warning. */ type ttl = type_points_to(marginal_field->type), ttr = type_points_to(rhstype); ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum, FALSE); } if (pedantic && !(fundecl && fundecl->in_system_header)) pedwarn("ANSI C prohibits argument conversion to union type"); return TRUE; } } if (type_pointer(lhstype) && type_pointer(rhstype)) { type ttl = type_points_to(lhstype), ttr = type_points_to(rhstype); bool goodmatch = assignable_pointer_targets(ttl, ttr, pedantic); /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (goodmatch || (type_equal_unqualified(make_unsigned_type(ttl), make_unsigned_type(ttr)))) ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum, pedantic); else warn_for_assignment("%s from incompatible pointer type", context, funname, parmnum); return check_conversion(lhstype, rhstype); } /* enum = ptr and ptr = enum counts as an error, so use type_integral */ else if (type_pointer(lhstype) && type_integral(rhstype)) { if (!zerorhs) warn_for_assignment("%s makes pointer from integer without a cast", context, funname, parmnum); return check_conversion(lhstype, rhstype); } else if (type_integral(lhstype) && type_pointer(rhstype)) { warn_for_assignment("%s makes integer from pointer without a cast", context, funname, parmnum); return check_conversion(lhstype, rhstype); } if (!context) if (funname) error("incompatible type for argument %d of `%s'", parmnum, funname); else error("incompatible type for argument %d of indirect function call", parmnum); else error("incompatible types in %s", context); return FALSE; }