Skip to content

Commit c8784f8

Browse files
committed
[clang/AST] Make it possible to use SwiftAttr in type context
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 0215579 commit c8784f8

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
@@ -241,6 +241,19 @@ Removed Compiler Flags
241241
Attribute Changes in Clang
242242
--------------------------
243243

244+
- The ``swift_attr`` can now be applied to types. To make it possible to use imported APIs
245+
in Swift safely there has to be a way to annotate individual parameters and result types
246+
with relevant attributes that indicate that e.g. a block is called on a particular actor
247+
or it accepts a Sendable or global-actor (i.e. ``@MainActor``) isolated parameter.
248+
249+
For example:
250+
251+
.. code-block:: objc
252+
253+
@interface MyService
254+
-(void) handle: (void (^ __attribute__((swift_attr("@Sendable"))))(id)) handler;
255+
@end
256+
244257
- Clang now disallows more than one ``__attribute__((ownership_returns(class, idx)))`` with
245258
different class names attached to one function.
246259

clang/include/clang/AST/ASTContext.h

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

17121712
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
1713+
QualType equivalentType,
1714+
const Attr *attr = nullptr) const;
1715+
1716+
QualType getAttributedType(const Attr *attr, QualType modifiedType,
17131717
QualType equivalentType) const;
17141718

1719+
QualType getAttributedType(NullabilityKind nullability, QualType modifiedType,
1720+
QualType equivalentType);
1721+
17151722
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
17161723
QualType Wrapped) const;
17171724

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
@@ -68,6 +68,7 @@ class ValueDecl;
6868
class TagDecl;
6969
class TemplateParameterList;
7070
class Type;
71+
class Attr;
7172

7273
enum {
7374
TypeAlignmentInBits = 4,
@@ -6037,21 +6038,29 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
60376038
private:
60386039
friend class ASTContext; // ASTContext creates these
60396040

6041+
const Attr *Attribute;
6042+
60406043
QualType ModifiedType;
60416044
QualType EquivalentType;
60426045

60436046
AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
60446047
QualType equivalent)
6045-
: Type(Attributed, canon, equivalent->getDependence()),
6046-
ModifiedType(modified), EquivalentType(equivalent) {
6047-
AttributedTypeBits.AttrKind = attrKind;
6048-
}
6048+
: AttributedType(canon, attrKind, nullptr, modified, equivalent) {}
6049+
6050+
AttributedType(QualType canon, const Attr *attr, QualType modified,
6051+
QualType equivalent);
6052+
6053+
private:
6054+
AttributedType(QualType canon, attr::Kind attrKind, const Attr *attr,
6055+
QualType modified, QualType equivalent);
60496056

60506057
public:
60516058
Kind getAttrKind() const {
60526059
return static_cast<Kind>(AttributedTypeBits.AttrKind);
60536060
}
60546061

6062+
const Attr *getAttr() const { return Attribute; }
6063+
60556064
QualType getModifiedType() const { return ModifiedType; }
60566065
QualType getEquivalentType() const { return EquivalentType; }
60576066

@@ -6083,25 +6092,6 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
60836092

60846093
std::optional<NullabilityKind> getImmediateNullability() const;
60856094

6086-
/// Retrieve the attribute kind corresponding to the given
6087-
/// nullability kind.
6088-
static Kind getNullabilityAttrKind(NullabilityKind kind) {
6089-
switch (kind) {
6090-
case NullabilityKind::NonNull:
6091-
return attr::TypeNonNull;
6092-
6093-
case NullabilityKind::Nullable:
6094-
return attr::TypeNullable;
6095-
6096-
case NullabilityKind::NullableResult:
6097-
return attr::TypeNullableResult;
6098-
6099-
case NullabilityKind::Unspecified:
6100-
return attr::TypeNullUnspecified;
6101-
}
6102-
llvm_unreachable("Unknown nullability kind.");
6103-
}
6104-
61056095
/// Strip off the top-level nullability annotation on the given
61066096
/// type, if it's there.
61076097
///
@@ -6114,14 +6104,16 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
61146104
static std::optional<NullabilityKind> stripOuterNullability(QualType &T);
61156105

