Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -456,6 +456,10 @@ def err_drv_modules_validate_once_requires_timestamp : Error< "option '-fmodules-validate-once-per-build-session' requires " "'-fbuild-session-timestamp=' or '-fbuild-session-file='">; +def err_build_session_timestamp_date_time_macros_no_timestamp : Error< + "option '-fbuild-session-timestamp-date-time-macros' requires " + "'-fbuild-session-timestamp=' " + "or '-fbuild-session-file='">; def err_test_module_file_extension_format : Error< "-ftest-module-file-extension argument '%0' is not of the required form " Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2187,6 +2187,10 @@ def fbuild_session_file : Joined<["-"], "fbuild-session-file=">, Group, MetaVarName<"">, HelpText<"Use the last modification time of as the build session timestamp">; +def fbuild_session_timestamp_date_time_macros : Flag<["-"], "fbuild-session-timestamp-date-time-macros">, + Flags<[CC1Option]>, Group, + HelpText<"Use option -fbuild-session-timestamp or -fbuild-session-file= to set the predefined macros: __DATE__ and __TIME__">, + MarshallingInfoFlag>; def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-once-per-build-session">, Group, Flags<[CC1Option]>, HelpText<"Don't verify input files for the modules if the module has been " Index: clang/include/clang/Lex/HeaderSearchOptions.h =================================================================== --- clang/include/clang/Lex/HeaderSearchOptions.h +++ clang/include/clang/Lex/HeaderSearchOptions.h @@ -168,7 +168,8 @@ /// The time in seconds when the build session started. /// /// This time is used by other optimizations in header search and module - /// loading. + /// loading, and to set the predefined macros: __DATE__ & __TIME__ if so + /// desired. uint64_t BuildSessionTimestamp = 0; /// The set of macro names that should be ignored for the purposes Index: clang/include/clang/Lex/PreprocessorOptions.h =================================================================== --- clang/include/clang/Lex/PreprocessorOptions.h +++ clang/include/clang/Lex/PreprocessorOptions.h @@ -213,6 +213,10 @@ /// Prevents intended crashes when using #pragma clang __debug. For testing. bool DisablePragmaDebugCrash = false; + /// Use option -fbuild-session-timestamp/-fbuild-session-file to set the + /// predefined macros: __DATE__ and __TIME__ + bool BuildSessionTimestampDateTimeMacros = false; + public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5582,6 +5582,15 @@ // preprocessed inputs and configure concludes that -fPIC is not supported. Args.ClaimAllArgs(options::OPT_D); + // Check if the preprocessor needs to set the predefined __DATE__ and __TIME__ + // macros based on the build session timestamp. + if (Args.hasArg(options::OPT_fbuild_session_timestamp_date_time_macros)) { + if (!Args.getLastArg(options::OPT_fbuild_session_timestamp, + options::OPT_fbuild_session_file)) + D.Diag(diag::err_build_session_timestamp_date_time_macros_no_timestamp); + CmdArgs.push_back("-fbuild-session-timestamp-date-time-macros"); + } + // Manually translate -O4 to -O3; let clang reject others. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O4)) { Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -24,6 +24,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroArgs.h" @@ -1081,7 +1082,18 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, Preprocessor &PP) { time_t TT = time(nullptr); - struct tm *TM = localtime(&TT); + struct tm *TM = nullptr; + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts(); + if (HSOpts.BuildSessionTimestamp && + PPOpts.BuildSessionTimestampDateTimeMacros) { + TT = static_cast(HSOpts.BuildSessionTimestamp); + TM = gmtime(&TT); + } else { + TT = time(nullptr); + TM = localtime(&TT); + } static const char * const Months[] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" Index: clang/test/Preprocessor/build-session-timestamp-date-time-macros.c =================================================================== --- /dev/null +++ clang/test/Preprocessor/build-session-timestamp-date-time-macros.c @@ -0,0 +1,20 @@ +char build_date[] = __DATE__; +char build_time[] = __TIME__; + +// The predefined macros __DATE__ & __TIME__ are set via the -fbuild-session-timestamp option: +// NOTE: +// $ export SOURCE_DATE_EPOCH=`date +%s --date="Apr 2 2022 23:59:18 UTC"`; echo $SOURCE_DATE_EPOCH +// 1648943958 +// $ +// RUN: export SOURCE_DATE_EPOCH=1648943958; %clang_cc1 -fbuild-session-timestamp-date-time-macros -fbuild-session-timestamp=$SOURCE_DATE_EPOCH -E %s | FileCheck -check-prefix=SET_VIA_BUILD_SESSION_TIMESTAMP %s +// SET_VIA_BUILD_SESSION_TIMESTAMP: char build_date[] = "Apr 2 2022"; +// SET_VIA_BUILD_SESSION_TIMESTAMP: char build_time[] = "23:59:18"; + +// The predefined macros __DATE__ & __TIME__ are set via the -fbuild-session-file option: +// RUN: touch --date="Thu Feb 10 22:40:16 UTC 2020" %t.build-session-file; %clang -fbuild-session-timestamp-date-time-macros -fbuild-session-file=%t.build-session-file %s -E | FileCheck -check-prefix=SET_VIA_BUILD_SESSION_FILE %s +// SET_VIA_BUILD_SESSION_FILE: char build_date[] = "Feb 10 2020"; +// SET_VIA_BUILD_SESSION_FILE: char build_time[] = "22:40:16"; + +// An error is issued if neither -fbuild-session-timestamp nor -fbuild-session-file option is specified: +// RUN: %clang -fbuild-session-timestamp-date-time-macros -E -### %s 2>&1 | FileCheck -check-prefix=ERR_IF_NO_BUILD_SESSION_OPTION %s +// ERR_IF_NO_BUILD_SESSION_OPTION: option '-fbuild-session-timestamp-date-time-macros' requires '-fbuild-session-timestamp=' or '-fbuild-session-file='