[clang] [clang-tools-extra] [compiler-rt] [flang] [lld] [lldb] [llvm] [mlir] [openmp] [pstl] Finally formalise our defacto line-ending policy (PR #86318)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

> Also, it's a bit funny to have .bat files without CRLF endings given that 
> they run on Windows.

I'm not sure about the funny bit - but certainly dangerous. I've had cmd 
misinterpret batch files with LF vs CRLF.

https://github.com/llvm/llvm-project/pull/86318
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [compiler-rt] [flang] [lld] [lldb] [llvm] [mlir] [openmp] [pstl] Finally formalise our defacto line-ending policy (PR #86318)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

> changes to `clang/test/CXX/lex/lex.literal/lex.string/p4.cpp` should be 
> reverted (it's a CRLF related test)

This is the type of problems that I am concerned about. We certainly have some 
tests which are line-ending sensitive, and each test should be audited before 
we make such a change.

https://github.com/llvm/llvm-project/pull/86318
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [compiler-rt] [flang] [lld] [lldb] [llvm] [mlir] [openmp] [pstl] Finally formalise our defacto line-ending policy (PR #86318)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

> @compnerd I just realised I didn't respond to your concern. Apologies.
> 
> > I think that the concern that I have is that do we have sufficient testing 
> > for supporting line-ending dependent behaviour in the compiler?
> 
> For the first part: I don't know that it matters, since this patch changes 
> how the LLVM source code is stored, but not how its parsers operate. In any 
> case, we run parser testing on LF and CRLF systems since the precommit 
> testing runs on Linux, and Win32 at least. In addition, and there are several 
> tests dedicated to line ending, so I think we should be good there. Happy to 
> tend to this and fix anything I've missed if someone lets me know something 
> is broken after we merge.

I don't know if the pre-commit testing guarantees that. Configuration settings 
will permit the files to be checked out in either Unix (`\n`) or Windows 
(`\r\n`) line-endings. If the builders are all configured to run in Unix line 
endings we lose that coverage. While I understand that this change only changes 
how the LLVM sources are stored, the issue is that the LLVM sources include the 
_tests_ directory. These need to be tested in various manners to ensure that we 
test how we handle the different inputs (in clang). One option might be to 
exclude the tests directory from the line ending conversion if we cannot verify 
that we have tests in both formats.

> As for the second part
> 
> > Additionally, do we have sufficient documentation for others to figure out 
> > how to ensure that git does not munge the line endings if they are 
> > introducing a test which is dependent on it? In such a case, how do we 
> > ensure that they are aware that the SCM will do so without actually 
> > checking the post-commit state with a hex editor?
> 
> I don't think we do, but also this patch doesn't really change the problem 
> since right now basically _anything_ can happen due to local configuration 
> overrides (`~/.gitconfig`). I'll add a comment to the testing infrastructure 
> page to be mindful of how line endings are storedand link to the 
> `.gitattributes` documentation. Does that sound enough?

I think that the documentation should be good. While, yes, it is possible to 
get the wrong behaviour currently, if the user configures git explicitly for a 
line-ending, I would expect them to be aware of that. The use of 
`.gitattributes` means that their defaults are not necessarily honoured and 
thus this can catch them by surprise.

https://github.com/llvm/llvm-project/pull/86318
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits


@@ -1146,6 +1146,12 @@ class TagTableInfo : public 
CommonTypeTableInfo {
 
 writer.write(Flags);
 
+if (auto Copyable = TI.isSwiftCopyable()) {

compnerd wrote:

Unnecessary braces and we should be able to use the named constants here.

https://github.com/llvm/llvm-project/pull/90064
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/90064
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits


@@ -1125,10 +1125,10 @@ class CommonTypeTableInfo
 class TagTableInfo : public CommonTypeTableInfo {
 public:
   unsigned getUnversionedInfoSize(const TagInfo ) {
-return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
-   2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
-   2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
-   1 + getCommonTypeInfoSize(TI);
+return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 2 +
+   (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 +
+   (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + 2 +
+   getCommonTypeInfoSize(TI);

compnerd wrote:

This feels less readable :(

https://github.com/llvm/llvm-project/pull/90064
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits


@@ -527,6 +527,13 @@ class TagTableInfo
   Info.EnumExtensibility =
   static_cast((Payload & 0x3) - 1);
 
+uint8_t Copyable =
+endian::readNext(Data);
+if (Copyable == 1)
+  Info.setSwiftCopyable(std::optional(false));
+else if (Copyable == 2)
+  Info.setSwiftCopyable(std::optional(true));

compnerd wrote:

Can we use named constants for the non-traditional boolean values? Perhaps 
`kSwiftNonCopyable` and `kSwiftCopyable`? This should ensure that we do not 
drift.

https://github.com/llvm/llvm-project/pull/90064
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)

2024-04-25 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd edited 
https://github.com/llvm/llvm-project/pull/90064
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [lldb] Revert "NFC: Make clang resource headers an interface library (#88317)" (PR #89266)

2024-04-18 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.

Approving it in case it needs to be merged, but I think that we should try to 
determine how it is breaking. This change feels like it should be correct and 
is a pretty good cleanup, so I would prefer that fix forward rather than revert.

https://github.com/llvm/llvm-project/pull/89266
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] NFC: Make clang resource headers an interface library (PR #88317)

2024-04-10 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.

Thanks, this seems good!

https://github.com/llvm/llvm-project/pull/88317
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] NFC: Make clang resource headers an interface library (PR #88317)

2024-04-10 Thread Saleem Abdulrasool via cfe-commits


@@ -501,6 +501,10 @@ add_header_target("windows-resource-headers" 
${windows_only_files})
 add_header_target("utility-resource-headers" ${utility_files})
 
 get_clang_resource_dir(header_install_dir SUBDIR include)
+target_include_directories(clang-resource-headers INTERFACE
+  $

compnerd wrote:

Do we need to worry about other files accidentally being made visible by using 
the source directory?

https://github.com/llvm/llvm-project/pull/88317
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] NFC: Make clang resource headers an interface library (PR #88317)

2024-04-10 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.

This seems like a step in the right direction - avoiding custom targets is 
generally better.

https://github.com/llvm/llvm-project/pull/88317
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] NFC: Make clang resource headers an interface library (PR #88317)

2024-04-10 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd edited 
https://github.com/llvm/llvm-project/pull/88317
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Add test for C++ class templates (PR #87006)

2024-03-28 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/87006
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [compiler-rt] [flang] [lld] [lldb] [llvm] [mlir] [openmp] [pstl] Finally formalise our defacto line-ending policy (PR #86318)

2024-03-27 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

Philosophically, I agree with this change. Enshrining the information about the 
line endings into the SCM tool makes sense.

I think that the concern that I have is that do we have sufficient testing for 
supporting line-ending dependent behaviour in the compiler? Additionally, do we 
have sufficient documentation for others to figure out how to ensure that git 
does not munge the line endings if they are introducing a test which is 
dependent on it? In such a case, how do we ensure that they are aware that the 
SCM will do so without actually checking the post-commit state with a hex 
editor?

https://github.com/llvm/llvm-project/pull/86318
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] For a re-exported module, look for APINotes in the re-exporting module's apinotes file (PR #86820)

2024-03-27 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/86820
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: not %clang_cc1 -fsyntax-only -fapinotes  %s -I 
%S/Inputs/BrokenHeaders2 2>&1 | FileCheck %s

compnerd wrote:

Extra space after `-fapinotes`

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1 @@
+extern int TopLevelPrivateKit_Public;

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,2 @@
+#include 
+extern int FrameworkWithActualPrivateModule_Private;

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1 @@
+extern int FrameworkWithWrongCase;

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,55 @@
+#ifndef SOMEKIT_H
+#define SOMEKIT_H
+
+#define ROOT_CLASS __attribute__((objc_root_class))
+
+ROOT_CLASS
+@interface A
+-(A*)transform:(A*)input;
+-(A*)transform:(A*)input integer:(int)integer;
+
+@property (nonatomic, readonly, retain) A* someA;
+@property (nonatomic, retain) A* someOtherA;
+
+@property (nonatomic) int intValue;
+@end
+
+@interface B : A
+@end
+
+@interface C : A
+- (instancetype)init;
+- (instancetype)initWithA:(A*)a;
+@end
+
+
+@interface MyClass : A
+- Inst;
++ Clas;
+@end
+
+struct CGRect {
+  float origin;
+  float size;
+};
+typedef struct CGRect NSRect;
+
+@interface I
+- (void) Meth : (NSRect[4])exposedRects;
+- (void) Meth1 : (const  I*)exposedRects;
+- (void) Meth2 : (const I*)exposedRects;
+- (void) Meth3 : (I*)exposedRects;
+- (const I*) Meth4;
+- (const I*) Meth5 : (int) Arg1 : (const I*)Arg2 : (double)Arg3 :   (const I*) 
Arg4 :(const  volatile id) Arg5;
+- (volatile const I*) Meth6 : (const char *)Arg1 : (const char *)Arg2 : 
(double)Arg3 :   (const I*) Arg4 :(const  volatile id) Arg5;
+@end
+
+@class NSURL,  NSArray, NSError;

compnerd wrote:

Extra space after the initial comma.

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,187 @@
+// RUN: rm -rf %t && mkdir -p %t
+
+// Build and check the unversioned module file.
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash 
-fapinotes-modules  -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks 
%s
+// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | 
FileCheck -check-prefix=CHECK-UNVERSIONED %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash 
-fapinotes-modules  -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks 
%s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP 
-check-prefix=CHECK-UNVERSIONED-DUMP %s
+
+// Build and check the versioned module file.
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash 
-fapinotes-modules  -fapinotes-swift-version=3 -fsyntax-only -I 
%S/Inputs/Headers -F %S/Inputs/Frameworks %s
+// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned/VersionedKit.pcm | 
FileCheck -check-prefix=CHECK-VERSIONED %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash 
-fapinotes-modules  -fapinotes-swift-version=3 -fsyntax-only -I 
%S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' 
| FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-VERSIONED-DUMP %s

compnerd wrote:

And here

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,37 @@
+Name: HeaderLib
+SwiftInferImportAsMember: true
+Functions:
+  - Name: custom_realloc
+NullabilityOfRet: N
+Nullability: [ N, S ]
+  - Name: unavailable_function
+Availability: none
+AvailabilityMsg: "I beg you not to use this"
+  - Name: do_something_with_pointers
+NullabilityOfRet: O
+Nullability: [ N, O ]
+  - Name: do_something_with_arrays
+Parameters:
+  - Position: 0
+Nullability: N
+  - Position: 1
+Nullability: N
+  - Name: take_pointer_and_int
+Parameters:
+  - Position: 0
+Nullability: N
+NoEscape: true
+  - Position: 1
+NoEscape: true
+Globals:
+  - Name: global_int
+Nullability: N
+  - Name: unavailable_global_int
+Availability: none
+Tags:
+  - Name: unavailable_struct
+Availability: none
+
+Typedefs:
+  - Name: unavailable_typedef
+Availability: none

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1 @@
+garbage here because this file shouldn't get read

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1 @@
+extern int PrivateLib;

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,44 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %clang_cc1 -fmodules  -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module 
-fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify
+
+// Test with Swift version 3.0. This should only affect the few APIs that have 
an entry in the 3.0 tables.

compnerd wrote:

Hmm, do we still support Swift 3 in the Swift compiler even?

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1 @@
+garbage here because this file shouldn't get read

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1 @@
+extern int FrameworkWithActualPrivateModule;

compnerd wrote:

Missing newline

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,187 @@
+// RUN: rm -rf %t && mkdir -p %t
+
+// Build and check the unversioned module file.
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash 
-fapinotes-modules  -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks 
%s
+// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | 
FileCheck -check-prefix=CHECK-UNVERSIONED %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash 
-fapinotes-modules  -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks 
%s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP 
-check-prefix=CHECK-UNVERSIONED-DUMP %s

compnerd wrote:

Likewise

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -52,49 +52,54 @@ static void applyNullability(Sema , Decl *D, 
NullabilityKind Nullability,
   if (!Metadata.IsActive)
 return;
 
-  auto IsModified = [&](Decl *D, QualType QT,
-NullabilityKind Nullability) -> bool {
+  auto GetModified =
+  [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> std::optional {
 QualType Original = QT;
 S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
 isa(D),
 /*OverrideExisting=*/true);
-return QT.getTypePtr() != Original.getTypePtr();
+return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
+  : std::nullopt;
   };
 
   if (auto Function = dyn_cast(D)) {
-if (IsModified(D, Function->getReturnType(), Nullability)) {
-  QualType FnType = Function->getType();
-  Function->setType(FnType);
+if (auto Modified =
+GetModified(D, Function->getReturnType(), Nullability)) {
+  const FunctionType *FnType = Function->getType()->castAs();
+  if (const FunctionProtoType *proto = dyn_cast(FnType))
+Function->setType(S.Context.getFunctionType(
+*Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
+  else
+Function->setType(
+S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
 }
   } else if (auto Method = dyn_cast(D)) {
-QualType Type = Method->getReturnType();
-if (IsModified(D, Type, Nullability)) {
-  Method->setReturnType(Type);
+if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
+  Method->setReturnType(*Modified);
 
   // Make it a context-sensitive keyword if we can.
-  if (!isIndirectPointerType(Type))
+  if (!isIndirectPointerType(*Modified))
 Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
 Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
 }
   } else if (auto Value = dyn_cast(D)) {
-QualType Type = Value->getType();
-if (IsModified(D, Type, Nullability)) {
-  Value->setType(Type);
+if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
+  Value->setType(*Modified);
 
   // Make it a context-sensitive keyword if we can.
   if (auto Parm = dyn_cast(D)) {
-if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
   Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
   Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
   }
 }
   } else if (auto Property = dyn_cast(D)) {
-QualType Type = Property->getType();
-if (IsModified(D, Type, Nullability)) {
-  Property->setType(Type, Property->getTypeSourceInfo());
+if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
+  Property->setType(*Modified, Property->getTypeSourceInfo());
 
   // Make it a property attribute if we can.
-  if (!isIndirectPointerType(Type))
+  if (!isIndirectPointerType(*Modified))
 Property->setPropertyAttributes(
 ObjCPropertyAttribute::kind_null_resettable);
 }

compnerd wrote:

Could we add a test to ensure that the modified type is applied?

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,4 @@
+Name: SomeBrokenLib
+Functions:
+  - Name: do_something_with_pointers
+Nu llabilityOfRet: O

compnerd wrote:

Is it possible to comment that the space here is intentional? Particularly with 
this diff, it was difficult to verify until you get to the end.

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -638,15 +638,15 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
 PDecl->setInvalidDecl();
   }
 
-  ProcessDeclAttributes(S, PDecl, FD.D);
-
   // Regardless of setter/getter attribute, we save the default getter/setter
   // selector names in anticipation of declaration of setter/getter methods.
   PDecl->setGetterName(GetterSel, GetterNameLoc);
   PDecl->setSetterName(SetterSel, SetterNameLoc);
   PDecl->setPropertyAttributesAsWritten(
   
makePropertyAttributesAsWritten(AttributesAsWritten));
 
+  ProcessDeclAttributes(S, PDecl, FD.D);
+
   if (Attributes & ObjCPropertyAttribute::kind_readonly)
 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly);
 

compnerd wrote:

Could we add a test to ensure that the attributes are applied properly?

https://github.com/llvm/llvm-project/pull/84773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd edited 
https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-03-19 Thread Saleem Abdulrasool via cfe-commits


@@ -3191,6 +3191,22 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
, ArgList ,
   bool IsIndexHeaderMap = false;
   bool IsSysrootSpecified =
   Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
+
+  // Expand a leading `=` to the sysroot if one was passed (and it's not a
+  // framework flag).
+  auto PrefixHeaderPath = [IsSysrootSpecified,
+   ](const llvm::opt::Arg *A,
+  bool IsFramework = false) -> std::string {
+assert(A->getNumValues() != 0 && "Unexpected empty search path flag!");

compnerd wrote:

I'd likely drop the `!= 0`.

https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add `__has_extension(swiftcc)` support (PR #85347)

2024-03-18 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.

Might be nice to have a test for `swiftasynccc` as well.

https://github.com/llvm/llvm-project/pull/85347
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver,CrossWindows] Remove -isystem-after (PR #84121)

2024-03-13 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

I don't see why removing the help text is not sufficient to handle the issue? 
Even if no major players are using it, I think that there are people using it. 
It is a fairly self-contained bit of support.

https://github.com/llvm/llvm-project/pull/84121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver,CrossWindows] Remove -isystem-after (PR #84121)

2024-03-13 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

Perhaps the better approach here is to either indicate that it is only 
supported on a particular target or to drop the help information rather than 
removing the feature.

https://github.com/llvm/llvm-project/pull/84121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver,CrossWindows] Remove -isystem-after (PR #84121)

2024-03-13 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

Facebook was using it at one point (can't say if they are currently), I know 
that Sony had some interested users as well.

Yes, the order matters - that was the reason that the flag was implemented in 
the first place.

https://github.com/llvm/llvm-project/pull/84121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][AST] Print attributes of Obj-C interfaces (PR #84772)

2024-03-11 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/84772
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Fix a few accidental refactoring artifacts (PR #83057)

2024-02-26 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/83057
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (!IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Method->setReturnType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (!isIndirectPointerType(Type))
+Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Value = dyn_cast(D)) {
+QualType Type = Value->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Value->setType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (auto Parm = dyn_cast(D)) {
+if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+  Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+  }
+}
+  } else if (auto Property = dyn_cast(D)) {
+QualType Type = Property->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Property->setType(Type, Property->getTypeSourceInfo());
+
+  // Make it a property attribute if we can.
+  if (!isIndirectPointerType(Type))
+Property->setPropertyAttributes(
+ObjCPropertyAttribute::kind_null_resettable);
+}
+  }
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef ASTAllocateString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char *));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getPlaceholderAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X)
\
+  template <> struct AttrKindFor {
\
+static const attr::Kind value = attr::X;   
\
+  };
+#include "clang/Basic/AttrList.inc"
+
+/// Handle an attribute introduced by API notes.
+///
+/// \param IsAddition Whether we should add 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (!IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Method->setReturnType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (!isIndirectPointerType(Type))
+Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Value = dyn_cast(D)) {
+QualType Type = Value->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Value->setType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (auto Parm = dyn_cast(D)) {
+if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+  Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+  }
+}
+  } else if (auto Property = dyn_cast(D)) {
+QualType Type = Property->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Property->setType(Type, Property->getTypeSourceInfo());
+
+  // Make it a property attribute if we can.
+  if (!isIndirectPointerType(Type))
+Property->setPropertyAttributes(
+ObjCPropertyAttribute::kind_null_resettable);
+}
+  }
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef ASTAllocateString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char *));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getPlaceholderAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X)
\
+  template <> struct AttrKindFor {
\
+static const attr::Kind value = attr::X;   
\
+  };
+#include "clang/Basic/AttrList.inc"
+
+/// Handle an attribute introduced by API notes.
+///
+/// \param IsAddition Whether we should add 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (!IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Method->setReturnType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (!isIndirectPointerType(Type))
+Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Value = dyn_cast(D)) {
+QualType Type = Value->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Value->setType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (auto Parm = dyn_cast(D)) {
+if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+  Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+  }
+}
+  } else if (auto Property = dyn_cast(D)) {
+QualType Type = Property->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Property->setType(Type, Property->getTypeSourceInfo());
+
+  // Make it a property attribute if we can.
+  if (!isIndirectPointerType(Type))
+Property->setPropertyAttributes(
+ObjCPropertyAttribute::kind_null_resettable);
+}
+  }
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef ASTAllocateString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char *));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getPlaceholderAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X)
\
+  template <> struct AttrKindFor {
\
+static const attr::Kind value = attr::X;   
\
+  };
+#include "clang/Basic/AttrList.inc"
+
+/// Handle an attribute introduced by API notes.
+///
+/// \param IsAddition Whether we should add 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (!IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Method->setReturnType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (!isIndirectPointerType(Type))
+Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Value = dyn_cast(D)) {
+QualType Type = Value->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Value->setType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (auto Parm = dyn_cast(D)) {
+if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+  Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+  }
+}
+  } else if (auto Property = dyn_cast(D)) {
+QualType Type = Property->getType();
+if (!IsUnmodified(D, Type, Nullability)) {
+  Property->setType(Type, Property->getTypeSourceInfo());
+
+  // Make it a property attribute if we can.
+  if (!isIndirectPointerType(Type))
+Property->setPropertyAttributes(
+ObjCPropertyAttribute::kind_null_resettable);
+}
+  }
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef ASTAllocateString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char *));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getPlaceholderAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X)
\
+  template <> struct AttrKindFor {
\
+static const attr::Kind value = attr::X;   
\
+  };
+#include "clang/Basic/AttrList.inc"
+
+/// Handle an attribute introduced by API notes.
+///
+/// \param IsAddition Whether we should add 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.

