https://github.com/DougGregor created 
https://github.com/llvm/llvm-project/pull/149951

Forward declarations can still have useful API notes applied to them. When the 
use of the tag is not a definition, apply the API notes immediately.

Fixes rdar://156288588.

>From 00c5c51eb4bc359d45f22377b6d9fc4675559b7b Mon Sep 17 00:00:00 2001
From: Doug Gregor <dgre...@apple.com>
Date: Mon, 21 Jul 2025 14:04:59 -0700
Subject: [PATCH] [API Notes] Attach API notes to forward declarations of tags

Forward declarations can still have useful API notes applied to them.
When the use of the tag is not a definition, apply the API notes
immediately.

Fixes rdar://156288588.
---
 clang/lib/Sema/SemaDecl.cpp                               | 4 ++++
 clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes | 4 ++++
 clang/test/APINotes/Inputs/Headers/SwiftImportAs.h        | 5 +++++
 clang/test/APINotes/swift-import-as.cpp                   | 7 +++++++
 4 files changed, 20 insertions(+)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 14403e65e8f42..fd22e012ea8b0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18476,6 +18476,10 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind 
TUK, SourceLocation KWLoc,
   // record.
   AddPushedVisibilityAttribute(New);
 
+  // If this is not a definition, process API notes for it now.
+  if (TUK != TagUseKind::Definition)
+    ProcessAPINotes(New);
+
   if (isMemberSpecialization && !New->isInvalidDecl())
     CompleteMemberSpecialization(New, Previous);
 
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes 
b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
index 66fc46e50ba0d..c096822fb92b5 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
@@ -19,6 +19,10 @@ Tags:
   SwiftReleaseOp: release
   SwiftRetainOp: retain
   SwiftDefaultOwnership: unretained
+- Name: OpaqueRefCountedType
+  SwiftImportAs: reference
+  SwiftReleaseOp: ORCRelease
+  SwiftRetainOp: ORCRetain
 - Name: NonCopyableType
   SwiftCopyable: false
   SwiftConformsTo: MySwiftModule.MySwiftNonCopyableProtocol
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h 
b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
index 20b8f04b4a914..b0bed6eb96116 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
@@ -23,3 +23,8 @@ struct EscapableType { int value; };
 struct RefCountedTypeWithDefaultConvention {};
 inline void retain(RefCountedType *x) {}
 inline void release(RefCountedType *x) {}
+
+struct OpaqueRefCountedType;
+
+inline void ORCRetain(struct OpaqueRefCountedType *x);
+inline void ORCRelease(struct OpaqueRefCountedType *x);
diff --git a/clang/test/APINotes/swift-import-as.cpp 
b/clang/test/APINotes/swift-import-as.cpp
index 929f924f2afee..20c8bbfa99ec0 100644
--- a/clang/test/APINotes/swift-import-as.cpp
+++ b/clang/test/APINotes/swift-import-as.cpp
@@ -3,6 +3,7 @@
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter ImmortalRefType | 
FileCheck -check-prefix=CHECK-IMMORTAL %s
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | 
FileCheck -check-prefix=CHECK-REF-COUNTED %s
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter 
RefCountedTypeWithDefaultConvention | FileCheck 
-check-prefix=CHECK-REF-COUNTED-DEFAULT %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter OpaqueRefCountedType 
| FileCheck -check-prefix=CHECK-OPAQUE-REF-COUNTED %s
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonCopyableType | 
FileCheck -check-prefix=CHECK-NON-COPYABLE %s
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter CopyableType | 
FileCheck -check-prefix=CHECK-COPYABLE %s
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules 
-I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonEscapableType | 
FileCheck -check-prefix=CHECK-NON-ESCAPABLE %s
@@ -34,6 +35,12 @@
 // CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <<invalid sloc>> 
"release:release"
 // CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <<invalid sloc>> 
"returned_as_unretained_by_default"
 
+// CHECK-OPAQUE-REF-COUNTED: Dumping OpaqueRefCountedType:
+// CHECK-OPAQUE-REF-COUNTED-NEXT: CXXRecordDecl {{.+}} imported in 
SwiftImportAs{{.*}}struct OpaqueRefCountedType
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> 
"import_reference"
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> 
"retain:ORCRetain"
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> 
"release:ORCRelease"
+
 // CHECK-NON-COPYABLE: Dumping NonCopyableType:
 // CHECK-NON-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs 
{{.+}} struct NonCopyableType
 // CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> 
"conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to