Skip to content

[clang/AST] Make it possible to use SwiftAttr in type context #7918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1615,8 +1615,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;

QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
QualType equivalentType,
const Attr *attr = nullptr) const;

QualType getAttributedType(const Attr *attr, QualType modifiedType,
QualType equivalentType) const;

QualType getAttributedType(NullabilityKind nullability, QualType modifiedType,
QualType equivalentType);

QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped);

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def APValue : PropertyType { let PassByReference = 1; }
def APValueKind : EnumPropertyType<"APValue::ValueKind">;
def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
def AttrKind : EnumPropertyType<"attr::Kind">;
def Attr : PropertyType<"const Attr *">;
def AutoTypeKeyword : EnumPropertyType;
def Bool : PropertyType<"bool">;
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
Expand Down
35 changes: 15 additions & 20 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class ConceptDecl;
class TagDecl;
class TemplateParameterList;
class Type;
class Attr;

enum {
TypeAlignmentInBits = 4,
Expand Down Expand Up @@ -5073,13 +5074,24 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
private:
friend class ASTContext; // ASTContext creates these

const Attr *Attribute;

QualType ModifiedType;
QualType EquivalentType;

AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
QualType equivalent)
: AttributedType(canon, attrKind, nullptr, modified, equivalent) {}

AttributedType(QualType canon, const Attr *attr, QualType modified,
QualType equivalent);

private:
AttributedType(QualType canon, attr::Kind attrKind, const Attr *attr,
QualType modified, QualType equivalent)
: Type(Attributed, canon, equivalent->getDependence()),
ModifiedType(modified), EquivalentType(equivalent) {
Attribute(attr), ModifiedType(modified),
EquivalentType(equivalent) {
AttributedTypeBits.AttrKind = attrKind;
}

Expand All @@ -5088,6 +5100,8 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
return static_cast<Kind>(AttributedTypeBits.AttrKind);
}

const Attr *getAttr() const { return Attribute; }

QualType getModifiedType() const { return ModifiedType; }
QualType getEquivalentType() const { return EquivalentType; }

