Skip to content

Commit a074f88

Browse files
ilovepiPrabhuk
andauthored
[libc] Update libc namespace clang-tidy checks (#98424)
This patch updates the clang-tidy checks for llvm-libc to ensure that the namespace macro used to declare the libc namespace is updated from LIBC_NAMESPACE to LIBC_NAMESPACE_DECL which by default has hidden visibility. Co-authored-by: Prabhu Rajesakeran <[email protected]>
1 parent d6f314c commit a074f88

File tree

5 files changed

+58
-38
lines changed

5 files changed

+58
-38
lines changed

clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
5151
// __llvm_libc, we're good.
5252
const auto *NS = dyn_cast<NamespaceDecl>(getOutermostNamespace(FuncDecl));
5353
if (NS && Result.SourceManager->isMacroBodyExpansion(NS->getLocation()) &&
54-
NS->getName().starts_with(RequiredNamespaceStart))
54+
NS->getName().starts_with(RequiredNamespaceRefStart))
5555
return;
5656

5757
const DeclarationName &Name = FuncDecl->getDeclName();
@@ -62,7 +62,7 @@ void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
6262
diag(UsageSiteExpr->getBeginLoc(),
6363
"%0 must resolve to a function declared "
6464
"within the namespace defined by the '%1' macro")
65-
<< FuncDecl << RequiredNamespaceMacroName;
65+
<< FuncDecl << RequiredNamespaceRefMacroName;
6666

6767
diag(FuncDecl->getLocation(), "resolves to this declaration",
6868
clang::DiagnosticIDs::Note);

