Skip to content

Commit d3daa3c

Browse files
authored
[clang/AST] Make it possible to use SwiftAttr in type context (#108631)
Swift ClangImporter now supports concurrency annotations on imported declarations and their parameters/results, to make it possible to use imported APIs in Swift safely there has to be a way to annotate individual parameters and result types with relevant attributes that indicate that e.g. a block is called on a particular actor or it accepts a `Sendable` parameter. To faciliate that `SwiftAttr` is switched from `InheritableAttr` which is a declaration attribute to `DeclOrTypeAttr`. To support this attribute in type context we need access to its "Attribute" argument which requires `AttributedType` to be extended to include `Attr *` when available instead of just `attr::Kind` otherwise it won't be possible to determine what attribute should be imported.
1 parent 95c5042 commit d3daa3c

23 files changed

+255
-84
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,19 @@ Removed Compiler Flags
338338
Attribute Changes in Clang
339339
--------------------------
340340

341+
- The ``swift_attr`` can now be applied to types. To make it possible to use imported APIs
342+
in Swift safely there has to be a way to annotate individual parameters and result types
343+
with relevant attributes that indicate that e.g. a block is called on a particular actor
344+
or it accepts a Sendable or global-actor (i.e. ``@MainActor``) isolated parameter.
345+
346+
For example:
347+
348+
.. code-block:: objc
349+
350+
@interface MyService
351+
-(void) handle: (void (^ __attribute__((swift_attr("@Sendable"))))(id)) handler;
352+
@end
353+
341354
- Clang now disallows more than one ``__attribute__((ownership_returns(class, idx)))`` with
342355
different class names attached to one function.
343356

clang/include/clang/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,8 +1719,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
17191719
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
17201720

17211721
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
1722+
QualType equivalentType,
1723+
const Attr *attr = nullptr) const;
1724+
1725+
QualType getAttributedType(const Attr *attr, QualType modifiedType,
17221726
QualType equivalentType) const;
17231727

1728+
QualType getAttributedType(NullabilityKind nullability, QualType modifiedType,
1729+
QualType equivalentType);
1730+
17241731
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
17251732
QualType Wrapped) const;
17261733

clang/include/clang/AST/PropertiesBase.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def APValue : PropertyType { let PassByReference = 1; }
7676
def APValueKind : EnumPropertyType<"APValue::ValueKind">;
7777
def ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">;
7878
def AttrKind : EnumPropertyType<"attr::Kind">;
79+
def Attr : PropertyType<"const Attr *">;
7980
def AutoTypeKeyword : EnumPropertyType;
8081
def Bool : PropertyType<"bool">;
8182
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;

clang/include/clang/AST/Type.h

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class ValueDecl;
6969
class TagDecl;
7070
class TemplateParameterList;
7171
class Type;
72+
class Attr;
7273

7374
enum {
7475
TypeAlignmentInBits = 4,
@@ -6130,21 +6131,29 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
61306131
private:
61316132
friend class ASTContext; // ASTContext creates these
61326133

6134+
const Attr *Attribute;
6135+
61336136
QualType ModifiedType;
61346137
QualType EquivalentType;
61356138

61366139
AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
61376140
QualType equivalent)
6138-
: Type(Attributed, canon, equivalent->getDependence()),
6139-
ModifiedType(modified), EquivalentType(equivalent) {
6140-
AttributedTypeBits.AttrKind = attrKind;
6141-
}
6141+
: AttributedType(canon, attrKind, nullptr, modified, equivalent) {}
6142+
6143+
AttributedType(QualType canon, const Attr *attr, QualType modified,
6144+
QualType equivalent);
6145+
6146+
private:
6147+
AttributedType(QualType canon, attr::Kind attrKind, const Attr *attr,
6148+
QualType modified, QualType equivalent);
61426149

61436150
public:
61446151
Kind getAttrKind() const {
61456152
return static_cast<Kind>(AttributedTypeBits.AttrKind);
61466153
}
61476154

6155+
const Attr *getAttr() const { return Attribute; }
6156+
61486157
QualType getModifiedType() const { return ModifiedType; }
61496158
QualType getEquivalentType() const { return EquivalentType; }
61506159

@@ -6176,25 +6185,6 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
61766185

61776186
std::optional<NullabilityKind> getImmediateNullability() const;
61786187

