1 pontos por GN⁺ 2 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • A nova versão do GNU Compiler Collection marca uma mudança importante ao alterar o padrão padrão de C++ para gnu++20 e deixar de considerar a implementação de C++20 como experimental
  • Foram adicionados suporte a recursos de reflection, contracts e constexpr do C++26, recursos do C++23 e suporte experimental às bibliotecas C++23 e C++26; além disso, os diagnósticos de erros de template e falhas de restrições de type traits ficaram mais detalhados com mensagens hierárquicas
  • OpenMP e OpenACC expandiram alocação de memória em GPU, target memset e a API de device memcpy, e os front ends de Ada, Fortran, Modula-2 e Algol 68 também receberam novos recursos de linguagem e compiladores experimentais
  • O x86-64 passa a oferecer suporte a AMD Zen6, Intel Wildcat Lake e Intel Nova Lake, e também foram adicionados recursos específicos por alvo e mudanças de ABI para AMD GPU, LoongArch, IBM z Systems, Solaris e Windows
  • Com a remoção do formato de diagnóstico JSON, o reforço dos diagnósticos em SARIF e HTML, melhorias no analisador estático e a adição de 37 entrypoints em libgdiagnostics, a infraestrutura de diagnósticos e integração com ferramentas foi bastante ampliada

Mudanças de compatibilidade e melhorias gerais

  • No Solaris, int8_t e tipos semelhantes passaram a ser signed char para cumprir o padrão C99, o que é uma mudança incompatível
  • No Solaris, a opção -pthread não predefine mais _REENTRANT
  • O formato json de -fdiagnostics-format= foi removido, e diagnósticos legíveis por máquina devem usar SARIF
  • A Link-Time Optimization passou a lidar melhor com instruções asm de nível superior com -flto-toplevel-asm-heuristics
  • A speculative devirtualization agora trata chamadas indiretas gerais de função e oferece suporte a mais de um alvo especulado
  • O vectorizer ficou mais flexível na identificação de paralelismo interno ao loop em reductions e passou a oferecer suporte à vetorização de loops com número de iterações desconhecido e de uncounted loops
    • Também há suporte a peeling para alinhamento em loops vector length agnostic com masking, mutual peeling for alignment e remoção do cálculo de vector induction em loops com early break
  • As GCC Command Options e o option index foram corrigidos para incluir muitas opções que antes estavam faltando
  • A documentação de GCC-specific attributes foi modernizada para dar mais ênfase à sintaxe padrão de attributes permitida em todos os dialetos C/C++ suportados pelo GCC
    • O material sobre attributes foi reorganizado para reduzir repetições, e um novo attribute index foi adicionado
    • A documentação sobre arquivos spec de parâmetros e opções foi movida para o GCC internals manual, voltado a desenvolvedores do GCC e usuários que precisam de configurações personalizadas do GCC)

