GCC 16 เปิดตัวแล้ว
(gcc.gnu.org)- รีลีสใหม่ของ GNU Compiler Collection ถือเป็นจุดเปลี่ยนสำคัญที่ เปลี่ยนมาตรฐาน C++ เริ่มต้นเป็น gnu++20 และไม่มองการรองรับ C++20 ว่าเป็นสถานะแบบ experimental อีกต่อไป
- มีการเพิ่มการรองรับฟีเจอร์ C++26 อย่าง reflection, contracts และ constexpr, ฟีเจอร์ C++23 และไลบรารี C++23·C++26 แบบ experimental อีกทั้งการวินิจฉัยข้อผิดพลาดของ template และ type trait constraint failure ก็ละเอียดขึ้นด้วย ข้อความแบบลำดับชั้น
- OpenMP และ OpenACC ขยายการรองรับ GPU memory allocation, target memset และ device memcpy API และใน front end ของ Ada·Fortran·Modula-2·Algol 68 ก็มี ฟีเจอร์ภาษาใหม่และคอมไพเลอร์เชิงทดลอง เพิ่มเข้ามา
- x86-64 รองรับ AMD Zen6, Intel Wildcat Lake และ Intel Nova Lake แล้ว และยังมีการเพิ่ม ฟีเจอร์เฉพาะเป้าหมายและการเปลี่ยนแปลง ABI ฝั่ง AMD GPU·LoongArch·IBM z Systems·Solaris·Windows ด้วย
- มีการถอดรูปแบบการวินิจฉัยแบบ JSON ออก พร้อมเสริม SARIF·HTML diagnostics, ปรับปรุง static analyzer และเพิ่ม 37 entrypoint ใน libgdiagnostics ทำให้ การเชื่อมต่อกับเครื่องมือและโครงสร้างพื้นฐานด้านการวินิจฉัย กว้างขึ้นมาก
การเปลี่ยนแปลงด้านความเข้ากันได้และการปรับปรุงทั่วไป
- บน Solaris ค่าอย่าง
int8_tเป็นต้น ได้เปลี่ยนเป็นsigned charเพื่อให้สอดคล้องกับมาตรฐาน C99 ซึ่งเป็นการเปลี่ยนแปลงที่ไม่เข้ากันย้อนหลัง- ดูรายละเอียดได้ใน หัวข้อ Solaris ของ Porting to GCC 16
- บน Solaris ตัวเลือก
-pthreadจะไม่ predefine_REENTRANTอีกต่อไป- ดูรายละเอียดได้ใน หัวข้อ Solaris ของ Porting to GCC 16
- รูปแบบ
jsonของ-fdiagnostics-format=ถูกถอดออกแล้ว และควรใช้ SARIF สำหรับการวินิจฉัยที่เครื่องอ่านได้ - Link-Time Optimization จัดการคำสั่ง asm ระดับบนสุดได้ดีขึ้นด้วย
-flto-toplevel-asm-heuristics - speculative devirtualization รองรับการจัดการ indirect function call ทั่วไป และรองรับการคาดเดาปลายทางได้มากกว่าหนึ่งรายการ
- vectorizer มีความยืดหยุ่นมากขึ้นในการระบุ loop-invariant parallelism ของ reduction และรองรับการทำเวกเตอร์ไรซ์กับลูปที่ไม่ทราบจำนวนรอบการทำซ้ำและ uncounted loop
- ยังรองรับการ peeling เพื่อจัดแนวของ vector length agnostic loop ที่ใช้ masking, mutual peeling for alignment และการตัดการคำนวณ vector induction ของลูปแบบ early break ด้วย
- GCC Command Options และ option index ได้รับการแก้ไขให้ครอบคลุมตัวเลือกจำนวนมากที่ก่อนหน้านี้ตกหล่น
- เอกสาร GCC-specific attributes ถูกปรับให้ทันสมัย โดยเน้นรูปแบบ standard attribute syntax ที่ GCC อนุญาตในทุก C/C++ dialect ที่รองรับมากขึ้น
- เนื้อหาเกี่ยวกับ attribute ถูกจัดโครงสร้างใหม่เพื่อลดความซ้ำซ้อน และมีการเพิ่ม attribute index ใหม่
- เอกสาร parameter และ option spec file ถูกย้ายไปยัง GCC internals manual สำหรับนักพัฒนา GCC และผู้ใช้ที่ต้องการคอนฟิก GCC แบบกำหนดเอง
การเปลี่ยนแปลงสำคัญแยกตามภาษา
-
OpenMP และ OpenACC
- มีการเสริมการรองรับการจัดสรรหน่วยความจำของ OpenMP โดย
pinnedtrait allocator และompx_gnu_pinned_mem_allocจะใช้ CUDA API เมื่อใช้งานได้ และช่วยปรับปรุงประสิทธิภาพการเข้าถึงหน่วยความจำดังกล่าวบน Nvidia GPU - allocator
ompx_gnu_managed_mem_allocและompx_gnu_managed_mem_spaceซึ่งเป็น GNU extension จะจัดสรรหน่วยความจำที่อุปกรณ์สามารถเข้าถึงได้จาก host- อุปกรณ์ยังสามารถเข้าถึงได้แม้ไม่รองรับ unified-shared memory และแม้ในระบบที่หน่วยความจำทั้งหมดของ host สามารถเข้าถึงได้จากอุปกรณ์ พฤติกรรม page-migration ก็อาจแตกต่างจากหน่วยความจำประเภทอื่น
- OpenMP 5.0 เพิ่มการรองรับ
declare mapperแบบจำกัดใน C/C++ และ clauseuses_allocatorsครอบคลุมทั้งการเปลี่ยนไวยากรณ์ของ OpenMP 5.2 และการรองรับ semicolon ของ OpenMP 6.0 - OpenMP 5.1 เพิ่มการรองรับเบื้องต้นของตัวแก้ไข
iteratorสำหรับ map clause และtarget updateconstruct ใน C/C++ - OpenMP 5.2 รองรับ directive
begin declare variantใน C/C++ - OpenMP 6.0 เพิ่ม API routine
omp_target_memsetและomp_target_memset_asyncและยังสามารถใช้ assumptions clauseno_openmp_constructsได้ด้วย - directive และ clause ที่ถูก deprecated ใน OpenMP 5.0, 5.1 และ 5.2 จะมี deprecation warning ตามค่าเริ่มต้น และปิดได้ด้วย
-Wno-deprecated-openmp- การใช้ named constant หรือ API routine ที่ deprecated ก็จะมี warning เช่นกัน และปิดได้ด้วย
-Wno-deprecated-declarations
- การใช้ named constant หรือ API routine ที่ deprecated ก็จะมี warning เช่นกัน และปิดได้ด้วย
- OpenACC เพิ่ม API routine
acc_memcpy_deviceและacc_memcpy_device_asyncสำหรับ C/C++/Fortran - directive
waitของ OpenACC 3.0 รับifclause ได้ และ API routine ของ Fortran ใน OpenACC 3.3 คือacc_attachและacc_detachจะมาเสริม counterpart ฝั่ง C/C++ ของ OpenACC 2.6 - ใน OpenACC 3.4 สามารถใช้ named constant
PARAMETERใน Fortran data clause ได้ทั้งตามสเปกและใน GCC แต่ใน GCC จะไม่ส่งผลต่อพฤติกรรมตอน compile-time และ runtime
- มีการเสริมการรองรับการจัดสรรหน่วยความจำของ OpenMP โดย
-
Ada, Fortran, Modula-2, Algol 68
- มีการเพิ่ม Constructor และ Destructor ให้กับ Ada GNAT extension ทำให้มีกลไก construction/finalization ที่แตกต่างจาก Ada มาตรฐานอย่างมาก
- มีการเพิ่ม aspect ของ Ada ได้แก่ Implicit with, Structural Generic instantiation, และ Extended_Access
Extended_Accessสามารถระบุใน general access type declaration ที่ชี้ไปยัง unconstrained array subtype ได้ โดยจะเปลี่ยน pointer representation และช่วยให้ Ada ทำงานร่วมกับ foreign language เพื่อจัดการหน่วยความจำที่ Ada ไม่ได้จัดสรรได้ง่ายขึ้น
- Ada สามารถใช้ VAST สำหรับการดีบักคอมไพเลอร์ได้ด้วย
-gnatd_Vหรือ-gnatd_Wใน verbose mode และยังมีการปรับปรุง semantic analysis ของ Ada 2022 Reduction Expressions,Ada.Containers.Bounded_Indefinite_Holders, การติดตั้ง accessibility rule และการรองรับ Android - Fortran รองรับ coarray ที่ใช้ native shared memory multithreading บนเครื่อง single node และฟีเจอร์
TEAMของ Fortran 2018 - มีการปรับปรุงการรองรับ Parameterized Derived Types ของ Fortran 2003 และแม้การจัดการ LEN parameter จะทำงานได้ แต่ยังต้องมีการเปลี่ยน representation ในอนาคตตาม PR82649
- Fortran 2018 รองรับส่วนขยายของ
IMPORTstatement, intrinsicREDUCEและGENERICstatement ใหม่ - Fortran 2023 รองรับส่วนเพิ่มของฟังก์ชันตรีโกณมิติอย่าง
sinpi, intrinsic subroutinesplitและc_f_pointerที่รับ optional lower bound เป็นอาร์กิวเมนต์ - ตัวเลือก
-fexternal-blas64จะเรียก external BLAS routine จากMATMULด้วยอาร์กิวเมนต์จำนวนเต็ม 64-bit และใช้ได้เฉพาะบนระบบ 64-bit เมื่อใช้-ffrontend-optimize - Modula-2 จะแสดง spelling hint ระหว่างการจัดการ import list, ชื่อโมดูล และสัญลักษณ์ใน nested scope และเพิ่มการใช้งาน wide set แบบใหม่พร้อม library module
M2WIDESET- การเปลี่ยนแปลงของ wide set นี้เปลี่ยน ABI และอาจทำให้เกิด link-time error กับ object file จาก GCC เวอร์ชันก่อนหน้า
- มีการเพิ่มโมดูลพจนานุกรมไบนารี
BinDictในไลบรารีพื้นฐานของ Modula-2 พร้อมทั้งมี procedureWriteและWriteLnให้ในหลายโมดูล และปรับปรุงการเข้าถึง external library module ด้วยตัวเลือก-fm2-pathname-root= - GCC รวม
ga68ซึ่งเป็นคอมไพเลอร์ Algol 68 แบบ experimental ไว้ด้วย โดยมีเป้าหมายเพื่ออิมพลีเมนต์ Revised Report และ errata ที่ได้รับการอนุมัติจาก IFIP WG2.1 Algol 68 Support subcommittee- มีการอิมพลีเมนต์ GNU extension บางส่วนและ POSIX prelude ด้วย โดยข้อมูลภาษาอยู่ที่ Algol 68 website และข้อมูล front end ดูได้ที่ wiki
C++ และ libstdc++
- เวอร์ชันภาษาปริยายของการคอมไพล์ C++ เปลี่ยนจาก -std=gnu++17 เป็น -std=gnu++20
- โค้ดที่อาศัยมาตรฐาน C++ รุ่นก่อนหน้าต้องเพิ่ม -std= ใน build flag หรือพอร์ตโค้ด และดู porting notes
- การรองรับ C++20 modules ยังเป็น experimental และต้องเปิดใช้ด้วย -fmodules
- ฟีเจอร์ C++26 มีการนำมาใช้งานแล้วหลายรายการ เช่น reflection, annotations for reflection, base class subobject splicing, function parameter reflection, contracts, constexpr exceptions, constexpr virtual inheritance เป็นต้น
- P2996R13 Reflection เปิดใช้งานได้ด้วย
-std=c++26 -freflection - P2686R4 บางส่วนรองรับแบบบางส่วน โดย structured binding สามารถเป็น
constexprได้ แต่การอ้างอิงconstexprautomatic variable ยังไม่อนุญาต
- P2996R13 Reflection เปิดใช้งานได้ด้วย
- ฟีเจอร์ C++23 ที่ถูกนำมาใช้งานแล้วได้แก่ P2036R3, P2590R2, P2246R1
- ข้อความ error ของ C++ มี โครงสร้างแบบลำดับชั้น สำหรับปัญหาที่เกี่ยวข้องกับ template เป็นต้น โดยใช้ indentation และ bullet point เพื่อแสดงการซ้อนของข้อความ
- สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วย
-fno-diagnostics-show-nestingหรือ-fdiagnostics-plain-output
- สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วย
- การรองรับ experimental C++20 modules จะเพิ่มตัวเลือก
--compile-std-moduleเพื่อ build<bits/stdc++.h>header unit และโมดูลstd,std.compatก่อนคอมไพล์ source file- หากมีการ build
<bits/stdc++.h>header unit แล้ว#includeของ standard library header ที่ import ได้จะถูกแปลงแบบโปร่งใสเป็นการ import<bits/stdc++.h> - มีการแก้ไขบั๊กที่มีการรายงานไว้จำนวนมาก
- หากมีการ build
- constraint failure diagnostics ของ standard library type trait จะบอกรายละเอียดมากขึ้นว่าเหตุใด
is_constructible_v,is_invocable_vเป็นต้น จึงเป็นfalse - ใน libstdc++ target ที่รองรับ 128-bit integer จะทำให้
std::is_integral<__int128>และ trait ที่คล้ายกันเป็น true เสมอ- ก่อนหน้านี้ใน GNU dialect จะเป็น true แต่ใน strict dialect จะไม่เป็นเช่นนั้น
- P0952R2: A new specification for
std::generate_canonicalถูกนำมาใช้งานในทุกโหมดที่ได้รับผลกระทบตั้งแต่ C++11 เป็นต้นมา และส่งผลต่อ output ที่สังเกตได้- สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วยการกำหนด
_GLIBCXX_USE_OLD_GENERATE_CANONICAL
- สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วยการกำหนด
- ABI ของ
std::variantถูกอัปเดตให้สอดคล้องกับโหมด C++20 ขึ้นไป และส่งผลต่อ class layout ของบางกรณีในโหมด C++17- สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วยการกำหนด
_GLIBCXX_USE_VARIANT_CXX17_OLD_ABIและผลกระทบนี้มีเฉพาะในโหมด C++17 เท่านั้น
- สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วยการกำหนด
- การทำงานของ
std::regexถูกเขียนใหม่ให้ใช้ stack แบบอิง heap แทน system stack เพื่อหลีกเลี่ยง stack overflow ระหว่างการจับคู่ string ที่มีขนาดใหญ่ขึ้น - การรองรับ C++20 ไม่ถือเป็น experimental อีกต่อไปแล้ว และ
std::chrono::current_zone()ทำงานได้บน Windows - เนื่องจากการรองรับ C++20 ก่อน GCC 16 ยังเป็น experimental จึงควรถือว่าโปรแกรมที่ใช้คอมโพเนนต์ C++20 จะไม่เข้ากันกับรุ่นเก่า
- รายการที่มีการเปลี่ยนแปลง ABI ได้แก่ฟังก์ชัน waiting/notifying ใน
<atomic>, ชนิด semaphore ใน<semaphore>, synchronization ใน<syncstream>, อาร์กิวเมนต์ของstd::formatและ representation ของstd::formatter,std::partial_orderingใน<compare>, รวมถึง representation ของ adaptor บางตัวใน<ranges>
- รายการที่มีการเปลี่ยนแปลง ABI ได้แก่ฟังก์ชัน waiting/notifying ใน
- การรองรับไลบรารี C++23 แบบ experimental ครอบคลุม
std::mdspan,ranges::starts_with,ranges::ends_with,ranges::shift_left,ranges::shift_right,std::allocator_traits::allocate_at_least - การรองรับไลบรารี C++26 แบบ experimental ครอบคลุม
std::simd,std::inplace_vector,std::optional<T&>,std::copyable_function,std::function_ref,std::indirect,std::polymorphic,std::owner_equalสำหรับ shared pointer, และ header<debugging>เป็นต้น
การรองรับเป้าหมายและระบบปฏิบัติการ
-
IA-32/x86-64
- CPU ที่อิง AMD Zen6 รองรับด้วย
-march=znver6และจะเปิดใช้ AVX512_BMM, AVX_NE_CONVERT, AVX_IFMA, AVX_VNNI_INT8, AVX512_FP16 เพิ่มเติมจาก ISA extension ที่เปิดใช้งานใน Zen5 - เมื่อเปิดการรองรับ AVX512 และมีการ tuning เป็น
znver4,znver5,znver6การทำ auto-vectorization จะพยายามใช้ masked vector epilog เพื่อลดขนาดโค้ดและปรับปรุงประสิทธิภาพ - Intel Wildcat Lake รองรับด้วย
-march=wildcatlakeและ Intel Nova Lake รองรับด้วย-march=novalake-march=novalakeจะเปิดใช้ APX_F, AVX10.1, AVX10.2, PREFETCHI เพิ่มเติมจาก ISA extension ที่อิง Panther Lake
- ตั้งแต่ GCC 16 เป็นต้นไป ได้ยกเลิกการเปิดใช้ AMX-TRANSPOSE, USER_MSR, CLDEMOTE, KL, WIDEKL, PREFETCHI ในหลาย
-march=switch -mavx10.1-256,-mavx10.1-512,-mevex512ถูกถอดออก และคำเตือนการเปลี่ยนพฤติกรรมของ-mavx10.1ก็หายไปด้วย- การรองรับ AMX-TRANSPOSE ถูกถอดออกใน GCC 16 และ GCC จะไม่รับ
-mamx-transposeอีกต่อไป - configure option ใหม่
--enable-x86-64-mfentryจะเปิดใช้-mfentryซึ่งใช้__fentry__แทนmcountสำหรับการทำ profiling บน x86-64 และจะเปิดเป็นค่าเริ่มต้นบน glibc target --enable-tls=DIALECTรองรับการควบคุม TLS dialect เริ่มต้น โดยค่าเริ่มต้นคือgnuและค่าที่อนุญาตคือgnuกับgnu2สำหรับ TLS descriptor
- CPU ที่อิง AMD Zen6 รองรับด้วย
-
AMD GPU, LoongArch, IBM z Systems
- overhead ในการ launch ของ OpenMP target region และ OpenACC compute region บน AMD GPU offloading ลดลงอย่างมาก
- เพิ่มการรองรับแบบ experimental สำหรับอุปกรณ์ AMD Instinct MI300
gfx942และรวมถึงgfx950ที่เข้ากันได้กับ genericgfx9-4-genericเป็นส่วนใหญ่ - ชุด multilib build เริ่มต้นของ AMD GPU เปลี่ยนเป็น
gfx908,gfx90a,gfx9-generic,gfx9-4-generic,gfx10-3-generic,gfx11-generic- หากมี generic arch แล้ว จะไม่ build multilib สำหรับอุปกรณ์เฉพาะเป็นค่าเริ่มต้นอีกต่อไป
- generic architecture ต้องใช้ ROCm 6.4.0 ขึ้นไป
- ชุด multilib เริ่มต้นใหม่ต้องใช้ assembler และ linker ของ LLVM 20 ขึ้นไป
- ดู AMD installation notes และ configuration notes ของ GCC
- LoongArch รองรับ bit-precise integer type เช่น
_BitInt (N)และunsigned _BitInt (N) - LoongArch รองรับ Function Multi-Versioning ผ่าน attribute
target_clonesเพื่อสร้าง function version ตาม CPU feature และเลือกเวอร์ชันที่เหมาะสมที่สุดโดยอัตโนมัติขณะ runtime - เพิ่มการรองรับสถาปัตยกรรม LoongArch32 โดยมี ABI เริ่มต้นเป็น
ilp32dและรวม ABIilp32f,ilp32s- ครอบคลุมทั้ง LA32 ซึ่งเป็นเวอร์ชัน 32-bit มาตรฐาน และ LA32R ซึ่งเป็นเวอร์ชัน 32-bit แบบลดรูป ทำให้สามารถสร้าง target code แบบ 32-bit สำหรับ embedded application ได้
- ความสามารถนี้ขึ้นอยู่กับการรองรับจาก Binutils และ glibc
- S/390, System z, IBM z Systems รองรับ bit-precise integer type และ floating-point type แบบ
_Float16- การทำงานของ
_Float16จะดำเนินการด้วยซอฟต์แวร์หรือคำสั่งfloat
- การทำงานของ
- ในตระกูล S/390 ได้เพิ่ม global stack protector สำหรับรองรับ runtime patching ของ Linux kernel สำหรับการโหลด canary address ด้วย
-mstack-protector-guard=globalและเพิ่ม-mstack-protector-guard-recordด้วย - การรองรับ
-m31ในตระกูล S/390 ถูกประกาศเลิกใช้แล้ว และจะถูกถอดออกในรีลีสถัดไป
-
ระบบปฏิบัติการ
- Solaris รองรับการสร้าง Solaris CTF หรือ Compact C Type Format ได้สะดวกผ่านตัวเลือก
-gsctf - Windows รองรับ native TLS หรือ Thread-Local Storage
- หากต้องการเปิดใช้ ต้องระบุ
--enable-tlsตอน configure และใช้ GNU binutils 2.44 ขึ้นไป
- หากต้องการเปิดใช้ ต้องระบุ
- Solaris รองรับการสร้าง Solaris CTF หรือ Compact C Type Format ได้สะดวกผ่านตัวเลือก
การวินิจฉัย, ปลั๊กอิน, การวิเคราะห์แบบสถิต
- GCC รองรับเอาต์พุตการวินิจฉัยในรูปแบบ HTMLด้วย
-fdiagnostics-add-output=experimental-html - เอาต์พุต SARIF จะอ้างอิงตาม dump directory และในตัวอย่างเอาต์พุต
build-dir/foo.oนั้น GCC 16 จะเขียน SARIF ไปที่build-dir/foo.c.sarif- ในตัวอย่างเดียวกัน GCC 15 เขียนไปที่
foo.c.sarif
- ในตัวอย่างเดียวกัน GCC 15 เขียนไปที่
- เอาต์พุต SARIF จะเก็บ logical location nesting และในหลายกรณีจะมี
descriptionproperty อยู่ในfixobject kindsproperty ของ SARIFthreadFlowLocationได้เพิ่มค่าthrow,catch,unwind,setjmp,longjmpสำหรับการแสดง control flow ที่ไม่เป็นมาตรฐาน- GCC diagnostics สามารถเชื่อม directed graph ได้ และยังสามารถรายงาน global directed graph ได้ด้วย
- graph จะถูกละเลยใน text sink แต่จะถูกเก็บใน SARIF sink และ
experimental-htmlจะเรนเดอร์เป็นแบบ SVG โดยใช้ dot - หากตั้งค่า
cfgs=yesใน SARIF หรือ HTML diagnostic sink จะเปิดใช้งานการเก็บ GCC intermediate representation ของทุกฟังก์ชันในทุก optimization pass
- graph จะถูกละเลยใน text sink แต่จะถูกเก็บใน SARIF sink และ
- GCC diagnostics สามารถอ้างอิง logical location ภายในไฟล์ XML และ JSON ได้
- เครื่องมือ
sarif-replayใช้สิ่งนี้เพื่อให้ JSON pointer เมื่อรายงานปัญหาจาก SARIF input
- เครื่องมือ
- หากตั้งค่า
GCC_DIAGNOSTICS_LOGไว้ใน environment ระบบย่อยการวินิจฉัยจะส่งออก text log ไปยัง stderr หรือไฟล์ที่ระบุชื่อไว้- ใช้เพื่อติดตามการตัดสินใจภายใน เช่น การ reject diagnostic ว่าเกิดขึ้นเมื่อใดและเพราะเหตุใด
- หากตั้งค่า
EXPERIMENTAL_SARIF_SOCKETไว้ใน environment GCC จะพยายามเชื่อมต่อกับ socket ดังกล่าวตอนเริ่มต้น และส่ง JSON-RPC notification สำหรับ diagnostic ทุกตัวที่เกิดขึ้น - สำหรับผู้เขียนปลั๊กอิน มีการเพิ่มเฟรมเวิร์กแบบ publish/subscribe สำหรับส่งต่อข้อความแบบ strongly-typed ระหว่าง sender และ receiver ที่ loosely-coupled
- ในรีลีสนี้ topic ที่ปลั๊กอินสามารถ subscribe ได้มีเพียง event เริ่ม/หยุดของ optimization pass ของฟังก์ชันที่กำหนด และ event ที่เกี่ยวข้องกับ static analyzer
- GCC diagnostic sink สามารถมี
extensionobject ที่มีfinalizerhook ได้ และปลั๊กอินสามารถใช้สิ่งนี้เพื่อเก็บข้อมูลเพิ่มเติมลงในไฟล์เอาต์พุต SARIF - ใน GCC 16 มีการจัดระเบียบ diagnostic machinery ครั้งใหญ่ และไม่ควรส่งผลกระทบต่อปลั๊กอินที่ใช้เพียง
diagnostic-core.h- ผู้ดูแลปลั๊กอินที่ใช้งาน diagnostics แบบซับซ้อนกว่านี้ควรดู porting guide
- Static analyzer รองรับการทำงานกับ C++ Named Return Value Optimization และการรองรับ exception ขั้นต้น ทำให้ใช้งานได้กับ simple C++ example
- แต่เนื่องจากปัญหาเรื่อง scaling จึงมีแนวโน้มว่ายังใช้งานกับ production C++ code ได้ยากในรีลีสนี้
-fanalyzerจะถือว่า external function call ที่ไม่มีnothrowattribute อาจ throw exception ได้เมื่อเปิดใช้-fexceptions- ตัวเลือกใหม่
-fanalyzer-assume-nothrowใช้ปิดสมมติฐานนี้ - มีไว้เพื่อหลีกเลี่ยง warning ที่เพิ่มขึ้นในโปรเจกต์ที่ใช้
-fexceptionsกับโค้ด C เพื่อการทำงานร่วมกับ C++ แต่ C API ที่ใช้งานอยู่มีโอกาส throw exception ต่ำ
- ตัวเลือกใหม่
- โครงสร้างข้อมูล representation ของ user code ใน
-fanalyzerถูกเขียนใหม่เพื่อให้เข้าใจและ debug ได้ง่ายขึ้น และปรับปรุง diagnostic location เล็กน้อย- แต่แลกมากับการใช้หน่วยความจำของ analyzer ที่เพิ่มขึ้น
- โครงสร้างข้อมูลสำหรับ simulation เนื้อหาหน่วยความจำของ
-fanalyzerถูกนำไป implement ใหม่ ทำให้เร็วขึ้นและดูแลรักษาง่ายขึ้น - analyzer เริ่มใช้
value_rangemachinery ของ GCC แล้ว จึงช่วยกำจัด false positive บางส่วน
libgdiagnostics และปัญหาที่แก้ไขแล้ว
- libgdiagnostics ได้รับ entrypoint ใหม่ทั้งหมด 37 รายการ
- เพิ่ม entrypoint 5 รายการสำหรับการทำงานกับ logical location
- เพิ่ม entrypoint 2 รายการสำหรับตัวเลือก command-line และการรองรับ SARIF playback
- เพิ่ม entrypoint 12 รายการสำหรับการทำงานกับ directed graph เพื่อรองรับการสร้าง graph, การส่งผ่าน global graph, การเชื่อมต่อ diagnostic graph, การเพิ่มและค้นหา node กับ edge, และการตั้งค่า label กับ location ของ node
- เพิ่ม entrypoint 17 รายการสำหรับประกอบ diagnostic text เป็น buffer
- รวมถึงการสร้างและปล่อย message buffer, การ append string/text/byte/printf, การ append event id, การจัดการช่วง URL/quote/color, การ dump, และการ finish diagnostic แบบอิง buffer พร้อมการเพิ่ม location label/event
- เพิ่ม
diagnostic_manager_set_debug_physical_locations()ด้วย - สามารถดูรายการ problem report ที่ระบบติดตามบั๊กของ GCC ระบุว่า fixed ในรีลีส 16.1 ได้ที่ PR list
- รายการดังกล่าวอาจไม่สมบูรณ์ และอาจมี PR บางส่วนที่แก้ไขแล้วแต่ไม่ได้ถูกรวมไว้
1 ความคิดเห็น
ความเห็นจาก Hacker News
อยากชี้ไปที่ P2590R2 Explicit lifetime management ว่าเป็นฟีเจอร์ที่คนควรนำไปใช้ แต่ในความเป็นจริงน่าจะไม่ได้ถูกใช้กันมากนัก
มันมีไว้สำหรับ
std::start_lifetime_asซึ่งเป็นวิธี ที่ไม่เป็น UB ในการ type-pun พอยน์เตอร์ให้เป็นชนิดข้อมูลแบบมีโครงสร้างโค้ด zero-copy เกือบทั้งหมดที่จัดการ external I/O buffer มักมีหน้าตาประมาณ
reinterpret_cast(buffer.get())และนั่นคือ undefined behavior แต่ตอนนี้ถ้าเปลี่ยนจากreinterpret_castเป็นstart_lifetime_asก็จะไม่ใช่สิ่งที่ผิดอีกต่อไปhttps://en.cppreference.com/cpp/memory/start_lifetime_as
การใช้
reinterpret_castตรงนี้ถือเป็นบั๊กstart_lifetime_asไม่ได้แค่ตั้งชื่อมาตรฐานที่ดูเรียบร้อยให้กับคาถา laundering หน่วยความจำเท่านั้น แต่ยังทำเพิ่มอีกอย่างด้วย คือในเชิงความหมายแล้วมันไม่แตะต้องหน่วยความจำ ขณะที่ no-opmemmoveโดยเนื้อแท้ยังถือว่าแตะหน่วยความจำอยู่ แม้ในทางปฏิบัติความต่างจะไม่มาก เพราะคอมไพเลอร์มักมองออกว่าmemmoveเป็น no-op และ optimize ทิ้งได้readถ้าจากมุมมองของคอมไพเลอร์มัน opaque อย่างสมบูรณ์ ก็อาจมองได้ว่าเคอร์เนลหรือการ์ดเครือข่ายเป็นผู้สร้างFooขึ้นมาจริง ๆ ภายในบัฟเฟอร์นั้น ทำให้ cast ดังกล่าวสมเหตุสมผลเต็มที่start_lifetime_asมีประโยชน์เมื่อ lifetime ของบัฟเฟอร์โปร่งใสต่อคอมไพเลอร์ จนไปทำลายสมมติฐานเกี่ยวกับ aliasing ได้มันดูเหมือนจะหมายความว่า
Tเป็นอ็อบเจ็กต์ใหม่ที่สมบูรณ์ มี subobject อยู่ภายใน และหนึ่งในนั้นมีชนิดเป็นUโดยUจะถูก initialize แบบbit_castซึ่งน่าจะตั้งใจสื่อว่ามัน cast จากบิตที่มีอยู่แล้ว ณ ตำแหน่งนั้น แต่objโผล่มาโดยไม่มีนิยาม จึงน่าจะต้องตีความว่าหมายถึงบางสิ่งที่อยู่ที่ address ที่ถูกต้องแต่สิ่งที่กำกวมคือ E คืออะไร หน้าเว็บบอกว่า “E is the lvalue of type U denoting obj” ซึ่ง
objน่าจะเป็นชนิดอย่างcharและถ้ามันเป็นUอยู่แล้วก็คงไม่ต้องใช้bit_castcharได้เพิ่งมารู้ก่อนหน้านี้ไม่นานว่า รอบการออกรุ่นของ GCC มีความสม่ำเสมอขนาดนี้: https://gcc.gnu.org/develop.html
ย้อนกลับไปถึงยุค 90 ผู้คนยังคิดว่าสามารถทำรีลีสใหญ่แบบ waterfall โดยยัดฟีเจอร์ที่ต้องการทั้งหมดเข้าไปได้ แต่พอโปรเจ็กต์ใหญ่ขึ้น จะมีคนที่กำลังทำฟีเจอร์ซึ่งยังไม่พร้อมอยู่เสมอ ถ้ามีการออกรุ่นเป็นประจำ อย่างน้อยก็ยังส่งมอบรีลีสให้ลูกค้าได้
วิธีนี้บังคับให้นักพัฒนาที่ยังไม่แน่ใจว่าฟีเจอร์จะพร้อมหรือไม่ ต้องทำ toggle สำหรับปิดฟีเจอร์ที่ยังไม่เสถียร ซึ่งในโลกความเป็นจริงก็นับว่าใกล้เคียงกับวิธีที่ดีที่สุดแล้ว
ก่อนหน้านั้นช้ากว่านี้มาก และผมเสียเวลาไปเยอะกับการหาทางเลี่ยงบั๊ก C++ ของ GCC 2.95
แค่ยังจำเวอร์ชันเจ้าปัญหานั้นได้ก็บอกอะไรได้เยอะแล้ว
ผมใช้มันมาสักพักแล้ว Debian sid มีแพ็กเกจ trunk
มันมี
c++26 reflectionด้วย เลยได้ทำอะไรแนวเวทมนตร์กับ reflection อยู่บ้าง และในบางกรณี เช่น ser-des นั้นดีกว่ามากถ้ามี LSP server ใน ecosystem ด้วยก็คงดี
libstdกำลังก่อปัญหาอยู่ฟอร์แมตที่เรียกว่า
jsonของ-fdiagnostics-format=ถูกถอดออกในรีลีสนี้ และบอกว่าถ้าต้องการ diagnostics แบบ machine-readable จาก GCC ให้ใช้ SARIFแต่ขณะเดียวกันก็เพิ่มความสามารถให้ส่งออก diagnostics เป็น HTML ได้ด้วย
-fdiagnostics-add-output=experimental-htmlเลยสงสัยว่าเบื้องหลังการตัดสินใจลบ JSON output แต่เพิ่ม HTML output คืออะไร
ขอถามแบบมือใหม่หน่อยว่า GCC ใช้ LLVM ภายในตรงไหนบ้างไหม หรือว่ามี code generation กับ optimization pipeline ของตัวเองทั้งหมด และถ้าเทียบกับ LLVM แล้วอยู่ระดับไหน
มันรองรับ target ได้มากกว่า LLVM และในกรณีส่วนใหญ่ก็สร้าง executable ที่ใกล้เคียงกันหรือดีกว่า
ตาม Wikipedia, GCC คือวันที่ 22 มีนาคม 1987 ส่วน LLVM รุ่นแรกคือปี 2003
อีกความต่างใหญ่คือเรื่องไลเซนส์ GCC เป็น GPL ส่วน LLVM เป็น Apache License ดังนั้นสองโปรเจ็กต์นี้จึงไม่แชร์โค้ดกัน
Apple เคยใช้
llvm-gccราวปี 2012 ตอนที่กำลังเปลี่ยนจาก GCC ไป LLVM ซึ่งเป็นการจับคู่ GCC front end เข้ากับ LLVM back endhttps://dragonegg.llvm.org
-Ofastยังเมิน-fno-fast-mathอยู่หรือเปล่า?ช่วงประมาณ 3 เดือนที่ผ่านมา ผมลองใช้ ซอร์ส unstable
มีบางโปรแกรมที่คอมไพล์ด้วย GCC รุ่นล่าสุดไม่ได้ แต่กลับใช้ GCC รุ่นเก่าได้ดี ดังนั้นตอนนี้โดยรวมแล้ว
gcc 15.xยังเหมาะกับผมมากกว่าถึงอย่างนั้นถ้าดูว่าคอมไพล์โปรแกรมไปมากกว่า 3000 ตัว ส่วนใหญ่ก็ผ่านได้ดี และมีเพียงบางตัวที่ต้องแพตช์ ซึ่งแพตช์แบบนั้นมักหาได้จาก LFS/BLFS และถ้าแก้ปัญหาเฉพาะหน้าด้วย
sedก็มักจะใช้งานได้หวังว่าปัญหาเหล่านั้นจะถูกแก้แล้ว เพราะพวกเราทุกคนต้องการความเสถียรและความรู้สึกว่า “มันใช้งานได้เลย”