Most of the new comments are nits and small readability tweaks. I still would 
like to avoid the double `dyn_cast` checks, but I don't know if this is worth 
holding up on at that point.  Thank you for the multiple rounds on this and 
sorry about the delay, the length made it daunting.

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (!IsUnmodified(D, Function->getReturnType(), Nullability)) {

compnerd wrote:

An alternative to consider: rename the function to `IsModified` and return the 
negated value so simplify the callees.

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };

compnerd wrote:

I'd consider renaming these now with the `enum class`:

```suggestion
enum class State : bool { Inactive, Active };
enum class SubstitutionType : bool { Original, Replacement };
```

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-24 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd edited 
https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-23 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (IsUnmodified(D, Type, Nullability)) {
+  Method->setReturnType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (!isIndirectPointerType(Type))
+Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Value = dyn_cast(D)) {
+QualType Type = Value->getType();
+if (IsUnmodified(D, Type, Nullability)) {

compnerd wrote:

And here

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-23 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (IsUnmodified(D, Type, Nullability)) {
+  Method->setReturnType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (!isIndirectPointerType(Type))
+Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Value = dyn_cast(D)) {
+QualType Type = Value->getType();
+if (IsUnmodified(D, Type, Nullability)) {
+  Value->setType(Type);
+
+  // Make it a context-sensitive keyword if we can.
+  if (auto Parm = dyn_cast(D)) {
+if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+  Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+  }
+}
+  } else if (auto Property = dyn_cast(D)) {
+QualType Type = Property->getType();
+if (IsUnmodified(D, Type, Nullability)) {

compnerd wrote:

And here

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-23 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (IsUnmodified(D, Function->getReturnType(), Nullability)) {

compnerd wrote:

Wait if there is no change to the nullability, why reset the type?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-23 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,989 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  auto IsUnmodified = [&](Decl *D, QualType QT,
+  NullabilityKind Nullability) -> bool {
+QualType Original = QT;
+S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
+isa(D),
+/*OverrideExisting=*/true);
+return QT.getTypePtr() == Original.getTypePtr();
+  };
+
+  if (auto Function = dyn_cast(D)) {
+if (IsUnmodified(D, Function->getReturnType(), Nullability)) {
+  QualType FnType = Function->getType();
+  Function->setType(FnType);
+}
+  } else if (auto Method = dyn_cast(D)) {
+QualType Type = Method->getReturnType();
+if (IsUnmodified(D, Type, Nullability)) {

compnerd wrote:

Similar

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-23 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,995 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum class IsActive_t : bool { Inactive, Active };
+enum class IsReplacement_t : bool { Original, Replacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::Active),
+IsReplacement(Replacement == IsReplacement_t::Replacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isIndirectPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+
+  if (Type.isNull())
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+QualType FnType = Function->getType();
+Function->setType(FnType);
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isIndirectPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isIndirectPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");

compnerd wrote:

That should allow us to get rid of this as well.

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-23 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;

compnerd wrote:

I was thinking something like:

```c++
auto IsUnmodified = [](Decl *D, QualType QT, NullabilityKind Nullability) -> 
Bool {
  QualType Original = QT;
  S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
  isa(D),
  /*OverrideExisting=*/true);
  return QT.getTypePtr() == Original.getTypePtr();
}
```

Then, we could just do an inline `if (IsUnmodified(...)) return;` allowing us 
to fold the two if slides together.

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-22 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-22 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));

compnerd wrote:

Should this be `alignof(char)` or `alignof(char *)`?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {

compnerd wrote:

```suggestion
static AttributeCommonInfo getPlaceholderAttrInfo() {
```

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;

compnerd wrote:

How about converting this to a lambda and collapsing the subsequent cast and 
check? The `dyn_cast` is not exactly free and should simplify the code flow at 
the small cost of duplication of the call to the lambda.

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {

compnerd wrote:

How about `ASTAllocString` or `ASTDuplicateString`?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;

compnerd wrote:

Could we get away with:

```
if (Type.isNull())
  return;
```

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };

compnerd wrote:

```suggestion
enum IsReplacement_t : bool { Original, Replacement };
```

Similarly, consider `enum class`?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast(D)) {
+Method->setReturnType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (!isMultiLevelPointerType(Type))
+  Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+  Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast(D)) {
+Value->setType(Type);
+
+// Make it a context-sensitive keyword if we can.
+if (auto Parm = dyn_cast(D)) {
+  if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+}
+  } else if (auto Property = dyn_cast(D)) {
+Property->setType(Type, Property->getTypeSourceInfo());
+
+// Make it a property attribute if we can.
+if (!isMultiLevelPointerType(Type))
+  Property->setPropertyAttributes(
+  ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext , StringRef String) {
+  void *mem = Ctx.Allocate(String.size(), alignof(char));
+  memcpy(mem, String.data(), String.size());
+  return StringRef(static_cast(mem), String.size());
+}
+
+static AttributeCommonInfo getDummyAttrInfo() {
+  return AttributeCommonInfo(SourceRange(),
+ AttributeCommonInfo::UnknownAttribute,
+ {AttributeCommonInfo::AS_GNU,
+  /*Spelling*/ 0, /*IsAlignas*/ false,
+  /*IsRegularKeywordAttribute*/ false});
+}
+
+namespace {
+template  struct AttrKindFor {};
+
+#define ATTR(X) 

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+ Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema , Decl *D, NullabilityKind Nullability,
+ VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast(D))
+Type = Function->getReturnType();
+  else if (auto Method = dyn_cast(D))
+Type = Method->getReturnType();
+  else if (auto Value = dyn_cast(D))
+Type = Value->getType();
+  else if (auto Property = dyn_cast(D))
+Type = Property->getType();
+  else
+return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+  isa(D),
+  /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+return;
+
+  if (auto Function = dyn_cast(D)) {
+const FunctionType *FnType = Function->getType()->castAs();
+if (const FunctionProtoType *Proto = dyn_cast(FnType))
+  Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+  Proto->getExtProtoInfo()));
+else
+  Function->setType(
+  S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));

compnerd wrote:

Can we not use a QualType for the new type and then call `Function->setType` 
once?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+IsReplacement_t Replacement)
+  : Version(Version), IsActive(Active == IsActive_t::IsActive),
+IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {

compnerd wrote:

Perhaps `IsIndirectPointer`?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

2024-02-21 Thread Saleem Abdulrasool via cfe-commits


@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===--===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };

compnerd wrote:

```suggestion
enum IsActive_t : bool { Inactive, Active };
```

Should we consider `enum class`?

https://github.com/llvm/llvm-project/pull/78445
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-02-17 Thread Saleem Abdulrasool via cfe-commits


@@ -3218,6 +3218,21 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
, ArgList ,
   bool IsIndexHeaderMap = false;
   bool IsSysrootSpecified =
   Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
+
+  // Expand a leading `=` to the sysroot if one was passed (and it's not a
+  // framework flag).
+  auto ConvertHeaderPath = [IsSysrootSpecified,
+](const llvm::opt::Arg *A,
+   bool IsFramework = false) -> std::string {
+if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {

compnerd wrote:

路‍♂️ clang-format does what clang-format wants.

https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-02-17 Thread Saleem Abdulrasool via cfe-commits


@@ -3218,6 +3218,21 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
, ArgList ,
   bool IsIndexHeaderMap = false;
   bool IsSysrootSpecified =
   Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
+
+  // Expand a leading `=` to the sysroot if one was passed (and it's not a
+  // framework flag).
+  auto ConvertHeaderPath = [IsSysrootSpecified,
+](const llvm::opt::Arg *A,
+   bool IsFramework = false) -> std::string {
+if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {

compnerd wrote:

This feels double indented?

https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-02-17 Thread Saleem Abdulrasool via cfe-commits


@@ -3218,6 +3218,21 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
, ArgList ,
   bool IsIndexHeaderMap = false;
   bool IsSysrootSpecified =
   Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
+
+  // Expand a leading `=` to the sysroot if one was passed (and it's not a
+  // framework flag).
+  auto ConvertHeaderPath = [IsSysrootSpecified,

compnerd wrote:

I think that `Prefix` or `Expand` would both be better than `Convert`. We 
aren't really converting this.

https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add support for sysroot-relative system header search paths (PR #82084)

2024-02-17 Thread Saleem Abdulrasool via cfe-commits


@@ -3218,6 +3218,21 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
, ArgList ,
   bool IsIndexHeaderMap = false;
   bool IsSysrootSpecified =
   Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
+
+  // Expand a leading `=` to the sysroot if one was passed (and it's not a
+  // framework flag).
+  auto ConvertHeaderPath = [IsSysrootSpecified,
+](const llvm::opt::Arg *A,
+   bool IsFramework = false) -> std::string {
+if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {

compnerd wrote:

Might be nice to take `const llvm::opt::Arg &` instead. It also feels unsafe as 
we do not know if the argument has a value before you get it - you should do a 
`A->hasValue()` or assert it perhaps?

https://github.com/llvm/llvm-project/pull/82084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Frontend: sink vendor definitions from Basic to Frontend (PR #80364)

2024-02-04 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd updated 
https://github.com/llvm/llvm-project/pull/80364

>From c895dff0e59b9d851c15e5b3b25a735478b811fc Mon Sep 17 00:00:00 2001
From: Saleem Abdulrasool 
Date: Thu, 1 Feb 2024 15:37:39 -0800
Subject: [PATCH] Frontend: sink vendor definitions from Basic to Frontend

The vendor specific macro definitions are based on the vendor rather
than the target specific information. This ensures that `__APPLE__` is
always defined for `*-apple-*` targets. Take the opportunity to do
likewise with the `__AMD__` vendor macro.
---
 clang/lib/Basic/Targets/AMDGPU.cpp  | 1 -
 clang/lib/Basic/Targets/OSTargets.cpp   | 1 -
 clang/lib/Frontend/InitPreprocessor.cpp | 5 +
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp 
b/clang/lib/Basic/Targets/AMDGPU.cpp
index 141501e8a4d9a..c6d68f591a5a8 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -266,7 +266,6 @@ ArrayRef 
AMDGPUTargetInfo::getTargetBuiltins() const {
 
 void AMDGPUTargetInfo::getTargetDefines(const LangOptions ,
 MacroBuilder ) const {
-  Builder.defineMacro("__AMD__");
   Builder.defineMacro("__AMDGPU__");
 
   if (isAMDGCN(getTriple()))
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp 
b/clang/lib/Basic/Targets/OSTargets.cpp
index 899aefa6173ac..64b4514ba55bb 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -23,7 +23,6 @@ void getDarwinDefines(MacroBuilder , const 
LangOptions ,
   const llvm::Triple , StringRef ,
   VersionTuple ) {
   Builder.defineMacro("__APPLE_CC__", "6000");
-  Builder.defineMacro("__APPLE__");
   Builder.defineMacro("__STDC_NO_THREADS__");
 
   // AddressSanitizer doesn't play well with source fortification, which is on
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 877e205e2e9bf..42c391a7214dc 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -804,6 +804,11 @@ static void InitializePredefinedMacros(const TargetInfo 
,
 }
   }
 
+  if (TI.getTriple().getVendor() == llvm::Triple::AMD)
+Builder.defineMacro("__AMD__");
+  if (TI.getTriple().getVendor() == llvm::Triple::Apple)
+Builder.defineMacro("__APPLE__");
+
   // Define macros for the C11 / C++11 memory orderings
   Builder.defineMacro("__ATOMIC_RELAXED", "0");
   Builder.defineMacro("__ATOMIC_CONSUME", "1");

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


[clang] Frontend: sink vendor definitions from Basic to Frontend (PR #80364)

2024-02-03 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd updated 
https://github.com/llvm/llvm-project/pull/80364

>From 2bff496bd1b3c1bc5177f5072c2c7b8a4db54f14 Mon Sep 17 00:00:00 2001
From: Saleem Abdulrasool 
Date: Thu, 1 Feb 2024 15:37:39 -0800
Subject: [PATCH] Frontend: sink vendor definitions from Basic to Frontend

The vendor specific macro definitions are based on the vendor rather
than the target specific information. This ensures that `__APPLE__` is
always defined for `*-apple-*` targets. Take the opportunity to do
likewise with the `__AMD__` vendor macro.
---
 clang/lib/Basic/Targets/AMDGPU.cpp  | 1 -
 clang/lib/Basic/Targets/OSTargets.cpp   | 1 -
 clang/lib/Frontend/InitPreprocessor.cpp | 5 +
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp 
b/clang/lib/Basic/Targets/AMDGPU.cpp
index 141501e8a4d9a..c6d68f591a5a8 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -266,7 +266,6 @@ ArrayRef 
AMDGPUTargetInfo::getTargetBuiltins() const {
 
 void AMDGPUTargetInfo::getTargetDefines(const LangOptions ,
 MacroBuilder ) const {
-  Builder.defineMacro("__AMD__");
   Builder.defineMacro("__AMDGPU__");
 
   if (isAMDGCN(getTriple()))
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp 
b/clang/lib/Basic/Targets/OSTargets.cpp
index 899aefa6173ac..64b4514ba55bb 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -23,7 +23,6 @@ void getDarwinDefines(MacroBuilder , const 
LangOptions ,
   const llvm::Triple , StringRef ,
   VersionTuple ) {
   Builder.defineMacro("__APPLE_CC__", "6000");
-  Builder.defineMacro("__APPLE__");
   Builder.defineMacro("__STDC_NO_THREADS__");
 
   // AddressSanitizer doesn't play well with source fortification, which is on
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 877e205e2e9bf..27621ee332419 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -804,6 +804,11 @@ static void InitializePredefinedMacros(const TargetInfo 
,
 }
   }
 
+  if (TI.getTriple().getVendor() == Triple::AMD)
+Builder.defineMacro("__AMD__");
+  if (TI.getTriple().getVendor() == Triple::Apple)
+Builder.defineMacro("__APPLE__");
+
   // Define macros for the C11 / C++11 memory orderings
   Builder.defineMacro("__ATOMIC_RELAXED", "0");
   Builder.defineMacro("__ATOMIC_CONSUME", "1");

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


[clang] Frontend: sink vendor definitions from Basic to Frontend (PR #80364)

2024-02-01 Thread Saleem Abdulrasool via cfe-commits


@@ -804,6 +804,11 @@ static void InitializePredefinedMacros(const TargetInfo 
,
 }
   }
 
+  if (TI.getTriple().getVendor() == Triple::AMD)
+Builder.defineMacro("__AMD__");
+  if (TI.getTriple().getVendor() == Triple::Apple)
+Builder.defineMacro("__APPLE__");

compnerd wrote:

Yes, and something that I think that is desirable in the context of Swift as 
well (where we are looking at some of the embedded system usage where the 
target triple may be something like `arm64-apple-none-macho`).

https://github.com/llvm/llvm-project/pull/80364
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Frontend: sink vendor definitions from Basic to Frontend (PR #80364)

2024-02-01 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

CC: @kubamracek

https://github.com/llvm/llvm-project/pull/80364
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Frontend: sink vendor definitions from Basic to Frontend (PR #80364)

2024-02-01 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd created 
https://github.com/llvm/llvm-project/pull/80364

The vendor specific macro definitions are based on the vendor rather than the 
target specific information. This ensures that `__APPLE__` is always defined 
for `*-apple-*` targets. Take the opportunity to do likewise with the `__AMD__` 
vendor macro.

>From c83d6f34d446e63d5f82a14887b17edd666c6f13 Mon Sep 17 00:00:00 2001
From: Saleem Abdulrasool 
Date: Thu, 1 Feb 2024 15:37:39 -0800
Subject: [PATCH] Frontend: sink vendor definitions from Basic to Frontend

The vendor specific macro definitions are based on the vendor rather
than the target specific information. This ensures that `__APPLE__` is
always defined for `*-apple-*` targets. Take the opportunity to do
likewise with the `__AMD__` vendor macro.
---
 clang/lib/Basic/Targets/AMDGPU.cpp  | 1 -
 clang/lib/Basic/Targets/OSTargets.cpp   | 1 -
 clang/lib/Frontend/InitPreprocessor.cpp | 5 +
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp 
b/clang/lib/Basic/Targets/AMDGPU.cpp
index 141501e8a4d9a..c6d68f591a5a8 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -266,7 +266,6 @@ ArrayRef 
AMDGPUTargetInfo::getTargetBuiltins() const {
 
 void AMDGPUTargetInfo::getTargetDefines(const LangOptions ,
 MacroBuilder ) const {
-  Builder.defineMacro("__AMD__");
   Builder.defineMacro("__AMDGPU__");
 
   if (isAMDGCN(getTriple()))
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp 
b/clang/lib/Basic/Targets/OSTargets.cpp
index 899aefa6173ac..64b4514ba55bb 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -23,7 +23,6 @@ void getDarwinDefines(MacroBuilder , const 
LangOptions ,
   const llvm::Triple , StringRef ,
   VersionTuple ) {
   Builder.defineMacro("__APPLE_CC__", "6000");
-  Builder.defineMacro("__APPLE__");
   Builder.defineMacro("__STDC_NO_THREADS__");
 
   // AddressSanitizer doesn't play well with source fortification, which is on
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 877e205e2e9bf..27621ee332419 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -804,6 +804,11 @@ static void InitializePredefinedMacros(const TargetInfo 
,
 }
   }
 
+  if (TI.getTriple().getVendor() == Triple::AMD)
+Builder.defineMacro("__AMD__");
+  if (TI.getTriple().getVendor() == Triple::Apple)
+Builder.defineMacro("__APPLE__");
+
   // Define macros for the C11 / C++11 memory orderings
   Builder.defineMacro("__ATOMIC_RELAXED", "0");
   Builder.defineMacro("__ATOMIC_CONSUME", "1");

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


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-21 Thread Saleem Abdulrasool via cfe-commits


@@ -463,7 +471,8 @@ class ObjCRuntime {
 case iOS: return true;
 case WatchOS: return true;
 case GCC: return false;
-case GNUstep: return false;
+case GNUstep:
+  return (getVersion() >= VersionTuple(2, 2));

compnerd wrote:

The parenthesis are unnecessary.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-21 Thread Saleem Abdulrasool via cfe-commits


@@ -2649,13 +2767,18 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction ,
 }
   }
 
+  bool isDirect = Method && Method->isDirectMethod();
+
   IdTy = cast(CGM.getTypes().ConvertType(ASTIdTy));
   llvm::Value *cmd;
-  if (Method)
-cmd = GetSelector(CGF, Method);
-  else
-cmd = GetSelector(CGF, Sel);
-  cmd = EnforceType(Builder, cmd, SelectorTy);
+  if (!isDirect) {
+if (Method)
+  cmd = GetSelector(CGF, Method);
+else
+  cmd = GetSelector(CGF, Sel);

compnerd wrote:

Probably more compact as a ternary.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-21 Thread Saleem Abdulrasool via cfe-commits


@@ -2006,6 +2024,106 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty 
});
 }
 
+void GenerateDirectMethodPrologue(CodeGenFunction , llvm::Function *Fn,
+  const ObjCMethodDecl *OMD,
+  const ObjCContainerDecl *CD) override {
+  auto  = CGF.Builder;
+  bool ReceiverCanBeNull = true;
+  auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
+  auto selfValue = Builder.CreateLoad(selfAddr);
+
+  // Generate:
+  //
+  // /* unless the receiver is never NULL */
+  // if (self == nil) {
+  // return (ReturnType){ };
+  // }
+  //
+  // /* for class methods only to force class lazy initialization */
+  // if (!__objc_{class}_initialized)
+  // {
+  //   objc_send_initialize(class);
+  //   __objc_{class}_initialized = 1;
+  // }
+  //
+  // _cmd = @selector(...)
+  // ...
+
+  if (OMD->isClassMethod()) {
+const ObjCInterfaceDecl *OID = cast(CD);
+
+// Nullable `Class` expressions cannot be messaged with a direct method
+// so the only reason why the receive can be null would be because
+// of weak linking.
+ReceiverCanBeNull = isWeakLinkedClass(OID);
+  }
+
+  llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+  if (ReceiverCanBeNull) {
+llvm::BasicBlock *SelfIsNilBlock =
+CGF.createBasicBlock("objc_direct_method.self_is_nil");
+llvm::BasicBlock *ContBlock =
+CGF.createBasicBlock("objc_direct_method.cont");
+
+// if (self == nil) {
+auto selfTy = cast(selfValue->getType());
+auto Zero = llvm::ConstantPointerNull::get(selfTy);
+
+Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
+ SelfIsNilBlock, ContBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+
+CGF.EmitBlock(SelfIsNilBlock);
+
+//   return (ReturnType){ };
+auto retTy = OMD->getReturnType();
+Builder.SetInsertPoint(SelfIsNilBlock);
+if (!retTy->isVoidType()) {
+  CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
+}

compnerd wrote:

Unnecessary braces.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-21 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd edited 
https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-21 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.

Left some minor nits.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-cl] document correct defaults for `-fms-compatibility-version` / `-fmsc-version` (PR #76418)

2024-01-16 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd closed 
https://github.com/llvm/llvm-project/pull/76418
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-cl] document correct defaults for `-fms-compatibility-version` / `-fmsc-version` (PR #76418)

2024-01-16 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

Thank you for fixing the documentation!

https://github.com/llvm/llvm-project/pull/76418
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream dependencies of Sema logic to apply API Notes to decls (PR #73017)

2024-01-16 Thread Saleem Abdulrasool via cfe-commits

https://github.com/compnerd approved this pull request.


https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2024-01-16 Thread Saleem Abdulrasool via cfe-commits

compnerd wrote:

Do we want to submit the first three in the series and then take on the topmost 
commit?

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2024-01-16 Thread Saleem Abdulrasool via cfe-commits


@@ -7539,74 +7559,65 @@ static NullabilityKind 
mapNullabilityAttrKind(ParsedAttr::Kind kind) {
   }
 }
 
-/// Applies a nullability type specifier to the given type, if possible.
-///
-/// \param state The type processing state.
-///
-/// \param type The type to which the nullability specifier will be
-/// added. On success, this type will be updated appropriately.
-///
-/// \param attr The attribute as written on the type.
-///
-/// \param allowOnArrayType Whether to accept nullability specifiers on an
-/// array type (e.g., because it will decay to a pointer).
-///
-/// \returns true if a problem has been diagnosed, false on success.
-static bool checkNullabilityTypeSpecifier(TypeProcessingState ,
-  QualType ,
-  ParsedAttr ,
-  bool allowOnArrayType) {
-  Sema  = state.getSema();
-
-  NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind());
-  SourceLocation nullabilityLoc = attr.getLoc();
-  bool isContextSensitive = attr.isContextSensitiveKeywordAttribute();
-
-  recordNullabilitySeen(S, nullabilityLoc);
+static bool CheckNullabilityTypeSpecifier(
+Sema , TypeProcessingState *State, ParsedAttr *PAttr, QualType ,
+NullabilityKind Nullability, SourceLocation NullabilityLoc,
+bool IsContextSensitive, bool AllowOnArrayType, bool OverrideExisting) {
+  bool Implicit = (State == nullptr);
+  if (!Implicit)
+recordNullabilitySeen(S, NullabilityLoc);
 
   // Check for existing nullability attributes on the type.
-  QualType desugared = type;
-  while (auto attributed = dyn_cast(desugared.getTypePtr())) {
+  QualType Desugared = QT;
+  while (auto Attributed = dyn_cast(Desugared.getTypePtr())) {
 // Check whether there is already a null
-if (auto existingNullability = attributed->getImmediateNullability()) {
+if (auto ExistingNullability = Attributed->getImmediateNullability()) {

compnerd wrote:

Let's leave it as is for now.

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2024-01-16 Thread Saleem Abdulrasool via cfe-commits


@@ -2601,6 +2604,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {

compnerd wrote:

Ah, okay.

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-14 Thread Saleem Abdulrasool via cfe-commits


@@ -1994,6 +2004,106 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty 
});
 }
 
+void GenerateDirectMethodPrologue(CodeGenFunction , llvm::Function *Fn,
+  const ObjCMethodDecl *OMD,
+  const ObjCContainerDecl *CD) override {
+  auto  = CGF.Builder;
+  bool ReceiverCanBeNull = true;
+  auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
+  auto selfValue = Builder.CreateLoad(selfAddr);
+
+  // Generate:
+  //
+  // /* unless the receiver is never NULL */
+  // if (self == nil) {
+  // return (ReturnType){ };
+  // }
+  //
+  // /* for class methods only to force class lazy initialization */
+  // if (!__objc_{class}_initialized)
+  // {
+  //   objc_send_initialize(class);
+  //   __objc_{class}_initialized = 1;
+  // }
+  //
+  // _cmd = @selector(...)
+  // ...
+
+  if (OMD->isClassMethod()) {
+const ObjCInterfaceDecl *OID = cast(CD);
+
+// Nullable `Class` expressions cannot be messaged with a direct method
+// so the only reason why the receive can be null would be because
+// of weak linking.
+ReceiverCanBeNull = isWeakLinkedClass(OID);
+  }
+
+  if (ReceiverCanBeNull) {
+llvm::BasicBlock *SelfIsNilBlock =
+CGF.createBasicBlock("objc_direct_method.self_is_nil");
+llvm::BasicBlock *ContBlock =
+CGF.createBasicBlock("objc_direct_method.cont");
+
+// if (self == nil) {
+auto selfTy = cast(selfValue->getType());
+auto Zero = llvm::ConstantPointerNull::get(selfTy);
+
+llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
+ SelfIsNilBlock, ContBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+
+CGF.EmitBlock(SelfIsNilBlock);
+
+//   return (ReturnType){ };
+auto retTy = OMD->getReturnType();
+Builder.SetInsertPoint(SelfIsNilBlock);
+if (!retTy->isVoidType()) {
+  CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
+}
+CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+// }
+
+// rest of the body
+CGF.EmitBlock(ContBlock);
+Builder.SetInsertPoint(ContBlock);
+  }
+
+  if (OMD->isClassMethod()) {
+// Prefix of the class type.
+auto *classStart =
+llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
+auto  = CGM.getContext();
+auto flags = Builder.CreateLoad(
+Address{Builder.CreateStructGEP(classStart, selfValue, 4), LongTy,
+CharUnits::fromQuantity(
+astContext.getTypeAlign(astContext.UnsignedLongTy))});
+auto isInitialized = Builder.CreateAnd(flags, (1 << 8));
+llvm::BasicBlock *notInitializedBlock =
+CGF.createBasicBlock("objc_direct_method.send_initialize");
+llvm::BasicBlock *initializedBlock =
+CGF.createBasicBlock("objc_direct_method.class_initialized");
+llvm::MDBuilder MDHelper(CGM.getLLVMContext());

compnerd wrote:

Perhaps hoist the MDBuilder as you need it previously as well.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-14 Thread Saleem Abdulrasool via cfe-commits


@@ -3906,14 +4028,50 @@ llvm::Function *CGObjCGNU::GenerateMethod(const 
ObjCMethodDecl *OMD,
   CodeGenTypes  = CGM.getTypes();
   llvm::FunctionType *MethodTy =
 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
-  std::string FunctionName = getSymbolNameForMethod(OMD);
-
-  llvm::Function *Method
-= llvm::Function::Create(MethodTy,
- llvm::GlobalValue::InternalLinkage,
- FunctionName,
- );
-  return Method;
+
+  bool isDirect = OMD->isDirectMethod();
+  std::string FunctionName =
+  getSymbolNameForMethod(OMD, /*include category*/ !isDirect);
+
+  if (!isDirect)
+return llvm::Function::Create(MethodTy,
+  llvm::GlobalVariable::InternalLinkage,
+  FunctionName, );
+
+  auto *COMD = OMD->getCanonicalDecl();
+  auto I = DirectMethodDefinitions.find(COMD);
+  llvm::Function *OldFn = nullptr, *Fn = nullptr;
+
+  if (I != DirectMethodDefinitions.end()) {
+// Objective-C allows for the declaration and implementation types
+// to differ slightly.
+//
+// If we're being asked for the Function associated for a method
+// implementation, a previous value might have been cached
+// based on the type of the canonical declaration.
+//
+// If these do not match, then we'll replace this function with
+// a new one that has the proper type below.
+if (!OMD->getBody() || COMD->getReturnType() == OMD->getReturnType())
+  return I->second;
+OldFn = I->second;
+  }
+
+  if (OldFn) {
+Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
+"", ());
+Fn->takeName(OldFn);
+OldFn->replaceAllUsesWith(Fn);
+OldFn->eraseFromParent();
+
+// Replace the cached function in the map.
+I->second = Fn;
+  } else {
+Fn = llvm::Function::Create(MethodTy, 
llvm::GlobalVariable::ExternalLinkage,
+FunctionName, );
+DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
+  }
+  return Fn;

compnerd wrote:

Feels like this would be clearer as:

```c++
if (I == DirectMethodDefinitions.end()) {
  auto *F = llvm::Function::Create(MethodTy, 
llvm::GlobalVariable::ExternalLinkage,
   FunctionName, );
  DirectMethodDefinitions.insert(std::make_pair(COMD, F));
  return F;
}

// Objective-C allows for ...
```

That will merge the block on L4061-4068, with L4046-4057.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-14 Thread Saleem Abdulrasool via cfe-commits


@@ -1994,6 +2004,106 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty 
});
 }
 
+void GenerateDirectMethodPrologue(CodeGenFunction , llvm::Function *Fn,
+  const ObjCMethodDecl *OMD,
+  const ObjCContainerDecl *CD) override {
+  auto  = CGF.Builder;
+  bool ReceiverCanBeNull = true;
+  auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
+  auto selfValue = Builder.CreateLoad(selfAddr);
+
+  // Generate:
+  //
+  // /* unless the receiver is never NULL */
+  // if (self == nil) {
+  // return (ReturnType){ };
+  // }
+  //
+  // /* for class methods only to force class lazy initialization */
+  // if (!__objc_{class}_initialized)
+  // {
+  //   objc_send_initialize(class);
+  //   __objc_{class}_initialized = 1;
+  // }
+  //
+  // _cmd = @selector(...)
+  // ...
+
+  if (OMD->isClassMethod()) {
+const ObjCInterfaceDecl *OID = cast(CD);
+
+// Nullable `Class` expressions cannot be messaged with a direct method
+// so the only reason why the receive can be null would be because
+// of weak linking.
+ReceiverCanBeNull = isWeakLinkedClass(OID);
+  }
+
+  if (ReceiverCanBeNull) {
+llvm::BasicBlock *SelfIsNilBlock =
+CGF.createBasicBlock("objc_direct_method.self_is_nil");
+llvm::BasicBlock *ContBlock =
+CGF.createBasicBlock("objc_direct_method.cont");
+
+// if (self == nil) {
+auto selfTy = cast(selfValue->getType());
+auto Zero = llvm::ConstantPointerNull::get(selfTy);
+
+llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
+ SelfIsNilBlock, ContBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+
+CGF.EmitBlock(SelfIsNilBlock);
+
+//   return (ReturnType){ };
+auto retTy = OMD->getReturnType();
+Builder.SetInsertPoint(SelfIsNilBlock);
+if (!retTy->isVoidType()) {
+  CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
+}
+CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+// }
+
+// rest of the body
+CGF.EmitBlock(ContBlock);
+Builder.SetInsertPoint(ContBlock);
+  }
+
+  if (OMD->isClassMethod()) {
+// Prefix of the class type.
+auto *classStart =
+llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
+auto  = CGM.getContext();
+auto flags = Builder.CreateLoad(
+Address{Builder.CreateStructGEP(classStart, selfValue, 4), LongTy,
+CharUnits::fromQuantity(
+astContext.getTypeAlign(astContext.UnsignedLongTy))});
+auto isInitialized = Builder.CreateAnd(flags, (1 << 8));

compnerd wrote:

It might be nice to extract the flags enumeration into named constants for 
re-use.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)

2024-01-14 Thread Saleem Abdulrasool via cfe-commits


@@ -1994,6 +2004,106 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty 
});
 }
 
+void GenerateDirectMethodPrologue(CodeGenFunction , llvm::Function *Fn,
+  const ObjCMethodDecl *OMD,
+  const ObjCContainerDecl *CD) override {
+  auto  = CGF.Builder;
+  bool ReceiverCanBeNull = true;
+  auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
+  auto selfValue = Builder.CreateLoad(selfAddr);
+
+  // Generate:
+  //
+  // /* unless the receiver is never NULL */
+  // if (self == nil) {
+  // return (ReturnType){ };
+  // }
+  //
+  // /* for class methods only to force class lazy initialization */
+  // if (!__objc_{class}_initialized)
+  // {
+  //   objc_send_initialize(class);
+  //   __objc_{class}_initialized = 1;
+  // }
+  //
+  // _cmd = @selector(...)
+  // ...
+
+  if (OMD->isClassMethod()) {
+const ObjCInterfaceDecl *OID = cast(CD);
+
+// Nullable `Class` expressions cannot be messaged with a direct method
+// so the only reason why the receive can be null would be because
+// of weak linking.
+ReceiverCanBeNull = isWeakLinkedClass(OID);
+  }
+
+  if (ReceiverCanBeNull) {
+llvm::BasicBlock *SelfIsNilBlock =
+CGF.createBasicBlock("objc_direct_method.self_is_nil");
+llvm::BasicBlock *ContBlock =
+CGF.createBasicBlock("objc_direct_method.cont");
+
+// if (self == nil) {
+auto selfTy = cast(selfValue->getType());
+auto Zero = llvm::ConstantPointerNull::get(selfTy);
+
+llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
+ SelfIsNilBlock, ContBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+
+CGF.EmitBlock(SelfIsNilBlock);
+
+//   return (ReturnType){ };
+auto retTy = OMD->getReturnType();
+Builder.SetInsertPoint(SelfIsNilBlock);
+if (!retTy->isVoidType()) {
+  CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
+}
+CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+// }
+
+// rest of the body
+CGF.EmitBlock(ContBlock);
+Builder.SetInsertPoint(ContBlock);
+  }
+
+  if (OMD->isClassMethod()) {
+// Prefix of the class type.
+auto *classStart =
+llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
+auto  = CGM.getContext();
+auto flags = Builder.CreateLoad(
+Address{Builder.CreateStructGEP(classStart, selfValue, 4), LongTy,
+CharUnits::fromQuantity(
+astContext.getTypeAlign(astContext.UnsignedLongTy))});
+auto isInitialized = Builder.CreateAnd(flags, (1 << 8));
+llvm::BasicBlock *notInitializedBlock =
+CGF.createBasicBlock("objc_direct_method.send_initialize");

compnerd wrote:

I would call this `objc_direct_method.class_uninitialized`.  The BB will fall 
through to the class_initialized block, so while the block itself is only 
sending the initialization message, the path does more.

https://github.com/llvm/llvm-project/pull/78030
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2024-01-12 Thread Saleem Abdulrasool via cfe-commits


@@ -7519,6 +7519,26 @@ static bool 
HandleWebAssemblyFuncrefAttr(TypeProcessingState ,
   return false;
 }
 
+/// Rebuild an attributed type without the nullability attribute on it.
+static QualType rebuildAttributedTypeWithoutNullability(ASTContext ,
+QualType Type) {
+  auto Attributed = dyn_cast(Type.getTypePtr());
+  if (!Attributed)
+return Type;
+
+  // Skip the nullability attribute; we're done.
+  if (Attributed->getImmediateNullability()) {
+return Attributed->getModifiedType();
+  }

compnerd wrote:

Unnecessary braces

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2024-01-12 Thread Saleem Abdulrasool via cfe-commits


@@ -7539,74 +7559,65 @@ static NullabilityKind 
mapNullabilityAttrKind(ParsedAttr::Kind kind) {
   }
 }
 
-/// Applies a nullability type specifier to the given type, if possible.
-///
-/// \param state The type processing state.
-///
-/// \param type The type to which the nullability specifier will be
-/// added. On success, this type will be updated appropriately.
-///
-/// \param attr The attribute as written on the type.
-///
-/// \param allowOnArrayType Whether to accept nullability specifiers on an
-/// array type (e.g., because it will decay to a pointer).
-///
-/// \returns true if a problem has been diagnosed, false on success.
-static bool checkNullabilityTypeSpecifier(TypeProcessingState ,
-  QualType ,
-  ParsedAttr ,
-  bool allowOnArrayType) {
-  Sema  = state.getSema();
-
-  NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind());
-  SourceLocation nullabilityLoc = attr.getLoc();
-  bool isContextSensitive = attr.isContextSensitiveKeywordAttribute();
-
-  recordNullabilitySeen(S, nullabilityLoc);
+static bool CheckNullabilityTypeSpecifier(
+Sema , TypeProcessingState *State, ParsedAttr *PAttr, QualType ,
+NullabilityKind Nullability, SourceLocation NullabilityLoc,
+bool IsContextSensitive, bool AllowOnArrayType, bool OverrideExisting) {
+  bool Implicit = (State == nullptr);
+  if (!Implicit)
+recordNullabilitySeen(S, NullabilityLoc);
 
   // Check for existing nullability attributes on the type.
-  QualType desugared = type;
-  while (auto attributed = dyn_cast(desugared.getTypePtr())) {
+  QualType Desugared = QT;
+  while (auto Attributed = dyn_cast(Desugared.getTypePtr())) {

compnerd wrote:

Make this `auto *Attribute` to indicate that its a pointer.

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2024-01-12 Thread Saleem Abdulrasool via cfe-commits


@@ -7519,6 +7519,26 @@ static bool 
HandleWebAssemblyFuncrefAttr(TypeProcessingState ,
   return false;
 }
 
+/// Rebuild an attributed type without the nullability attribute on it.
+static QualType rebuildAttributedTypeWithoutNullability(ASTContext ,
+QualType Type) {
+  auto Attributed = dyn_cast(Type.getTypePtr());
+  if (!Attributed)
+return Type;
+
+  // Skip the nullability attribute; we're done.
+  if (Attributed->getImmediateNullability()) {
+return Attributed->getModifiedType();
+  }
+
+  // Build the modified type.
+  auto Modified = rebuildAttributedTypeWithoutNullability(

compnerd wrote:

I assume that this is an `AttributedType`? I don't think its necessarily clear 
what the type of the expression is, so it might be worth spelling it out.

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   3   4   5   6   7   8   9   >