Principais mudanças por linguagem

  • OpenMP e OpenACC

    • O suporte à alocação de memória no OpenMP foi reforçado, e o allocator com trait pinned e ompx_gnu_pinned_mem_alloc usam a API CUDA quando disponível, melhorando o desempenho de acesso a essa memória em GPUs da Nvidia
    • O allocator de extensão GNU ompx_gnu_managed_mem_alloc e ompx_gnu_managed_mem_space alocam memória acessível ao dispositivo a partir do host
      • O acesso pelo dispositivo é possível mesmo sem suporte a unified-shared memory, e mesmo em sistemas em que toda a memória do host é acessível ao dispositivo, o comportamento de page migration pode ser diferente do de outras memórias
    • O OpenMP 5.0 adicionou suporte limitado a declare mapper em C/C++, e a cláusula uses_allocators agora inclui a mudança de sintaxe do OpenMP 5.2 e o suporte a ponto e vírgula do OpenMP 6.0
    • O OpenMP 5.1 adiciona suporte inicial ao modificador iterator na cláusula map e no construct target update em C/C++
    • O OpenMP 5.2 oferece suporte à diretiva begin declare variant em C/C++
    • O OpenMP 6.0 adicionou as rotinas de API omp_target_memset e omp_target_memset_async, e a cláusula de assumptions no_openmp_constructs também pode ser usada
    • Diretivas e cláusulas descontinuadas no OpenMP 5.0, 5.1 e 5.2 emitem aviso de depreciação por padrão, que pode ser desativado com -Wno-deprecated-openmp
      • Também há aviso ao usar constantes nomeadas ou rotinas de API descontinuadas, e isso pode ser desativado com -Wno-deprecated-declarations
    • O OpenACC adicionou as rotinas de API acc_memcpy_device e acc_memcpy_device_async para C/C++/Fortran
    • A diretiva wait do OpenACC 3.0 aceita a cláusula if, e as rotinas de API Fortran acc_attach e acc_detach do OpenACC 3.3 complementam suas contrapartes em C/C++ do OpenACC 2.6
    • No OpenACC 3.4, o uso da constante nomeada PARAMETER na cláusula de dados do Fortran é permitido pela especificação e pelo GCC, mas no GCC isso não afeta o comportamento em tempo de compilação nem em tempo de execução
  • Ada, Fortran, Modula-2, Algol 68

    • As extensões Ada GNAT agora incluem Constructor e Destructor, oferecendo um mecanismo de construction/finalization bastante diferente do Ada padrão
    • Foram adicionados ao Ada o aspecto Implicit with, a Structural Generic instantiation e o aspecto Extended_Access
      • Extended_Access pode ser especificado em declarações de tipo de acesso geral que apontam para subtipos de array não restringidos, alterando a representação do ponteiro e facilitando a interoperabilidade com linguagens estrangeiras em memórias não alocadas por Ada
    • O Ada pode usar o VAST para depuração do compilador com -gnatd_V ou -gnatd_W no modo verbose, e houve melhorias na análise semântica de Reduction Expressions do Ada 2022, em Ada.Containers.Bounded_Indefinite_Holders, na implementação das regras de accessibility e no suporte ao Android
    • O Fortran lida com coarrays que usam multithreading nativo em memória compartilhada em máquinas de nó único, além do recurso TEAM do Fortran 2018
    • O suporte a Parameterized Derived Types do Fortran 2003 foi aprimorado, e o tratamento do parâmetro LEN funciona, mas ainda exige futuras mudanças de representação conforme o PR82649
    • O Fortran 2018 oferece suporte à expansão da instrução IMPORT, ao intrinsic REDUCE e à nova instrução GENERIC
    • O Fortran 2023 oferece suporte a adições de funções trigonométricas como sinpi, à intrinsic subroutine split e a c_f_pointer com optional lower bound como argumento
    • A opção -fexternal-blas64 chama rotinas BLAS externas com argumentos inteiros de 64 bits em MATMUL, e só é válida em sistemas 64-bit e com -ffrontend-optimize aplicado
    • O Modula-2 agora fornece hints de grafia durante o tratamento de import list, nome de módulo e símbolos em escopo aninhado, além de introduzir uma nova implementação de wide set e o módulo de biblioteca M2WIDESET
      • Essa mudança em wide set altera a ABI e pode causar erro de link em tempo de link com object files de versões anteriores do GCC
    • A biblioteca padrão do Modula-2 ganhou o módulo de dicionário binário BinDict, vários módulos agora oferecem os procedimentos Write e WriteLn, e a opção -fm2-pathname-root= melhora o acesso a módulos de biblioteca externos
    • O GCC passa a incluir ga68, um compilador experimental de Algol 68, com o objetivo de implementar o Revised Report e as erratas aprovadas pelo subcomitê de suporte ao Algol 68 da IFIP WG2.1
      • Algumas extensões GNU e um prelude POSIX também são implementados; para mais informações sobre a linguagem, veja o site do Algol 68, e para o front end, a wiki

C++ e libstdc++

  • A versão padrão da linguagem para compilação de C++ mudou de -std=gnu++17 para -std=gnu++20
    • Códigos que dependem de padrões C++ anteriores precisam adicionar -std= às flags de build ou portar o código; consulte as notas de portabilidade
    • O suporte a modules do C++20 ainda é experimental e deve ser ativado com -fmodules
  • Muitos recursos do C++26 foram implementados, incluindo reflection, annotations for reflection, base class subobject splicing, function parameter reflection, contracts, constexpr exceptions e constexpr virtual inheritance
    • P2996R13 Reflection é ativado com -std=c++26 -freflection
    • Partes do P2686R4 têm suporte parcial; structured binding pode ser constexpr, mas referências a constexpr automatic variable ainda não são permitidas
  • Recursos do C++23 como P2036R3, P2590R2 e P2246R1 foram implementados
  • As mensagens de erro de C++ agora têm uma estrutura hierárquica em problemas relacionados a templates e afins, com indentação e marcadores para indicar o aninhamento das mensagens
  • O suporte experimental a modules do C++20 passa a compilar a header unit <bits/stdc++.h> e os módulos std e std.compat antes da compilação do arquivo-fonte, ao adicionar a opção --compile-std-module
    • Se a header unit <bits/stdc++.h> estiver compilada, #include de headers importáveis da biblioteca padrão é convertido de forma transparente em import de <bits/stdc++.h>
    • Muitos bugs reportados foram corrigidos
  • Os diagnósticos de falha de constraints nos type traits da biblioteca padrão agora explicam com mais detalhes por que is_constructible_v, is_invocable_v e similares retornam false
  • Em alvos com suporte a inteiro de 128 bits no libstdc++, std::is_integral<__int128> e traits semelhantes agora sempre retornam true
    • Antes, isso era true no dialeto GNU, mas não no dialeto estrito
  • P0952R2: A new specification for std::generate_canonical foi implementado em todos os modos afetados desde o C++11, impactando a saída observada
    • O comportamento anterior pode ser restaurado com a definição _GLIBCXX_USE_OLD_GENERATE_CANONICAL
  • A ABI de std::variant foi atualizada para ficar consistente com os modos C++20 ou superiores, afetando o layout de classes em certos modos C++17
    • O comportamento anterior pode ser restaurado com a definição _GLIBCXX_USE_VARIANT_CXX17_OLD_ABI, e o impacto se limita ao modo C++17
  • A execução de std::regex foi reescrita para usar uma pilha baseada em heap em vez da pilha do sistema, evitando stack overflow em correspondências com strings maiores
  • A implementação de C++20 não é mais experimental, e std::chrono::current_zone() funciona no Windows
  • Como o suporte a C++20 antes do GCC 16 era experimental, programas que usam componentes de C++20 devem ser considerados incompatíveis com versões anteriores
    • Entre as mudanças de ABI estão as funções de waiting/notifying de <atomic>, o tipo semaphore de <semaphore>, a sincronização de <syncstream>, a representação dos argumentos de std::format e de std::formatter, std::partial_ordering de <compare> e a representação de alguns adaptadores de <ranges>
  • O suporte experimental à biblioteca C++23 inclui std::mdspan, ranges::starts_with, ranges::ends_with, ranges::shift_left, ranges::shift_right e std::allocator_traits::allocate_at_least
  • O suporte experimental à biblioteca C++26 inclui std::simd, std::inplace_vector, std::optional<T&>, std::copyable_function, std::function_ref, std::indirect, std::polymorphic, std::owner_equal para shared pointer e o header <debugging>, entre outros

Suporte a targets e sistemas operacionais

  • IA-32/x86-64

    • CPUs baseadas em AMD Zen6 são suportadas com -march=znver6 e ativam AVX512_BMM, AVX_NE_CONVERT, AVX_IFMA, AVX_VNNI_INT8 e AVX512_FP16 sobre as extensões ISA já ativadas no Zen5
    • Quando o suporte a AVX512 está ativado e o tuning é znver4, znver5 ou znver6, a auto-vetorização tenta usar epílogos vetoriais mascarados para reduzir o tamanho do código e melhorar o desempenho
    • Intel Wildcat Lake é suportado com -march=wildcatlake e Intel Nova Lake com -march=novalake
      • -march=novalake ativa adicionalmente APX_F, AVX10.1, AVX10.2 e PREFETCHI sobre as extensões ISA baseadas em Panther Lake
    • A partir do GCC 16, a ativação de AMX-TRANSPOSE, USER_MSR, CLDEMOTE, KL, WIDEKL e PREFETCHI foi removida de vários switches -march=
    • -mavx10.1-256, -mavx10.1-512 e -mevex512 foram removidos, e o aviso de mudança de comportamento de -mavx10.1 também desapareceu
    • O suporte a AMX-TRANSPOSE foi removido no GCC 16, e o GCC não aceita mais -mamx-transpose
    • A nova opção de configuração --enable-x86-64-mfentry ativa -mfentry, que usa __fentry__ em vez de mcount no profiling de x86-64, e vem ativada por padrão em targets glibc
    • --enable-tls=DIALECT oferece controle do dialeto TLS padrão; o valor padrão é gnu, e os valores permitidos são gnu e gnu2 para TLS descriptor
  • AMD GPU, LoongArch, IBM z Systems

    • No offloading para AMD GPU, o overhead de lançamento de regiões target do OpenMP e regiões compute do OpenACC foi bastante reduzido
    • Foi adicionado suporte experimental ao dispositivo AMD Instinct MI300 gfx942, e também ao gfx950, compatível com gfx9-4-generic na maioria dos casos
    • O conjunto padrão de build multilib para AMD GPU mudou para gfx908, gfx90a, gfx9-generic, gfx9-4-generic, gfx10-3-generic e gfx11-generic
      • Quando há uma arquitetura genérica, multilibs para dispositivos específicos deixam de ser compilados por padrão
      • Arquiteturas genéricas exigem ROCm 6.4.0 ou superior
      • O novo conjunto padrão de multilib requer assembler e linker do LLVM 20 ou superior
      • Consulte as AMD installation notes e as configuration notes do GCC
    • LoongArch suporta tipos inteiros com precisão exata em bits, como _BitInt (N) e unsigned _BitInt (N)
    • LoongArch suporta Function Multi-Versioning com o atributo target_clones, criando versões de função por recurso de CPU e selecionando automaticamente em runtime a versão ideal
    • Foi adicionado suporte à arquitetura LoongArch32, incluindo a ABI padrão ilp32d e as ABIs ilp32f e ilp32s
      • Cobre tanto a versão padrão de 32 bits LA32 quanto a versão reduzida de 32 bits LA32R, permitindo gerar código target de 32 bits para aplicações embarcadas
      • Esse recurso depende do suporte de Binutils e glibc
    • S/390, System z e IBM z Systems suportam tipos inteiros com precisão exata em bits e o tipo de ponto flutuante _Float16
      • Operações com _Float16 são executadas via software ou com instruções float
    • Na família S/390, foi adicionado um stack protector global com -mstack-protector-guard=global para suportar o runtime patching do carregamento de endereço do canary no kernel Linux, e -mstack-protector-guard-record também foi adicionado
    • O suporte a -m31 na família S/390 foi descontinuado e será removido em uma versão futura
  • Sistemas operacionais

    • Solaris passa a oferecer suporte simplificado à geração de Solaris CTF, ou Compact C Type Format, com a opção -gsctf
    • Windows suporta TLS nativo, ou seja, Thread-Local Storage
      • Para ativar, é preciso especificar --enable-tls na configuração e usar GNU binutils 2.44 ou superior

Diagnósticos, plugins e análise estática

  • O GCC oferece suporte a saída de diagnóstico em formato HTML com -fdiagnostics-add-output=experimental-html
  • A saída SARIF segue o dump directory, e no exemplo de saída build-dir/foo.o, o GCC 16 grava o SARIF em build-dir/foo.c.sarif
    • No GCC 15, no mesmo exemplo, ele era gravado em foo.c.sarif
  • A saída SARIF captura o logical location nesting e, em muitos casos, inclui a propriedade description no objeto fix
  • A kinds property de threadFlowLocation no SARIF passa a ter os valores throw, catch, unwind, setjmp e longjmp para representar fluxos de controle não padronizados
  • Os diagnósticos do GCC podem vincular um grafo direcionado, e também é possível reportar um grafo direcionado global
    • O grafo é ignorado no text sink, mas é capturado no SARIF sink, e experimental-html o renderiza em SVG usando dot
    • Definir cfgs=yes no diagnostic sink SARIF ou HTML ativa a captura da representação intermediária do GCC para todas as funções em todos os passes de otimização
  • Os diagnósticos do GCC podem fazer referência a logical locations dentro de arquivos XML e JSON
    • A ferramenta sarif-replay usa isso para fornecer um JSON pointer ao reportar problemas de entrada SARIF
  • Se GCC_DIAGNOSTICS_LOG estiver definido no ambiente, o subsistema de diagnóstico emite um log em texto para stderr ou para um arquivo nomeado
    • Isso é usado para rastrear decisões internas, como exatamente quando e por que um diagnóstico é rejeitado
  • Se EXPERIMENTAL_SARIF_SOCKET estiver definido no ambiente, o GCC tenta se conectar ao socket durante a inicialização e envia uma notificação JSON-RPC para cada diagnóstico gerado
  • Para autores de plugins, foi adicionado um framework de publish/subscribe que transmite mensagens fortemente tipadas entre emissores e receptores fracamente acoplados
    • Nesta release, os tópicos aos quais os plugins podem se inscrever se limitam a eventos de início/fim de passes de otimização de funções específicas e a eventos relacionados ao analisador estático
  • O diagnostic sink do GCC pode ter um objeto extension com hook finalizer, e os plugins podem usá-lo para capturar informações adicionais no arquivo de saída SARIF
  • No GCC 16, a infraestrutura de diagnósticos foi amplamente reorganizada, e isso não deve afetar plugins que usam apenas diagnostic-core.h
    • Mantenedores de plugins que usam diagnósticos de forma mais complexa devem consultar o guia de portabilidade
  • O analisador estático agora lida com suporte inicial a C++ Named Return Value Optimization e exceções, podendo ser usado em exemplos simples de C++
    • Porém, por causa de problemas de escalabilidade, é bem provável que ainda seja difícil usá-lo em código C++ de produção nesta release
  • -fanalyzer assume que chamadas a funções externas sem o atributo nothrow podem lançar exceções quando -fexceptions está ativado
    • A nova opção -fanalyzer-assume-nothrow desativa essa suposição
    • Isso serve para contornar o aumento de warnings em projetos que usam -fexceptions em código C por interoperabilidade com C++, mas em que a API C usada dificilmente lançará exceções
  • As estruturas de dados da representação do código do usuário em -fanalyzer foram reescritas para facilitar o entendimento e o debugging, e a localização dos diagnósticos foi levemente melhorada
    • Em contrapartida, o uso de memória do analisador aumentou
  • As estruturas de dados de simulação de conteúdo de memória do -fanalyzer foram reimplementadas, ficando mais rápidas e mais fáceis de manter
  • O analisador passou a usar a infraestrutura value_range do GCC, eliminando alguns falsos positivos

libgdiagnostics e problemas corrigidos

