1515#include "fs/exists.h"
1616#include "fs/basename.h"
1717#include "biggestint.h"
18+ #include "clang_option.h"
1819
1920#if !(defined(OBGGCC ) || defined(PINO ))
2021 #error "Please define the cross-compiler flavor for which we will be a wrapper"
@@ -68,6 +69,7 @@ static const char GCC_OPT_STATIC_LIBLSAN[] = "-static-liblsan";
6869static const char GCC_OPT_STATIC_LIBUBSAN [] = "-static-libubsan" ;
6970static const char GCC_OPT_STATIC_LIBHWASAN [] = "-static-libhwasan" ;
7071
72+ static const char GCC_OPT_VERSION [] = "--version" ;
7173static const char GCC_OPT_L [] = "-l" ;
7274static const char GCC_OPT_V [] = "-v" ;
7375static const char GCC_OPT_D [] = "-D" ;
@@ -110,13 +112,17 @@ static const char GCC_OPT_D_CLANG_PATCHLEVEL[] = "-D__clang_patchlevel__=0";
110112static const char GCC_OPT_F_STACK_PROTECTOR [] = "-fstack-protector" ;
111113
112114static const char CLANG_OPT_OZ [] = "-Oz" ;
113- static const char CLANG_OPT_ICF [] = "--icf= " ;
115+ static const char CLANG_OPT_ICF [] = "--icf" ;
114116static const char CLANG_OPT_TARGET [] = "--target" ;
115117static const char CLANG_OPT_Q_UNUSED_ARGUMENTS [] = "-Qunused-arguments" ;
116118static const char CLANG_OPT_W_NO_UNUSED_COMMAND_LINE_ARGUMENT [] = "-Wno-unused-command-line-argument" ;
117119static const char CLANG_OPT_W_NO_INVALID_COMMAND_LINE_ARGUMENT [] = "-Wno-invalid-command-line-argument" ;
120+ static const char CLANG_OPT_W_NEWLINE_EOF [] = "-Wnewline-eof" ;
118121static const char CLANG_OPT_PRINT_RESOURCE_DIR [] = "-print-resource-dir" ;
119122static const char CLANG_OPT_F_NO_LIMIT_DEBUG_INFO [] = "-fno-limit-debug-info" ;
123+ static const char CLANG_OPT_GCC_TOOLCHAIN [] = "--gcc-toolchain" ;
124+ static const char CLANG_OPT_F_COLOR_DIAGNOSTICS [] = "-fcolor-diagnostics" ;
125+ static const char CLANG_OPT_F_NO_INTEGRATED_AS [] = "-fno-integrated-as" ;
120126
121127static const char LD_OPT_DYNAMIC_LINKER [] = "-dynamic-linker" ;
122128static const char LD_OPT_RPATH_LINK [] = "-rpath-link" ;
@@ -188,7 +194,9 @@ static const char VENDOR_UNKNOWN[] = "-unknown-";
188194
189195static const char LD_PREFIX [] = "ld." ;
190196
197+ static const char DASH = '-' ;
191198static const char EQUAL = '=' ;
199+ static const char ZERO = '\0' ;
192200static const char EQUAL_S [] = "=" ;
193201
194202static const char * const FASTER_LINKERS [] = {
@@ -197,6 +205,55 @@ static const char* const FASTER_LINKERS[] = {
197205 "gold"
198206};
199207
208+ static const char CLANG_VERSION_TEMPLATE [] =
209+ "clang version 21.0.0\n"
210+ "Target: %s\n"
211+ "Thread model: posix\n"
212+ "InstalledDir: %s\n" ;
213+
214+ static clang_option_t CLANG_SPECIFIC_REMOVE [] = {
215+ {
216+ .name = CLANG_OPT_Q_UNUSED_ARGUMENTS ,
217+ .value = 0
218+ },
219+ {
220+ .name = CLANG_OPT_W_NO_UNUSED_COMMAND_LINE_ARGUMENT ,
221+ .value = 0
222+ },
223+ {
224+ .name = CLANG_OPT_W_NO_INVALID_COMMAND_LINE_ARGUMENT ,
225+ .value = 0
226+ },
227+ {
228+ .name = CLANG_OPT_ICF ,
229+ .value = 1
230+ },
231+ {
232+ .name = CLANG_OPT_F_NO_LIMIT_DEBUG_INFO ,
233+ .value = 0
234+ },
235+ {
236+ .name = CLANG_OPT_GCC_TOOLCHAIN ,
237+ .value = 1
238+ },
239+ {
240+ .name = CLANG_OPT_W_NEWLINE_EOF ,
241+ .value = 0
242+ },
243+ {
244+ .name = CLANG_OPT_F_COLOR_DIAGNOSTICS ,
245+ .value = 0
246+ },
247+ {
248+ .name = CLANG_OPT_F_NO_INTEGRATED_AS ,
249+ .value = 0
250+ },
251+ };
252+
253+ #define CLANG_SPECIFIC_REMOVE_NON 0
254+ #define CLANG_SPECIFIC_REMOVE_CUR 1
255+ #define CLANG_SPECIFIC_REMOVE_NXT 2
256+
200257#define ERR_SUCCESS 0
201258#define ERR_MEM_ALLOC_FAILURE -1
202259#define ERR_UNKNOWN_COMPILER -2
@@ -358,36 +415,59 @@ static int clang_specific_remove(const char* const prev, const char* const cur)
358415 Remove Clang-specific options that have no GCC equivalents.
359416 */
360417
361- int status = 1 ;
418+ int status = CLANG_SPECIFIC_REMOVE_CUR ;
419+ size_t index = 0 ;
420+
421+ size_t size = 0 ;
362422
363423 const char * previous = prev ;
364424 const char * current = cur ;
365425
366- if ( strncmp ( current , GCC_OPT_WL , strlen ( GCC_OPT_WL )) == 0 ) {
367- current += strlen ( GCC_OPT_WL ) ;
368- }
426+ const char * name = cur ;
427+ int value = 0 ;
428+ const clang_option_t * option = NULL ;
369429
370- if (strcmp (current , CLANG_OPT_Q_UNUSED_ARGUMENTS ) == 0 ) {
371- goto end ;
372- }
430+ unsigned char ch = 0 ;
373431
374- if (strcmp (current , CLANG_OPT_W_NO_UNUSED_COMMAND_LINE_ARGUMENT ) == 0 ) {
375- goto end ;
432+ if (strncmp (current , GCC_OPT_WL , strlen ( GCC_OPT_WL ) ) == 0 ) {
433+ current += strlen ( GCC_OPT_WL ) ;
376434 }
377435
378- if (strcmp (current , CLANG_OPT_W_NO_INVALID_COMMAND_LINE_ARGUMENT ) == 0 ) {
436+ if (* current != DASH || * current == ZERO ) {
437+ status = CLANG_SPECIFIC_REMOVE_NON ;
379438 goto end ;
380439 }
381440
382- if (strncmp (current , CLANG_OPT_ICF , strlen (CLANG_OPT_ICF )) == 0 ) {
383- goto end ;
384- }
441+ while (* (++ current ) == DASH ) {};
385442
386- if (strcmp (current , CLANG_OPT_F_NO_LIMIT_DEBUG_INFO ) == 0 ) {
443+ for (index = 0 ; index < sizeof (CLANG_SPECIFIC_REMOVE ) / sizeof (* CLANG_SPECIFIC_REMOVE ); index ++ ) {
444+ option = & CLANG_SPECIFIC_REMOVE [index ];
445+
446+ name = option -> name ;
447+ value = option -> value ;
448+
449+ while (* (++ name ) == DASH ) {};
450+
451+ size = strlen (name );
452+
453+ if (strncmp (current , name , size ) != 0 ) {
454+ continue ;
455+ }
456+
457+ ch = current [size ];
458+
459+ if (!(ch == EQUAL || ch == ZERO )) {
460+ continue ;
461+ }
462+
463+ if (value && ch == ZERO ) {
464+ status = CLANG_SPECIFIC_REMOVE_NXT ;
465+ }
466+
387467 goto end ;
388468 }
389469
390- status = 0 ;
470+ status = CLANG_SPECIFIC_REMOVE_NON ;
391471
392472 end :;
393473
@@ -608,6 +688,7 @@ int main(int argc, char* argv[], char* envp[]) {
608688
609689 int address_sanitizer = 0 ;
610690 int stack_protector = 0 ;
691+ int version = 0 ;
611692 int verbose = 0 ;
612693 int wants_libcxx = 0 ;
613694 int wants_static_libcxx = 0 ;
@@ -757,6 +838,8 @@ int main(int argc, char* argv[], char* envp[]) {
757838 override_linker = 1 ;
758839 } else if (strncmp (cur , GCC_OPT_F_STACK_PROTECTOR , strlen (GCC_OPT_F_STACK_PROTECTOR )) == 0 ) {
759840 stack_protector = 1 ;
841+ } else if (strcmp (cur , GCC_OPT_VERSION ) == 0 ) {
842+ version = 1 ;
760843 } else if (strcmp (cur , GCC_OPT_V ) == 0 ) {
761844 verbose = 1 ;
762845 } else if (strcmp (cur , GCC_OPT_L_STDCXX ) == 0 ) {
@@ -811,16 +894,18 @@ int main(int argc, char* argv[], char* envp[]) {
811894 }
812895 }
813896 } else if (strncmp (cur , CLANG_OPT_TARGET , strlen (CLANG_OPT_TARGET )) == 0 || strncmp (cur , CLANG_OPT_TARGET + 1 , strlen (CLANG_OPT_TARGET + 1 )) == 0 ) {
814- cur + = strlen (CLANG_OPT_TARGET );
897+ size = strlen (CLANG_OPT_TARGET );
815898
816899 /* Clang has two variants of this flag: one with double hyphens, and one with a single hyphen. */
817900 if (strncmp (cur , CLANG_OPT_TARGET + 1 , strlen (CLANG_OPT_TARGET + 1 )) == 0 ) {
818- cur -= 1 ;
901+ size -- ;
819902 }
820903
904+ cur += size ;
905+
821906 ch = * cur ;
822907
823- if (!(ch == EQUAL || ch == '\0' )) {
908+ if (!(ch == EQUAL || ch == ZERO )) {
824909 goto next ;
825910 }
826911
@@ -898,10 +983,20 @@ int main(int argc, char* argv[], char* envp[]) {
898983
899984 next :;
900985
901- if (clang_specific_remove (prev , cur )) {
986+ status = clang_specific_remove (prev , cur );
987+
988+ if (status != CLANG_SPECIFIC_REMOVE_NON ) {
989+ if (status == CLANG_SPECIFIC_REMOVE_NXT ) {
990+ index ++ ;
991+ }
992+
902993 if (prev != NULL && strcmp (prev , GCC_OPT_XLINKER ) == 0 ) {
903994 prev = NULL ;
904995 kargv [-- kargc ] = (char * ) prev ;
996+
997+ if (status == CLANG_SPECIFIC_REMOVE_NXT ) {
998+ index ++ ;
999+ }
9051000 }
9061001
9071002 continue ;
@@ -1005,6 +1100,11 @@ int main(int argc, char* argv[], char* envp[]) {
10051100 }
10061101 }
10071102
1103+ if (version && known_clang (cc )) {
1104+ printf (CLANG_VERSION_TEMPLATE , DEFAULT_TARGET , parent_directory );
1105+ goto end ;
1106+ }
1107+
10081108 wants_libcxx += (strcmp (cc , GPP ) == 0 || strcmp (cc , CPP ) == 0 || strcmp (cc , GM2 ) == 0 || strcmp (cc , CLANGPP ) == 0 );
10091109
10101110 if (wants_libcxx ) {
0 commit comments