6179-
/// Retrieve the attribute kind corresponding to the given
6180-
/// nullability kind.
6181-
static Kind getNullabilityAttrKind(NullabilityKind kind) {
6182-
switch (kind) {
6183-
case NullabilityKind::NonNull:
6184-
return attr::TypeNonNull;
6185-
6186-
case NullabilityKind::Nullable:
6187-
return attr::TypeNullable;
6188-
6189-
case NullabilityKind::NullableResult:
6190-
return attr::TypeNullableResult;
6191-
6192-
case NullabilityKind::Unspecified:
6193-
return attr::TypeNullUnspecified;
6194-
}
6195-
llvm_unreachable("Unknown nullability kind.");
6196-
}
6197-
61986188
/// Strip off the top-level nullability annotation on the given
61996189
/// type, if it's there.
62006190
///
@@ -6207,14 +6197,16 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
62076197
static std::optional<NullabilityKind> stripOuterNullability(QualType &T);
62086198

62096199
void Profile(llvm::FoldingSetNodeID &ID) {
6210-
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
6200+
Profile(ID, getAttrKind(), ModifiedType, EquivalentType, Attribute);
62116201
}
62126202

62136203
static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
6214-
QualType modified, QualType equivalent) {
6204+
QualType modified, QualType equivalent,
6205+
const Attr *attr) {
62156206
ID.AddInteger(attrKind);
62166207
ID.AddPointer(modified.getAsOpaquePtr());
62176208
ID.AddPointer(equivalent.getAsOpaquePtr());
6209+
ID.AddPointer(attr);
62186210
}
62196211

