IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

La version 15.1 de GCC est disponible avec un compilateur COBOL, un meilleur support pour les langages de programmation C, C++ et Rust, ainsi que de nombreuses autres améliorations

Le , par Anthony

0PARTAGES

6  0 
GCC 15.1 vient d'être publié en tant que nouvelle version annuelle de la GNU Compiler Collection. Cette première version stable de GCC 15 apporte un compilateur COBOL frontal, de nombreuses améliorations dans le support des langages C et C++, le support de nouveaux processeurs et de nouvelles capacités ISA, un meilleur support du langage de programmation Rust, des améliorations dans le débogage, et bien d'autres choses encore.

GCC est une collection de compilateurs du projet GNU qui prend en charge différents langages de programmation, architectures matérielles et systèmes d'exploitation. La Free Software Foundation (FSF) distribue GCC en tant que logiciel libre sous la licence publique générale GNU (GNU GPL). GCC est un composant clé de la chaîne d'outils GNU, utilisée pour la plupart des projets liés à GNU et au noyau Linux. Avec environ 15 millions de lignes de code en 2019, GCC est l'un des plus grands programmes libres existants. Il a joué un rôle important dans la croissance du logiciel libre, à la fois comme outil et comme exemple.

La nouvelle version GCC 15.1 propose une interface pour le langage COBOL, diverses améliorations de la convivialité, de nombreuses améliorations du langage de programmation Rust pour gccrs, le passage de la version par défaut du langage C à C23, des améliorations de la cible AMD Zen 5 « znver5 » parmi d'autres nouvelles optimisations de la cible AMD Zen, le ciblage des Intel Xeon 7 Diamond Rapids, la prise en charge de l'Intel AVX10. 2 pour la nouvelle révision de 512 bits seulement, plus d'activations Intel Advanced Performance Extensions « APX », la suppression du support Xeon Phi, des améliorations OpenMP offloading, et beaucoup d'autres changements du support matériel aux caractéristiques du langage.


Le back-end AMDGPU pour les processeurs graphiques AMD prend désormais en charge la bibliothèque C++ standard (libstdc++), la prise en charge expérimentale des périphériques génériques et le retrait de la prise en charge du GPU Fiji. De même, le back-end NVIDIA NVPTX avec GCC15 prend également en charge libstdc++.

Les interfaces des langages D et Modula-2 de GCC, dont on parle moins, ont également fait l'objet d'un travail considérable, tout comme l'interface Fortran.

Fonctionnalités de C++26

Les fonctionnalités C++26 de GCC 15 comprennent l'indexation des paquets, les attributs pour les liaisons structurées, la prise en charge améliorée des fonctions dont la définition consiste en =delete, et plus encore.

Indexation des paquets

C++11 a introduit les modèles variadiques qui permettent au programmeur d'écrire des modèles qui acceptent n'importe quel nombre d'arguments de modèle. Un paquet peut représenter une série de types ou de valeurs. Par exemple, pour imprimer des arguments arbitraires, on peut écrire :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T, typename... Types>
void print (T t, Types... args)
{
  std::cout << t << '\n';
  if constexpr (sizeof...(args) > 0)
    print (args...);
}

int main ()
{
  print ('a', "foo", 42);
}

Cependant, il n'était pas possible d'indexer un élément d'un pack, à moins que le programmeur n'ait recours à diverses astuces récursives qui sont généralement lentes à compiler. Avec cette fonctionnalité du C++26, pour indexer un paquet, on peut écrire pack...[N] (où N doit être une expression constante). L'index d'un paquet se comporte alors exactement comme si l'expression résultante était utilisée. Un paquet vide ne peut pas être indexé. Le programme suivant imprimera a :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
template<typename... Types>
void print (Types... args)
{
  std::cout << args...[0] << '\n';
}

int main ()
{
  print ('a', "foo", 42);
}

Attributs pour les liaisons structurées

Cette proposition permet d'ajouter un attribut à chacune des liaisons structurées introduites, comme dans l'exemple suivant :

Code : Sélectionner tout
1
2
3
4
5
6
7
struct S { int a, b; };

void
g (S& s)
{
  auto [ a, b [[gnu::deprecated]] ] = s;
}

=delete avec une raison

Le C++11 prend en charge les fonctions supprimées, c'est-à-dire les fonctions dont la définition consiste en =delete. Les fonctions supprimées participent à la résolution des surcharges, mais leur appel constitue une erreur. Cela remplace l'ancien mécanisme qui consistait à déclarer les fonctions membres spéciales comme private.

