Skip to content

Commit 16d41c3

Browse files
committed
[API Notes] Add Swift versioning to API notes files
Extend the API notes format with support for specifying API notes at a particular Swift version. A single API notes file has "unversioned" information, followed optionally by more information about the various classes/functions/etc. at a specific Swift version. The intent is to allow API notes to provide backward-compatibility information Parse Swift-versioned API notes, store version API notes in the binary format, and ensure that it round-trips. For now, Clang still only adds attributes based on the unversioned information. This is the first step of rdar://problem/28455809.
1 parent 13d60b8 commit 16d41c3

File tree

9 files changed

+1049
-767
lines changed

9 files changed

+1049
-767
lines changed

include/clang/APINotes/APINotesReader.h

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define LLVM_CLANG_API_NOTES_READER_H
1818

1919
#include "clang/APINotes/Types.h"
20+
#include "clang/Basic/VersionTuple.h"
2021
#include "llvm/ADT/Optional.h"
2122
#include "llvm/Support/MemoryBuffer.h"
2223
#include <memory>
@@ -65,21 +66,33 @@ class APINotesReader {
6566
/// Retrieve the module options
6667
ModuleOptions getModuleOptions() const;
6768

69+
/// Look for the context ID of the given Objective-C class.
70+
///
71+
/// \param name The name of the class we're looking for.
72+
///
73+
/// \returns The ID, if known.
74+
Optional<ContextID> lookupObjCClassID(StringRef name);
75+
6876
/// Look for information regarding the given Objective-C class.
6977
///
7078
/// \param name The name of the class we're looking for.
7179
///
72-
/// \returns The ID and information about the class, if known.
73-
Optional<std::pair<ContextID, ObjCContextInfo>>
74-
lookupObjCClass(StringRef name);
80+
/// \returns The information about the class, if known.
81+
Optional<ObjCContextInfo> lookupObjCClassInfo(StringRef name);
82+
83+
/// Look for the context ID of the given Objective-C protocol.
84+
///
85+
/// \param name The name of the protocol we're looking for.
86+
///
87+
/// \returns The ID of the protocol, if known.
88+
Optional<ContextID> lookupObjCProtocolID(StringRef name);
7589

7690
/// Look for information regarding the given Objective-C protocol.
7791
///
7892
/// \param name The name of the protocol we're looking for.
7993
///
80-
/// \returns The ID and information about the protocol, if known.
81-
Optional<std::pair<ContextID, ObjCContextInfo>>
82-
lookupObjCProtocol(StringRef name);
94+
/// \returns The information about the protocol, if known.
95+
Optional<ObjCContextInfo> lookupObjCProtocolInfo(StringRef name);
8396

8497
/// Look for information regarding the given Objective-C property in
8598
/// the given context.
@@ -88,6 +101,7 @@ class APINotesReader {
88101
/// \param name The name of the property we're looking for.
89102
/// \param isInstance Whether we are looking for an instance property (vs.
90103
/// a class property).
104+
/// \param swiftVersion The Swift version to filter for, if any.
91105
///
92106
/// \returns Information about the property, if known.
93107
Optional<ObjCPropertyInfo> lookupObjCProperty(ContextID contextID,
@@ -149,39 +163,48 @@ class APINotesReader {
149163

150164
/// Visit an Objective-C class.
151165
virtual void visitObjCClass(ContextID contextID, StringRef name,
152-
const ObjCContextInfo &info);
166+
const ObjCContextInfo &info,
167+
VersionTuple swiftVersion);
153168

154169
/// Visit an Objective-C protocol.
155170
virtual void visitObjCProtocol(ContextID contextID, StringRef name,
156-
const ObjCContextInfo &info);
171+
const ObjCContextInfo &info,
172+
VersionTuple swiftVersion);
157173

158174
/// Visit an Objective-C method.
159175
virtual void visitObjCMethod(ContextID contextID, StringRef selector,
160176
bool isInstanceMethod,
161-
const ObjCMethodInfo &info);
177+
const ObjCMethodInfo &info,
178+
VersionTuple swiftVersion);
162179

163180
/// Visit an Objective-C property.
164181
virtual void visitObjCProperty(ContextID contextID, StringRef name,
165182
bool isInstance,
166-
const ObjCPropertyInfo &info);
183+
const ObjCPropertyInfo &info,
184+
VersionTuple swiftVersion);
167185

168186
/// Visit a global variable.
169187
virtual void visitGlobalVariable(StringRef name,
170-
const GlobalVariableInfo &info);
188+
const GlobalVariableInfo &info,
189+
VersionTuple swiftVersion);
171190

172191
/// Visit a global function.
173192
virtual void visitGlobalFunction(StringRef name,
174-
const GlobalFunctionInfo &info);
193+
const GlobalFunctionInfo &info,
194+
VersionTuple swiftVersion);
175195

