La notion de linkage est une vielle relique ; tant qu'on
ne l'applique qu'aux noms, ça va encore, mais commencer à
le mettre dans un type est une erreur.
La notion de linkage est une vielle relique ; tant qu'on
ne l'applique qu'aux noms, ça va encore, mais commencer à
le mettre dans un type est une erreur.
La notion de linkage est une vielle relique ; tant qu'on
ne l'applique qu'aux noms, ça va encore, mais commencer à
le mettre dans un type est une erreur.
Jean-Marc Bourguet writes:
| Gabriel Dos Reis writes:
| > La notion de linkage est une vielle relique ; tant qu'on
| > ne l'applique qu'aux noms, ça va encore, mais commencer à
| > le mettre dans un type est une erreur.
| Je ne suis pas aussi sûr. Il me semble normal que le
| linkage "C", "C++" ou autre fasse partie du type d'une
| fonction (ça change le code à générer) . Mais le linkage
| interne ou externe non.
Il y a deux chose distinctes :
(1) linkage ;
(2) convention d'appel (« language specification » en standardais).
Pour le linkage, c'est un machin qui était plus ou moins imposé par C
et la technologie de lieur d'il y a plus de 30 ans et qu'on traîne
toujours comme un boulet.
Lorsque la convention d'appel (e.g. « extern "C" ») a été introduite
en C++, cela n'est pas pour changer le type des fonctions (ou des
variables), mais c'est pour spécifier la convention d'appel. Plus
précisément, il a été introduit comme un mécanisme de glue pour lier
du code C++ avec une partie de programme écrit dans un langage X.
Mais comme il n'est pas possible d'exprimer le langage X directement
en C++, il est une erreur de modifier le type d'une entité en se
basant uniquement sur la spécification de langage « extern "X" ».
Cette spécification n'est pas à l'adresse du système de type. Il est à
l'adresse du générateur de code. D'ailleurs dans un bloc extern "X",
on écrit pas du X, on écrit du C++.
Jean-Marc Bourguet <jm@bourguet.org> writes:
| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| > La notion de linkage est une vielle relique ; tant qu'on
| > ne l'applique qu'aux noms, ça va encore, mais commencer à
| > le mettre dans un type est une erreur.
| Je ne suis pas aussi sûr. Il me semble normal que le
| linkage "C", "C++" ou autre fasse partie du type d'une
| fonction (ça change le code à générer) . Mais le linkage
| interne ou externe non.
Il y a deux chose distinctes :
(1) linkage ;
(2) convention d'appel (« language specification » en standardais).
Pour le linkage, c'est un machin qui était plus ou moins imposé par C
et la technologie de lieur d'il y a plus de 30 ans et qu'on traîne
toujours comme un boulet.
Lorsque la convention d'appel (e.g. « extern "C" ») a été introduite
en C++, cela n'est pas pour changer le type des fonctions (ou des
variables), mais c'est pour spécifier la convention d'appel. Plus
précisément, il a été introduit comme un mécanisme de glue pour lier
du code C++ avec une partie de programme écrit dans un langage X.
Mais comme il n'est pas possible d'exprimer le langage X directement
en C++, il est une erreur de modifier le type d'une entité en se
basant uniquement sur la spécification de langage « extern "X" ».
Cette spécification n'est pas à l'adresse du système de type. Il est à
l'adresse du générateur de code. D'ailleurs dans un bloc extern "X",
on écrit pas du X, on écrit du C++.
Jean-Marc Bourguet writes:
| Gabriel Dos Reis writes:
| > La notion de linkage est une vielle relique ; tant qu'on
| > ne l'applique qu'aux noms, ça va encore, mais commencer à
| > le mettre dans un type est une erreur.
| Je ne suis pas aussi sûr. Il me semble normal que le
| linkage "C", "C++" ou autre fasse partie du type d'une
| fonction (ça change le code à générer) . Mais le linkage
| interne ou externe non.
Il y a deux chose distinctes :
(1) linkage ;
(2) convention d'appel (« language specification » en standardais).
Pour le linkage, c'est un machin qui était plus ou moins imposé par C
et la technologie de lieur d'il y a plus de 30 ans et qu'on traîne
toujours comme un boulet.
Lorsque la convention d'appel (e.g. « extern "C" ») a été introduite
en C++, cela n'est pas pour changer le type des fonctions (ou des
variables), mais c'est pour spécifier la convention d'appel. Plus
précisément, il a été introduit comme un mécanisme de glue pour lier
du code C++ avec une partie de programme écrit dans un langage X.
Mais comme il n'est pas possible d'exprimer le langage X directement
en C++, il est une erreur de modifier le type d'une entité en se
basant uniquement sur la spécification de langage « extern "X" ».
Cette spécification n'est pas à l'adresse du système de type. Il est à
l'adresse du générateur de code. D'ailleurs dans un bloc extern "X",
on écrit pas du X, on écrit du C++.
writes:
[...]
| > Lorsque la convention d'appel (e.g. « extern "C" ») a été
| > introduite en C++, cela n'est pas pour changer le type des
| > fonctions (ou des variables), mais c'est pour spécifier la
| > convention d'appel. Plus précisément, il a été introduit comme un
| > mécanisme de glue pour lier du code C++ avec une partie de
| > programme écrit dans un langage X. Mais comme il n'est pas
| > possible d'exprimer le langage X directement en C++, il est une
| > erreur de modifier le type d'une entité en se basant uniquement
| > sur la spécification de langage « extern "X" ». Cette
| > spécification n'est pas à l'adresse du système de type. Il est à
| > l'adresse du générateur de code. D'ailleurs dans un bloc extern
| > "X", on écrit pas du X, on écrit du C++.
| C'est probablement vrai de point de vue théorique.
Non seulement, c'est légitime du point de vue théorique, mais aussi du
point de vue pratique. Par exemple, std::ptr_fun() ne peut pas être
utilisé avec std::strlen() de manière portable. Ce n'est pas
seulement, une erreur, mais c'est également une faute lorsqu'on
considère la bibliothèque standard, ou la programmation générique par
exemple.
| Je n'ai rien contre, mais... Il faut bien qu'un pointeur à une
| fonction soit lié à une convention d'appel, et à une seule, et que
| le programmeur ne peut pas affecter l'adresse d'une fonction «
| extern "C++" » à un pointeur « extern "C" ».
D'abord il vaut virer cette notion de pointeur « extern "C" » et
pointeur « extern "C++" ». Cela n'a pas grand sens -- d'accord tu peux
reciter la norme, mais ce que je suis en train de dire, c'est que
cette décision a été prise sans bien en mesurer l'impact (et c'est
loin d'être le seul ; pour une raison ou une autre Core me donne
l'impression d'être fâché avec les types de fonctions).
Supposons que j'ai une fonction foo() avec une convention d'appel
« X ». Si je l'appelle lexicalement, alors le compilateur a les
informations nécessaires pour « réorganiser » l'appel de manière à
satisfaire les contraintes idoines. Donc pas de problème là. Si je
prends l'addresse d'une telle fonction, le compilateur est moralement
obligé d'en avoir une définition off-line. Mais, dans ce cas, le
compilateur peut très bien générer un thunk qui réorganise les
arguments et branche sur le code effectif. Il n'y a rien de sorcier,
rien que de l'ordinaire -- les thunks sont déjà utilisés pour
implémenter les « covariante returns », fonctions virtuelles de
classes de bases virtuelles, l'héritage multiple.
| Intuititivement, je dirais que la façon naturelle d'exprimer cette
| contrainte, c'est à travers le système de types. Mais
Mais pas celui de C++ -- il n'est pas assez puissant pouor ça.
| je suis ouvert à toute autre suggestion.
Le problème de fond, c'est que si on a une fonction à convention
d'appel « X », et qu'on l'invoque par un pointeur sur une fonction,
elle risque de ne pas recevoir le bon nombre d'arguments ou de les
recevoir dans le mauvais ordre. Mais ça c'est un problème de
génération de code. Là où l'adresse de la fonction est prise, le
compilateur le sait et peut donc générer un thunk pour ça. Il n'est
nul besoin de corrompre le système de type.
kanze@gabi-soft.fr writes:
[...]
| > Lorsque la convention d'appel (e.g. « extern "C" ») a été
| > introduite en C++, cela n'est pas pour changer le type des
| > fonctions (ou des variables), mais c'est pour spécifier la
| > convention d'appel. Plus précisément, il a été introduit comme un
| > mécanisme de glue pour lier du code C++ avec une partie de
| > programme écrit dans un langage X. Mais comme il n'est pas
| > possible d'exprimer le langage X directement en C++, il est une
| > erreur de modifier le type d'une entité en se basant uniquement
| > sur la spécification de langage « extern "X" ». Cette
| > spécification n'est pas à l'adresse du système de type. Il est à
| > l'adresse du générateur de code. D'ailleurs dans un bloc extern
| > "X", on écrit pas du X, on écrit du C++.
| C'est probablement vrai de point de vue théorique.
Non seulement, c'est légitime du point de vue théorique, mais aussi du
point de vue pratique. Par exemple, std::ptr_fun() ne peut pas être
utilisé avec std::strlen() de manière portable. Ce n'est pas
seulement, une erreur, mais c'est également une faute lorsqu'on
considère la bibliothèque standard, ou la programmation générique par
exemple.
| Je n'ai rien contre, mais... Il faut bien qu'un pointeur à une
| fonction soit lié à une convention d'appel, et à une seule, et que
| le programmeur ne peut pas affecter l'adresse d'une fonction «
| extern "C++" » à un pointeur « extern "C" ».
D'abord il vaut virer cette notion de pointeur « extern "C" » et
pointeur « extern "C++" ». Cela n'a pas grand sens -- d'accord tu peux
reciter la norme, mais ce que je suis en train de dire, c'est que
cette décision a été prise sans bien en mesurer l'impact (et c'est
loin d'être le seul ; pour une raison ou une autre Core me donne
l'impression d'être fâché avec les types de fonctions).
Supposons que j'ai une fonction foo() avec une convention d'appel
« X ». Si je l'appelle lexicalement, alors le compilateur a les
informations nécessaires pour « réorganiser » l'appel de manière à
satisfaire les contraintes idoines. Donc pas de problème là. Si je
prends l'addresse d'une telle fonction, le compilateur est moralement
obligé d'en avoir une définition off-line. Mais, dans ce cas, le
compilateur peut très bien générer un thunk qui réorganise les
arguments et branche sur le code effectif. Il n'y a rien de sorcier,
rien que de l'ordinaire -- les thunks sont déjà utilisés pour
implémenter les « covariante returns », fonctions virtuelles de
classes de bases virtuelles, l'héritage multiple.
| Intuititivement, je dirais que la façon naturelle d'exprimer cette
| contrainte, c'est à travers le système de types. Mais
Mais pas celui de C++ -- il n'est pas assez puissant pouor ça.
| je suis ouvert à toute autre suggestion.
Le problème de fond, c'est que si on a une fonction à convention
d'appel « X », et qu'on l'invoque par un pointeur sur une fonction,
elle risque de ne pas recevoir le bon nombre d'arguments ou de les
recevoir dans le mauvais ordre. Mais ça c'est un problème de
génération de code. Là où l'adresse de la fonction est prise, le
compilateur le sait et peut donc générer un thunk pour ça. Il n'est
nul besoin de corrompre le système de type.
writes:
[...]
| > Lorsque la convention d'appel (e.g. « extern "C" ») a été
| > introduite en C++, cela n'est pas pour changer le type des
| > fonctions (ou des variables), mais c'est pour spécifier la
| > convention d'appel. Plus précisément, il a été introduit comme un
| > mécanisme de glue pour lier du code C++ avec une partie de
| > programme écrit dans un langage X. Mais comme il n'est pas
| > possible d'exprimer le langage X directement en C++, il est une
| > erreur de modifier le type d'une entité en se basant uniquement
| > sur la spécification de langage « extern "X" ». Cette
| > spécification n'est pas à l'adresse du système de type. Il est à
| > l'adresse du générateur de code. D'ailleurs dans un bloc extern
| > "X", on écrit pas du X, on écrit du C++.
| C'est probablement vrai de point de vue théorique.
Non seulement, c'est légitime du point de vue théorique, mais aussi du
point de vue pratique. Par exemple, std::ptr_fun() ne peut pas être
utilisé avec std::strlen() de manière portable. Ce n'est pas
seulement, une erreur, mais c'est également une faute lorsqu'on
considère la bibliothèque standard, ou la programmation générique par
exemple.
| Je n'ai rien contre, mais... Il faut bien qu'un pointeur à une
| fonction soit lié à une convention d'appel, et à une seule, et que
| le programmeur ne peut pas affecter l'adresse d'une fonction «
| extern "C++" » à un pointeur « extern "C" ».
D'abord il vaut virer cette notion de pointeur « extern "C" » et
pointeur « extern "C++" ». Cela n'a pas grand sens -- d'accord tu peux
reciter la norme, mais ce que je suis en train de dire, c'est que
cette décision a été prise sans bien en mesurer l'impact (et c'est
loin d'être le seul ; pour une raison ou une autre Core me donne
l'impression d'être fâché avec les types de fonctions).
Supposons que j'ai une fonction foo() avec une convention d'appel
« X ». Si je l'appelle lexicalement, alors le compilateur a les
informations nécessaires pour « réorganiser » l'appel de manière à
satisfaire les contraintes idoines. Donc pas de problème là. Si je
prends l'addresse d'une telle fonction, le compilateur est moralement
obligé d'en avoir une définition off-line. Mais, dans ce cas, le
compilateur peut très bien générer un thunk qui réorganise les
arguments et branche sur le code effectif. Il n'y a rien de sorcier,
rien que de l'ordinaire -- les thunks sont déjà utilisés pour
implémenter les « covariante returns », fonctions virtuelles de
classes de bases virtuelles, l'héritage multiple.
| Intuititivement, je dirais que la façon naturelle d'exprimer cette
| contrainte, c'est à travers le système de types. Mais
Mais pas celui de C++ -- il n'est pas assez puissant pouor ça.
| je suis ouvert à toute autre suggestion.
Le problème de fond, c'est que si on a une fonction à convention
d'appel « X », et qu'on l'invoque par un pointeur sur une fonction,
elle risque de ne pas recevoir le bon nombre d'arguments ou de les
recevoir dans le mauvais ordre. Mais ça c'est un problème de
génération de code. Là où l'adresse de la fonction est prise, le
compilateur le sait et peut donc générer un thunk pour ça. Il n'est
nul besoin de corrompre le système de type.
Jean-Marc Bourguet writes:
| Gabriel Dos Reis writes:
(On obtient un même problème similaire lorsque les gens
ont commencé à vouloir exprimer l'aliasing avec « restrict
». Le système de type C++/C ne peut pas exprimer cela
correctement. Donc le mettre là est une erreur).
Jean-Marc Bourguet <jm@bourguet.org> writes:
| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
(On obtient un même problème similaire lorsque les gens
ont commencé à vouloir exprimer l'aliasing avec « restrict
». Le système de type C++/C ne peut pas exprimer cela
correctement. Donc le mettre là est une erreur).
Jean-Marc Bourguet writes:
| Gabriel Dos Reis writes:
(On obtient un même problème similaire lorsque les gens
ont commencé à vouloir exprimer l'aliasing avec « restrict
». Le système de type C++/C ne peut pas exprimer cela
correctement. Donc le mettre là est une erreur).