1 comentários

 
GN⁺ 2 시간 전
Comentários no Hacker News
  • Quero destacar P2590R2 Explicit lifetime management como um recurso de implementação que as pessoas deveriam adotar, mas que provavelmente não será muito usado na prática
    Isso serve para std::start_lifetime_as, que é uma forma sem UB de fazer type-punning de um ponteiro para um tipo estruturado
    Quase todo código zero-copy que lida com buffers de I/O externos se parece com algo como reinterpret_cast(buffer.get()), e isso é undefined behavior; agora, se você trocar reinterpret_cast por start_lifetime_as, deixa de ser algo errado
    https://en.cppreference.com/cpp/memory/start_lifetime_as

    • Já existia uma forma legal de fazer isso, e todo mundo já deveria estar usando. Era lavar o ponteiro com um memmove no-op
      Usar reinterpret_cast aqui é um bug
      start_lifetime_as também faz mais uma coisa além de dar um nome padrão elegante para o feitiço de laundering de memória. Semanticamente ele não toca na memória, enquanto um memmove no-op essencialmente toca nela. Na prática, isso faz pouca diferença, porque o compilador consegue ver que o memmove é no-op e otimizar
    • Ignorando as restrições de alignment, depende de como read é implementado. Se isso for totalmente opaco do ponto de vista do compilador, então algo como o kernel ou a placa de rede está de fato construindo um Foo dentro daquele buffer, então o cast fica totalmente justificado
      start_lifetime_as é útil quando o lifetime do buffer é transparente para o compilador e pode quebrar as suposições de aliasing
    • A explicação da cppreference parece meio suspeita
      Parece dizer que T é um objeto novo completo, com subobjetos dentro dele, e que um deles é do tipo U. U é inicializado como em bit_cast, o que provavelmente queria dizer que ele faz cast dos bits já presentes naquele endereço. Mas obj aparece sem definição, então imagino que deva significar alguma coisa que esteja no endereço correto
      Mas o que é E não está claro. A página diz “E is the lvalue of type U denoting obj”, mas obj provavelmente seria algo como um tipo char, e se já fosse do tipo U, não haveria necessidade de bit_cast
    • Type punning com buffer de char é permitido
    • Esse código não é só ruim, ele também não está correto por causa de problemas de alignment
  • Até eu ir procurar agora há pouco, eu não sabia que o cronograma de releases do GCC era tão regular: https://gcc.gnu.org/develop.html

    • Projetos grandes já migraram há muito tempo para releases regulares
      Até os anos 90, achava-se que era possível fazer releases grandes em waterfall colocando tudo o que se queria; mas, quando o projeto cresce, sempre há alguém trabalhando em algum recurso que ainda não está pronto. Com releases regulares, ainda assim dá para entregar releases aos usuários
      Essa abordagem força os desenvolvedores cujo trabalho pode não ficar pronto a criar toggles para desativar recursos instáveis e, na prática, isso é o mais próximo do ideal
    • Os releases major recentes do GCC têm sido bem regulares, e também lembram o release de primavera do Fedora, encaixando-se num ritmo maior. A pista é Red Hat
    • Ficou assim depois que o pessoal da Cygnus reorganizou o projeto. Hoje isso segue Red Hat→IBM
    • Pelo que lembro, foi a partir da adoção da GPL3 no GCC
      Antes era mais lento, e eu perdi tempo demais contornando bugs de C++ do GCC 2.95
      O simples fato de eu ainda lembrar qual versão problemática era essa já diz muita coisa
  • Já venho usando há algum tempo. O Debian sid tem pacote do trunk
    Tem c++26 reflection, então estou fazendo algumas coisas mágicas com reflection, e em alguns casos como ser-des isso é muito melhor
    Queria apenas que houvesse um servidor LSP dentro do ecossistema

    • Ao executar os binários do GCC 16 no Debian 12 e 13, libstd está causando problemas
  • O suposto formato json de -fdiagnostics-format= foi removido nesta release, e agora dizem para usar SARIF se você precisa de diagnostics legíveis por máquina no GCC
    Mas também dizem que agora é possível gerar saída HTML de diagnostics com -fdiagnostics-add-output=experimental-html
    Fico curioso sobre o motivo por trás da decisão de remover a saída JSON e adicionar saída HTML

    • SARIF parece ser um JSON com schema formal. A saída JSON anterior aparentemente usava um schema próprio e não padronizado
  • Pergunta de iniciante: queria saber se o GCC usa LLVM internamente em algum lugar, ou se ele tem seu próprio pipeline de geração de código e otimização. Também queria saber em que nível ele está em comparação com o LLVM

    • GCC não usa LLVM
      Suporta mais targets do que o LLVM e, na maioria dos casos, gera executáveis equivalentes ou melhores
    • Respondendo em estilo Wikipédia, como já foi dito, o GCC é muito mais antigo que o LLVM
      Pela Wikipédia, o GCC é de 22 de março de 1987, enquanto o release inicial do LLVM é de 2003
      Outra grande diferença é a licença. O GCC é GPL, o LLVM usa Apache License, então os dois projetos não compartilham código
    • Não usa
    • Os “não!” das outras respostas estão certos, mas no passado houve um plugin do GCC que usava um backend do LLVM no GCC
      A Apple usou llvm-gcc por volta de 2012, durante a transição de GCC para LLVM, e isso era uma combinação do front end do GCC com o back end do LLVM
      https://dragonegg.llvm.org
    • O GCC é muito mais antigo que o LLVM, e os dois não compartilham código
  • -Ofast ainda ignora -fno-fast-math?

  • Usei o source unstable nos últimos três meses mais ou menos
    Há programas que não compilam com o GCC recente, mas funcionam bem com GCCs mais antigos, então, por enquanto, no geral o gcc 15.x está me atendendo melhor
    Ainda assim, se você compila mais de 3000 programas, a maioria funciona bem, e só alguns precisam de patches. Muitas vezes esses patches podem ser encontrados no LFS/BLFS, e corrigindo problemas pontuais com sed normalmente funciona
    Espero que esses problemas tenham sido corrigidos. Todos nós precisamos de estabilidade e de coisas que “simplesmente funcionem”

    • Você chegou a enviar relatórios de bug sobre esses problemas?