Clazy Web UI, une interface Web pour visualiser les messages de Clang

Clazy est une extension au compilateur Clang qui effectue une analyse statique principalement orientée Qt, afin de faciliter le déploiement de bonnes pratiques, mais aussi de limiter les allocations de mémoire dues à une mauvaise utilisation de l’API.

KDAB annonce maintenant, après Clazy, une interface Web pour faciliter la visualisation des résultats, ainsi que des messages produits par le compilateur en général : Clazy Web UI. KDAB en héberge une instance pour Qt, ce qui permet de voir l’outil en situation réelle.

L’interface est prévue pour être simple à utiliser : après avoir sélectionné un module Qt, elle montre tous les types d’avertissement trouvés lors de la compilation et les endroits dans le code. Il est aussi possible de filtrer les résultats bruts, afin d’éliminer les faux positifs ou encore les mentions les moins intéressantes.

Outre l’amélioration de l’outillage C++, l’objectif est bien évidemment d’attirer plus de contributeurs à Qt, en leur montrant une série de tâches relativement simples à accomplir. Cela pourrait les aider à franchir la barre de gerrit.

Source : Clazy Results Visualizer for Qt, Web UI to view clazy and gcc warnings.

Advertisements

Sortie de CLion 2017.1

JetBrains est une société spécialisée dans la conception d’environnements de développement. Ses produits les plus connus sont IntelliJ (un EDI indépendant d’abord orienté Java) et ReSharper (une extension C# pour Visual Studio), sans oublier PyCharm (pour Python) ou encore WebStorm (pour le développement Web). En 2015, la firme a lancé CLion, son EDI pour les langages C et C++, en partie dérivé d’AppCode (destiné, quant à lui, à la création d’applications iOS en Objective-C). À presque deux ans, voici la version 2017.1 de l’EDI, qui continue à gagner en maturité et à faire de l’ombre aux grands que sont Visual Studio ou encore Eclipse.

Au niveau des dernières fonctionnalités, on trouve principalement les nouveautés de C++14 et 17. De manière générale, presque tout C++14 est géré (tout sauf constexpr) : par rapport à la version précédente, ce sont donc le type auto, les fonctions anonymes génériques, les modèles variables (au lieu d’un nombre fixé de paramètres) et les captures généralisées. Côté C++17, seuls les espaces de noms imbriqués sont apparus (c’est l’apport de la nouvelle norme plébiscité par les utilisateurs) — le reste de la norme suivra dans les versions à venir de l’EDI. Cela signifie que tous ces aspects du langage bénéficient d’une coloration syntaxique et d’une complétion automatique, sans oublier une intégration aux mécanismes de navigation et de refactorisation du code ; par exemple, CLion peut déterminer le type que prendra une variable automatique afin de proposer l’autocomplétion en conséquence.

Une nouvelle intention est disponible. Elle permet de moderniser d’un clic un bout de code : plus précisément, de remplacer le type d’une variable par le mot clé auto.

Le débogueur a été l’objet de bon nombre d’attentions, avec la correction d’un grand nombre de défauts (notamment des temps d’attente expirés avec GDB). Un désassembleur est maintenant intégré, de telle sorte qu’il est possible de poursuivre l’exécution pas à pas y compris dans du code pour lequel les sources ne sont pas disponibles (une version future de CLion permettra d’accéder à ce désassembleur de manière autonome). Le code assembleur aura aussi une coloration syntaxique (même en dehors du débogueur), à condition de respecter la syntaxe AT&T et de ne pas utiliser de préprocesseur.

CLion est maintenant compatible avec de nouveaux outils de l’écosystème C++. Pour les tests, Google Test est géré depuis le début, Catch apparaît avec cette version. Le compilateur Visual C++ est aussi de la partie (versions 2013 à 2017), sous Windows, mais uniquement de manière expérimentale. Ainsi, CLion ne cherche pas automatiquement le compilateur, il faut l’activer manuellement (le résultat n’est pas encore parfait). msbuild n’est pas géré, CMake reste la seule manière de créer un projet avec CLion. Le débogueur de Visual C++ n’est pas intégré.

Ceci n’est qu’un aperçu des différences fonctionnalités apparues. On peut aussi compter la saisie sans délai (la latence entre l’appui d’une touche sur le clavier et l’impact à l’écran est le plus faible parmi tous les EDI !), la recherche dans un dossier avec prévisualisation automatique, une vue améliorée de l’historique d’un dépôt (avec possibilité d’utiliser des expressions régulières !) ou encore une extension pour les langages Swift (remplaçant d’Objective-C) et Go (un EDI spécifique est en cours de développement).

Télécharger CLion 2017.1.

Source et images : CLion 2017.1 released: C++14, C++17, PCH, disassembly view, Catch, MSVC and more.

Un nouvel optimiseur de code pour Visual C++

Les compilateurs sont des programmes informatiques d’une importante complexité. Ils sont généralement structurés en une partie frontale, qui comprend le langage d’entrée, puis d’une partie arrière, qui s’occupe de traduire le programme d’entrée en du code binaire exécutable par le processeur. Les deux parties communiquent à l’aide d’une représentation intermédiaire (IR). Ainsi, pour qu’une même suite de compilateurs comprenne plusieurs langages et puisse générer du code pour plusieurs processeurs, il n’est pas nécessaire d’écrire un compilateur spécifique pour chaque paire langage-processeur : il suffit d’écrire les paires langage-IR et IR-processeur. Tout le travail effectué pour un processeur sera alors utilisable pour n’importe quel langage d’entrée.

Dès la génération du code intermédiaire, un compilateur utilise énormément de passes d’optimisation, afin de rendre le code plus rapide. Elle utilise des techniques comme la propagation des valeurs : si une variable a une valeur connue à un endroit du code (initialisation, condition…), alors cette valeur peut être propagée dans une série de calculs, qui seront alors effectués à la compilation au lieu de l’exécution. Ces passes sont effectuées en partie sur la représentation intermédiaire, pour les optimisations indépendantes du processeur, mais également sur du code machine déjà généré, pour tirer le meilleur parti possible du matériel.

Généralement, cette phase d’optimisation est extrêmement cruciale, étant donné que la représentation intermédiaire est suffisamment générale pour plusieurs types de processeurs et relativement simple dans les instructions disponibles : pour effectuer certaines opérations, il est parfois nécessaire d’écrire des dizaines d’instructions IR, alors que certains processeurs peuvent réaliser la même opération en une seule instruction. De plus, une représentation intermédiaire doit être prête pour les phases d’optimisation qui suivent, notamment en simplifiant toutes les étapes de raisonnement : dans les IR de type SSA, notamment, une variable ne peut être assignée qu’une seule fois, ce qui allonge d’autant plus le code.

Un nouvel optimiseur pour Visual C++

Le compilateur C++ de Microsoft, connu sous le nom de Visual C++, a longtemps été laissé dans un état proche de l’abandon. Depuis quelques années, les équipes de développement ont mis les bouchées doubles pour ramener le compilateur dans la course, avec une compatibilité avec les normes les plus récentes, au niveau de GCC ou Clang. Depuis lors, ils ont effectivement rattrapé en grande partie leur retard à ce niveau, mais pas encore pour les optimisations du code.

L’optimiseur actuel ne disposait que d’une série de transformations assez basiques, n’exploitant qu’une vue assez limitée des fonctions. Bon nombre d’optimisations fonctionnent en trouvant des motifs et en les remplaçant par une version améliorée, mais tous les motifs les plus utiles ne sont pas toujours implémentés. De plus, le code vectorisable n’est pas optimisé au meilleur de ses possibilités. Toutes ces limitations ont une origine historique : le compilateur C++ de Microsoft a des origines très anciennes, il provient de l’époque DOS où la mémoire était très limitée, ce qui limite les possibilités. Les efforts actuels portent principalement sur une modernisation du code, en éliminant les compromis d’un autre âge.

Le nouvel optimiseur exploite désormais une représentation intermédiaire SSA. Les algorithmes implémentés par-dessus peuvent ainsi être plus efficaces en temps par rapport aux approches par analyse du flux de données. Il se base sur une bibliothèque C++ avancée, exploitant les templates à foison, pour décrire les transformations à effectuer, ce qui a permis d’ajouter bon nombre d’optimisations simples en très peu de temps (surtout par rapport à l’infrastructure précédente).

Les développeurs de Visual C++ indiquent également avoir prêté attention à la correction de ces optimisations : il n’y a rien de plus désagréable que de passer des journées à déboguer son code pour trouver que, finalement, le problème n’est pas dû au code, mais bien au compilateur. Linus Torvalds a récemment torpillé GCC à ce sujet. Ici, les développeurs ont absolument cherché à éviter ces écueils, en testant leurs passes d’optimisation sur des programmes courants comme Chrome ou Firefox, puis sur des bibliothèques imposantes côté Microsoft comme CoreCLR ou Chakra.

Ils ont aussi employé des techniques de vérification formelle (à l’aide d’ALIVE et l’outil de démonstration automatique Z3, tous deux issus de Microsoft Research et aussi utilisés pour LLVM) et de la génération de code aléatoire avec Csmith (et C-Reduce pour réduire le code posant problème au strict minimum). Certains outils du projet LLVM ont pu être utilisés, puisque Visual C++ peut en exploiter les parties avant, comme Opt-fuzz, qui génère des expressions arithmétiques à optimiser.

Un exemple

Ces nouvelles optimisations peuvent avoir un effet assez radical sur certains bouts de code. Par exemple, pour un test de parité :

[cce lang=”cpp”]int test(int a) {
return a % 2 != 0 ? 4 : 2;
}[/cce]

Les précédentes versions du compilateur produisaient un code qui prenait entre cinq et dix cycles en x86, selon que tout le processeur est exploité (prédiction du branchement parfaite) ou non :

[cce lang=”asm”]?test@@YAHH@Z PROC
and ecx, -2147483647
jge SHORT $LN3@test
dec ecx
or ecx, -2
inc ecx
$LN3@test:
test ecx, ecx
mov eax, 2
mov edx, 4
cmovne eax, edx
ret 0[/cce]

Sauf que… Dans le test [ccei lang=”cpp”]a % 2 == 0[/ccei], le signe de [ccei lang=”cpp”]a[/ccei] n’a aucune espèce d’importance, seul un bit est important : le modulo peut être remplacé par une opération logique, c’est-à-dire [ccei lang=”cpp”]a & 1 == 0[/ccei]. Or, la comparaison implique un branchement dans le code, forcément lent sur les architectures x86 modernes : pour s’en débarrasser, la structure [ccei lang=”cpp”]bool(a) ? C1 : C2[/ccei] peut être remplacée par [ccei lang=”cpp”]C2 + a*(C1-C2)[/ccei], c’est-à-dire exclusivement des calculs. Par conséquent, le nouveau code assembleur est le suivant :

[cce lang=”asm”]?test@@YAHH@Z PROC
and ecx, 1
lea eax, DWORD PTR [rcx*2+2]
ret 0[/cce]

Celui-ci prend, à tous les coups, deux cycles d’horloge : par rapport à cinq à dix cycles, le gain est important, tant en rapidité qu’en taille de l’exécutable.

D’autres mécanismes effectuent une analyse statique du code, en précalculant autant de bits que possible dans les variables. Par exemple, lors d’une conversion vers un type plus grand, une série de bits est forcément à zéro, peu importe la valeur d’entrée. Ensuite, cette information peut être adaptée en fonction des opérations effectuées, ce qui peut guider le reste du processus.

[cce lang=”cpp”]int test(unsigned char a) {
short b = a; // b: 00000000________, a: ________
b <<= 4; // b: 0000________0000
b |= 3; // b: 0000________0011
return b != 0; // -> return true
}[/cce]

Impact sur la taille du code généré

L’impact de ces modifications sur le code généré n’est pas facile à établir : certaines optimisations diminuent forcément la quantité de code, le compilateur sera alors plus enclin à recopier in extenso le code de petites fonctions pour éviter le surcoût dû à tout appel de fonction (qui n’est négligeable que pour des fonctions plus grandes) — ce qui conduit à l’augmentation de la taille du code. Il n’empêche, les résultats sont intéressants : sur tout Windows, c’est-à-dire plus d’un gigaoctet, les gains sont de 438 Ko par rapport à l’optimiseur précédent (0,3 %) ; sur SQL Server, 46 Ko sur 64 Mo (0,8 %) ; sur Chakra, le nouveau moteur JavaScript, 10 Ko sur 6 Mo (1,7 %).

En analysant plus en détail l’impact au niveau des instructions, les plus lentes sont largement évitées (branchements, multiplications, divisions), remplacées par des opérations plus rapides (comme des déplacements conditionnels). Les temps de compilation ont été impacté de diverses manières : une augmentation de 1,7 % pour Chrome ou une diminution de 2,6 % pour le noyau Windows.

Et alors ?

Les travaux sur l’optimiseur viennent seulement d’être annoncés : l’architecture choisie permettra aux développeurs d’ajouter des optimisations supplémentaires rapidement (et certaines sont déjà en cours de planification). Cet optimiseur devrait arriver dès Visual C++ 2015 Update 3, mais le travail continuera sur cet aspect du compilateur, afin de le rendre compétitif par rapport à ses concurrents, voire de les dépasser. Il est d’ores et déjà possible de le tester.

Source : Introducing a new, advanced Visual C++ code optimizer.
L’image a été créée par l’auteur et est soumise au droit d’auteur.

Sortie de GCC 6.1 : C++14 activé par défaut, OpenMP 4.5

GCC vient de sortir sa version majeure annuelle, numérotée 6.1. Elle cumule les développements d’une année entière, avec des évolutions dans tous les domaines : côté C++, le compilateur se positionnera sur la norme C++14 par défaut, au lieu de C++98 auparavant, quelques fonctionnalités de C++17 ont été implémentées ; pour le domaine HPC, OpenMP 4.5 est complètement implémenté, les calculs peuvent être déportés sur des coprocesseurs Intel Xeon Phi “Knights Landing” et sur du matériel AMD par HSAIL ; l’implémentation de OpenACC 2.0a a été améliorée, avec une possible déportation sur du matériel NVIDIA par PTX. Au niveau matériel, les prochains processeurs d’AMD, basés sur l’architecture Zen, sont déjà pris en charge ; les plateformes ARM ont été le théâtre de bon nombre d’améliorations ; l’architecture PowerPC a reçu la compatibilité avec POWER9, la prochaine itération des processeurs d’IBM.

Côté C++

La précédente version majeure de GCC, numérotée 5.1, apportait les dernières touches à l’implémentation de C++14, en apportant des fonctionnalités comme la désallocation d’une partie d’un tableau, des constexpr plus généraux, des fonctions anonymes génériques.

Cette nouvelle version de GCC s’arme déjà pour C++17, avec par exemple, la définition d’attributs sur les énumérateurs ou encore des expressions utilisant l’opérateur fold (aussi nommé reduce ou autre, selon les modes) :

[cce lang=”cpp”]// Cette fonction somme tous ses arguments.
template<typename… Args>
bool f(Args… args) {
return (true + … + args);
}[/cce]

Plus de détails dans la documentation.

Une nouvelle optimisation en C++ casse du code existant

Une nouvelle optimisation fait parler d’elle : la propagation de valeurs considère désormais que le pointeur this en C++ (qui pointe vers l’objet courant) est toujours initialisé (sa valeur n’est jamais nullptr). Ce point particulier n’a jamais été précisé dans une norme, les compilateurs sont donc libres quant à son interprétation — même si Qt 5 ou Chromium exploitaient l’implémentation précédente. Ce cas peut arriver pour des structures, comme un arbre binaire :
[cce lang=”c”]struct Node {
Node * left;
Node * right;
};[/cce]

Pour traverser cet arbre en C, la manière la plus naturelle d’écrire l’algorithme est récursive. Pour traiter le cas d’une branche absente, la fonction commence par vérifier que le pointeur passé en argument est bien valide :

[cce lang=”c”]void in_order(Node* n) {
if (! n) return;
in_order(n->left);
in_order(n->right);
}[/cce]

En C++, la syntaxe est plus plaisante avec une fonction membre. Dans ce cas, l’argument de la fonction est passé de manière implicite, à travers le pointeur this :

[cce lang=”cpp”]void in_order() {
if (this == nullptr) return;
left->in_order();
right->in_order();
}[/cce]

Cependant, avec cette optimisation (permise par le standard C++), le premier test sera toujours faux, puisque, par hypothèse, this est toujours un pointeur valide… et ce code plantera lamentablement à l’arrivée d’une feuille. Heureusement, cette optimisation peut être désactivée avec un simple paramètre lors de la compilation (-fno-delete-null-pointer-checks) et l’absence de tel code peut aussi être vérifiée (-fsanitize=undefined).

Bien évidemment, une meilleure manière d’écrire le code vérifie directement chacun des deux pointeurs contenus dans la structure avant de continuer la récursion — ce qui évite en passant les problèmes potentiels avec cette optimisation :

[cce lang=”cpp”]void in_order() {
if (left) left->in_order();
if (right) right->in_order();
}[/cce]

Sources : GCC 6.1 Released, Why does the enhanced GCC 6 optimizer break practical C++ code?, GCC 6 Release Series: Changes, New Features, and Fixes, C++ Standards Support in GCC.
Merci à Winjerome pour ses conseils à la rédaction.

Sortie de LLVM 3.8

Avec à peu près un mois de retard sur le planning, la nouvelle version de la suite de compilation LLVM est sortie, numérotée 3.8. Elle inclut notamment le compilateur C et C++ Clang. Quelques points sont mis en évidence par les développeurs :

  • OpenMP est maintenant activé par défaut dans Clang (la norme en version 3.1 était disponible en préversion dès Clang 3.7, le travail continue pour OpenMP 4.0 puis 4.5) ;
  • la compatibilité avec les autres compilateurs : une gestion des exceptions compatible avec les compilateurs Microsoft sous Windows, du TLS (une zone de mémoire privée pour chaque fil d’exécution pour des programmes parallèles à mémoire partagée) compatible avec GCC ;
  • la compilation de LLVM se fait maintenant de manière privilégiée avec CMake (plutôt que les autotools) ;
  • le tutoriel Kaleidoscope a été retravaillé pour faciliter l’utilisation de la plateforme LLVM par de nouveaux développeurs (notamment pour gérer d’autres langages en entrée) ;
  • LLVM ne garantit plus la compatibilité avec les versions les plus anciennes de Windows, c’est-à-dire antérieures à Windows 7.

Calcul de haute performance

Pour le calcul de haute performance, cette nouvelle version apporte bien des nouveautés intéressantes. Un certain nombre de fonctionnalités d’OpenCL 2.0 est implémenté, notamment au niveau de la gestion des espaces d’adressage ou encore des types atomiques (compatibles avec ceux définis par C11) et d’images (des tableaux bidimensionnels, comme image2d_depth_t ou image2d_array_depth_t).

Du côté d’OpenMP, la version 3.1 de la norme est maintenant entièrement supportée. À l’exécution, ce ne sera plus la bibliothèque GCC OpenMP qui sera utilisée, mais bien celle de Clang, développée par Intel (et développée à partir de celle utilisée pour leurs compilateurs propriétaires). Le développement continue pour OpenMP 4.0 et 4.5, avec notamment les clauses map, num_teams et thread_limit ou encore les dépendances entre tâches.

Pour CUDA, la technologie propriétaire de calcul sur processeurs graphiques de NVIDIA, les fonctionnalités arrivent petit à petit (elles sont toujours considérées comme expérimentales). Le code de Google n’est toujours pas intégré à Clang, mais il peut maintenant s’interfacer avec cette version sans modification spécifique.

Source : [llvm-announce] LLVM 3.8 Release, Clang 3.8 Release Notes

Build2 : une chaîne de compilation et de distribution de code C++

Build2 a vu sa première version sortir ce mois-ci. Cet outil C++ est prévu comme une chaîne de compilation, un gestionnaire de paquets et une interface en ligne, principalement pour le monde C++ (même si les autres langages ne sont pas mis en avant, l’outil pourra les gérer). Il gère le même genre de problèmes que Conan : pour utiliser une nouvelle bibliothèque en C++, il faut gérer la compilation (qui peut varier fortement d’une plateforme à l’autre, d’un compilateur à l’autre) et les dépendances éventuelles, qui à leur tour viennent avec leurs particularités. Build2 propose ainsi une nouvelle syntaxe pour gérer les fichiers dictant le mode opératoire pour la compilation, comparable à make et CMake.

Concrètement, le projet est divisé en plusieurs morceaux : build2 pour le système de compilation, bpkg pour le gestionnaire de paquets et brep pour l’interface Web. Ce dernier est déjà à l’œuvre sur cppget.org, que les développeurs espèrent voir devenir la plateforme de référence pour les bibliothèques C++ (même s’il ne contient, à ce jour, que quelques paquets, tous issus de Build2).

bpkg est le point central pour tout utilisateur : il sert à créer un nouveau projet, à ajouter des dépôts pour la gestion des dépendances, puis à la compilation et à la gestion de la mise à jour de ces dépendances. Ensuite, le pilote b s’occupe de la compilation de tout projet C++, une fois les dépendances installées. Ainsi, la manière la plus courante de l’utiliser est d’utiliser ces commandes, de la création du projet à sa compilation, en passant par les dépendances :

$ bpkg create cxx config.cxx=clang++
created new configuration in ./

$ bpkg add https://pkg.cppget.org/1/alpha
added repository cppget.org/alpha

$ bpkg fetch
fetching cppget.org/alpha
fetching cppget.org/beta (complements cppget.org/alpha)
[...]
10 package(s) in 4 repository(s)

$ bpkg build bpkg
build libbutl 0.2.0 (required by bpkg libbpkg)
build libbpkg 0.2.0 (required by bpkg)
build bpkg 0.2.0
continue? [Y/n] y
[...]
bpkg-0.2.0.tar.gz 100% of 144 kB 130 kBps 00m01s
fetched bpkg 0.2.0
unpacked bpkg 0.2.0
configured bpkg 0.2.0
c++ bpkg-0.2.0/bpkg/cxx{bpkg}
[...]
ld bpkg-0.2.0/bpkg/exe{bpkg}

$ b -v
g++-5 -I/tmp/hello-gcc5-release/libhello-1.0.0+1 -O3 -std=c++11 -o hello.o -c ../hello2/hello.cpp
g++-5 -O3 -std=c++11 -o hello hello.o /tmp/hello-gcc5-release/libhello-1.0.0+1/hello/libhello.so

Pour le moment, le projet est décrit comme une préversion technologique, rien n’est véritablement fixé dans le marbre. Il est porté par la société Code Synthesis, qui ne s’oriente pas complètement autour de ce gestionnaire de dépendances : contrairement au prédécesseur de Conan, Biicode, la viabilité de ce nouvel écosystème ne dépendra pas uniquement du modèle économique développé pour lui, ce qui pourrait en augmenter les chances de survie.

Site de Build2.

Fedora et GCC 6 montrent de mauvaises pratiques de codage

Pour leur version 24, les développeurs de la distribution Linux Fedora ont notamment voulu utiliser la dernière version du compilateur GCC, qui sera la GCC 6.1 quand la nouvelle version de la distribution sera disponible (GCC 6 est prévu pour avril 2016, Fedora 24 vers juin). Ainsi, cette semaine, les développeurs ont lancé une compilation complète de l’entièreté des paquets de Fedora, en préparation de ce changement de compilateur.

Leur processus était le suivant : d’abord tenter une compilation de tous les 17 741 paquets avec GCC 6, puis, pour ceux dont la compilation a échoué, retenter la compilation avec GCC 5. Si la compilation échoue deux fois, le problème vient du paquet, sinon de GCC. Un peu moins de mille paquets ont ainsi échoué deux fois, ce qui en laisse à peu près six cents qui ont échoué avec GCC 6 mais pas GCC 5. En comparaison, pour le passage de GCC 4.9 à GCC 5, moins de la moitié avait posé problème. La nouvelle version de GCC serait-elle si mauvaise ?

Effectivement, une série de ces problèmes était due à des régressions au niveau de GCC, des défauts qui ont rapidement été corrigés en vue de la sortie de la version finale. La majorité des cas, cependant, vient des développeurs des applications concernées. Pour une série d’entre eux, le problème vient du fait que GCC 6 compilera le code C++ par défaut en mode C++14 (au lieu de C++98, une norme bien dépassée) : ces paquets n’étaient pas prêts et ont dû être recompilés avec GCC 5.

Pour d’autres, certains changements dans l’implémentation de la bibliothèque standard C++ et, surtout, de nouveaux messages d’erreur ont montré des pratiques de programmation douteuses dans le chef des développeurs des applications disponibles dans Fedora. Les réponses des développeurs de GCC sont parfois éloquentes quant à ces mauvaises pratiques :

The code is nonsense, what’s it even supposed to do? […] It’s useless, and only compiled by accident.

Allowing it with -fpermissive might make sense though, as that flag allows all kinds of terrible rubbish to compile.

Les mêmes défauts seront probablement remarqués par les autres distributions en passant à GCC 6, comme Gentoo, habituellement prompte à se mettre à jour.

Source : Fedora mass rebuild 2016.