Author: Gábor Horváth
Date: 2026-01-20T10:05:02Z
New Revision: 2428a684978e5816c3a83c55a1395e4fe8cfe50e

URL: 
https://github.com/llvm/llvm-project/commit/2428a684978e5816c3a83c55a1395e4fe8cfe50e
DIFF: 
https://github.com/llvm/llvm-project/commit/2428a684978e5816c3a83c55a1395e4fe8cfe50e.diff

LOG: [APINotes] Apply APINotes to non-global decls in a LinkageSpecDecl 
(#176792)

We checked if a declaration has a LinkageSpecDecl ancestor and assumed
that it would be a declaration in global/namespace scope. This prevented
us from applying APINotes to methods or fields of a class that was
declared in a LinkageSpecDecl. This PR changes the logic to only check
whether the parent DeclContext is a LinkageSpecDecl instead of checking
for all the ancestors.

Co-authored-by: Gabor Horvath <[email protected]>

Added: 
    

Modified: 
    clang/lib/Sema/SemaAPINotes.cpp
    clang/test/APINotes/Inputs/Headers/Methods.apinotes
    clang/test/APINotes/Inputs/Headers/Methods.h
    clang/test/APINotes/methods.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 0d8d0faa59abd..d041d0f1f0a30 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -987,8 +987,8 @@ void Sema::ProcessAPINotes(Decl *D) {
 
   auto *DC = D->getDeclContext();
   // Globals.
-  if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
-      DC->isExternCXXContext()) {
+  if (DC->isFileContext() || DC->isNamespace() ||
+      DC->getDeclKind() == Decl::LinkageSpec) {
     std::optional<api_notes::Context> APINotesContext =
         UnwindNamespaceContext(DC, APINotes);
     // Global variables.

diff  --git a/clang/test/APINotes/Inputs/Headers/Methods.apinotes 
b/clang/test/APINotes/Inputs/Headers/Methods.apinotes
index 618c2cb14b47f..98fb7c5a489cb 100644
--- a/clang/test/APINotes/Inputs/Headers/Methods.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/Methods.apinotes
@@ -9,6 +9,16 @@ Tags:
   - Name: getDecremented
     Availability: none
     AvailabilityMsg: "this should have no effect"
+- Name: IntWrapper2
+  Methods:
+  - Name: getIncremented
+    Availability: none
+    AvailabilityMsg: "oh no"
+- Name: IntWrapper3
+  Methods:
+  - Name: getIncremented
+    Availability: none
+    AvailabilityMsg: "oh no"
 - Name: Outer
   Tags:
   - Name: Inner

diff  --git a/clang/test/APINotes/Inputs/Headers/Methods.h 
b/clang/test/APINotes/Inputs/Headers/Methods.h
index cbb57ccd0afbd..f4eb3589429d3 100644
--- a/clang/test/APINotes/Inputs/Headers/Methods.h
+++ b/clang/test/APINotes/Inputs/Headers/Methods.h
@@ -6,6 +6,22 @@ struct IntWrapper {
   IntWrapper operator+(const IntWrapper& RHS) const { return {value + 
RHS.value}; }
 };
 
+extern "C++" {
+struct IntWrapper2 {
+  int value;
+
+  IntWrapper2 getIncremented() const { return {value + 1}; }
+};
+}
+
+extern "C++" {
+extern "C" {
+  struct IntWrapper3 {
+    static IntWrapper3 getIncremented(IntWrapper3 val) { return val; }
+  };
+}
+}
+
 struct Outer {
   struct Inner {
     int value;

diff  --git a/clang/test/APINotes/methods.cpp b/clang/test/APINotes/methods.cpp
index 910565745bea2..a38642604a175 100644
--- a/clang/test/APINotes/methods.cpp
+++ b/clang/test/APINotes/methods.cpp
@@ -1,6 +1,8 @@
 // RUN: rm -rf %t && mkdir -p %t
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash 
-fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks 
%s -x c++
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter IntWrapper::getIncremented -x c++ | FileCheck 
--check-prefix=CHECK-METHOD %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter IntWrapper2::getIncremented -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-2 %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter IntWrapper3::getIncremented -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-3 %s
 // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter Outer::Inner::getDecremented -x c++ | FileCheck 
--check-prefix=CHECK-DEEP-METHOD %s
 
 #include "Methods.h"
@@ -9,6 +11,14 @@
 // CHECK-METHOD-NEXT: CXXMethodDecl {{.+}} getIncremented
 // CHECK-METHOD: UnavailableAttr {{.+}} <<invalid sloc>> "oh no"
 
+// CHECK-METHOD-2: Dumping IntWrapper2::getIncremented:
+// CHECK-METHOD-2-NEXT: CXXMethodDecl {{.+}} getIncremented
+// CHECK-METHOD-2: UnavailableAttr {{.+}} <<invalid sloc>> "oh no"
+
+// CHECK-METHOD-3: Dumping IntWrapper3::getIncremented:
+// CHECK-METHOD-3-NEXT: CXXMethodDecl {{.+}} getIncremented
+// CHECK-METHOD-3: UnavailableAttr {{.+}} <<invalid sloc>> "oh no"
+
 // CHECK-DEEP-METHOD: Dumping Outer::Inner::getDecremented:
 // CHECK-DEEP-METHOD-NEXT: CXXMethodDecl {{.+}} getDecremented
 // CHECK-DEEP-METHOD: UnavailableAttr {{.+}} <<invalid sloc>> "nope"


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to