Skip to content

Commit 19b39da

Browse files
xedinNoumanAmir657
authored andcommitted
[clang/AST] Make it possible to use SwiftAttr in type context (llvm#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 7a02eeb commit 19b39da

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
}

clang/lib/AST/ASTImporter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,8 +1580,9 @@ ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
15801580
if (!ToEquivalentTypeOrErr)
15811581
return ToEquivalentTypeOrErr.takeError();
15821582

1583-
return Importer.getToContext().getAttributedType(T->getAttrKind(),
1584-
*ToModifiedTypeOrErr, *ToEquivalentTypeOrErr);
1583+
return Importer.getToContext().getAttributedType(
1584+
T->getAttrKind(), *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr,
1585+
T->getAttr());
15851586
}
15861587

15871588
ExpectedType

clang/lib/AST/Type.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,8 +1241,8 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
12411241
== T->getEquivalentType().getAsOpaquePtr())
12421242
return QualType(T, 0);
12431243

1244-
return Ctx.getAttributedType(T->getAttrKind(), modifiedType,
1245-
equivalentType);
1244+
return Ctx.getAttributedType(T->getAttrKind(), modifiedType, equivalentType,
1245+
T->getAttr());
12461246
}
12471247

12481248
QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
@@ -1545,7 +1545,8 @@ struct SubstObjCTypeArgsVisitor
15451545

15461546
// Rebuild the attributed type.
15471547
return Ctx.getAttributedType(newAttrType->getAttrKind(),
1548-
newAttrType->getModifiedType(), newEquivType);
1548+
newAttrType->getModifiedType(), newEquivType,
1549+
newAttrType->getAttr());
15491550
}
15501551
};
15511552

@@ -4115,6 +4116,19 @@ bool RecordType::hasConstFields() const {
41154116
return false;
41164117
}
41174118

4119+
AttributedType::AttributedType(QualType canon, const Attr *attr,
4120+
QualType modified, QualType equivalent)
4121+
: AttributedType(canon, attr->getKind(), attr, modified, equivalent) {}
4122+
4123+
AttributedType::AttributedType(QualType canon, attr::Kind attrKind,
4124+
const Attr *attr, QualType modified,
4125+
QualType equivalent)
4126+
: Type(Attributed, canon, equivalent->getDependence()), Attribute(attr),
4127+
ModifiedType(modified), EquivalentType(equivalent) {
4128+
AttributedTypeBits.AttrKind = attrKind;
4129+
assert(!attr || attr->getKind() == attrKind);
4130+
}
4131+
41184132
bool AttributedType::isQualifier() const {
41194133
// FIXME: Generate this with TableGen.
41204134
switch (getAttrKind()) {

clang/lib/AST/TypePrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,6 +1934,14 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19341934
return;
19351935
}
19361936

1937+
if (T->getAttrKind() == attr::SwiftAttr) {
1938+
if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(T->getAttr())) {
1939+
OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
1940+
<< "\")))";
1941+
}
1942+
return;
1943+
}
1944+
19371945
OS << " __attribute__((";
19381946
switch (T->getAttrKind()) {
19391947
#define TYPE_ATTR(NAME)
@@ -1994,6 +2002,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19942002
case attr::NonAllocating:
19952003
case attr::Blocking:
19962004
case attr::Allocating:
2005+
case attr::SwiftAttr:
19972006
llvm_unreachable("This attribute should have been handled already");
19982007

19992008
case attr::NSReturnsRetained:

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3332,9 +3332,7 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam,
33323332
}
33333333
} else {
33343334
QualType NewT = NewParam->getType();
3335-
NewT = S.Context.getAttributedType(
3336-
AttributedType::getNullabilityAttrKind(*Oldnullability),
3337-
NewT, NewT);
3335+
NewT = S.Context.getAttributedType(*Oldnullability, NewT, NewT);
33383336
NewParam->setType(NewT);
33393337
}
33403338
}

clang/lib/Sema/SemaDeclObjC.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,9 +4572,7 @@ static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,
45724572
return type;
45734573

45744574
// Otherwise, provide the result with the same nullability.
4575-
return S.Context.getAttributedType(
4576-
AttributedType::getNullabilityAttrKind(*prevNullability),
4577-
type, type);
4575+
return S.Context.getAttributedType(*prevNullability, type, type);
45784576
}
45794577

45804578
/// Merge information from the declaration of a method in the \@interface

clang/lib/Sema/SemaExpr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8757,8 +8757,7 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
87578757
ResTy = ResTy.getSingleStepDesugaredType(Ctx);
87588758

87598759
// Create a new AttributedType with the new nullability kind.
8760-
auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind);
8761-
return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
8760+
return Ctx.getAttributedType(MergedKind, ResTy, ResTy);
87628761
}
87638762

87648763
ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,

0 commit comments

Comments
 (0)