[Sema] Directly use written attributes in ObjC (#179703)

Clang's AST builder uses the `getPropertyAttributesAsWritten()` method
that contains the bitmasks of only the attributes present in the source,
and not the default attributes that are present in
`getPropertyAttributes()`. This method was relevant in the past when two
separate enums existed for Objective-C property attributes, and had to
be updated whenever new property attributes were introduced. As of this
commit, nullability attributes are not present when written due to the
method not containing the bitmask comparison for the `nullable` and
`null_resettable` attributes.

9721fbf85b83c1cb67cea542c5558f99a07766cf consolidated the two property
attribute enums into a single
enum. With this change, the AST can directly store the written
attributes without having to construct the bitmask again. This commit
removes the `getPropertyAttributesAsWritten()` method and updates the
AST to directly store the written attributes instead.

rdar://131053727
This commit is contained in:
Prajwal Nadig 2026-02-06 15:01:50 +00:00 committed by GitHub
parent 21f3875ffd
commit 85eb10e270
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 38 deletions

View File

@ -246,6 +246,7 @@ Bug Fixes to C++ Support
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed a bug where explicit nullability property attributes were not stored in AST nodes in Objective-C. (#GH179703)
Miscellaneous Bug Fixes
^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -43,7 +43,7 @@ enum Kind {
// Also, don't forget to update the Clang C API at CXObjCPropertyAttrKind and
// clang_Cursor_getObjCPropertyAttributes.
};
} // namespace ObjCPropertyAttribute::Kind
} // namespace ObjCPropertyAttribute
enum {
/// Number of bits fitting all the property attributes.

View File

@ -269,41 +269,6 @@ Decl *SemaObjC::ActOnProperty(Scope *S, SourceLocation AtLoc,
return Res;
}
static ObjCPropertyAttribute::Kind
makePropertyAttributesAsWritten(unsigned Attributes) {
unsigned attributesAsWritten = 0;
if (Attributes & ObjCPropertyAttribute::kind_readonly)
attributesAsWritten |= ObjCPropertyAttribute::kind_readonly;
if (Attributes & ObjCPropertyAttribute::kind_readwrite)
attributesAsWritten |= ObjCPropertyAttribute::kind_readwrite;
if (Attributes & ObjCPropertyAttribute::kind_getter)
attributesAsWritten |= ObjCPropertyAttribute::kind_getter;
if (Attributes & ObjCPropertyAttribute::kind_setter)
attributesAsWritten |= ObjCPropertyAttribute::kind_setter;
if (Attributes & ObjCPropertyAttribute::kind_assign)
attributesAsWritten |= ObjCPropertyAttribute::kind_assign;
if (Attributes & ObjCPropertyAttribute::kind_retain)
attributesAsWritten |= ObjCPropertyAttribute::kind_retain;
if (Attributes & ObjCPropertyAttribute::kind_strong)
attributesAsWritten |= ObjCPropertyAttribute::kind_strong;
if (Attributes & ObjCPropertyAttribute::kind_weak)
attributesAsWritten |= ObjCPropertyAttribute::kind_weak;
if (Attributes & ObjCPropertyAttribute::kind_copy)
attributesAsWritten |= ObjCPropertyAttribute::kind_copy;
if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
attributesAsWritten |= ObjCPropertyAttribute::kind_unsafe_unretained;
if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
attributesAsWritten |= ObjCPropertyAttribute::kind_nonatomic;
if (Attributes & ObjCPropertyAttribute::kind_atomic)
attributesAsWritten |= ObjCPropertyAttribute::kind_atomic;
if (Attributes & ObjCPropertyAttribute::kind_class)
attributesAsWritten |= ObjCPropertyAttribute::kind_class;
if (Attributes & ObjCPropertyAttribute::kind_direct)
attributesAsWritten |= ObjCPropertyAttribute::kind_direct;
return (ObjCPropertyAttribute::Kind)attributesAsWritten;
}
static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
SourceLocation LParenLoc, SourceLocation &Loc) {
if (LParenLoc.isMacroID())
@ -629,7 +594,7 @@ ObjCPropertyDecl *SemaObjC::CreatePropertyDecl(
PDecl->setGetterName(GetterSel, GetterNameLoc);
PDecl->setSetterName(SetterSel, SetterNameLoc);
PDecl->setPropertyAttributesAsWritten(
makePropertyAttributesAsWritten(AttributesAsWritten));
static_cast<ObjCPropertyAttribute::Kind>(AttributesAsWritten));
SemaRef.ProcessDeclAttributes(S, PDecl, FD.D);

View File

@ -1,6 +1,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify
// RUN: FileCheck %s --input-file %t/output.symbols.json
@protocol Protocol
@property(class) int myProtocolTypeProp;
@ -14,6 +15,30 @@
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myInterfaceTypeProp $ c:objc(cs)Interface"
@property int myInterfaceInstanceProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myInterfaceInstanceProp $ c:objc(cs)Interface"
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NULLABLE
@property(nullable, strong) id myNullableProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myNullableProp $ c:objc(cs)Interface"
// NULLABLE: "!testLabel": "c:objc(cs)Interface(py)myNullableProp"
// NULLABLE: "declarationFragments": [
// NULLABLE: "kind": "keyword",
// NULLABLE-NEXT: "spelling": "@property"
// NULLABLE: "kind": "keyword",
// NULLABLE-NEXT: "spelling": "strong"
// NULLABLE: "kind": "keyword",
// NULLABLE-NEXT: "spelling": "nullable"
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NULLRESETTABLE
@property(null_resettable, strong) id myNullResettableProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myNullResettableProp $ c:objc(cs)Interface"
// NULLRESETTABLE: "!testLabel": "c:objc(cs)Interface(py)myNullResettableProp"
// NULLABLE: "declarationFragments": [
// NULLABLE: "kind": "keyword",
// NULLABLE-NEXT: "spelling": "@property"
// NULLABLE: "kind": "keyword",
// NULLABLE-NEXT: "spelling": "strong"
// NULLABLE: "kind": "keyword",
// NULLABLE-NEXT: "spelling": "null_resettable"
@end
@interface Interface (Category) <Protocol>