[clang] [clang-tools-extra] [compiler-rt] [flang] [lld] [lldb] [llvm] [mlir] [openmp] [pstl] Finally formalise our defacto line-ending policy (PR #86318)
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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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