[clang] c44ac9e - [clang][APINotes] Do not drop attributes applied after a definition (#222902)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 07:32:59 PDT 2026
Author: Gábor Horváth
Date: 2026-09-11T15:32:54+01:00
New Revision: c44ac9eedba61129a76ff5964db9a0d6bf639b64
URL: https://github.com/llvm/llvm-project/commit/c44ac9eedba61129a76ff5964db9a0d6bf639b64
DIFF: https://github.com/llvm/llvm-project/commit/c44ac9eedba61129a76ff5964db9a0d6bf639b64.diff
LOG: [clang][APINotes] Do not drop attributes applied after a definition (#222902)
API notes are matched against whichever declaration the compiler
reaches, which can be a redeclaration that follows the definition. When
the definition lives in one module and the annotated redeclaration in
another, that is exactly what happens: checkNewAttributesAfterDef()
warns "attribute declaration must precede definition" and erases the
attribute, so the annotation is silently lost.
The warning exists to tell users that an attribute they wrote has no
effect. Attributes from API notes are not written in the source, so the
warning has nowhere to point and there is nothing for the user to
correct. Skip attributes with an invalid location, alongside the
existing exceptions.
rdar://186930250
Co-authored-by: Gabor Horvath <gaborh at apple.com>
Added:
clang/test/APINotes/Inputs/Headers/RedeclAnnotation.apinotes
clang/test/APINotes/Inputs/Headers/RedeclAnnotation.h
clang/test/APINotes/Inputs/Headers/RedeclDefinition.h
clang/test/APINotes/redecl-after-definition.c
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/test/APINotes/Inputs/Headers/module.modulemap
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a9047f61a8bf5..5de5821fe263e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3144,6 +3144,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
continue; // regular attr merging will take care of validating this.
}
+ if (NewAttribute->getLocation().isInvalid()) {
+ // An attribute with no source location was not written by the user. API
+ // notes, in particular, are matched against whichever declaration the
+ // compiler reaches, which can be a redeclaration that follows the
+ // definition, possibly in a
diff erent module. There is nothing for the
+ // user to correct, and erasing the attribute would silently change what
+ // the annotated API means.
+ ++I;
+ continue;
+ }
+
if (isa<C11NoReturnAttr>(NewAttribute)) {
// C's _Noreturn is allowed to be added to a function after it is defined.
++I;
diff --git a/clang/test/APINotes/Inputs/Headers/RedeclAnnotation.apinotes b/clang/test/APINotes/Inputs/Headers/RedeclAnnotation.apinotes
new file mode 100644
index 0000000000000..512732766fb46
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/RedeclAnnotation.apinotes
@@ -0,0 +1,5 @@
+Name: RedeclAnnotation
+Functions:
+- Name: redeclaredAfterDefinition
+ Availability: none
+ AvailabilityMsg: not available
diff --git a/clang/test/APINotes/Inputs/Headers/RedeclAnnotation.h b/clang/test/APINotes/Inputs/Headers/RedeclAnnotation.h
new file mode 100644
index 0000000000000..6383cee22a833
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/RedeclAnnotation.h
@@ -0,0 +1,3 @@
+#include "RedeclDefinition.h"
+
+int redeclaredAfterDefinition(int x);
diff --git a/clang/test/APINotes/Inputs/Headers/RedeclDefinition.h b/clang/test/APINotes/Inputs/Headers/RedeclDefinition.h
new file mode 100644
index 0000000000000..5b034df6077df
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/RedeclDefinition.h
@@ -0,0 +1 @@
+inline int redeclaredAfterDefinition(int x) { return x; }
diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap
index 592d482ea7a57..a9b273ccc90e6 100644
--- a/clang/test/APINotes/Inputs/Headers/module.modulemap
+++ b/clang/test/APINotes/Inputs/Headers/module.modulemap
@@ -75,3 +75,12 @@ module WhereParametersSema {
header "WhereParametersSema.h"
export *
}
+
+module RedeclDefinition {
+ header "RedeclDefinition.h"
+}
+
+module RedeclAnnotation {
+ header "RedeclAnnotation.h"
+ export *
+}
diff --git a/clang/test/APINotes/redecl-after-definition.c b/clang/test/APINotes/redecl-after-definition.c
new file mode 100644
index 0000000000000..466105d613fee
--- /dev/null
+++ b/clang/test/APINotes/redecl-after-definition.c
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -verify
+
+#include "RedeclDefinition.h"
+#include "RedeclAnnotation.h"
+
+void test(void) {
+ redeclaredAfterDefinition(1); // expected-error{{'redeclaredAfterDefinition' is unavailable: not available}}
+ // expected-note at Inputs/Headers/RedeclAnnotation.h:3{{'redeclaredAfterDefinition' has been explicitly marked unavailable here}}
+}
More information about the cfe-commits
mailing list