Expand Down Expand Up @@ -5119,25 +5133,6 @@ class AttributedType : public Type, public llvm::FoldingSetNode {

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

/// Retrieve the attribute kind corresponding to the given
/// nullability kind.
static Kind getNullabilityAttrKind(NullabilityKind kind) {
switch (kind) {
case NullabilityKind::NonNull:
return attr::TypeNonNull;

case NullabilityKind::Nullable:
return attr::TypeNullable;

case NullabilityKind::NullableResult:
return attr::TypeNullableResult;

case NullabilityKind::Unspecified:
return attr::TypeNullUnspecified;
}
llvm_unreachable("Unknown nullability kind.");
}

/// Strip off the top-level nullability annotation on the given
/// type, if it's there.
///
Expand Down
8 changes: 6 additions & 2 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -614,12 +614,16 @@ let Class = AttributedType in {
def : Property<"equivalentType", QualType> {
let Read = [{ node->getEquivalentType() }];
}
def : Property<"attribute", AttrKind> {
def : Property<"attrKind", AttrKind> {
let Read = [{ node->getAttrKind() }];
}
def : Property<"attribute", Attr> {
let Read = [{ node->getAttr() }];
}

def : Creator<[{
return ctx.getAttributedType(attribute, modifiedType, equivalentType);
return ctx.getAttributedType(attrKind, modifiedType,
equivalentType, attribute);
}]>;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2519,7 +2519,7 @@ def SwiftAsyncName : InheritableAttr {
let Documentation = [SwiftAsyncNameDocs];
}

def SwiftAttr : InheritableAttr {
def SwiftAttr : DeclOrTypeAttr {
let Spellings = [GNU<"swift_attr">];
let Args = [StringArgument<"Attribute">];
let Documentation = [SwiftAttrDocs];
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -4372,8 +4372,8 @@ def SwiftAttrDocs : Documentation {
let Heading = "swift_attr";
let Content = [{
The ``swift_attr`` provides a Swift-specific annotation for the declaration
to which the attribute appertains to. It can be used on any declaration
in Clang. This kind of annotation is ignored by Clang as it doesn't have any
or type to which the attribute appertains to. It can be used on any declaration
or type in Clang. This kind of annotation is ignored by Clang as it doesn't have any
semantic meaning in languages supported by Clang. The Swift compiler can
interpret these annotations according to its own rules when importing C or
Objective-C declarations.
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Serialization/ASTRecordWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ class ASTRecordWriter
AddStmt(const_cast<Stmt*>(S));
}

void writeAttr(const Attr *A) { AddAttr(A); }

/// Write an BTFTypeTagAttr object.
void writeBTFTypeTagAttr(const BTFTypeTagAttr *A) { AddAttr(A); }

Expand Down
47 changes: 40 additions & 7 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3147,11 +3147,13 @@ QualType ASTContext::getFunctionTypeWithExceptionSpec(
MQT->getMacroIdentifier());

// Might have a calling-convention attribute.
if (const auto *AT = dyn_cast<AttributedType>(Orig))
if (const auto *AT = dyn_cast<AttributedType>(Orig)) {
return getAttributedType(
AT->getAttrKind(),
getFunctionTypeWithExceptionSpec(AT->getModifiedType(), ESI),
getFunctionTypeWithExceptionSpec(AT->getEquivalentType(), ESI));
getFunctionTypeWithExceptionSpec(AT->getEquivalentType(), ESI),
AT->getAttr());
}

// Anything else must be a function type. Rebuild it with the new exception
// specification.
Expand Down Expand Up @@ -4730,24 +4732,54 @@ QualType ASTContext::getUnresolvedUsingType(

QualType ASTContext::getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType) const {
QualType equivalentType,
const Attr *attr) const {
llvm::FoldingSetNodeID id;
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);

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

assert(!attr || attr->getKind() == attrKind);

QualType canon = getCanonicalType(equivalentType);
type = new (*this, TypeAlignment)
AttributedType(canon, attrKind, modifiedType, equivalentType);
AttributedType(canon, attrKind, attr, modifiedType, equivalentType);

Types.push_back(type);
AttributedTypes.InsertNode(type, insertPos);

return QualType(type, 0);
}

QualType ASTContext::getAttributedType(const Attr *attr, QualType modifiedType,
QualType equivalentType) const {
return getAttributedType(attr->getKind(), modifiedType, equivalentType, attr);
}

QualType ASTContext::getAttributedType(NullabilityKind nullability,
QualType modifiedType,
QualType equivalentType) {
switch (nullability) {
case NullabilityKind::NonNull:
return getAttributedType(attr::TypeNonNull, modifiedType, equivalentType);

case NullabilityKind::Nullable:
return getAttributedType(attr::TypeNullable, modifiedType, equivalentType);

case NullabilityKind::NullableResult:
return getAttributedType(attr::TypeNullableResult, modifiedType,
equivalentType);

case NullabilityKind::Unspecified:
return getAttributedType(attr::TypeNullUnspecified, modifiedType,
equivalentType);
}

llvm_unreachable("Unknown nullability kind");
}

QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped) {
llvm::FoldingSetNodeID ID;
Expand Down Expand Up @@ -6916,8 +6948,8 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const {

// int x[_Nullable] -> int * _Nullable
if (auto Nullability = Ty->getNullability()) {
Result = const_cast<ASTContext *>(this)->getAttributedType(
AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
Result = const_cast<ASTContext *>(this)->getAttributedType(*Nullability,
Result, Result);
}
return Result;
}
Expand Down Expand Up @@ -12996,7 +13028,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
return QualType();
// FIXME: It's inefficient to have to unify the modified types.
return Ctx.getAttributedType(Kind, Ctx.getCommonSugaredType(MX, MY),
Ctx.getQualifiedType(Underlying));
Ctx.getQualifiedType(Underlying),
AX->getAttr());
}
case Type::BTFTagAttributed: {
const auto *BX = cast<BTFTagAttributedType>(X);
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/AST/ASTDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
QualType SugarRT = FT->getReturnType();
QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);
if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
RT = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*nullability), RT, RT);
RT = Context.getAttributedType(*nullability, RT, RT);
}

bool DesugarArgument = false;
Expand All @@ -97,8 +96,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);
if (auto nullability =
AttributedType::stripOuterNullability(SugarPT)) {
PT = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*nullability), PT, PT);
PT = Context.getAttributedType(*nullability, PT, PT);
}
Args.push_back(PT);
}
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,8 +1505,9 @@ ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
if (!ToEquivalentTypeOrErr)
return ToEquivalentTypeOrErr.takeError();