62206212
static bool classof(const Type *T) {

clang/include/clang/AST/TypeProperties.td

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,12 +668,16 @@ let Class = AttributedType in {
668668
def : Property<"equivalentType", QualType> {
669669
let Read = [{ node->getEquivalentType() }];
670670
}
671-
def : Property<"attribute", AttrKind> {
671+
def : Property<"attrKind", AttrKind> {
672672
let Read = [{ node->getAttrKind() }];
673673
}
674+
def : Property<"attribute", Attr> {
675+
let Read = [{ node->getAttr() }];
676+
}
674677

675678
def : Creator<[{
676-
return ctx.getAttributedType(attribute, modifiedType, equivalentType);
679+
return ctx.getAttributedType(attrKind, modifiedType,
680+
equivalentType, attribute);
677681
}]>;
678682
}
679683

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2838,7 +2838,7 @@ def SwiftAsyncName : InheritableAttr {
28382838
let Documentation = [SwiftAsyncNameDocs];
28392839
}
28402840

2841-
def SwiftAttr : InheritableAttr {
2841+
def SwiftAttr : DeclOrTypeAttr {
28422842
let Spellings = [GNU<"swift_attr">];
28432843
let Args = [StringArgument<"Attribute">];
28442844
let Documentation = [SwiftAttrDocs];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4507,8 +4507,8 @@ def SwiftAttrDocs : Documentation {
45074507
let Heading = "swift_attr";
45084508
let Content = [{
45094509
The ``swift_attr`` provides a Swift-specific annotation for the declaration
4510-
to which the attribute appertains to. It can be used on any declaration
4511-
in Clang. This kind of annotation is ignored by Clang as it doesn't have any
4510+
or type to which the attribute appertains to. It can be used on any declaration
4511+
or type in Clang. This kind of annotation is ignored by Clang as it doesn't have any
45124512
semantic meaning in languages supported by Clang. The Swift compiler can
45134513
interpret these annotations according to its own rules when importing C or
45144514
Objective-C declarations.

clang/include/clang/Serialization/ASTRecordWriter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class ASTRecordWriter
128128
AddStmt(const_cast<Stmt*>(S));
129129
}
130130

131+
void writeAttr(const Attr *A) { AddAttr(A); }
132+
131133
/// Write an BTFTypeTagAttr object.
132134
void writeBTFTypeTagAttr(const BTFTypeTagAttr *A) { AddAttr(A); }
133135

clang/lib/AST/ASTContext.cpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3552,7 +3552,8 @@ ASTContext::adjustType(QualType Orig,
35523552
const auto *AT = dyn_cast<AttributedType>(Orig);
35533553
return getAttributedType(AT->getAttrKind(),
35543554
adjustType(AT->getModifiedType(), Adjust),
3555-
adjustType(AT->getEquivalentType(), Adjust));
3555+
adjustType(AT->getEquivalentType(), Adjust),
3556+
AT->getAttr());
35563557
}
35573558

35583559
case Type::BTFTagAttributed: {
@@ -5197,24 +5198,54 @@ QualType ASTContext::getUnresolvedUsingType(
51975198

51985199
QualType ASTContext::getAttributedType(attr::Kind attrKind,
51995200
QualType modifiedType,
5200-
QualType equivalentType) const {
5201+
QualType equivalentType,
5202+
const Attr *attr) const {
52015203
llvm::FoldingSetNodeID id;
5202-
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
5204+
AttributedType::Profile(id, attrKind, modifiedType, equivalentType, attr);
52035205

52045206
void *insertPos = nullptr;
52055207
AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
52065208
if (type) return QualType(type, 0);
52075209

5210+
assert(!attr || attr->getKind() == attrKind);
5211+
52085212
QualType canon = getCanonicalType(equivalentType);
5209-
type = new (*this, alignof(AttributedType))
5210-
AttributedType(canon, attrKind, modifiedType, equivalentType);
5213+
type = new (*this, alignof(AttributedType))
5214+
AttributedType(canon, attrKind, attr, modifiedType, equivalentType);
52115215

52125216
Types.push_back(type);
52135217
AttributedTypes.InsertNode(type, insertPos);
52145218

52155219
return QualType(type, 0);
52165220
}
52175221

5222+
QualType ASTContext::getAttributedType(const Attr *attr, QualType modifiedType,
5223+
QualType equivalentType) const {
5224+
return getAttributedType(attr->getKind(), modifiedType, equivalentType, attr);
5225+
}
5226+
5227+
QualType ASTContext::getAttributedType(NullabilityKind nullability,
5228+
QualType modifiedType,
5229+
QualType equivalentType) {
5230+
switch (nullability) {
5231+
case NullabilityKind::NonNull:
5232+
return getAttributedType(attr::TypeNonNull, modifiedType, equivalentType);
5233+
5234+
case NullabilityKind::Nullable:
5235+
return getAttributedType(attr::TypeNullable, modifiedType, equivalentType);
5236+
5237+
case NullabilityKind::NullableResult:
5238+
return getAttributedType(attr::TypeNullableResult, modifiedType,
5239+
equivalentType);
5240+
5241+
case NullabilityKind::Unspecified:
5242+
return getAttributedType(attr::TypeNullUnspecified, modifiedType,
5243+
equivalentType);
5244+
}
5245+
5246+
llvm_unreachable("Unknown nullability kind");
5247+
}
5248+
52185249
QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
52195250
QualType Wrapped) const {
52205251
llvm::FoldingSetNodeID ID;
@@ -7537,8 +7568,8 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const {
75377568

75387569
// int x[_Nullable] -> int * _Nullable
75397570
if (auto Nullability = Ty->getNullability()) {
7540-
Result = const_cast<ASTContext *>(this)->getAttributedType(
7541-
AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
7571+
Result = const_cast<ASTContext *>(this)->getAttributedType(*Nullability,
7572+
Result, Result);
75427573
}
75437574
return Result;
75447575
}
@@ -13773,7 +13804,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
1377313804
return QualType();
1377413805
// FIXME: It's inefficient to have to unify the modified types.
1377513806
return Ctx.getAttributedType(Kind, Ctx.getCommonSugaredType(MX, MY),
13776-
Ctx.getQualifiedType(Underlying));
13807+
Ctx.getQualifiedType(Underlying),
13808+
AX->getAttr());
1377713809
}
1377813810
case Type::BTFTagAttributed: {
1377913811
const auto *BX = cast<BTFTagAttributedType>(X);

clang/lib/AST/ASTDiagnostic.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
8585
QualType SugarRT = FT->getReturnType();
8686
QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);
8787
if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
88-
RT = Context.getAttributedType(
89-
AttributedType::getNullabilityAttrKind(*nullability), RT, RT);
88+
RT = Context.getAttributedType(*nullability, RT, RT);
9089
}
9190

9291
bool DesugarArgument = false;
@@ -97,8 +96,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
9796
QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);
9897
if (auto nullability =
9998
AttributedType::stripOuterNullability(SugarPT)) {
100-
PT = Context.getAttributedType(
101-
AttributedType::getNullabilityAttrKind(*nullability), PT, PT);
99+
PT = Context.getAttributedType(*nullability, PT, PT);
102100
}
103101
Args.push_back(PT);
104102
}

0 commit comments

Comments
 (0)