Skip to content

Commit 1f3c662

Browse files
authored
[LangOptions] Introduce a new enum class for platform conditions (#7843)
1 parent c6dc44d commit 1f3c662

File tree

4 files changed

+109
-120
lines changed

4 files changed

+109
-120
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@
2929
#include <vector>
3030

3131
namespace swift {
32+
33+
/// Kind of implicit platform conditions.
34+
enum class PlatformConditionKind {
35+
/// The active os target (OSX, iOS, Linux, etc.)
36+
OS,
37+
/// The active arch target (x86_64, i386, arm, arm64, etc.)
38+
Arch,
39+
/// The active endianness target (big or little)
40+
Endianness,
41+
/// Runtime support (_ObjC or _Native)
42+
Runtime,
43+
};
44+
enum { NumPlatformConditionKind = 4 };
45+
3246
/// \brief A collection of options that affect the language dialect and
3347
/// provide compiler debugging facilities.
3448
class LangOptions {
@@ -202,14 +216,9 @@ namespace swift {
202216
}
203217

204218
/// Sets an implicit platform condition.
205-
///
206-
/// There are currently three supported platform conditions:
207-
/// - os: The active os target (OSX or iOS)
208-
/// - arch: The active arch target (x86_64, i386, arm, arm64)
209-
/// - _runtime: Runtime support (_ObjC or _Native)
210-
void addPlatformConditionValue(StringRef Name, StringRef Value) {
211-
assert(!Name.empty() && !Value.empty());
212-
PlatformConditionValues.emplace_back(Name, Value);
219+
void addPlatformConditionValue(PlatformConditionKind Kind, StringRef Value) {
220+
assert(!Value.empty());
221+
PlatformConditionValues.emplace_back(Kind, Value);
213222
}
214223

215224
/// Removes all values added with addPlatformConditionValue.
@@ -218,7 +227,7 @@ namespace swift {
218227
}
219228

220229
/// Returns the value for the given platform condition or an empty string.
221-
StringRef getPlatformConditionValue(StringRef Name) const;
230+
StringRef getPlatformConditionValue(PlatformConditionKind Kind) const;
222231

223232
/// Explicit conditional compilation flags, initialized via the '-D'
224233
/// compiler flag.
@@ -230,7 +239,7 @@ namespace swift {
230239
/// Determines if a given conditional compilation flag has been set.
231240
bool isCustomConditionalCompilationFlagSet(StringRef Name) const;
232241

233-
ArrayRef<std::pair<std::string, std::string>>
242+
ArrayRef<std::pair<PlatformConditionKind, std::string>>
234243
getPlatformConditionValues() const {
235244
return PlatformConditionValues;
236245
}
@@ -244,35 +253,18 @@ namespace swift {
244253
return EffectiveLanguageVersion.isVersion3();
245254
}
246255

247-
/// Returns true if the 'os' platform condition argument represents
256+
/// Returns true if the given platform condition argument represents
248257
/// a supported target operating system.
249258
///
250-
/// Note that this also canonicalizes the OS name if the check returns
251-
/// true.
252-
///
253-
/// \param suggestions Populated with suggested replacements
254-
/// if a match is not found.
255-
static bool checkPlatformConditionOS(
256-
StringRef &OSName, std::vector<StringRef> &suggestions);
257-
258-
/// Returns true if the 'arch' platform condition argument represents
259-
/// a supported target architecture.
260-
///
261-
/// \param suggestions Populated with suggested replacements
262-
/// if a match is not found.
263-
static bool isPlatformConditionArchSupported(
264-
StringRef ArchName, std::vector<StringRef> &suggestions);
265-
266-
/// Returns true if the 'endian' platform condition argument represents
267-
/// a supported target endianness.
268-
///
269259
/// \param suggestions Populated with suggested replacements
270260
/// if a match is not found.
271-
static bool isPlatformConditionEndiannessSupported(
272-
StringRef endianness, std::vector<StringRef> &suggestions);
261+
static bool checkPlatformConditionSupported(
262+
PlatformConditionKind Kind, StringRef Value,
263+
std::vector<StringRef> &suggestions);
273264

274265
private:
275-
llvm::SmallVector<std::pair<std::string, std::string>, 3>
266+
llvm::SmallVector<std::pair<PlatformConditionKind, std::string>,
267+
NumPlatformConditionKind>
276268
PlatformConditionValues;
277269
llvm::SmallVector<std::string, 2> CustomConditionalCompilationFlags;
278270
};

lib/Basic/LangOptions.cpp

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ static const StringRef SupportedConditionalCompilationEndianness[] = {
5252
"big"
5353
};
5454

55+
static const StringRef SupportedConditionalCompilationRuntimes[] = {
56+
"_ObjC",
57+
"_Native",
58+
};
59+
5560
template <size_t N>
5661
bool contains(const StringRef (&Array)[N], const StringRef &V,
5762
std::vector<StringRef> &suggestions) {
@@ -75,36 +80,31 @@ bool contains(const StringRef (&Array)[N], const StringRef &V,
7580
return false;
7681
}
7782

78-
bool LangOptions::checkPlatformConditionOS(
79-
StringRef &OSName, std::vector<StringRef> &suggestions) {
80-
if (OSName == "macOS")
81-
OSName = "OSX";
82-
return contains(SupportedConditionalCompilationOSs,
83-
OSName,
84-
suggestions);
85-
}
86-
87-
bool
88-
LangOptions::isPlatformConditionArchSupported(
89-
StringRef ArchName, std::vector<StringRef> &suggestions) {
90-
return contains(SupportedConditionalCompilationArches,
91-
ArchName,
92-
suggestions);
93-
}
94-
95-
bool
96-
LangOptions::isPlatformConditionEndiannessSupported(
97-
StringRef Endianness, std::vector<StringRef> &suggestions) {
98-
return contains(SupportedConditionalCompilationEndianness,
99-
Endianness,
100-
suggestions);
83+
bool LangOptions::
84+
checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value,
85+
std::vector<StringRef> &suggestions) {
86+
switch (Kind) {
87+
case PlatformConditionKind::OS:
88+
return contains(SupportedConditionalCompilationOSs, Value,
89+
suggestions);
90+
case PlatformConditionKind::Arch:
91+
return contains(SupportedConditionalCompilationArches, Value,
92+
suggestions);
93+
case PlatformConditionKind::Endianness:
94+
return contains(SupportedConditionalCompilationEndianness, Value,
95+
suggestions);
96+
case PlatformConditionKind::Runtime:
97+
return contains(SupportedConditionalCompilationRuntimes, Value,
98+
suggestions);
99+
}
100+
llvm_unreachable("Unhandled enum value");
101101
}
102102

103103
StringRef
104-
LangOptions::getPlatformConditionValue(StringRef Name) const {
104+
LangOptions::getPlatformConditionValue(PlatformConditionKind Kind) const {
105105
// Last one wins.
106106
for (auto &Opt : reversed(PlatformConditionValues)) {
107-
if (Opt.first == Name)
107+
if (Opt.first == Kind)
108108
return Opt.second;
109109
}
110110
return StringRef();
@@ -141,23 +141,23 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
141141

142142
// Set the "os" platform condition.
143143
if (Target.isMacOSX())
144-
addPlatformConditionValue("os", "OSX");
144+
addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
145145
else if (triple.isTvOS())
146-
addPlatformConditionValue("os", "tvOS");
146+
addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
147147
else if (triple.isWatchOS())
148-
addPlatformConditionValue("os", "watchOS");
148+
addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
149149
else if (triple.isiOS())
150-
addPlatformConditionValue("os", "iOS");
150+
addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
151151
else if (triple.isAndroid())
152-
addPlatformConditionValue("os", "Android");
152+
addPlatformConditionValue(PlatformConditionKind::OS, "Android");
153153
else if (triple.isOSLinux())
154-
addPlatformConditionValue("os", "Linux");
154+
addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
155155
else if (triple.isOSFreeBSD())
156-
addPlatformConditionValue("os", "FreeBSD");
156+
addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
157157
else if (triple.isOSWindows())
158-
addPlatformConditionValue("os", "Windows");
158+
addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
159159
else if (triple.isPS4())
160-
addPlatformConditionValue("os", "PS4");
160+
addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
161161
else
162162
UnsupportedOS = true;
163163

@@ -167,25 +167,25 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
167167
switch (Target.getArch()) {
168168
case llvm::Triple::ArchType::arm:
169169
case llvm::Triple::ArchType::thumb:
170-
addPlatformConditionValue("arch", "arm");
170+
addPlatformConditionValue(PlatformConditionKind::Arch, "arm");
171171
break;
172172
case llvm::Triple::ArchType::aarch64:
173-
addPlatformConditionValue("arch", "arm64");
173+
addPlatformConditionValue(PlatformConditionKind::Arch, "arm64");
174174
break;
175175
case llvm::Triple::ArchType::ppc64:
176-
addPlatformConditionValue("arch", "powerpc64");
176+
addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64");
177177
break;
178178
case llvm::Triple::ArchType::ppc64le:
179-
addPlatformConditionValue("arch", "powerpc64le");
179+
addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le");
180180
break;
181181
case llvm::Triple::ArchType::x86:
182-
addPlatformConditionValue("arch", "i386");
182+
addPlatformConditionValue(PlatformConditionKind::Arch, "i386");
183183
break;
184184
case llvm::Triple::ArchType::x86_64:
185-
addPlatformConditionValue("arch", "x86_64");
185+
addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64");
186186
break;
187187
case llvm::Triple::ArchType::systemz:
188-
addPlatformConditionValue("arch", "s390x");
188+
addPlatformConditionValue(PlatformConditionKind::Arch, "s390x");
189189
break;
190190
default:
191191
UnsupportedArch = true;
@@ -198,35 +198,35 @@ std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
198198
switch (Target.getArch()) {
199199
case llvm::Triple::ArchType::arm:
200200
case llvm::Triple::ArchType::thumb:
201-
addPlatformConditionValue("_endian", "little");
201+
addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
202202
break;
203203
case llvm::Triple::ArchType::aarch64:
204-
addPlatformConditionValue("_endian", "little");
204+
addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
205205
break;
206206
case llvm::Triple::ArchType::ppc64:
207-
addPlatformConditionValue("_endian", "big");
207+
addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
208208
break;
209209
case llvm::Triple::ArchType::ppc64le:
210-
addPlatformConditionValue("_endian", "little");
210+
addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
211211
break;
212212
case llvm::Triple::ArchType::x86:
213-
addPlatformConditionValue("_endian", "little");
213+
addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
214214
break;
215215
case llvm::Triple::ArchType::x86_64:
216-
addPlatformConditionValue("_endian", "little");
216+
addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
217217
break;
218218
case llvm::Triple::ArchType::systemz:
219-
addPlatformConditionValue("_endian", "big");
219+
addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
220220
break;
221221
default:
222222
llvm_unreachable("undefined architecture endianness");
223223
}
224224

225225
// Set the "runtime" platform condition.
226226
if (EnableObjCInterop)
227-
addPlatformConditionValue("_runtime", "_ObjC");
227+
addPlatformConditionValue(PlatformConditionKind::Runtime, "_ObjC");
228228
else
229-
addPlatformConditionValue("_runtime", "_Native");
229+
addPlatformConditionValue(PlatformConditionKind::Runtime, "_Native");
230230

231231
// If you add anything to this list, change the default size of
232232
// PlatformConditionValues to not require an extra allocation

lib/Parse/ParseIfConfig.cpp

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
#include "swift/Parse/Parser.h"
1818
#include "swift/Basic/Defer.h"
19+
#include "swift/Basic/LangOptions.h"
1920
#include "swift/Basic/Version.h"
2021
#include "swift/Parse/Lexer.h"
22+
#include "llvm/ADT/StringSwitch.h"
2123
#include "llvm/Support/Compiler.h"
2224
#include "llvm/Support/SaveAndRestore.h"
2325

@@ -356,51 +358,46 @@ Parser::classifyConditionalCompilationExpr(Expr *condition,
356358
// tolerate extra parens).
357359
auto argumentIdent = UDRE->getName().getBaseName();
358360
auto argument = argumentIdent.str();
361+
PlatformConditionKind Kind =
362+
llvm::StringSwitch<PlatformConditionKind>(fnName)
363+
.Case("os", PlatformConditionKind::OS)
364+
.Case("arch", PlatformConditionKind::Arch)
365+
.Case("_endian", PlatformConditionKind::Endianness)
366+
.Case("_runtime", PlatformConditionKind::Runtime);
359367

360-
// Error for values that don't make sense if there's a clear definition
361-
// of the possible values (as there is for _runtime).
362-
if (fnName.equals("_runtime") &&
363-
!argument.equals("_ObjC") && !argument.equals("_Native")) {
364-
D.diagnose(CE->getLoc(),
365-
diag::unsupported_platform_runtime_condition_argument);
366-
return ConditionalCompilationExprState::error();
367-
}
368+
// FIXME: Perform the replacement macOS -> OSX elsewhere.
369+
if (Kind == PlatformConditionKind::OS && argument == "macOS")
370+
argument = "OSX";
368371

369372
std::vector<StringRef> suggestions;
370-
SWIFT_DEFER {
371-
for (const StringRef& suggestion : suggestions) {
372-
D.diagnose(UDRE->getLoc(), diag::note_typo_candidate,
373-
suggestion)
374-
.fixItReplace(UDRE->getSourceRange(), suggestion);
375-
}
376-
};
377-
if (fnName == "os") {
378-
if (!LangOptions::checkPlatformConditionOS(argument,
379-
suggestions)) {
380-
D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
381-
"operating system", fnName);
373+
if (!LangOptions::checkPlatformConditionSupported(Kind, argument,
374+
suggestions)) {
375+
if (Kind == PlatformConditionKind::Runtime) {
376+
// Error for _runtime()
377+
D.diagnose(UDRE->getLoc(),
378+
diag::unsupported_platform_runtime_condition_argument);
382379
return ConditionalCompilationExprState::error();
383380
}
384-
} else if (fnName == "arch") {
385-
if (!LangOptions::isPlatformConditionArchSupported(argument,
386-
suggestions)) {
387-
D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
388-
"architecture", fnName);
389-
return ConditionalCompilationExprState::error();
381+
StringRef DiagName;
382+
switch (Kind) {
383+
case PlatformConditionKind::OS:
384+
DiagName = "operating system"; break;
385+
case PlatformConditionKind::Arch:
386+
DiagName = "architecture"; break;
387+
case PlatformConditionKind::Endianness:
388+
DiagName = "endianness"; break;
389+
case PlatformConditionKind::Runtime:
390+
llvm_unreachable("handled above");
390391
}
391-
} else if (fnName == "_endian") {
392-
if (!LangOptions::isPlatformConditionEndiannessSupported(argument,
393-
suggestions)) {
394-
D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
395-
"endianness", fnName);
392+
D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
393+
DiagName, fnName);
394+
for (const StringRef &suggestion : suggestions) {
395+
D.diagnose(UDRE->getLoc(), diag::note_typo_candidate, suggestion)
396+
.fixItReplace(UDRE->getSourceRange(), suggestion);
396397
}
397398
}
398399

399-
// FIXME: Perform the replacement macOS -> OSX elsewhere.
400-
if (fnName == "os" && argument == "macOS")
401-
argument = "OSX";
402-
403-
auto target = Context.LangOpts.getPlatformConditionValue(fnName);
400+
auto target = Context.LangOpts.getPlatformConditionValue(Kind);
404401
return {target == argument, ConditionalCompilationExprKind::DeclRef};
405402
} else {
406403
D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_argument,

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ findModule(ASTContext &ctx, AccessPathElem moduleID,
9696
// FIXME: Which name should we be using here? Do we care about CPU subtypes?
9797
// FIXME: At the very least, don't hardcode "arch".
9898
llvm::SmallString<16> archFile{
99-
ctx.LangOpts.getPlatformConditionValue("arch")};
99+
ctx.LangOpts.getPlatformConditionValue(PlatformConditionKind::Arch)};
100100
llvm::SmallString<16> archDocFile{archFile};
101101
if (!archFile.empty()) {
102102
archFile += '.';

0 commit comments

Comments
 (0)