From dea2b60bb472c6cd0f818dd96168686e2395f18c Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 24 Aug 2023 15:55:20 +0100 Subject: [PATCH] [APINotes] Support globals in `extern "C++"` blocks This will be used to apply attributes to the C++ stdlib functions like `strstr`, `exit`, etc. rdar://114382260 (cherry picked from commit 2e44311031eaf1035d4c86bc7612091be87e23c8) --- clang/lib/Sema/SemaAPINotes.cpp | 3 ++- .../Inputs/Headers/ExternCtx.apinotes | 15 ++++++++++++ .../test/APINotes/Inputs/Headers/ExternCtx.h | 11 +++++++++ .../APINotes/Inputs/Headers/module.modulemap | 4 ++++ clang/test/APINotes/extern-context.cpp | 23 +++++++++++++++++++ 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/ExternCtx.h create mode 100644 clang/test/APINotes/extern-context.cpp diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 9ac857be2d27c..c326f85dd5ad1 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -812,7 +812,8 @@ void Sema::ProcessAPINotes(Decl *D) { // Globals. if (D->getDeclContext()->isFileContext() || - D->getDeclContext()->isExternCContext()) { + D->getDeclContext()->isExternCContext() || + D->getDeclContext()->isExternCXXContext()) { // Global variables. if (auto VD = dyn_cast(D)) { for (auto Reader : APINotes.findAPINotes(D->getLocation())) { diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes new file mode 100644 index 0000000000000..0f47ac6deea85 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes @@ -0,0 +1,15 @@ +Name: ExternCtx +Globals: + - Name: globalInExternC + Availability: none + AvailabilityMsg: "oh no" + - Name: globalInExternCXX + Availability: none + AvailabilityMsg: "oh no #2" +Functions: + - Name: globalFuncInExternC + Availability: none + AvailabilityMsg: "oh no #3" + - Name: globalFuncInExternCXX + Availability: none + AvailabilityMsg: "oh no #4" diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.h b/clang/test/APINotes/Inputs/Headers/ExternCtx.h new file mode 100644 index 0000000000000..669d443f60ecf --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.h @@ -0,0 +1,11 @@ +extern "C" { + static int globalInExternC = 1; + + static void globalFuncInExternC() {} +} + +extern "C++" { + static int globalInExternCXX = 2; + + static void globalFuncInExternCXX() {} +} diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index 5b44e7b055843..c672355d57844 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -1,3 +1,7 @@ +module ExternCtx { + header "ExternCtx.h" +} + module HeaderLib { header "HeaderLib.h" } diff --git a/clang/test/APINotes/extern-context.cpp b/clang/test/APINotes/extern-context.cpp new file mode 100644 index 0000000000000..331dee002361c --- /dev/null +++ b/clang/test/APINotes/extern-context.cpp @@ -0,0 +1,23 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternC -x c++ | FileCheck -check-prefix=CHECK-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternCXX -x c++ | FileCheck -check-prefix=CHECK-EXTERN-CXX %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternC -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternCXX -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-CXX %s + +#include "ExternCtx.h" + +// CHECK-EXTERN-C: Dumping globalInExternC: +// CHECK-EXTERN-C: VarDecl {{.+}} imported in ExternCtx globalInExternC 'int' +// CHECK-EXTERN-C: UnavailableAttr {{.+}} <> "oh no" + +// CHECK-EXTERN-CXX: Dumping globalInExternCXX: +// CHECK-EXTERN-CXX: VarDecl {{.+}} imported in ExternCtx globalInExternCXX 'int' +// CHECK-EXTERN-CXX: UnavailableAttr {{.+}} <> "oh no #2" + +// CHECK-FUNC-EXTERN-C: Dumping globalFuncInExternC: +// CHECK-FUNC-EXTERN-C: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternC 'void ()' +// CHECK-FUNC-EXTERN-C: UnavailableAttr {{.+}} <> "oh no #3" + +// CHECK-FUNC-EXTERN-CXX: Dumping globalFuncInExternCXX: +// CHECK-FUNC-EXTERN-CXX: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternCXX 'void ()' +// CHECK-FUNC-EXTERN-CXX: UnavailableAttr {{.+}} <> "oh no #4"