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,16 @@ 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" ;
120125
121126static const char LD_OPT_DYNAMIC_LINKER [] = "-dynamic-linker" ;
122127static const char LD_OPT_RPATH_LINK [] = "-rpath-link" ;
@@ -188,7 +193,9 @@ static const char VENDOR_UNKNOWN[] = "-unknown-";
188193
189194static const char LD_PREFIX [] = "ld." ;
190195
196+ static const char DASH = '-' ;
191197static const char EQUAL = '=' ;
198+ static const char ZERO = '\0' ;
192199static const char EQUAL_S [] = "=" ;
193200
194201static const char * const FASTER_LINKERS [] = {
@@ -197,6 +204,51 @@ static const char* const FASTER_LINKERS[] = {
197204 "gold"
198205};
199206
207+ static const char CLANG_VERSION_TEMPLATE [] =
208+ "clang version 21.0.0\n"
209+ "Target: %s\n"
210+ "Thread model: posix\n"
211+ "InstalledDir: %s\n" ;
212+
213+ static clang_option_t CLANG_SPECIFIC_REMOVE [] = {
214+ {
215+ .name = CLANG_OPT_Q_UNUSED_ARGUMENTS ,
216+ .value = 0
217+ },
218+ {
219+ .name = CLANG_OPT_W_NO_UNUSED_COMMAND_LINE_ARGUMENT ,
220+ .value = 0
221+ },
222+ {
223+ .name = CLANG_OPT_W_NO_INVALID_COMMAND_LINE_ARGUMENT ,
224+ .value = 0
225+ },
226+ {
227+ .name = CLANG_OPT_ICF ,
228+ .value = 1
229+ },
230+ {
231+ .name = CLANG_OPT_F_NO_LIMIT_DEBUG_INFO ,
232+ .value = 0
233+ },
234+ {
235+ .name = CLANG_OPT_GCC_TOOLCHAIN ,
236+ .value = 1
237+ },
238+ {
239+ .name = CLANG_OPT_W_NEWLINE_EOF ,
240+ .value = 0
241+ },
242+ {
243+ .name = CLANG_OPT_F_COLOR_DIAGNOSTICS ,
244+ .value = 0
245+ },
246+ };
247+
248+ #define CLANG_SPECIFIC_REMOVE_NON 0
249+ #define CLANG_SPECIFIC_REMOVE_CUR 1
250+ #define CLANG_SPECIFIC_REMOVE_NXT 2
251+
200252#define ERR_SUCCESS 0
201253#define ERR_MEM_ALLOC_FAILURE -1
202254#define ERR_UNKNOWN_COMPILER -2
@@ -358,36 +410,59 @@ static int clang_specific_remove(const char* const prev, const char* const cur)
358410 Remove Clang-specific options that have no GCC equivalents.
359411 */
360412
361- int status = 1 ;
413+ int status = CLANG_SPECIFIC_REMOVE_CUR ;
414+ size_t index = 0 ;
415+
416+ size_t size = 0 ;
362417
363418 const char * previous = prev ;
364419 const char * current = cur ;
365420
366- if ( strncmp ( current , GCC_OPT_WL , strlen ( GCC_OPT_WL )) == 0 ) {
367- current += strlen ( GCC_OPT_WL ) ;
368- }
421+ const char * name = cur ;
422+ int value = 0 ;
423+ const clang_option_t * option = NULL ;
369424
370- if (strcmp (current , CLANG_OPT_Q_UNUSED_ARGUMENTS ) == 0 ) {
371- goto end ;
372- }
425+ unsigned char ch = 0 ;
373426
374- if (strcmp (current , CLANG_OPT_W_NO_UNUSED_COMMAND_LINE_ARGUMENT ) == 0 ) {
375- goto end ;
427+ if (strncmp (current , GCC_OPT_WL , strlen ( GCC_OPT_WL ) ) == 0 ) {
428+ current += strlen ( GCC_OPT_WL ) ;
376429 }
377430
378- if (strcmp (current , CLANG_OPT_W_NO_INVALID_COMMAND_LINE_ARGUMENT ) == 0 ) {
431+ if (* current != DASH || * current == ZERO ) {
432+ status = CLANG_SPECIFIC_REMOVE_NON ;
379433 goto end ;
380434 }
381435
382- if (strncmp (current , CLANG_OPT_ICF , strlen (CLANG_OPT_ICF )) == 0 ) {
383- goto end ;
384- }
436+ while (* (++ current ) == DASH ) {};
385437
386- if (strcmp (current , CLANG_OPT_F_NO_LIMIT_DEBUG_INFO ) == 0 ) {
438+ for (index = 0 ; index < sizeof (CLANG_SPECIFIC_REMOVE ) / sizeof (* CLANG_SPECIFIC_REMOVE ); index ++ ) {
439+ option = & CLANG_SPECIFIC_REMOVE [index ];
440+
441+ name = option -> name ;
442+ value = option -> value ;
443+
444+ while (* (++ name ) == DASH ) {};
445+
446+ size = strlen (name );
447+
448+ if (strncmp (current , name , size ) != 0 ) {
449+ continue ;
450+ }
451+
452+ ch = current [size ];
453+
454+ if (!(ch == EQUAL || ch == ZERO )) {
455+ continue ;
456+ }
457+
458+ if (value && ch == ZERO ) {
459+ status = CLANG_SPECIFIC_REMOVE_NXT ;
460+ }
461+
387462 goto end ;
388463 }
389464
390- status = 0 ;
465+ status = CLANG_SPECIFIC_REMOVE_NON ;
391466
392467 end :;
393468
@@ -608,6 +683,7 @@ int main(int argc, char* argv[], char* envp[]) {
608683
609684 int address_sanitizer = 0 ;
610685 int stack_protector = 0 ;
686+ int version = 0 ;
611687 int verbose = 0 ;
612688 int wants_libcxx = 0 ;
613689 int wants_static_libcxx = 0 ;
@@ -757,6 +833,8 @@ int main(int argc, char* argv[], char* envp[]) {
757833 override_linker = 1 ;
758834 } else if (strncmp (cur , GCC_OPT_F_STACK_PROTECTOR , strlen (GCC_OPT_F_STACK_PROTECTOR )) == 0 ) {
759835 stack_protector = 1 ;
836+ } else if (strcmp (cur , GCC_OPT_VERSION ) == 0 ) {
837+ version = 1 ;
760838 } else if (strcmp (cur , GCC_OPT_V ) == 0 ) {
761839 verbose = 1 ;
762840 } else if (strcmp (cur , GCC_OPT_L_STDCXX ) == 0 ) {
@@ -811,16 +889,18 @@ int main(int argc, char* argv[], char* envp[]) {
811889 }
812890 }
813891 } 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 );
892+ size = strlen (CLANG_OPT_TARGET );
815893
816894 /* Clang has two variants of this flag: one with double hyphens, and one with a single hyphen. */
817895 if (strncmp (cur , CLANG_OPT_TARGET + 1 , strlen (CLANG_OPT_TARGET + 1 )) == 0 ) {
818- cur -= 1 ;
896+ size -- ;
819897 }
820898
899+ cur += size ;
900+
821901 ch = * cur ;
822902
823- if (!(ch == EQUAL || ch == '\0' )) {
903+ if (!(ch == EQUAL || ch == ZERO )) {
824904 goto next ;
825905 }
826906
@@ -898,10 +978,20 @@ int main(int argc, char* argv[], char* envp[]) {
898978
899979 next :;
900980
901- if (clang_specific_remove (prev , cur )) {
981+ status = clang_specific_remove (prev , cur );
982+
983+ if (status != CLANG_SPECIFIC_REMOVE_NON ) {
984+ if (status == CLANG_SPECIFIC_REMOVE_NXT ) {
985+ index ++ ;
986+ }
987+
902988 if (prev != NULL && strcmp (prev , GCC_OPT_XLINKER ) == 0 ) {
903989 prev = NULL ;
904990 kargv [-- kargc ] = (char * ) prev ;
991+
992+ if (status == CLANG_SPECIFIC_REMOVE_NXT ) {
993+ index ++ ;
994+ }
905995 }
906996
907997 continue ;
@@ -1005,6 +1095,11 @@ int main(int argc, char* argv[], char* envp[]) {
10051095 }
10061096 }
10071097
1098+ if (version && known_clang (cc )) {
1099+ printf (CLANG_VERSION_TEMPLATE , DEFAULT_TARGET , parent_directory );
1100+ goto end ;
1101+ }
1102+
10081103 wants_libcxx += (strcmp (cc , GPP ) == 0 || strcmp (cc , CPP ) == 0 || strcmp (cc , GM2 ) == 0 || strcmp (cc , CLANGPP ) == 0 );
10091104
10101105 if (wants_libcxx ) {
0 commit comments