Винтажный код C 1998 года теперь не компилируется под gcc

У меня есть ~16k строк старого кода C 1998 года (~50 основных программ), которые в то время безупречно строились под gcc, но теперь терпят неудачу со многими ошибками «lvalue, требуемое как левый операнд присваивания» в первой подпрограмме, «stutter.c». Я недостаточно программист C, чтобы найти проблему, и я не могу найти ответ в Интернете, относящийся к моей проблеме (с этим довольно общим сообщением об ошибке).

Вот особенности:

Скомпилируйте строку из (винтажного) Makefile:

gcc -O3 -Wall -D__dest_os=unix -I/usr/X11/include -DPLOTX11 -c -o stutter.o ../src/stutter.c

Примеры неудачных утверждений:

    cell_car(cell) = free_list;
    cell_type(cell) = type;
    cell_name(atom) = strdup(name);
    cell_cdr(list) = binding_list;
    cell_cdr(cell_car(current)) = b;

... (и многие подобные)

предшествует:

    typedef enum CELL_ENUM {
      CELL_LAMBDA, CELL_SFUNC, CELL_VFUNC, CELL_LIST, CELL_ATOM
    } CELL_TYPE;

    typedef struct CELL_STRUCT {
    void *car, *cdr;
    unsigned type : 7;
    unsigned mark : 1;
    char empty[3];
    } CELL;

а также:

    #define cell_car(c)      ((CELL *)(c)->car)
    #define cell_cdr(c)      ((CELL *)(c)->cdr)        
    #define cell_name(c)     ((char *)(c)->car)
    #define cell_func(c)     ((CELL *(*)())(c)->car)
    #define cell_type(c)     ((CELL_TYPE)(c)->type)
    #define cell_mark(c)     ((c)->mark)

При необходимости доступны дополнительные сведения о коде. Есть ли здесь какая-то очевидная устаревшая функция, которая объясняет эту ошибку??

У меня многолетний опыт научного программирования на Фортране, но я ушел на пенсию, прежде чем достаточно изучил C, чтобы полностью переключиться. Не нашел ничего полезного об устаревшем коде на http://gcc.gnu.org/bugs/. . Я был бы признателен за любую помощь, которая избавила бы меня от необходимости завершать обучение C, C++ и gcc, прежде чем я получу эти подпрограммы, работающие под Linux для моего текущего проекта. Спасибо большое!


person sambledsoe    schedule 14.04.2014    source источник
comment
@dyp, трудно сказать, не зная типа free_list... @sambledsoe, можете ли вы попробовать скомпилировать с clang вместо gcc, если вы получите более информативные сообщения об ошибках?   -  person Maxime Chéramy    schedule 15.04.2014
comment
Было ли разрешено в прошлом в C говорить (some_variable) = 123? Потому что это то, что ты здесь делаешь.   -  person Eric Lippert    schedule 15.04.2014
comment
@EricLippert это все еще законно ...   -  person Maxime Chéramy    schedule 15.04.2014
comment
@Maxime: каждый день я узнаю что-то новое. :-)   -  person Eric Lippert    schedule 15.04.2014
comment
@Maxime Приведение никогда не дает lvalue (в C). Таким образом, каким бы ни был тип free_list, макрос не может находиться в левой части присваивания.   -  person dyp    schedule 15.04.2014
comment
car (содержимое адресного регистра) и cdr (содержимое регистра данных). Хм, я чую Lisp.   -  person chux - Reinstate Monica    schedule 15.04.2014


Ответы (2)


gcc больше не позволяет вам назначать актеров.

i.e.

((CELL *)(cell)->car) = free_list;

уже не законно. Вместо того, чтобы приводить левые для соответствия правым, было бы лучше, если бы вы привели правые, чтобы они соответствовали левым. Один из способов обойти это — взять адрес lvalue, привести его к типу указателя, а затем разыменовать этот указатель, чтобы присваивание выполнялось к разыменованию указателя, а не к приведению.

i.e.

*((CELL **)&(cell)->car) = free_list;

Это можно решить, обновив макросы, так что это должно быть довольно безболезненно...

i.e.

#define cell_car(c)      (*((CELL **)&(c)->car))

так далее...

Затем этот макрос можно использовать либо как lvalue, либо как rvalue.

person pat    schedule 14.04.2014
comment
clang вызовет следующую ошибку: ошибка: присвоение приведения недопустимо, приведения по lvalue не поддерживаются. - person Maxime Chéramy; 15.04.2014
comment
@ Максим, да, это сообщение об ошибке более информативно, чем gcc, lvalue требуется как левый операнд присваивания. - person pat; 15.04.2014
comment
Я думаю, что это это расширение Документация от 2001 года. , хотя (более старый не нашел). - person dyp; 15.04.2014
comment
Приведения Lvalue кажутся расширением GCC, которое теперь устарело. - person pat; 15.04.2014
comment
Да, я думаю, что они устарели в 3.3. 6 (2004 г.), их нет в документах 4.X. - person dyp; 15.04.2014
comment
Расширение языка C для преобразования значения в значение (устарело в версии 3.3.4) было удалено в GCC 4.0 (2005 г.): gcc.gnu.org/gcc-4.0/changes.html - person Michael Burr; 15.04.2014
comment
@pat, спасибо (и всем остальным). Теперь я понимаю проблему, и ваши моды, похоже, работали с макросами -car, -cdr и -name. Я более или менее догадался (многочисленные указатели, адреса и разыменования полностью сбили меня с толку) в переопределениях -type и -func: ((CELL ()())(c )-›car) стало (((CELL *(*)())&(c)-›car)) и ((CELL_TYPE)(c)-›type) стало (*(( CELL_TYPE *)(c)-›тип)) ?? --stutter компилируется только с приведением к указателю из целого числа с предупреждениями разного размера (много), но выдает seg-fault при выполнении. -- Много работы! - person sambledsoe; 16.04.2014
comment
К сожалению, этот стиль приведения указателя имеет тенденцию вызывать неопределенное поведение в C99 и более поздних версиях, если только нельзя отключить строгое правило псевдонимов. - person supercat; 31.07.2015

В дополнение к изменению кода для получения адреса, приведения указателя и разыменования, скорее всего, также потребуется использовать параметр «no_strict_aliasing». C99 добавил некоторые правила с целью облегчения оптимизации, которые отрицают модель состояния системы C как группу unsigned char[]. Самым печально известным из них является строгое правило псевдонимов. В то время как код, который приводит указатели как средство сказать «интерпретировать объект, на который указывает этот указатель, как X», может компилироваться, запись в указатель с использованием одного типа и чтение с использованием другого обычно приводит к неопределенному поведению, и некоторые компиляторы интерпретируют это как разрешение вести себя довольно странным и причудливым образом, не ограниченным законами времени и причинно-следственных связей.

person supercat    schedule 30.07.2015