En C++26, il est possible de fournir un message expliquant pourquoi la fonction est marquée comme supprimée : =delete(« reason »). Le programme suivant :

Code : Sélectionner tout
1
2
3
4
5
6
7
void oldfn(char *) = delete("unsafe, use newfn");
void newfn(char *);

void g ()
{
  oldfn ("bagel");
}

provoquera l'émission par le compilateur du message suivant :

Code : Sélectionner tout
1
2
3
4
5
6
7
q.C: In function ‘void g()’:
q.C:7:9: error: use of deleted function ‘void oldfn(char*)’: unsafe, use newfn
7 |   oldfn ("bagel");
  |   ~~~~~~^~~~~~~~~
q.C:1:6: note: declared here
1 | void oldfn(char *) = delete("unsafe, use newfn");
  |      ^~~~~

Amis variadiques

La fonctionnalité suivante permet d'utiliser une déclaration friend avec un paquet de paramètres :

Code : Sélectionner tout
1
2
3
4
template<class... Ts>
class Foo {
  friend Ts...;
};

Un exemple où cette fonctionnalité peut être utilisée en pratique est l'idiome Passkey :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
template<typename... Ts>
class Passkey {
  friend Ts...;
  Passkey() {}
};

class A;
class B;

struct Widget {
  // Only callable from A and B.
  void secret (Passkey<A, B>);
};

class A {
  void doit (Widget& w) {
    w.secret ({}); // OK
  }
};

class B {
  void doit (Widget& w) {
    w.secret ({}); // OK
  }
};

class D {
  void doit (Widget& w) {
    w.secret ({}); // won't compile!
  }
};

Placement constexpr new

Le C++20 a ajouté la possibilité d'utiliser new dans un contexte constexpr :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
constexpr void use (int *) { }

constexpr int
foo ()
{
  auto *p = new int[]{1, 2, 3};
  use (p);
  delete[] p;
  return 1;
}

int main ()
{
  constexpr auto r = foo ();
}

GCC a mis en œuvre la proposition dans GCC 10. Cependant, constexpr placement new n'était pas encore possible. Le C++26 rectifie cette situation et permet au programmeur d'écrire du code comme :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <memory>

constexpr int foo ()
{
  std::allocator<int> alloc;
  auto p = alloc.allocate (16);
  new (p) int(42);
  alloc.deallocate (p, 16);
  return 1;
}

int main ()
{
  constexpr int r = foo ();
}

Déclaration de liaison structurée en tant que condition

La fonctionnalité des liaisons structurées a été ajoutée en C++17, et GCC la supporte depuis longtemps. GCC 15 implémente P0963R3, qui permet la déclaration de liaisons structurées dans les conditions if/while/for/switch ; auparavant, ce n'était pas possible.

Si une liaison structurée est utilisée dans un contexte de condition, sa variable de décision est la variable artificielle sous-jacente créée par le compilateur. Cette variable doit être convertible en bool (sauf lorsqu'elle est utilisée dans une instruction switch). En voici un exemple :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
struct S {
  int a, b;
  explicit operator bool () const noexcept { return a != b; }
};
void use (int, int);

void g (S s)
{
  if (auto [ a, b ] = s)
    use (a, b);
}

Dans l'exemple précédent, use sera appelé lorsque a et b, décomposés à partir de s, ne sont pas égaux. La variable artificielle utilisée comme variable de décision a un nom unique et son type est ici S.

Suppression d'un pointeur sur un type incomplet

Le C++26 a clairement indiqué que les fonctions delete et delete[] sur un pointeur vers un type de classe incomplet ne sont pas valides. Auparavant, cela invoquait un comportement indéfini à moins que la classe n'ait un destructeur trivial et pas de désallocateur personnalisé. Par conséquent, GCC 15 émettra une erreur en mode C++26, ou un avertissement dans les modes plus anciens pour cet exemple :

Code : Sélectionner tout
1
2
3
4
5
6
struct S;

void foo (S *p)
{
  delete p;
}

Virgule variadique d'Oxford

L'utilisation d'une ellipse variadique sans virgule précédente en C++26 est dépréciée dans cet article. Cela signifie que GCC 15, lorsqu'il compilera le cas de test suivant de la proposition, émettra trois avertissements en mode C++26 :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
void d_depr(auto......); // deprecated
void d_okay(auto..., ...);  // OK

void g_depr(int...);     // deprecated
void g_okay(int, ...);   // OK

void h_depr(int x...);   // deprecated
void h_okay(int x, ...); // OK

Les utilisateurs peuvent activer l'avertissement dans les modes plus anciens en spécifiant ...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !