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 <[email protected]> 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@Inputs/Headers/RedeclAnnotation.h:3{{'redeclaredAfterDefinition' has been explicitly marked unavailable here}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