clang-tools-extra/clang-tidy/llvmlibc/ImplementationInNamespaceCheck.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,35 @@ void ImplementationInNamespaceCheck::check(
3030
const auto *MatchedDecl =
3131
Result.Nodes.getNodeAs<Decl>("child_of_translation_unit");
3232
const auto *NS = dyn_cast<NamespaceDecl>(MatchedDecl);
33+
34+
// LLVM libc declarations should be inside of a non-anonymous namespace.
3335
if (NS == nullptr || NS->isAnonymousNamespace()) {
3436
diag(MatchedDecl->getLocation(),
3537
"declaration must be enclosed within the '%0' namespace")
36-
<< RequiredNamespaceMacroName;
38+
<< RequiredNamespaceDeclMacroName;
3739
return;
3840
}
41+
42+
// Enforce that the namespace is the result of macro expansion
3943
if (Result.SourceManager->isMacroBodyExpansion(NS->getLocation()) == false) {
4044
diag(NS->getLocation(), "the outermost namespace should be the '%0' macro")
41-
<< RequiredNamespaceMacroName;
45+
<< RequiredNamespaceDeclMacroName;
4246
return;
4347
}
44-
if (NS->getName().starts_with(RequiredNamespaceStart) == false) {
48+
49+
// We want the macro to have [[gnu::visibility("hidden")]] as a prefix, but
50+
// visibility is just an attribute in the AST construct, so we check that
51+
// instead.
52+
if (NS->getVisibility() != Visibility::HiddenVisibility) {
4553
diag(NS->getLocation(), "the '%0' macro should start with '%1'")
46-
<< RequiredNamespaceMacroName << RequiredNamespaceStart;
54+
<< RequiredNamespaceDeclMacroName << RequiredNamespaceDeclStart;
55+
return;
56+
}
57+
58+
// Lastly, make sure the namespace name actually has the __llvm_libc prefix
59+
if (NS->getName().starts_with(RequiredNamespaceRefStart) == false) {
60+
diag(NS->getLocation(), "the '%0' macro expansion should start with '%1'")
61+
<< RequiredNamespaceDeclMacroName << RequiredNamespaceRefStart;
4762
return;
4863
}
4964
}

clang-tools-extra/clang-tidy/llvmlibc/NamespaceConstants.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010

1111
namespace clang::tidy::llvm_libc {
1212

13-
const static llvm::StringRef RequiredNamespaceStart = "__llvm_libc";
14-
const static llvm::StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE";
13+
const static llvm::StringRef RequiredNamespaceRefStart = "__llvm_libc";
14+
const static llvm::StringRef RequiredNamespaceRefMacroName = "LIBC_NAMESPACE";
15+
const static llvm::StringRef RequiredNamespaceDeclStart =
16+
"[[gnu::visibility(\"hidden\")]] __llvm_libc";
17+
const static llvm::StringRef RequiredNamespaceDeclMacroName =
18+
"LIBC_NAMESPACE_DECL";
1519

1620
} // namespace clang::tidy::llvm_libc

clang-tools-extra/docs/clang-tidy/checks/llvmlibc/implementation-in-namespace.rst

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,30 @@ correct namespace.
88

99
.. code-block:: c++
1010

11-
// Implementation inside the LIBC_NAMESPACE namespace.
11+
// Implementation inside the LIBC_NAMESPACE_DECL namespace.
1212
// Correct if:
13-
// - LIBC_NAMESPACE is a macro
14-
// - LIBC_NAMESPACE expansion starts with `__llvm_libc`
15-
namespace LIBC_NAMESPACE {
13+
// - LIBC_NAMESPACE_DECL is a macro
14+
// - LIBC_NAMESPACE_DECL expansion starts with `[[gnu::visibility("hidden")]] __llvm_libc`
15+
namespace LIBC_NAMESPACE_DECL {
1616
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
17-
// Namespaces within LIBC_NAMESPACE namespace are allowed.
17+
// Namespaces within LIBC_NAMESPACE_DECL namespace are allowed.
1818
namespace inner {
1919
int localVar = 0;
2020
}
2121
// Functions with C linkage are allowed.
2222
extern "C" void str_fuzz() {}
2323
}
2424
25-
// Incorrect: implementation not in the LIBC_NAMESPACE namespace.
25+
// Incorrect: implementation not in the LIBC_NAMESPACE_DECL namespace.
2626
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
2727
28-
// Incorrect: outer most namespace is not the LIBC_NAMESPACE macro.
28+
// Incorrect: outer most namespace is not the LIBC_NAMESPACE_DECL macro.
2929
namespace something_else {
3030
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
3131
}
3232
33-
// Incorrect: outer most namespace expansion does not start with `__llvm_libc`.
34-
#define LIBC_NAMESPACE custom_namespace
35-
namespace LIBC_NAMESPACE {
33+
// Incorrect: outer most namespace expansion does not start with `[[gnu::visibility("hidden")]] __llvm_libc`.
34+
#define LIBC_NAMESPACE_DECL custom_namespace
35+
namespace LIBC_NAMESPACE_DECL {
3636
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
3737
}

clang-tools-extra/test/clang-tidy/checkers/llvmlibc/implementation-in-namespace.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,61 @@
33
#define MACRO_A "defining macros outside namespace is valid"
44

55
class ClassB;
6-
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
6+
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be enclosed within the 'LIBC_NAMESPACE_DECL' namespace
77
struct StructC {};
8-
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
9-
char *VarD = MACRO_A;
10-
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
8+
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration must be enclosed within the 'LIBC_NAMESPACE_DECL' namespace
9+
const char *VarD = MACRO_A;
10+
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: declaration must be enclosed within the 'LIBC_NAMESPACE_DECL' namespace
1111
typedef int typeE;
12-
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
12+
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: declaration must be enclosed within the 'LIBC_NAMESPACE_DECL' namespace
1313
void funcF() {}
14-
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
14+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration must be enclosed within the 'LIBC_NAMESPACE_DECL' namespace
1515

1616
namespace outer_most {
17-
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the outermost namespace should be the 'LIBC_NAMESPACE' macro
17+
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the outermost namespace should be the 'LIBC_NAMESPACE_DECL' macro
1818
class A {};
1919
}
2020

2121
// Wrapped in anonymous namespace.
2222
namespace {
23-
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration must be enclosed within the 'LIBC_NAMESPACE' namespace
23+
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration must be enclosed within the 'LIBC_NAMESPACE_DECL' namespace
2424
class A {};
2525
}
2626

2727
namespace namespaceG {
28-
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the outermost namespace should be the 'LIBC_NAMESPACE' macro
28+
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the outermost namespace should be the 'LIBC_NAMESPACE_DECL' macro
2929
namespace __llvm_libc {
3030
namespace namespaceH {
3131
class ClassB;
3232
} // namespace namespaceH
3333
struct StructC {};
3434
} // namespace __llvm_libc
35-
char *VarD = MACRO_A;
35+
const char *VarD = MACRO_A;
3636
typedef int typeE;
3737
void funcF() {}
3838
} // namespace namespaceG
3939

4040
// Wrapped in macro namespace but with an incorrect name
41-
#define LIBC_NAMESPACE custom_namespace
42-
namespace LIBC_NAMESPACE {
43-
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the 'LIBC_NAMESPACE' macro should start with '__llvm_libc'
41+
#define LIBC_NAMESPACE_DECL [[gnu::visibility("hidden")]] custom_namespace
42+
namespace LIBC_NAMESPACE_DECL {
43+
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the 'LIBC_NAMESPACE_DECL' macro expansion should start with '__llvm_libc'
44+
4445
namespace namespaceH {
4546
class ClassB;
4647
} // namespace namespaceH
47-
} // namespace LIBC_NAMESPACE
48+
} // namespace LIBC_NAMESPACE_DECL
4849

4950

50-
// Wrapped in macro namespace with a valid name, LIBC_NAMESPACE starts with '__llvm_libc'
51-
#undef LIBC_NAMESPACE
52-
#define LIBC_NAMESPACE __llvm_libc_xyz
53-
namespace LIBC_NAMESPACE {
51+
// Wrapped in macro namespace with a valid name, LIBC_NAMESPACE_DECL starts with '__llvm_libc'
52+
#undef LIBC_NAMESPACE_DECL
53+
#define LIBC_NAMESPACE_DECL [[gnu::visibility("hidden")]] __llvm_libc_xyz
54+
namespace LIBC_NAMESPACE_DECL {
5455
namespace namespaceI {
5556
class ClassB;
5657
} // namespace namespaceI
5758
struct StructC {};
58-
char *VarD = MACRO_A;
59+
const char *VarD = MACRO_A;
5960
typedef int typeE;
6061
void funcF() {}
6162
extern "C" void extern_funcJ() {}
62-
} // namespace LIBC_NAMESPACE
63+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)