61166106
void Profile(llvm::FoldingSetNodeID &ID) {
6117-
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
6107+
Profile(ID, getAttrKind(), ModifiedType, EquivalentType, Attribute);
61186108
}
61196109

61206110
static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
6121-
QualType modified, QualType equivalent) {
6111+
QualType modified, QualType equivalent,
6112+
const Attr *attr) {
61226113
ID.AddInteger(attrKind);
61236114
ID.AddPointer(modified.getAsOpaquePtr());
61246115
ID.AddPointer(equivalent.getAsOpaquePtr());
6116+
ID.AddPointer(attr);
61256117
}
61266118

61276119
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
@@ -2842,7 +2842,7 @@ def SwiftAsyncName : InheritableAttr {
28422842
let Documentation = [SwiftAsyncNameDocs];
28432843
}
28442844

2845-
def SwiftAttr : InheritableAttr {
2845+
def SwiftAttr : DeclOrTypeAttr {
28462846
let Spellings = [GNU<"swift_attr">];
28472847
let Args = [StringArgument<"Attribute">];
28482848
let Documentation = [SwiftAttrDocs];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4495,8 +4495,8 @@ def SwiftAttrDocs : Documentation {
44954495
let Heading = "swift_attr";
44964496
let Content = [{
44974497
The ``swift_attr`` provides a Swift-specific annotation for the declaration
4498-
to which the attribute appertains to. It can be used on any declaration
4499-
in Clang. This kind of annotation is ignored by Clang as it doesn't have any
4498+
or type to which the attribute appertains to. It can be used on any declaration
4499+
or type in Clang. This kind of annotation is ignored by Clang as it doesn't have any
45004500
semantic meaning in languages supported by Clang. The Swift compiler can
45014501
interpret these annotations according to its own rules when importing C or
45024502
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
@@ -3543,7 +3543,8 @@ ASTContext::adjustType(QualType Orig,
35433543
const auto *AT = dyn_cast<AttributedType>(Orig);
35443544
return getAttributedType(AT->getAttrKind(),
35453545
adjustType(AT->getModifiedType(), Adjust),
3546-
adjustType(AT->getEquivalentType(), Adjust));
3546+
adjustType(AT->getEquivalentType(), Adjust),
3547+
AT->getAttr());
35473548
}
35483549

35493550
case Type::BTFTagAttributed: {
@@ -5181,24 +5182,54 @@ QualType ASTContext::getUnresolvedUsingType(
51815182

51825183
QualType ASTContext::getAttributedType(attr::Kind attrKind,
51835184
QualType modifiedType,
5184-
QualType equivalentType) const {
5185+
QualType equivalentType,
5186+
const Attr *attr) const {
51855187
llvm::FoldingSetNodeID id;
5186-
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
5188+
AttributedType::Profile(id, attrKind, modifiedType, equivalentType, attr);
51875189

51885190
void *insertPos = nullptr;
51895191
AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
51905192
if (type) return QualType(type, 0);
51915193

5194+
assert(!attr || attr->getKind() == attrKind);
5195+
51925196
QualType canon = getCanonicalType(equivalentType);
5193-
type = new (*this, alignof(AttributedType))
5194-
AttributedType(canon, attrKind, modifiedType, equivalentType);
5197+
type = new (*this, alignof(AttributedType))
5198+
AttributedType(canon, attrKind, attr, modifiedType, equivalentType);
51955199

51965200
Types.push_back(type);
51975201
AttributedTypes.InsertNode(type, insertPos);
51985202

51995203
return QualType(type, 0);
52005204
}
52015205

5206+
QualType ASTContext::getAttributedType(const Attr *attr, QualType modifiedType,
5207+
QualType equivalentType) const {
5208+
return getAttributedType(attr->getKind(), modifiedType, equivalentType, attr);
5209+
}
5210+
5211+
QualType ASTContext::getAttributedType(NullabilityKind nullability,
5212+
QualType modifiedType,
5213+
QualType equivalentType) {
5214+
switch (nullability) {
5215+
case NullabilityKind::NonNull:
5216+
return getAttributedType(attr::TypeNonNull, modifiedType, equivalentType);
5217+
5218+
case NullabilityKind::Nullable:
5219+
return getAttributedType(attr::TypeNullable, modifiedType, equivalentType);
5220+
5221+
case NullabilityKind::NullableResult:
5222+
return getAttributedType(attr::TypeNullableResult, modifiedType,
5223+
equivalentType);
5224+
5225+
case NullabilityKind::Unspecified:
5226+
return getAttributedType(attr::TypeNullUnspecified, modifiedType,
5227+
equivalentType);
5228+
}
5229+
5230+
llvm_unreachable("Unknown nullability kind");
5231+
}
5232+
52025233
QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
52035234
QualType Wrapped) const {
52045235
llvm::FoldingSetNodeID ID;
@@ -7530,8 +7561,8 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const {
75307561

75317562
// int x[_Nullable] -> int * _Nullable
75327563
if (auto Nullability = Ty->getNullability()) {
7533-
Result = const_cast<ASTContext *>(this)->getAttributedType(
7534-
AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
7564+
Result = const_cast<ASTContext *>(this)->getAttributedType(*Nullability,
7565+
Result, Result);
75357566
}
75367567
return Result;
75377568
}
@@ -13748,7 +13779,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
1374813779
return QualType();
1374913780
// FIXME: It's inefficient to have to unify the modified types.
1375013781
return Ctx.getAttributedType(Kind, Ctx.getCommonSugaredType(MX, MY),
13751-
Ctx.getQualifiedType(Underlying));
13782+
Ctx.getQualifiedType(Underlying),
13783+
AX->getAttr());
1375213784
}
1375313785
case Type::BTFTagAttributed: {
1375413786
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

@@ -4104,6 +4105,19 @@ bool RecordType::hasConstFields() const {
41044105
return false;
41054106
}
41064107

4108+
AttributedType::AttributedType(QualType canon, const Attr *attr,
4109+
QualType modified, QualType equivalent)
4110+
: AttributedType(canon, attr->getKind(), attr, modified, equivalent) {}
4111+
4112+
AttributedType::AttributedType(QualType canon, attr::Kind attrKind,
4113+
const Attr *attr, QualType modified,
4114+
QualType equivalent)
4115+
: Type(Attributed, canon, equivalent->getDependence()), Attribute(attr),
4116+
ModifiedType(modified), EquivalentType(equivalent) {
4117+
AttributedTypeBits.AttrKind = attrKind;
4118+
assert(!attr || attr->getKind() == attrKind);
4119+
}
4120+
41074121
bool AttributedType::isQualifier() const {
41084122
// FIXME: Generate this with TableGen.
41094123
switch (getAttrKind()) {

clang/lib/AST/TypePrinter.cpp

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

1935+
if (T->getAttrKind() == attr::SwiftAttr) {
1936+
if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(T->getAttr())) {
1937+
OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
1938+
<< "\")))";
1939+
}
1940+
return;
1941+
}
1942+
19351943
OS << " __attribute__((";
19361944
switch (T->getAttrKind()) {
19371945
#define TYPE_ATTR(NAME)
@@ -1992,6 +2000,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19922000
case attr::NonAllocating:
19932001
case attr::Blocking:
19942002
case attr::Allocating:
2003+
case attr::SwiftAttr:
19952004
llvm_unreachable("This attribute should have been handled already");
19962005

19972006
case attr::NSReturnsRetained:

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,9 +3329,7 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam,
33293329
}
33303330
} else {
33313331
QualType NewT = NewParam->getType();
3332-
NewT = S.Context.getAttributedType(
3333-
AttributedType::getNullabilityAttrKind(*Oldnullability),
3334-
NewT, NewT);
3332+
NewT = S.Context.getAttributedType(*Oldnullability, NewT, NewT);
33353333
NewParam->setType(NewT);
33363334
}
33373335
}

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
@@ -8738,8 +8738,7 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
87388738
ResTy = ResTy.getSingleStepDesugaredType(Ctx);
87398739

87408740
// Create a new AttributedType with the new nullability kind.
8741-
auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind);
8742-
return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
8741+
return Ctx.getAttributedType(MergedKind, ResTy, ResTy);
87438742
}
87448743

87458744
ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,

0 commit comments

Comments
 (0)