/* Reduced from qemu-7.2.0's qobject/json-parser.c, which is licensed under LGPLv2.1 or later. */ /* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */ #define NULL ((void *)0) typedef __builtin_va_list va_list; typedef struct _GQueue GQueue; typedef struct Error Error; typedef struct QList QList; typedef struct QObject QObject; struct QObjectBase_ { /* [...snip...] */ }; struct QObject { struct QObjectBase_ base; }; #define QOBJECT(obj) ((QObject *)obj) #define qobject_unref(OBJ) /* [...snip...] */ typedef struct QTailQLink { void *tql_next; struct QTailQLink *tql_prev; } QTailQLink; struct QList { struct QObjectBase_ base; union { struct QListEntry *tqh_first; QTailQLink tqh_circ; } head; }; QList *qlist_new(void); void qlist_append_obj(QList *qlist, QObject *obj); typedef enum json_token_type { /* [...snip...] */ JSON_LSQUARE, JSON_RSQUARE, /* [...snip...] */ JSON_COMMA, /* [...snip...] */ JSON_KEYWORD, /* [...snip...] */ } JSONTokenType; typedef struct JSONToken JSONToken; struct JSONToken { JSONTokenType type; int x; int y; char str[]; }; typedef struct JSONParserContext { Error *err; JSONToken *current; GQueue *buf; va_list *ap; } JSONParserContext; static QObject *parse_value(JSONParserContext *ctxt); JSONToken *parser_context_pop_token(JSONParserContext *ctxt); JSONToken *parser_context_peek_token(JSONParserContext *ctxt); static QObject *parse_array(JSONParserContext *ctxt) { QList *list = NULL; JSONToken *token, *peek; token = parser_context_pop_token(ctxt); list = qlist_new(); peek = parser_context_peek_token(ctxt); if (peek == NULL) { goto out; } if (peek->type != JSON_RSQUARE) { QObject *obj; obj = parse_value(ctxt); /* { dg-bogus "infinite recursion" } */ if (obj == NULL) { goto out; } qlist_append_obj(list, obj); token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } while (token->type != JSON_RSQUARE) { if (token->type != JSON_COMMA) { goto out; } obj = parse_value(ctxt); if (obj == NULL) { goto out; } qlist_append_obj(list, obj); token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } } } else { (void)parser_context_pop_token(ctxt); } return QOBJECT(list); out: qobject_unref(list); return NULL; } QObject *parse_keyword(JSONParserContext *ctxt); QObject *parse_value(JSONParserContext *ctxt) { JSONToken *token; token = parser_context_peek_token(ctxt); if (token == NULL) { return NULL; } switch (token->type) { case JSON_LSQUARE: return parse_array(ctxt); /* { dg-bogus "infinite recursion" } */ case JSON_KEYWORD: return parse_keyword(ctxt); default: return NULL; } }