llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Gábor Horváth (Xazax-hun)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/222902.diff


6 Files Affected:

- (modified) clang/lib/Sema/SemaDecl.cpp (+11) 
- (added) clang/test/APINotes/Inputs/Headers/RedeclAnnotation.apinotes (+5) 
- (added) clang/test/APINotes/Inputs/Headers/RedeclAnnotation.h (+3) 
- (added) clang/test/APINotes/Inputs/Headers/RedeclDefinition.h (+1) 
- (modified) clang/test/APINotes/Inputs/Headers/module.modulemap (+9) 
- (added) clang/test/APINotes/redecl-after-definition.c (+10) 


``````````diff
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 different 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}}
+}

``````````

</details>


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

Reply via email to