From b2870f378778f72cda226452d658f5171e1588e5 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sun, 3 Jul 2016 18:40:06 -0700 Subject: [PATCH] basic: introduce the _environment compilation conditional Windows has multiple environment flavours, each of which are different. cygwin provides a glibc based environment, MinGW provides a msvcrt based GNU environment, itanium provides a msvc environment with an itanium C++ ABI, and msvc is the pure msvc, msvcprt based environment as vended by Microsoft. Due to the differences in the environment, we need a means to differentiate them at the stdlib level. Provide the _environment conditional which would allow you to query what environment is being targeted. --- include/swift/Basic/LangOptions.h | 4 +++ lib/Basic/LangOptions.cpp | 30 +++++++++++++++++++ lib/Parse/ParseStmt.cpp | 10 +++++-- .../ConditionalCompilation/cygwinTarget.swift | 9 ++++++ .../ConditionalCompilation/mingwTarget.swift | 9 ++++++ .../windowsItaniumEnvironment.swift | 9 ++++++ .../windowsMSVCenvironment.swift | 9 ++++++ 7 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 test/Parse/ConditionalCompilation/cygwinTarget.swift create mode 100644 test/Parse/ConditionalCompilation/mingwTarget.swift create mode 100644 test/Parse/ConditionalCompilation/windowsItaniumEnvironment.swift create mode 100644 test/Parse/ConditionalCompilation/windowsMSVCenvironment.swift diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 97f69e5f65322..ea778f9d449b4 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -242,6 +242,10 @@ namespace swift { /// a supported target endianness. static bool isPlatformConditionEndiannessSupported(StringRef endianness); + /// Returns true if the 'environment' platform condition argument represents + /// a supported target environment. + static bool isPlatformConditionEnvironmentSupported(StringRef Environment); + private: llvm::SmallVector, 3> PlatformConditionValues; diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index 74175f1210483..06ee888dd1eb5 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -50,6 +50,13 @@ static const StringRef SupportedConditionalCompilationEndianness[] = { "big" }; +static const StringRef SupportedConditionalCompilationEnvironment[] = { + "cygnus", + "gnu", + "msvc", + "itanium", +}; + template bool contains(const Type (&Array)[N], const Type &V) { return std::find(std::begin(Array), std::end(Array), V) != std::end(Array); @@ -69,6 +76,11 @@ LangOptions::isPlatformConditionEndiannessSupported(StringRef Endianness) { return contains(SupportedConditionalCompilationEndianness, Endianness); } +bool +LangOptions::isPlatformConditionEnvironmentSupported(StringRef Environment) { + return contains(SupportedConditionalCompilationEnvironment, Environment); +} + StringRef LangOptions::getPlatformConditionValue(StringRef Name) const { // Last one wins. @@ -191,6 +203,24 @@ std::pair LangOptions::setTarget(llvm::Triple triple) { llvm_unreachable("undefined architecture endianness"); } + // Set the "_environment" platform condition. + switch (Target.getEnvironment()) { + default: break; + case llvm::Triple::MSVC: + addPlatformConditionValue("_environment", "msvc"); + break; + case llvm::Triple::Itanium: + addPlatformConditionValue("_environment", "itanium"); + break; + case llvm::Triple::Cygnus: + addPlatformConditionValue("_environment", "cygnus"); + break; + case llvm::Triple::GNU: + if (triple.isOSWindows()) + addPlatformConditionValue("_environment", "gnu"); + break; + } + // Set the "runtime" platform condition. if (EnableObjCInterop) addPlatformConditionValue("_runtime", "_ObjC"); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index d67401a410087..c7e0f1f35d931 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1603,9 +1603,8 @@ Parser::evaluateConditionalCompilationExpr(Expr *condition) { } if (!fnName.equals("arch") && !fnName.equals("os") && - !fnName.equals("_endian") && - !fnName.equals("_runtime") && - !fnName.equals("swift") && + !fnName.equals("_endian") && !fnName.equals("_environment") && + !fnName.equals("_runtime") && !fnName.equals("swift") && !fnName.equals("_compiler_version")) { diagnose(CE->getLoc(), diag::unsupported_platform_condition_expression); return ConditionalCompilationExprState::error(); @@ -1699,6 +1698,11 @@ Parser::evaluateConditionalCompilationExpr(Expr *condition) { diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument, "endianness", fnName); } + } else if (fnName == "_environment") { + if (!LangOptions::isPlatformConditionEnvironmentSupported(argument)) { + diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument, + "environment", fnName); + } } auto target = Context.LangOpts.getPlatformConditionValue(fnName); return {target == argument, ConditionalCompilationExprKind::DeclRef}; diff --git a/test/Parse/ConditionalCompilation/cygwinTarget.swift b/test/Parse/ConditionalCompilation/cygwinTarget.swift new file mode 100644 index 0000000000000..6eb18246a66b5 --- /dev/null +++ b/test/Parse/ConditionalCompilation/cygwinTarget.swift @@ -0,0 +1,9 @@ +// RUN: %swift -parse %s -target x86_64-unknown-windows-cygnus -parse-as-library -parse-stdlib -verify + +#if _environment(cygnus) +public class cygwin { +} +#endif + +let instance = cygwin() + diff --git a/test/Parse/ConditionalCompilation/mingwTarget.swift b/test/Parse/ConditionalCompilation/mingwTarget.swift new file mode 100644 index 0000000000000..37a249991c972 --- /dev/null +++ b/test/Parse/ConditionalCompilation/mingwTarget.swift @@ -0,0 +1,9 @@ +// RUN: %swift -parse %s -target i686-unknown-windows-gnu -parse-as-library -parse-stdlib -verify + +#if _environment(gnu) +public class MinGW { +} +#endif + +let instance = MinGW() + diff --git a/test/Parse/ConditionalCompilation/windowsItaniumEnvironment.swift b/test/Parse/ConditionalCompilation/windowsItaniumEnvironment.swift new file mode 100644 index 0000000000000..c4d146996a06d --- /dev/null +++ b/test/Parse/ConditionalCompilation/windowsItaniumEnvironment.swift @@ -0,0 +1,9 @@ +// RUN: %swift -parse %s -target i686-unknown-windows-itanium -parse-as-library -parse-stdlib -verify + +#if _environment(itanium) +public class itanium { +} +#endif + +let instance = itanium() + diff --git a/test/Parse/ConditionalCompilation/windowsMSVCenvironment.swift b/test/Parse/ConditionalCompilation/windowsMSVCenvironment.swift new file mode 100644 index 0000000000000..0da00c1504739 --- /dev/null +++ b/test/Parse/ConditionalCompilation/windowsMSVCenvironment.swift @@ -0,0 +1,9 @@ +// RUN: %swift -parse %s -target i686-unknown-windows-msvc -parse-as-library -parse-stdlib -verify + +#if _environment(msvc) +public class msvc { +} +#endif + +let instance = msvc() +