176196
/// Visit an enumerator.
177197
virtual void visitEnumConstant(StringRef name,
178-
const EnumConstantInfo &info);
198+
const EnumConstantInfo &info,
199+
VersionTuple swiftVersion);
179200

180201
/// Visit a tag.
181-
virtual void visitTag(StringRef name, const TagInfo &info);
202+
virtual void visitTag(StringRef name, const TagInfo &info,
203+
VersionTuple swiftVersion);
182204

183205
/// Visit a typedef.
184-
virtual void visitTypedef(StringRef name, const TypedefInfo &info);
206+
virtual void visitTypedef(StringRef name, const TypedefInfo &info,
207+
VersionTuple swiftVersion);
185208
};
186209

187210
/// Visit the contents of the API notes file, passing each entity to the

include/clang/APINotes/APINotesWriter.h

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef LLVM_CLANG_API_NOTES_WRITER_H
1717
#define LLVM_CLANG_API_NOTES_WRITER_H
1818

19+
#include "clang/Basic/VersionTuple.h"
1920
#include "clang/APINotes/Types.h"
2021

2122
namespace llvm {
@@ -46,23 +47,17 @@ class APINotesWriter {
4647
/// Write the API notes data to the given stream.
4748
void writeToStream(llvm::raw_ostream &os);
4849

49-
/// Add information about a specific Objective-C class.
50+
/// Add information about a specific Objective-C class or protocol.
5051
///
51-
/// \param name The name of this class.
52-
/// \param info Information about this class.
52+
/// \param name The name of this class/protocol.
53+
/// \param isClass Whether this is a class (vs. a protocol).
54+
/// \param info Information about this class/protocol.
5355
///
54-
/// \returns the ID of the class, which can be used to add properties and
55-
/// methods to the class.
56-
ContextID addObjCClass(StringRef name, const ObjCContextInfo &info);
57-
58-
/// Add information about a specific Objective-C protocol.
59-
///
60-
/// \param name The name of this protocol.
61-
/// \param info Information about this protocol.
62-
///
63-
/// \returns the ID of the protocol, which can be used to add properties and
64-
/// methods to the protocol.
65-
ContextID addObjCProtocol(StringRef name, const ObjCContextInfo &info);
56+
/// \returns the ID of the class or protocol, which can be used to add
57+
/// properties and methods to the class/protocol.
58+
ContextID addObjCContext(StringRef name, bool isClass,
59+
const ObjCContextInfo &info,
60+
VersionTuple swiftVersion);
6661

6762
/// Add information about a specific Objective-C property.
6863
///
@@ -71,7 +66,8 @@ class APINotesWriter {
7166
/// \param info Information about this property.
7267
void addObjCProperty(ContextID contextID, StringRef name,
7368
bool isInstanceProperty,
74-
const ObjCPropertyInfo &info);
69+
const ObjCPropertyInfo &info,
70+
VersionTuple swiftVersion);
7571

7672
/// Add information about a specific Objective-C method.
7773
///
@@ -81,37 +77,43 @@ class APINotesWriter {
8177
/// (vs. a class method).
8278
/// \param info Information about this method.
8379
void addObjCMethod(ContextID contextID, ObjCSelectorRef selector,
84-
bool isInstanceMethod, const ObjCMethodInfo &info);
80+
bool isInstanceMethod, const ObjCMethodInfo &info,
81+
VersionTuple swiftVersion);
8582

8683
/// Add information about a global variable.
8784
///
8885
/// \param name The name of this global variable.
8986
/// \param info Information about this global variable.
90-
void addGlobalVariable(StringRef name, const GlobalVariableInfo &info);
87+
void addGlobalVariable(StringRef name, const GlobalVariableInfo &info,
88+
VersionTuple swiftVersion);
9189

9290
/// Add information about a global function.
9391
///
9492
/// \param name The name of this global function.
9593
/// \param info Information about this global function.
96-
void addGlobalFunction(StringRef name, const GlobalFunctionInfo &info);
94+
void addGlobalFunction(StringRef name, const GlobalFunctionInfo &info,
95+
VersionTuple swiftVersion);
9796

9897
/// Add information about an enumerator.
9998
///
10099
/// \param name The name of this enumerator.
101100
/// \param info Information about this enumerator.
102-
void addEnumConstant(StringRef name, const EnumConstantInfo &info);
101+
void addEnumConstant(StringRef name, const EnumConstantInfo &info,
102+
VersionTuple swiftVersion);
103103

104104
/// Add information about a tag (struct/union/enum/C++ class).
105105
///
106106
/// \param name The name of this tag.
107107
/// \param info Information about this tag.
108-
void addTag(StringRef name, const TagInfo &info);
108+
void addTag(StringRef name, const TagInfo &info,
109+
VersionTuple swiftVersion);
109110

110111
/// Add information about a typedef.
111112
///
112113
/// \param name The name of this typedef.
113114
/// \param info Information about this typedef.
114-
void addTypedef(StringRef name, const TypedefInfo &info);
115+
void addTypedef(StringRef name, const TypedefInfo &info,
116+
VersionTuple swiftVersion);
115117

116118
/// Add module options
117119
void addModuleOptions(ModuleOptions opts);

include/clang/Basic/VersionTuple.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "clang/Basic/LLVM.h"
1919
#include "llvm/ADT/Optional.h"
20+
#include "llvm/ADT/DenseMapInfo.h"
2021
#include <string>
2122
#include <tuple>
2223

@@ -70,6 +71,9 @@ class VersionTuple {
7071
return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
7172
}
7273

74+
/// Whether this is a non-empty version tuple.
75+
explicit operator bool () const { return !empty(); }
76+
7377
/// \brief Retrieve the major version number.
7478
unsigned getMajor() const { return Major; }
7579

@@ -165,4 +169,35 @@ class VersionTuple {
165169
raw_ostream& operator<<(raw_ostream &Out, const VersionTuple &V);
166170

167171
} // end namespace clang
172+
173+
namespace llvm {
174+
// Provide DenseMapInfo for version tuples.
175+
template<>
176+
struct DenseMapInfo<clang::VersionTuple> {
177+
static inline clang::VersionTuple getEmptyKey() {
178+
return clang::VersionTuple(0x7FFFFFFF);
179+
}
180+
static inline clang::VersionTuple getTombstoneKey() {
181+
return clang::VersionTuple(0x7FFFFFFE);
182+
}
183+
static unsigned getHashValue(const clang::VersionTuple& value) {
184+
unsigned result = value.getMajor();
185+
if (auto minor = value.getMinor())
186+
result = combineHashValue(result, *minor);
187+
if (auto subminor = value.getSubminor())
188+
result = combineHashValue(result, *subminor);
189+
if (auto build = value.getBuild())
190+
result = combineHashValue(result, *build);
191+
192+
return result;
193+
}
194+
195+
static bool isEqual(const clang::VersionTuple &lhs,
196+
const clang::VersionTuple &rhs) {
197+
return lhs == rhs;
198+
}
199+
};
200+
201+
} // end namespace llvm
202+
168203
#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H

lib/APINotes/APINotesFormat.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const uint16_t VERSION_MAJOR = 0;
3636
/// API notes file minor version number.
3737
///
3838
/// When the format changes IN ANY WAY, this number should be incremented.
39-
const uint16_t VERSION_MINOR = 15; // source file info
39+
const uint16_t VERSION_MINOR = 16; // versioned API notes.
4040

4141
using IdentifierID = PointerEmbeddedInt<unsigned, 31>;
4242
using IdentifierIDField = BCVBR<16>;
@@ -60,8 +60,8 @@ enum BlockID {
6060
/// The identifier data block, which maps identifier strings to IDs.
6161
IDENTIFIER_BLOCK_ID,
6262

63-
/// The Objective-C class data block, which maps Objective-C class
64-
/// names to information about the class.
63+
/// The Objective-C context data block, which contains information about
64+
/// Objective-C classes and protocols.
6565
OBJC_CONTEXT_BLOCK_ID,
6666

6767
/// The Objective-C property data block, which maps Objective-C
@@ -147,13 +147,20 @@ namespace identifier_block {
147147

148148
namespace objc_context_block {
149149
enum {
150-
OBJC_CONTEXT_DATA = 1,
150+
OBJC_CONTEXT_ID_DATA = 1,
151+
OBJC_CONTEXT_INFO_DATA = 2,
151152
};
152153

153-
using ObjCContextDataLayout = BCRecordLayout<
154-
OBJC_CONTEXT_DATA, // record ID
154+
using ObjCContextIDLayout = BCRecordLayout<
155+
OBJC_CONTEXT_ID_DATA, // record ID
155156
BCVBR<16>, // table offset within the blob (see below)
156-
BCBlob // map from ObjC class names (as IDs) to ObjC class information
157+
BCBlob // map from ObjC class names/protocol (as IDs) to context IDs
158+
>;
159+
160+
using ObjCContextInfoLayout = BCRecordLayout<
161+
OBJC_CONTEXT_INFO_DATA, // record ID
162+
BCVBR<16>, // table offset within the blob (see below)
163+
BCBlob // map from ObjC context IDs to context information.
157164
>;
158165
}
159166

0 commit comments

Comments
 (0)