diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -211,9 +211,6 @@ /// The name of the relocation model to use. llvm::Reloc::Model RelocationModel; - /// The thread model to use - std::string ThreadModel; - /// If not an empty string, trap intrinsics are lowered to calls to this /// function instead of to trap instructions. std::string TrapFuncName; diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -232,6 +232,13 @@ BKey }; + enum class ThreadModelKind { + /// POSIX Threads. + POSIX, + /// Single Threaded Environment. + Single + }; + public: /// Set of enabled sanitizers. SanitizerSet Sanitize; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -330,6 +330,7 @@ "stop trivial automatic variable initialization after the specified number of instances. Must be greater than 0.") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") +ENUM_LANGOPT(ThreadModel , ThreadModelKind, 2, ThreadModelKind::POSIX, "Thread Model") BENIGN_LANGOPT(ArrowDepth, 32, 256, "maximum number of operator->s to follow") diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -453,10 +453,14 @@ const clang::TargetOptions &TargetOpts, const LangOptions &LangOpts, const HeaderSearchOptions &HSOpts) { - Options.ThreadModel = - llvm::StringSwitch(CodeGenOpts.ThreadModel) - .Case("posix", llvm::ThreadModel::POSIX) - .Case("single", llvm::ThreadModel::Single); + switch (LangOpts.getThreadModel()) { + case LangOptions::ThreadModelKind::POSIX: + Options.ThreadModel = llvm::ThreadModel::POSIX; + break; + case LangOptions::ThreadModelKind::Single: + Options.ThreadModel = llvm::ThreadModel::Single; + break; + } // Set float ABI type. assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" || diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp --- a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -49,7 +49,7 @@ const PreprocessorOptions &PreprocessorOpts; CodeGenOptions CodeGenOpts; const TargetOptions TargetOpts; - const LangOptions LangOpts; + LangOptions LangOpts; std::unique_ptr VMContext; std::unique_ptr M; std::unique_ptr Builder; @@ -147,7 +147,7 @@ // The debug info output isn't affected by CodeModel and // ThreadModel, but the backend expects them to be nonempty. CodeGenOpts.CodeModel = "default"; - CodeGenOpts.ThreadModel = "single"; + LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single); CodeGenOpts.DebugTypeExtRefs = true; // When building a module MainFileName is the name of the modulemap file. CodeGenOpts.MainFileName = diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1037,12 +1037,11 @@ Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers); Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); - Opts.ThreadModel = + std::string ThreadModel = std::string(Args.getLastArgValue(OPT_mthread_model, "posix")); - if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single") + if (ThreadModel != "posix" && ThreadModel != "single") Diags.Report(diag::err_drv_invalid_value) - << Args.getLastArg(OPT_mthread_model)->getAsString(Args) - << Opts.ThreadModel; + << Args.getLastArg(OPT_mthread_model)->getAsString(Args) << ThreadModel; Opts.TrapFuncName = std::string(Args.getLastArgValue(OPT_ftrap_function_EQ)); Opts.UseInitArray = !Args.hasArg(OPT_fno_use_init_array); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -403,6 +403,12 @@ Builder.defineMacro("__STDCPP_DEFAULT_NEW_ALIGNMENT__", Twine(TI.getNewAlign() / TI.getCharWidth()) + TI.getTypeConstantSuffix(TI.getSizeType())); + + // -- __STDCPP_­THREADS__ + // Defined, and has the value integer literal 1, if and only if a + // program can have more than one thread of execution. + if (LangOpts.getThreadModel() == LangOptions::ThreadModelKind::POSIX) + Builder.defineMacro("__STDCPP_THREADS__", "1"); } // In C11 these are environment macros. In C++11 they are only defined diff --git a/clang/test/CXX/cpp/cpp.predefined/p2.cpp b/clang/test/CXX/cpp/cpp.predefined/p2.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CXX/cpp/cpp.predefined/p2.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 %s -verify +// expected-no-diagnostics + +#ifndef __STDCPP_THREADS__ +#error __STDCPP_THREADS__ is not defined +#endif diff --git a/clang/test/Preprocessor/init-aarch64.c b/clang/test/Preprocessor/init-aarch64.c --- a/clang/test/Preprocessor/init-aarch64.c +++ b/clang/test/Preprocessor/init-aarch64.c @@ -233,6 +233,7 @@ // AARCH64-NEXT: #define __SIZE_TYPE__ long unsigned int // AARCH64-NEXT: #define __SIZE_WIDTH__ 64 // AARCH64_CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// AARCH64_CXX: #define __STDCPP_THREADS__ 1 // AARCH64-NEXT: #define __STDC_HOSTED__ 1 // AARCH64-NEXT: #define __STDC_UTF_16__ 1 // AARCH64-NEXT: #define __STDC_UTF_32__ 1