Skip to content

Commit b2870f3

Browse files
committed
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.
1 parent dfa2ba3 commit b2870f3

File tree

7 files changed

+77
-3
lines changed

7 files changed

+77
-3
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ namespace swift {
242242
/// a supported target endianness.
243243
static bool isPlatformConditionEndiannessSupported(StringRef endianness);
244244

245+
/// Returns true if the 'environment' platform condition argument represents
246+
/// a supported target environment.
247+
static bool isPlatformConditionEnvironmentSupported(StringRef Environment);
248+
245249
private:
246250
llvm::SmallVector<std::pair<std::string, std::string>, 3>
247251
PlatformConditionValues;

lib/Basic/LangOptions.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ static const StringRef SupportedConditionalCompilationEndianness[] = {
5050
"big"
5151
};
5252

53+
static const StringRef SupportedConditionalCompilationEnvironment[] = {
54+
"cygnus",
55+
"gnu",
56+
"msvc",
57+
"itanium",
58+
};
59+
5360
template <typename Type, size_t N>
5461
bool contains(const Type (&Array)[N], const Type &V) {
5562
return std::find(std::begin(Array), std::end(Array), V) != std::end(Array);
@@ -69,6 +76,11 @@ LangOptions::isPlatformConditionEndiannessSupported(StringRef Endianness) {
6976
return contains(SupportedConditionalCompilationEndianness, Endianness);
7077
}
7178

79+
bool
80+
LangOptions::isPlatformConditionEnvironmentSupported(StringRef Environment) {
81+
return contains(SupportedConditionalCompilationEnvironment, Environment);
82+
}
83+
7284
StringRef
7385
LangOptions::getPlatformConditionValue(StringRef Name) const {
7486
// Last one wins.
@@ -191,6 +203,24 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
191203
llvm_unreachable("undefined architecture endianness");
192204
}
193205

206+
// Set the "_environment" platform condition.
207+
switch (Target.getEnvironment()) {
208+
default: break;
209+
case llvm::Triple::MSVC:
210+
addPlatformConditionValue("_environment", "msvc");
211+
break;
212+
case llvm::Triple::Itanium:
213+
addPlatformConditionValue("_environment", "itanium");
214+
break;
215+
case llvm::Triple::Cygnus:
216+
addPlatformConditionValue("_environment", "cygnus");
217+
break;
218+
case llvm::Triple::GNU:
219+
if (triple.isOSWindows())
220+
addPlatformConditionValue("_environment", "gnu");
221+
break;
222+
}
223+
194224
// Set the "runtime" platform condition.
195225
if (EnableObjCInterop)
196226
addPlatformConditionValue("_runtime", "_ObjC");

lib/Parse/ParseStmt.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,9 +1603,8 @@ Parser::evaluateConditionalCompilationExpr(Expr *condition) {
16031603
}
16041604

16051605
if (!fnName.equals("arch") && !fnName.equals("os") &&
1606-
!fnName.equals("_endian") &&
1607-
!fnName.equals("_runtime") &&
1608-
!fnName.equals("swift") &&
1606+
!fnName.equals("_endian") && !fnName.equals("_environment") &&
1607+
!fnName.equals("_runtime") && !fnName.equals("swift") &&
16091608
!fnName.equals("_compiler_version")) {
16101609
diagnose(CE->getLoc(), diag::unsupported_platform_condition_expression);
16111610
return ConditionalCompilationExprState::error();
@@ -1699,6 +1698,11 @@ Parser::evaluateConditionalCompilationExpr(Expr *condition) {
16991698
diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
17001699
"endianness", fnName);
17011700
}
1701+
} else if (fnName == "_environment") {
1702+
if (!LangOptions::isPlatformConditionEnvironmentSupported(argument)) {
1703+
diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
1704+
"environment", fnName);
1705+
}
17021706
}
17031707
auto target = Context.LangOpts.getPlatformConditionValue(fnName);
17041708
return {target == argument, ConditionalCompilationExprKind::DeclRef};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %swift -parse %s -target x86_64-unknown-windows-cygnus -parse-as-library -parse-stdlib -verify
2+
3+
#if _environment(cygnus)
4+
public class cygwin {
5+
}
6+
#endif
7+
8+
let instance = cygwin()
9+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %swift -parse %s -target i686-unknown-windows-gnu -parse-as-library -parse-stdlib -verify
2+
3+
#if _environment(gnu)
4+
public class MinGW {
5+
}
6+
#endif
7+
8+
let instance = MinGW()
9+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %swift -parse %s -target i686-unknown-windows-itanium -parse-as-library -parse-stdlib -verify
2+
3+
#if _environment(itanium)
4+
public class itanium {
5+
}
6+
#endif
7+
8+
let instance = itanium()
9+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %swift -parse %s -target i686-unknown-windows-msvc -parse-as-library -parse-stdlib -verify
2+
3+
#if _environment(msvc)
4+
public class msvc {
5+
}
6+
#endif
7+
8+
let instance = msvc()
9+

0 commit comments

Comments
 (0)