so hätte ich eigentlich eine Warnung vom Linker erwartet, dass die Funktion dann nicht in den Interrupt-Vektor eingetragen wird. Kommt aber leider nicht.
Bitte keine Kommentare, dass das natürlich falsch ist: weiß ich doch. Ich möchte nur verstehen, warum da keine Fehlermeldung kommt bzw. wie ich eine Meldung bekommen könnte.
Aus Linkersicht ist alles in Ordnung, denn er hat default-Vektoren für alles.
Wenn, hätte der Compiler eine Chance, das anzumerken. Er sieht, dass du _vector* definierst und er sieht auch, dass das nicht global ist. Hat eben nur keiner einen Test dafür im Compiler implementiert bislang.
Das Problem ist, dass der Code ohne externally_visible falsch ist. Und mit externally_visible, kommt der Code erst garnicht zum Linker (da static).
Bevor du Warnungen vom Linker erwartest (die es nicht gibt) mach erst mal korrekten C/C++ Code.
Sowas gehört eh in einen System-Header, und wenn man die falsch hat, hat man nunmal schlechte Karten. Daher nimmt man ISR aus avr/interrupt.h der AVR-LibC als include oder als Vorlage für einen eigenen System-Header.
Ohne externally_visible dürfen Optimizer die Funktion in eine lokale umwandeln, und die wird nie in einer IRQ-Tabelle auftauchen. Daher ist der Code ohne externally_visible nicht korrekt.
Wenn, hätte der Compiler eine Chance, das anzumerken. Er sieht, dass du
_vector* definierst und er sieht auch, dass das nicht global ist. Hat
eben nur keiner einen Test dafür im Compiler implementiert bislang.
Und Leute, spart Euch die Hinweise, dass das falsch ist:
BMC schrieb:
Bitte keine Kommentare, dass das natürlich falsch ist: weiß ich doch.
Naja, deine Frage ist eben: Ich mache X, will aber Y. Warum warnt der Compiler/Linker mich nicht?
Und ja, diese Frage kann man stellen und sie ist auch oft angebracht.
Aber in diesem Fall eher nicht. Das hier ist ein Superspezialfall, wenn du deine eigenen Systemheader selbst neu implementierst.
Nutze einfach die ISR-Makros aus deinen Systemheadern und gut ist.
Deshalb ist hier die Antwort: Du machst es halt falsch.
D.h. ein Optimizer darf external-linkage zu internal-linkage ändern.
Kann doch aber nur bei LTO gemacht werden, oder?
Das umfasst alle globalen Optimierungen, nicht nur LTO.
Bitte keine Kommentare, dass das natürlich falsch ist: weiß ich doch.
Ich möchte nur verstehen, warum da keine Fehlermeldung kommt bzw. wie
ich eine Meldung bekommen könnte.
Erweiter ./gcc/config/avr/avr.cc::avr_set_current_function() oder ähnliche Stellen, die dafür geeignet sind.
D.h. ein Optimizer darf external-linkage zu internal-linkage ändern.
Kann doch aber nur bei LTO gemacht werden, oder?
Das umfasst alle globalen Optimierungen, nicht nur LTO.
Wie kann der Optimierer beim Übersetzen einer TU entscheiden, das external-linkage zu internal-linkage geändert werden darf, wenn nicht LTO verwendet wird?
Wie kann der Optimierer beim Übersetzen einer TU entscheiden, das
external-linkage zu internal-linkage geändert werden darf, wenn nicht
LTO verwendet wird?
Gar nicht.
Und das ist, wie gesagt, ja auch gar nicht, was hier passiert.
Die Funktion hatte nie external-linkage.
Und das ist, wie gesagt, ja auch gar nicht, was hier passiert.
Die Funktion hatte nie external-linkage.
Wir sind hier in der Diskussion ja schon einen Schritt weiter: natürlich schließen sich static und externally_visible gegenseitig aus bzw. es wirkt sich eben nur auf non-static aus.
Ohne externally_visible dürfen Optimizer die Funktion in eine lokale
umwandeln, und die wird nie in einer IRQ-Tabelle auftauchen. Daher ist
der Code ohne externally_visible nicht korrekt.
Daher verstehe ich Johann so, dass non-static Funktionen (external linkage) zu internal linkage umgewandelt werden können, sofern kein externally_visible angegeben ist. Und das erscheint mir unverständlich.
Daher verstehe ich Johann so, dass non-static Funktionen (external
linkage) zu internal linkage umgewandelt werden können, sofern kein
externally_visible angegeben ist. Und das erscheint mir
unverständlich.
Das kann es nur mit LTO (und je nachdem noch whole program optimization).
Wie gesagt, alle globalen Optimierungen: -flto, -fwhole-program. oder wie die heißen mögen, z.b. bei clang/llvm.
Prinzipiell ist es keine gute Idee, die Korrektheit eines Programms von Optimierungen abhängig zu machen. Für vanilla C/C++ kann das nur bedeuten, dass das Programm UB ist oder ill-formed.
Bei Features jenseits des Standards wie __asm oder Attributen muss man sich eben an das halten, was die Toolchain vorgibt, auch wenn sie nicht für jeden unsinnigen Code explizit austextet, dass er unsinnig ist.
Ich versteh auch nicht, worüber noch groß diskutiert wird und Unklarheit besteht. Du kannst
Auf falschem Code bestehen (scheint ja dein Favorit zu sein) und Design-Pattern Garbage-in/Garbage-out verwenden.
Korrekten Code schreiben, also mit externally_visible.
AVR-LibC avr/interrupt.h verwenden anstatt nochmal bei der Ursuppe anzufangen.
Den Compiler erweitern und deine eigene Version pflegen.
Code wie im OP wird man doch ohnehin in einen Convenience Header / Makro verstecken wollen, so dass die Chance einer falschen Verwendung minimiert wird.
Wie gesagt, alle globalen Optimierungen: -flto, -fwhole-program.
oder
wie die heißen mögen, z.b. bei clang/llvm.
Ok, gut. Dann ist es also so, wie ich es vermutet habe: das LTO stand für mich pars-pro-toto.
Ich versteh auch nicht, worüber noch groß diskutiert wird und Unklarheit
besteht.
Es bestand keine Unklarheit - jedenfalls nicht bei mir, das habe ich oben auch schon geschrieben.
Lediglich habe ich mich gewundert, dass bei meinem mutwillig falschen Code, keine Warnung entstand. Das war alles.
Auf falschem Code bestehen (scheint ja dein Favorit zu sein) und
Design-Pattern Garbage-in/Garbage-out verwenden.
Nö. Es war reine Neugier zu erfahren, warum die Dinge so sind, wie sie eben sind.
Korrekten Code schreiben, also mit externally_visible.
Nö.
AVR-LibC avr/interrupt.h verwenden anstatt nochmal bei der Ursuppe
anzufangen.
Klaro.
Den Compiler erweitern und deine eigene Version pflegen.
Vielleicht.
Code wie im OP wird man doch ohnehin in einen Convenience Header / Makro
verstecken wollen, so dass die Chance einer falschen Verwendung
minimiert wird.
Na klar, habe auch nichts anderes behauptet. Es war ja reine Neugier, was dort passiert und warum da keine Warnung kam. Nun ist es geklärt - es ist einfach nicht realisiert.
Gut, kann man natürlich einbauen, eine Diagnostic dass "externally_visible" erforderlich ist wenn Attribut "interrupt" und/oder "signal" vorhanden sind.
Auf die Linkage zu testen würde nicht funktionieren.