Warnungen mit -Wextra und -pedantic



  • Hallo,

    habe versucht, PrettyOS 107er Version mit -Wextra und -pedantic zu kompilieren und bekomme folgendes:

    ...
    gcc -Werror -Wall -Wextra -pedantic -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude   -c -o ckernel.o ckernel.c
    In Datei, eingefügt von ckernel.c:1:
    include/os.h:4:1: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/os.h:4:1: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von include/kheap.h:4,
                     von ckernel.c:2:
    include/os.h:4:1: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/os.h:4:1: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von ckernel.c:2:
    include/kheap.h:7:40: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/kheap.h:7:40: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von include/task.h:5,
                     von ckernel.c:3:
    include/paging.h:6:46: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/paging.h:6:46: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    cc1: warnings being treated as errors
    In file included from include/task.h:5,
                     from ckernel.c:3:
    include/paging.h:19: Fehler: Typ des Bitfeldes »present« ist eine Erweiterung des GCC
    include/paging.h:20: Fehler: Typ des Bitfeldes »rw« ist eine Erweiterung des GCC
    include/paging.h:21: Fehler: Typ des Bitfeldes »user« ist eine Erweiterung des GCC
    include/paging.h:22: Fehler: Typ des Bitfeldes »accessed« ist eine Erweiterung des GCC
    include/paging.h:23: Fehler: Typ des Bitfeldes »dirty« ist eine Erweiterung des GCC
    include/paging.h:24: Fehler: Typ des Bitfeldes »unused« ist eine Erweiterung des GCC
    include/paging.h:25: Fehler: Typ des Bitfeldes »frame_addr« ist eine Erweiterung des GCC
    In Datei, eingefügt von include/task.h:6,
                     von ckernel.c:3:
    include/descriptor_tables.h:8:1: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/descriptor_tables.h:8:1: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von ckernel.c:3:
    include/task.h:8:38: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/task.h:8:38: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von include/initrd.h:5,
                     von ckernel.c:4:
    include/fs.h:12:29: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/fs.h:12:29: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von ckernel.c:4:
    include/initrd.h:9:19: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/initrd.h:9:19: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von ckernel.c:5:
    include/syscall.h:6:1: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/syscall.h:6:1: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    In Datei, eingefügt von ckernel.c:7:
    include/flpydsk.h:5:27: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    include/flpydsk.h:5:27: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    ckernel.c:8:1: Fehler: C++-Stil-Kommentare sind in ISO-C90 nicht erlaubt
    ckernel.c:8:1: Fehler: (dies wird nur einmal pro Eingabedatei gemeldet)
    ckernel.c: In Funktion »main«:
    ckernel.c:53: Fehler: ISO-C90 verbietet gemischte Deklarationen und Code
    ckernel.c:62: Fehler: ISO-C90 verbietet gemischte Deklarationen und Code
    ckernel.c:101: Fehler: ISO-C90 verbietet gemischte Deklarationen und Code
    ckernel.c:120: Fehler: ISO-C90 verbietet gemischte Deklarationen und Code
    ckernel.c:139: Fehler: ISO-C90 verbietet gemischte Deklarationen und Code
    ckernel.c:161: Fehler: ISO-C90 verbietet gemischte Deklarationen und Code
    make: *** [ckernel.o] Fehler 1
    

    Tobiking hat ja u.a. das Thema angesprochen, ob C-Standard eingehalten werden soll oder nicht - was ja für die Code-Qualität sprechen würde...
    Man kann beim gcc mit -std= angeben, was man haben möchte: http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/C-Dialect-Options.html#C-Dialect-Options
    Was meinen die anderen dazu?



  • Man will -std=gnu99. 😉


  • Mod

    Um ANSI-C-kompatibel (möglichst plattformunabhängig) zu arbeiten, fehlt noch -ansi:

    -ansi:      Abschalten von Eigenschaften des gcc, die nicht mit ISO C90 kompatibel sind,
    -pedantic:  Warnungen beim Verstoß gegen Vorgaben von ISO C90,
    -Wall:      Warnungen bei fragwürdigen Code-Konstrukten,
    -Wextra:    Warnungen bei weiteren fragwürdigen Code-Konstrukten,
    -Werror:    Behandlung von Warnungen als Fehler.
    

  • Mod

    @taljeth: Wer ist "man"?

    CFLAGS= [b]-std=gnu99[/b] -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
    

    läuft übrigens problemlos durch.

    Bei tyndur finde ich:

    CC=i586-elf-gcc -m32 -g -c -fno-stack-protector -nostdinc -fno-leading-underscore -fno-omit-frame-pointer -Wall -Werror -Wstrict-prototypes -fno-strict-aliasing -O2 -fno-builtin -I
    


  • Plattformunabhängigkeit (damit ist wohl Compilerunabhängigkeit gemeint) ist für ein OS nicht erstrebenswert.

    Durch die Verwendung von Inline Assembler, Assembler in externen Dateien (Unterstrich vor Symbolen oder nicht), sowie selbstgebauten Linker-Skripten wird die Wartung von verschiedenen Konfigurationen für unterschiedliche Compiler zu einer unnötigen Belastung. Dazu kommt noch die seperate Verwaltung der dann nötigen Makefiles, Projekt-Dateien, etc. (Ein OS ist keine Übung in der Verwaltung von verschiedenen Projektkonfigurationen.)

    Eine frühe Festlegung auf einen bestimmten Compiler, Linker, sowie Umgebung, ermöglicht es sich auf die wesentlichen Dinge beim OS-Dev zu konzentrieren. Zum Beispiel GCC >=4.1 und Binutils >=2.19 sind solide, gut getestet, haben guten Support (Updates), und sind auch sehr gut zum selbst Kompilieren in exotischen Konfigurationen geeignet (gerade unter Windows).

    Als Standard gnu99 zu wählen ist dann nur konsequent und erlaubt viele nützliche Erweiterungen, die GCC bietet, zu nutzen. Default ist beim GCC gnu89, aber C99/gnu99 bietet halt auch ein paar nette Erweiterungen.



  • Erhard Henkes schrieb:

    @taljeth: Wer ist "man"?

    Jeder, der mit dem gcc C programmiert. 😉

    Ich hoffe, über c99 gegenüber c89 müssen wir nicht großartig reden. Es ist neuer, es ist besser, es ist schöner. Was die Entscheidung zwischen c99 und gnu99 betrifft, kann man sicher streiten, ob man sich an einen bestimmten Compiler binden will. Ich möchte nur darauf hinweisen, dass du an jeder Stelle, an der ein __attribute__ auftaucht oder Inline-Assembler benutzt wird, schon gcc-spezifischen Code hast. Du hast die Entscheidung also wahrscheinlich schon lang getroffen, ohne dir dessen bewusst zu sein.

    Bei tyndur finde ich:

    CC=i586-elf-gcc -m32 -g -c -fno-stack-protector -nostdinc -fno-leading-underscore -fno-omit-frame-pointer -Wall -Werror -Wstrict-prototypes -fno-strict-aliasing -O2 -fno-builtin -I
    

    Die allein selig machende Kommandozeile gibt es nicht. Gerade bei den Warnungen und schon vorhandenem Code muss man halt schauen, was sich aktivieren lässt ohne dass gar nichts mehr geht.


  • Mod

    Hier die Meldungen von -ansi:

    i586-elf-gcc -ansi -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude -c -o flpydsk.o flpydsk.c
    In file included from include/flpydsk.h:4,
    from flpydsk.c:1:
    include/os.h:4: error: expected identifier or '(' before '/' token
    include/os.h:4: error: stray '#' in program
    include/os.h:28: error: expected specifier-qualifier-list before '/' token
    include/os.h:44: error: expected identifier or '(' before '/' token
    include/os.h:68: error: expected identifier or '(' before '/' token
    include/os.h:85: error: expected identifier or '(' before '/' token
    include/os.h:94: error: expected identifier or '(' before '/' token
    include/os.h:102: error: expected identifier or '(' before '/' token
    include/os.h:111: error: expected declaration specifiers or '...' before 'size_t'
    include/os.h:112: error: expected declaration specifiers or '...' before 'size_t'
    include/os.h:113: error: expected declaration specifiers or '...' before 'size_t'
    include/os.h:114: error: expected declaration specifiers or '...' before 'size_t'
    include/os.h:115: error: expected '=', ',', ';', 'asm' or '__attribute__' before
    'k_strlen'
    include/os.h:118: error: expected declaration specifiers or '...' before 'size_t'
    include/os.h:128: error: expected identifier or '(' before '/' token
    include/os.h:146: error: expected identifier or '(' before '/' token
    include/os.h:150: error: expected identifier or '(' before '/' token
    In file included from flpydsk.c:1:
    include/flpydsk.h:6: error: expected identifier or '(' before '/' token
    In file included from flpydsk.c:1:
    include/flpydsk.h:6:47: error: invalid suffix "MB" on integer constant
    flpydsk.c:2: error: expected identifier or '(' before '/' token
    flpydsk.c:4: error: stray '#' in program
    flpydsk.c:17: error: expected identifier or '(' before '/' token
    flpydsk.c:31: error: expected identifier or '(' before '/' token
    flpydsk.c:39: error: expected identifier or '(' before '/' token
    flpydsk.c:54: error: expected identifier or '(' before '/' token
    flpydsk.c:67: error: expected identifier or '(' before '/' token
    flpydsk.c:81: error: expected identifier or '(' before '/' token
    flpydsk.c:90: error: expected identifier or '(' before '/' token
    flpydsk.c:98: error: expected identifier or '(' before '/' token
    flpydsk.c:112: error: expected identifier or '(' before '/' token
    flpydsk.c:113: error: expected identifier or '(' before '/' token
    flpydsk.c:114: error: expected identifier or '(' before '/' token
    flpydsk.c:115: error: expected identifier or '(' before '/' token
    flpydsk.c:133:69: error: missing terminating " character
    flpydsk.c:133: error: missing terminating " character
    flpydsk.c:140: error: expected identifier or '(' before '/' token
    flpydsk.c:148: error: expected identifier or '(' before '/' token
    flpydsk.c:161: error: expected identifier or '(' before '/' token
    flpydsk.c:167: error: expected identifier or '(' before '/' token
    flpydsk.c:173: error: expected identifier or '(' before '/' token
    flpydsk.c:183: error: expected identifier or '(' before '/' token
    flpydsk.c:194: error: expected identifier or '(' before '/' token
    flpydsk.c:204: error: expected identifier or '(' before '/' token
    flpydsk.c:212: error: expected identifier or '(' before '/' token
    flpydsk.c:223: error: expected identifier or '(' before '/' token
    flpydsk.c:231: error: expected identifier or '(' before '/' token
    flpydsk.c:257: error: expected identifier or '(' before '/' token
    flpydsk.c:268: error: expected identifier or '(' before '/' token
    flpydsk.c:293: error: expected identifier or '(' before '/' token
    flpydsk.c:299: error: expected identifier or '(' before '/' token
    flpydsk.c:305: error: expected identifier or '(' before '/' token
    flpydsk.c:317:55: error: invalid suffix "kb" on integer constant
    flpydsk.c:318:77: error: invalid suffix "ms" on integer constant
    flpydsk.c:318:92: error: invalid suffix "ms" on integer constant
    flpydsk.c:318:110: error: invalid suffix "ms" on integer constant
    flpydsk.c:322: error: expected identifier or '(' before '/' token
    flpydsk.c:352: error: expected identifier or '(' before '/' token
    flpydsk.c:369: error: expected identifier or '(' before '/' token
    flpydsk.c:378: error: expected identifier or '(' before '/' token
    flpydsk.c:381: error: expected identifier or '(' before '/' token
    flpydsk.c:384: error: expected identifier or '(' before '/' token
    flpydsk.c:386: error: expected '=', ',', ';', 'asm' or '__attribute__' before ':' token
    flpydsk.c:424: error: expected identifier or '(' before '/' token
    flpydsk.c:438:25: error: invalid suffix "KB" on integer constant
    flpydsk.c:441: error: expected identifier or '(' before '/' token
    flpydsk.c: In function 'flpydsk_read_directory':
    flpydsk.c:460: error: expected expression before '/' token
    flpydsk.c:464: error: expected expression before '/' token
    flpydsk.c:467:26: error: invalid suffix "KB" on integer constant
    flpydsk.c:468:26: error: invalid suffix "KB" on integer constant
    flpydsk.c:469:26: error: invalid suffix "KB" on integer constant
    flpydsk.c:472:16: error: invalid suffix "KB" on integer constant
    flpydsk.c:483:12: error: invalid suffix "KB" on integer constant
    flpydsk.c:490:40: error: invalid suffix "KB" on integer constant
    flpydsk.c:494:18: error: invalid suffix "KB" on integer constant
    flpydsk.c:495:29: error: invalid suffix "KB" on integer constant
    flpydsk.c:496:29: error: invalid suffix "KB" on integer constant
    flpydsk.c:497:29: error: invalid suffix "KB" on integer constant
    flpydsk.c:498:29: error: invalid suffix "KB" on integer constant
    flpydsk.c:499:29: error: invalid suffix "KB" on integer constant
    flpydsk.c:500:29: error: invalid suffix "KB" on integer constant
    flpydsk.c:502:7: error: invalid suffix "st" on integer constant
    flpydsk.c:503:60: error: invalid suffix "KB" on integer constant
    mingw32-make: *** [flpydsk.o] Error 1

    Ich bin bezüglich gcc-Compiler kein Experte, aber mein Vorschlag wäre:

    Muss: -Werror -Wall
    Ziel1: -Wextra
    Ziel2: -ansi
    Ziel3: -pedantic

    -std=gnu99 ist, soweit ich das verstanden habe, bereits erfüllt.



  • So wie das für mich aussieht, sollte man für -ansi erstmal alle "// Kommentare" durch "/* Kommentare */" ersetzen und ein Großteil müsste erledigt sein. 🙂


  • Mod

    alle "// Kommentare" durch "/* Kommentare */" ersetzen

    Das übernehme ich, genau wie ULONG ... ersetzen durch uint32_t usw., obwohl ich sowohl ULONG als auch "// comment" bevorzuge.



  • // ist perfektes C99. Aber wenn du dem Compiler das nicht sagst, geht er eben davon aus, dass du C89 schreiben möchtest und meckert.



  • Ich bevorzuge auch "// ...", aber wenn man -ansi will, dann ist muss man eben "/* ... */" nehmen.
    Wobei ANSI wohl "C90" entspricht und damit ein älterer Standard als C99 ist. Also ich an eurer Stelle würde die Kommentare so lassen und -std=c99 oder -std=gnu99 nehmen, immerhin ist C99 inzwischen auch schon zehn Jahre alt - wenn es auch nicht komplett umgesetzt ist, so müssten doch zumindest die Zeilenkommentare ("//") in allen Compilern drin sein, die C99 zumindest ansatzweise unterstützen.



  • edit: ich hab nichts gesagt^^


  • Mod

    Danke für den Tipp. Denn da ich die C++-Kommentare nicht als schädlich erachte, also -std=gnu99 anstelle -ansi. OK?

    Daraus folgt:

    Muss: -std=gnu99 -Werror -Wall
    Ziel1: -Wextra
    Ziel2: -pedantic

    CFLAGS= -std=gnu99 -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
    

    Läuft beim Kernel fehlerfrei durch.

    Akzeptiert?

    Bezüglich c99 (vs. gnu99) wird folgender Fehler angezeigt:

    i586-elf-gcc -std=c99 -Werror -Wall -O -ffreestanding -fleading-underscore -nost
    dlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude   -c -o isrs.o isrs.c
    
    isrs.c: In function 'fault_handler':
    isrs.c:97: error: 'asm' undeclared (first use in this function)
    isrs.c:97: error: (Each undeclared identifier is reported only once
    isrs.c:97: error: for each function it appears in.)
    isrs.c:97: error: expected ';' before 'volatile'
    mingw32-make: *** [isrs.o] Error 1
    


  • Das Schlüsselwort asm gibt es in c99 nicht, sondern ist eine GNU Extension. __asm__ sollte bei beiden gehen.


  • Mod

    Nach Austausch aller asm gegen __asm__ läuft im Kernel auch -std=c99 glatt durch.

    Daher können wir problemlos nach der Linie

    Muss: -std=c99 -Werror -Wall
    Ziel1: -Wextra
    Ziel2: -pedantic

    verfahren.

    Was beinhaltet -Wextra genau?



  • Erhard Henkes schrieb:

    Was beinhaltet -Wextra genau?

    Von http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

    -Wextra
    This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)

    -Wclobbered
    -Wempty-body
    -Wignored-qualifiers
    -Wmissing-field-initializers
    -Wmissing-parameter-type (C only)
    -Wold-style-declaration (C only)
    -Woverride-init
    -Wsign-compare
    -Wtype-limits
    -Wuninitialized
    -Wunused-parameter (only with -Wunused or -Wall)

    Die meisten sind auf der Seite auch erklärt. Zusammen mit -Werror sind da welche bei, die ich während des Programmierens recht nervig finde. So sorgt -Wunused-parameter für Fehler wenn in einer Funktion nicht jeder Parameter verwendet wurde. Gerade wenn man temporär eine Funktion schreibt, die noch nicht den vollen Funktionsumfang hat, stößt man da oft drauf.



  • Ich finde alle Schalter -Wall -Wextra -Werror -pedantic ok. Man muss sich nur auf ein -std= einigen. Und ich würde c89 bevorzugen. Meine Argumente dafür wären:
    - Kommentare mit // in C-Programmen sind ein Dorn im Auge 😉
    - Warnungen wie "Fehler: ISO-C90 verbietet gemischte Deklarationen und Code" bedeuten, der Programmierer weiss nicht, wie viele lokale Variablen in der Funktion verwendet werden. Pi mal Daumen Regel sagt, maximal sieben lokale Variablen...
    - Alle Compiler heutzutage können c89 - bedeutet u.a. "bessere" Portabilität des Codes (unter Windows z.B. wird portabilität klein geschrieben ;), Windows läuft ja nur auf x86 ab Pentium II oder so, Linux z.B. läuft auf alpha, arm, avr32, blackfin, cris, frv, h8300, i386, ia64, m32r, m68k, m68knommu, microblaze, mips, mn10300, parisc, powerpc, s390, sh, sparc, um, x86, xtensa, ich gebe zu, habe bloss linux/arch Inhalt wiedergegeben, aber man scheint unter Linux irgendwas doch anders zu machen, als unter Windows...)

    Ansonsten - egal, Hauptsache, alle einigen sich auf einen -std= Schalter 🙂


  • Mod

    Kommentare mit // in C-Programmen sind ein Dorn im Auge

    Einem C++-Programmierer fällt das überhaupt nicht negativ auf. C99 ist vor allem modernes C:

    Mit C99 flossen einige aus C++ bekannte Erweiterungen in die Sprache C ein, zum Beispiel das Schlüsselwort inline und die Möglichkeit, Variablen innerhalb der for-Anweisung zu deklarieren.

    Die Deklaration innerhalb der for-Schleife würde ich auch sehr begrüßen. Das ist wirklich sinnvoll! Daher bitte ich um Zustimmung für -std=c99.
    http://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C#C99



  • Erhard Henkes schrieb:

    Die Deklaration innerhalb der for-Schleife würde ich auch sehr begrüßen. Das ist wirklich sinnvoll!

    Ich weiss nicht, ob es sinnvoll ist. Dieses "Feature" hat ja, glaube ich, dazu geführt, dass Code, der z.B. unter MSVS sauber kompiliert, unter anderen Compilern aber nicht, weil unter MSVS konnten/können(?) die Variablen, die in for() deklariert wurden, ausserhalb der for() Schleife doch benützt werden (was ja nicht erlaubt ist)... 😉



  • abc.w schrieb:

    Erhard Henkes schrieb:

    Die Deklaration innerhalb der for-Schleife würde ich auch sehr begrüßen. Das ist wirklich sinnvoll!

    Ich weiss nicht, ob es sinnvoll ist. Dieses "Feature" hat ja, glaube ich, dazu geführt, dass Code, der z.B. unter MSVS sauber kompiliert, unter anderen Compilern aber nicht, weil unter MSVS konnten/können(?) die Variablen, die in for() deklariert wurden, ausserhalb der for() Schleife doch benützt werden (was ja nicht erlaubt ist)... 😉

    MSVC ist inzwischen repariert.
    Und vorher haben wir uns immer beholfen mit dem Bugfix

    #define for if(false){}else for
    

Log in to reply