Skip to content

Commit a5a84f1

Browse files
authored
Merge pull request #79466 from beccadax/abi-inspected-your-appearance
@abi checking
2 parents c481769 + 6759ad5 commit a5a84f1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+4542
-401
lines changed

include/swift/AST/Attr.h

+266-7
Large diffs are not rendered by default.

include/swift/AST/AttrKind.h

+2
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ enum class DeclAttrKind : unsigned {
145145
#include "swift/AST/DeclAttr.def"
146146
};
147147

148+
StringRef getDeclAttrKindID(DeclAttrKind kind);
149+
148150
enum : unsigned {
149151
NumDeclAttrKinds = static_cast<unsigned>(DeclAttrKind::Last_DeclAttr) + 1,
150152
NumDeclAttrKindBits = countBitsUsed(NumDeclAttrKinds - 1),

include/swift/AST/Decl.h

+11-7
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
10411041
/// from source code.
10421042
void attachParsedAttrs(DeclAttributes attrs);
10431043

1044+
/// Retrieve the custom name in the \c @objc attribute, if present.
1045+
std::optional<ObjCSelector>
1046+
getExplicitObjCName(bool allowInvalid = false) const;
1047+
10441048
/// True if this declaration provides an implementation for an imported
10451049
/// Objective-C declaration. This implies various restrictions and special
10461050
/// behaviors for it and, if it's an extension, its members.
@@ -5919,6 +5923,13 @@ class AbstractStorageDecl : public ValueDecl {
59195923
/// Return the interface type of the stored value.
59205924
Type getValueInterfaceType() const;
59215925

5926+
/// Retrieve the source range of the variable type, or an invalid range if the
5927+
/// variable's type is not explicitly written in the source.
5928+
///
5929+
/// Only for use in diagnostics. It is not always possible to always
5930+
/// precisely point to the variable type because of type aliases.
5931+
SourceRange getTypeSourceRangeForDiagnostics() const;
5932+
59225933
/// Determine how this storage is implemented.
59235934
StorageImplInfo getImplInfo() const;
59245935

@@ -6353,13 +6364,6 @@ class VarDecl : public AbstractStorageDecl {
63536364
/// and not just getInterfaceType().
63546365
Type getTypeInContext() const;
63556366

6356-
/// Retrieve the source range of the variable type, or an invalid range if the
6357-
/// variable's type is not explicitly written in the source.
6358-
///
6359-
/// Only for use in diagnostics. It is not always possible to always
6360-
/// precisely point to the variable type because of type aliases.
6361-
SourceRange getTypeSourceRangeForDiagnostics() const;
6362-
63636367
/// Determine the mutability of this variable declaration when
63646368
/// accessed from a given declaration context.
63656369
StorageMutability mutability(

include/swift/AST/DeclAttr.def

+158-157
Large diffs are not rendered by default.

include/swift/AST/DiagnosticEngine.h

+8
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,10 @@ namespace swift {
702702
/// Flush the active diagnostic to the diagnostic output engine.
703703
void flush();
704704

705+
/// Returns the \c SourceManager associated with \c SourceLoc s for this
706+
/// diagnostic.
707+
SourceManager &getSourceManager();
708+
705709
/// Prevent the diagnostic from behaving more severely than \p limit. For
706710
/// instance, if \c DiagnosticBehavior::Warning is passed, an error will be
707711
/// emitted as a warning, but a note will still be emitted as a note.
@@ -1561,6 +1565,10 @@ namespace swift {
15611565
}
15621566
};
15631567

1568+
inline SourceManager &InFlightDiagnostic::getSourceManager() {
1569+
return Engine->SourceMgr;
1570+
}
1571+
15641572
/// Remember details about the state of a diagnostic engine and restore them
15651573
/// when the object is destroyed.
15661574
///

include/swift/AST/DiagnosticsSema.def

+81-5
Original file line numberDiff line numberDiff line change
@@ -8351,16 +8351,16 @@ ERROR(attr_abi_mismatched_kind,none,
83518351

83528352
ERROR(attr_abi_mismatched_arity,none,
83538353
"cannot give %kind0 the ABI of a %kindonly0 with a different number of "
8354-
"low-level parameters",
8355-
(ValueDecl *))
8354+
"%select{|generic }1parameters",
8355+
(Decl *, /*genericParams=*/bool))
83568356

83578357
ERROR(attr_abi_mismatched_throws,none,
83588358
"cannot give %0 the ABI of a %kindonly0 which %select{cannot|can}1 throw",
8359-
(ValueDecl *, /*abiCanThrow=*/bool))
8359+
(Decl *, /*abiCanThrow=*/bool))
83608360

83618361
ERROR(attr_abi_mismatched_async,none,
83628362
"cannot give %0 the ABI of %select{a non-async|an async}1 %kindonly0",
8363-
(ValueDecl *, /*abiIsAsync=*/bool))
8363+
(Decl *, /*abiIsAsync=*/bool))
83648364

83658365
ERROR(attr_abi_mismatched_pbd_size,none,
83668366
"cannot give pattern binding the ABI of a binding with "
@@ -8369,13 +8369,89 @@ ERROR(attr_abi_mismatched_pbd_size,none,
83698369

83708370
ERROR(attr_abi_mismatched_var,none,
83718371
"no match for %select{%kind0 in the ABI|ABI %kind0}1",
8372-
(ValueDecl *, /*isABI=*/bool))
8372+
(Decl *, /*isABI=*/bool))
83738373

83748374
ERROR(attr_abi_incompatible_with_silgen_name,none,
83758375
"cannot use '@_silgen_name' and '@abi' on the same %0 because they serve "
83768376
"the same purpose",
83778377
(DescriptiveDeclKind))
83788378

8379+
ERROR(attr_abi_missing_attr,none,
8380+
"missing '%0' %select{attribute|modifier}1 in '@abi'",
8381+
(StringRef, bool))
8382+
ERROR(attr_abi_extra_attr,none,
8383+
"extra %select{|implicit }2'%0' %select{attribute|modifier}1 in '@abi'",
8384+
(StringRef, bool, /*isImplicit=*/bool))
8385+
ERROR(attr_abi_forbidden_attr,none,
8386+
"unused '%0' %select{attribute|modifier}1 in '@abi'",
8387+
(StringRef, bool))
8388+
REMARK(abi_attr_inferred_attribute,none,
8389+
"inferred '%0' in '@abi' to match %select{attribute|modifier}1 on API",
8390+
(StringRef, bool))
8391+
8392+
ERROR(attr_abi_mismatched_attr,none,
8393+
"'%0' %select{attribute|modifier}1 in '@abi' should match '%2'",
8394+
(StringRef, bool, StringRef))
8395+
NOTE(attr_abi_matching_attr_here,none,
8396+
"%select{should match|matches}0 %select{attribute|modifier}1 "
8397+
"%select{|implicitly added }2here",
8398+
(/*matches=*/bool, /*isModifier=*/bool, /*isImplicit=*/bool))
8399+
8400+
#define TYPE_ORIGIN(KIND_IDX, DECL_IDX) "%select{|%kind" #DECL_IDX " |" \
8401+
"self parameter |result |thrown |%error}" #KIND_IDX
8402+
ERROR(attr_abi_mismatched_type,none,
8403+
TYPE_ORIGIN(0, 1) "type %2 in '@abi' should match %3",
8404+
(unsigned, Decl *, Type, Type))
8405+
NOTE(attr_abi_should_match_type_here,none,
8406+
"should match type here", ())
8407+
8408+
ERROR(attr_abi_mismatched_generic_signature,none,
8409+
"generic signature '%0' in '@abi' is not compatible with '%1'",
8410+
(StringRef, StringRef))
8411+
ERROR(attr_abi_missing_generic_signature,none,
8412+
"declaration in '@abi' should have generic signature compatible with "
8413+
"'%0'",
8414+
(StringRef))
8415+
ERROR(attr_abi_extra_generic_signature,none,
8416+
"declaration in '@abi' should not have generic signature because %0 "
8417+
"is not generic",
8418+
(Decl *))
8419+
8420+
ERROR(attr_abi_mismatched_param_modifier,none,
8421+
"%select{default |}0%select{attribute|modifier}2 %select{|'%0' }0"
8422+
"on " TYPE_ORIGIN(3, 4) "in '@abi' is not compatible with "
8423+
"%select{default|'%1'}1",
8424+
(StringRef, StringRef, /*isModifier=*/bool, unsigned, Decl *))
8425+
ERROR(attr_abi_no_default_arguments,none,
8426+
"%kind0 in '@abi' should not have a default argument; it does not "
8427+
"affect the parameter's ABI",
8428+
(Decl *))
8429+
8430+
// These macros insert 'final', 'non-final', or nothing depending on both the
8431+
// current decl and its counterpart, such that 'non-final' is used if the
8432+
// counterpart would be described as 'final' or 'static'. They must be kept in
8433+
// sync with `StaticnessAndFinality`.
8434+
#define NONFINAL_OR_NOTHING(COUNTERPART) \
8435+
"%select{||non-final |non-final |non-final |%error}" #COUNTERPART
8436+
#define FINAL_OR_NONFINAL_OR_NOTHING(CURRENT, COUNTERPART, FINAL_OK) \
8437+
"%select{|%select{" NONFINAL_OR_NOTHING(COUNTERPART) \
8438+
"|" NONFINAL_OR_NOTHING(COUNTERPART) \
8439+
"|final |final ||%error}" #CURRENT "}" #FINAL_OK
8440+
8441+
ERROR(attr_abi_static_final_mismatch,none,
8442+
FINAL_OR_NONFINAL_OR_NOTHING(0, 2, 4) "%kind1 in '@abi' should be "
8443+
FINAL_OR_NONFINAL_OR_NOTHING(2, 0, 4) "%kindonly3 to ensure ABI "
8444+
"compatibility",
8445+
(uint8_t, Decl *, uint8_t, Decl *, /*isClass=*/bool))
8446+
8447+
#undef NONFINAL_OR_NOTHING
8448+
#undef FINAL_OR_NONFINAL_OR_NOTHING
8449+
8450+
ERROR(attr_abi_failable_mismatch,none,
8451+
"cannot give %select{non-failable|failable}1 %kind0 the ABI of a "
8452+
"%select{non-failable|failable}2 %kindonly0",
8453+
(Decl *, bool, bool))
8454+
83798455
//===----------------------------------------------------------------------===//
83808456
// MARK: Isolated conformances
83818457
//===----------------------------------------------------------------------===//

include/swift/AST/Types.h

+4
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,10 @@ enum class ParamSpecifier : uint8_t {
23782378

23792379
StringRef getNameForParamSpecifier(ParamSpecifier name);
23802380

2381+
/// What does \c ParamSpecifier::Default mean for a parameter that's directly
2382+
/// attached to \p VD ? Pass \c nullptr for the value for a closure.
2383+
ParamSpecifier getDefaultParamSpecifier(const ValueDecl *VD);
2384+
23812385
/// Provide parameter type relevant flags, i.e. variadic, autoclosure, and
23822386
/// escaping.
23832387
class ParameterTypeFlags {

include/swift/Basic/LangOptions.h

+3
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ namespace swift {
269269
/// Emit a remark on early exit in explicit interface build
270270
bool EnableSkipExplicitInterfaceModuleBuildRemarks = false;
271271

272+
/// Emit a remark when \c \@abi infers an attribute or modifier.
273+
bool EnableABIInferenceRemarks = false;
274+
272275
///
273276
/// Support for alternate usage modes
274277
///

include/swift/Option/Options.td

+4
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,10 @@ def remark_module_serialization : Flag<["-"], "Rmodule-serialization">,
468468
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
469469
HelpText<"Emit remarks about module serialization">;
470470

471+
def remark_abi_inference : Flag<["-"], "Rabi-inference">,
472+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
473+
HelpText<"Emit a remark when an '@abi' attribute adds an attribute or modifier to the ABI declaration based on its presence in the API">;
474+
471475
def emit_tbd : Flag<["-"], "emit-tbd">,
472476
HelpText<"Emit a TBD file">,
473477
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>;

lib/AST/ASTMangler.cpp

+5-8
Original file line numberDiff line numberDiff line change
@@ -1193,11 +1193,9 @@ getOverriddenSwiftProtocolObjCName(const ValueDecl *decl,
11931193
return std::nullopt;
11941194

11951195
// If there is an 'objc' attribute with a name, use that name.
1196-
if (auto objc = proto->getAttrs().getAttribute<ObjCAttr>()) {
1197-
if (auto name = objc->getName()) {
1198-
llvm::SmallString<4> buffer;
1199-
return std::string(name->getString(buffer));
1200-
}
1196+
if (auto objcName = proto->getExplicitObjCName()) {
1197+
llvm::SmallString<4> buffer;
1198+
return std::string(objcName->getString(buffer));
12011199
}
12021200

12031201
return std::nullopt;
@@ -3379,8 +3377,7 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
33793377
}
33803378
}
33813379

3382-
static ParamSpecifier
3383-
getDefaultOwnership(const ValueDecl *forDecl) {
3380+
ParamSpecifier swift::getDefaultParamSpecifier(const ValueDecl *forDecl) {
33843381
// `consuming` is the default ownership for initializers and setters.
33853382
// Everything else defaults to borrowing.
33863383
if (!forDecl) {
@@ -3451,7 +3448,7 @@ getParameterFlagsForMangling(ParameterTypeFlags flags,
34513448
void ASTMangler::appendFunctionInputType(
34523449
AnyFunctionType *fnType, ArrayRef<AnyFunctionType::Param> params,
34533450
GenericSignature sig, const ValueDecl *forDecl, bool isRecursedInto) {
3454-
auto defaultSpecifier = getDefaultOwnership(forDecl);
3451+
auto defaultSpecifier = getDefaultParamSpecifier(forDecl);
34553452

34563453
switch (params.size()) {
34573454
case 0:

lib/AST/ASTPrinter.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,15 @@ void PrintAST::printAttributes(const Decl *D) {
12841284
// for each decl They cannot be shared across different decls.
12851285
assert(Options.ExcludeCustomAttrList.empty());
12861286

1287+
// If there is an `@abi` attr, we need to print it first so that it isn't
1288+
// affected by subsequent mutation of `Options.ExcludeAttrList`.
1289+
if (auto abiAttr = attrs.getAttribute<ABIAttr>()) {
1290+
if (Options.PrintImplicitAttrs && !Options.excludeAttr(abiAttr)) {
1291+
abiAttr->print(Printer, Options, D);
1292+
Options.ExcludeAttrList.push_back(DeclAttrKind::ABI);
1293+
}
1294+
}
1295+
12871296
if (Options.PrintSyntheticSILGenName
12881297
&& !D->getAttrs().hasAttribute<SILGenNameAttr>()) {
12891298
if (canPrintSyntheticSILGenName(D)) {
@@ -1334,7 +1343,8 @@ void PrintAST::printAttributes(const Decl *D) {
13341343
// Add SPIs to both private and package interfaces
13351344
if (!Options.printPublicInterface() &&
13361345
DeclAttribute::canAttributeAppearOnDeclKind(
1337-
DeclAttrKind::SPIAccessControl, D->getKind())) {
1346+
DeclAttrKind::SPIAccessControl, D->getKind()) &&
1347+
!Options.excludeAttrKind(DeclAttrKind::SPIAccessControl)) {
13381348
interleave(D->getSPIGroups(),
13391349
[&](Identifier spiName) {
13401350
Printer.printAttrName("_spi", true);
@@ -1358,7 +1368,7 @@ void PrintAST::printAttributes(const Decl *D) {
13581368
// If the declaration is implicitly @objc, print the attribute now.
13591369
if (auto VD = dyn_cast<ValueDecl>(D)) {
13601370
if (VD->isObjC() && !isa<EnumElementDecl>(VD) &&
1361-
!attrs.hasAttribute<ObjCAttr>()) {
1371+
!attrs.hasAttribute<ObjCAttr>() && ABIRoleInfo(D).providesAPI()) {
13621372
Printer.printAttrName("@objc");
13631373
Printer << " ";
13641374
}

lib/AST/AccessRequests.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ AccessLevel
4343
AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const {
4444
assert(!D->hasAccess());
4545

46+
// ABI decls share the access level of their API decl.
47+
auto abiRole = ABIRoleInfo(D);
48+
if (!abiRole.providesAPI() && abiRole.getCounterpart())
49+
return abiRole.getCounterpart()->getFormalAccess();
50+
4651
// Check if the decl has an explicit access control attribute.
4752
if (auto *AA = D->getAttrs().getAttribute<AccessControlAttr>())
4853
return AA->getAccess();
@@ -201,6 +206,12 @@ AccessLevel
201206
SetterAccessLevelRequest::evaluate(Evaluator &evaluator,
202207
AbstractStorageDecl *ASD) const {
203208
assert(!ASD->Accessors.getInt().hasValue());
209+
210+
// ABI decls share the access level of their API decl.
211+
auto abiRole = ABIRoleInfo(ASD);
212+
if (!abiRole.providesAPI() && abiRole.getCounterpart())
213+
return abiRole.getCounterpart()->getSetterFormalAccess();
214+
204215
if (auto *SAA = ASD->getAttrs().getAttribute<SetterAccessAttr>())
205216
return SAA->getAccess();
206217

0 commit comments

Comments
 (0)