return Importer.getToContext().getAttributedType(T->getAttrKind(),
*ToModifiedTypeOrErr, *ToEquivalentTypeOrErr);
return Importer.getToContext().getAttributedType(
T->getAttrKind(), *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr,
T->getAttr());
}

ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1159,8 +1159,8 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
== T->getEquivalentType().getAsOpaquePtr())
return QualType(T, 0);

return Ctx.getAttributedType(T->getAttrKind(), modifiedType,
equivalentType);
return Ctx.getAttributedType(T->getAttrKind(), modifiedType, equivalentType,
T->getAttr());
}

QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
Expand Down Expand Up @@ -1458,7 +1458,8 @@ struct SubstObjCTypeArgsVisitor

// Rebuild the attributed type.
return Ctx.getAttributedType(newAttrType->getAttrKind(),
newAttrType->getModifiedType(), newEquivType);
newAttrType->getModifiedType(), newEquivType,
newAttrType->getAttr());
}
};

Expand Down Expand Up @@ -3755,6 +3756,10 @@ bool RecordType::hasConstFields() const {
return false;
}

AttributedType::AttributedType(QualType canon, const Attr *attr,
QualType modified, QualType equivalent)
: AttributedType(canon, attr->getKind(), attr, modified, equivalent) {}

bool AttributedType::isQualifier() const {
// FIXME: Generate this with TableGen.
switch (getAttrKind()) {
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,14 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
return;
}

if (T->getAttrKind() == attr::SwiftAttr) {
if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(T->getAttr())) {
OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
<< "\")))";
}
return;
}

OS << " __attribute__((";
switch (T->getAttrKind()) {
#define TYPE_ATTR(NAME)
Expand Down Expand Up @@ -1826,6 +1834,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::AnnotateType:
case attr::WebAssemblyFuncref:
case attr::ArmStreaming:
case attr::SwiftAttr:
llvm_unreachable("This attribute should have been handled already");

case attr::NSReturnsRetained:
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3430,9 +3430,7 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam,
}
} else {
QualType NewT = NewParam->getType();
NewT = S.Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*Oldnullability),
NewT, NewT);
NewT = S.Context.getAttributedType(*Oldnullability, NewT, NewT);
NewParam->setType(NewT);
}
}
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6347,11 +6347,16 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
}

static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (AL.isInvalid() || AL.isUsedAsTypeAttr())
return;

// Make sure that there is a string literal as the annotation's single
// argument.
StringRef Str;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) {
AL.setInvalid();
return;
}

D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str));
}
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Sema/SemaDeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4623,9 +4623,7 @@ static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,
return type;

// Otherwise, provide the result with the same nullability.
return S.Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*prevNullability),
type, type);
return S.Context.getAttributedType(*prevNullability, type, type);
}

/// Merge information from the declaration of a method in the \@interface
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9593,8 +9593,7 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
ResTy = ResTy.getSingleStepDesugaredType(Ctx);

// Create a new AttributedType with the new nullability kind.
auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind);
return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
return Ctx.getAttributedType(MergedKind, ResTy, ResTy);
}

/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
Expand Down
Loading