Skip to content

Commit 813a2e3

Browse files
committed
[ClangImporter] Predefine __swift__ in imported (Obj)C code.
This macro expands to a numeric value representing the current Swift language version; for Swift 3.1.2, it would be 30102. See discussion in https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20160822/002754.html. rdar://problem/26921435
1 parent 5d21c2a commit 813a2e3

File tree

6 files changed

+45
-24
lines changed

6 files changed

+45
-24
lines changed

include/swift/Basic/Version.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,15 @@ class Version {
6565

6666
/// Return a string to be used as an internal preprocessor define.
6767
///
68-
/// Assuming the project version is at most X.Y.Z.a.b, the integral constant
69-
/// representing the version is:
68+
/// The components of the version are multiplied element-wise by
69+
/// \p componentWeights, then added together (a dot product operation).
70+
/// If either array is longer than the other, the missing elements are
71+
/// treated as zero.
7072
///
71-
/// X*1000*1000*1000 + Z*1000*1000 + a*1000 + b
72-
///
73-
/// The second version component is not used.
74-
std::string preprocessorDefinition() const;
73+
/// The resulting string will have the form "-DMACRO_NAME=XYYZZ".
74+
/// The combined value must fit in a uint64_t.
75+
std::string preprocessorDefinition(StringRef macroName,
76+
ArrayRef<uint64_t> componentWeights) const;
7577

7678
/// Return the ith version component.
7779
unsigned operator[](size_t i) const {

lib/Basic/Version.cpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -269,25 +269,20 @@ raw_ostream &operator<<(raw_ostream &os, const Version &version) {
269269
return os;
270270
}
271271

272-
std::string Version::preprocessorDefinition() const {
273-
SmallString<64> define("-D__SWIFT_COMPILER_VERSION=");
274-
llvm::raw_svector_ostream OS(define);
272+
std::string
273+
Version::preprocessorDefinition(StringRef macroName,
274+
ArrayRef<uint64_t> componentWeights) const {
275275
uint64_t versionConstant = 0;
276276

277-
auto NumComponents = Components.size();
278-
279-
if (NumComponents > 0)
280-
versionConstant += Components[0] * 1000 * 1000 * 1000;
281-
// Component 2 is not used.
282-
if (NumComponents > 2)
283-
versionConstant += Components[2] * 1000 * 1000;
284-
if (NumComponents > 3)
285-
versionConstant += Components[3] * 1000;
286-
if (NumComponents > 4)
287-
versionConstant += Components[4];
277+
for (size_t i = 0, e = std::min(componentWeights.size(), Components.size());
278+
i < e; ++i) {
279+
versionConstant += componentWeights[i] * Components[i];
280+
}
288281

289-
OS << versionConstant;
290-
return OS.str().str();
282+
std::string define("-D");
283+
llvm::raw_string_ostream(define) << macroName << '=' << versionConstant;
284+
// This isn't using stream.str() so that we get move semantics.
285+
return define;
291286
}
292287

293288
bool operator>=(const class Version &lhs,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
315315
const llvm::Triple &triple = ctx.LangOpts.Target;
316316
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
317317

318+
auto languageVersion = swift::version::Version::getCurrentLanguageVersion();
319+
318320
// Construct the invocation arguments for the current target.
319321
// Add target-independent options first.
320322
invocationArgStrs.insert(
@@ -332,9 +334,11 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
332334
// Don't emit LLVM IR.
333335
"-fsyntax-only",
334336

335-
// enable block support
337+
// Enable block support.
336338
"-fblocks",
337339

340+
languageVersion.preprocessorDefinition("__swift__", {10000, 100, 1}),
341+
338342
"-fretain-comments-from-system-headers",
339343

340344
SHIMS_INCLUDE_FLAG, searchPathOpts.RuntimeResourcePath,
@@ -396,7 +400,8 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
396400
auto V = version::Version::getCurrentCompilerVersion();
397401
if (!V.empty()) {
398402
invocationArgStrs.insert(invocationArgStrs.end(), {
399-
V.preprocessorDefinition(),
403+
V.preprocessorDefinition("__SWIFT_COMPILER_VERSION",
404+
{1000000000, /*ignored*/0, 1000000, 1000, 1}),
400405
});
401406
}
402407
} else {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#if !defined(__swift__)
2+
# error "__swift__ not defined"
3+
#elif __swift__ < 30000
4+
# error "Why are you using such an old version of Swift?"
5+
#elif __swift__ >= 810000
6+
# error "Is Swift 81 out already? If so, please update this test."
7+
#else
8+
void swift3ReadyToGo();
9+
#endif

test/ClangModules/Inputs/custom-modules/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ module ObjCSubscripts {
103103
export *
104104
}
105105

106+
module PredefinedMacros {
107+
header "PredefinedMacros.h"
108+
export *
109+
}
110+
106111
module ProtoWithInitializer {
107112
header "ProtoWithInitializer.h"
108113
export *
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse -verify -I %S/Inputs/custom-modules/ %s
2+
3+
import PredefinedMacros
4+
5+
swift3ReadyToGo()

0 commit comments

Comments
 (0)