Skip to content

Commit daca972

Browse files
[clang-tidy][libc] Fix namespace check with macro (#68134)
The name of the namespace for LLVM's libc is now provided by a macro. The ImplementationNamespaceCheck was updated to handle this, but the CalleeNamespaceCheck was missed. This patch updates the CalleeNamespaceCheck to handle the macro.
1 parent aade746 commit daca972

File tree

6 files changed

+73
-24
lines changed

6 files changed

+73
-24
lines changed

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

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "CalleeNamespaceCheck.h"
10+
#include "NamespaceConstants.h"
1011
#include "clang/AST/ASTContext.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213

14+
#include "clang/ASTMatchers/ASTMatchers.h"
1315
#include "llvm/ADT/StringSet.h"
1416

1517
using namespace clang::ast_matchers;
@@ -45,19 +47,22 @@ void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
4547
if (FuncDecl->getBuiltinID() != 0)
4648
return;
4749

48-
// If the outermost namespace of the function is __llvm_libc, we're good.
50+
// If the outermost namespace of the function is a macro that starts with
51+
// __llvm_libc, we're good.
4952
const auto *NS = dyn_cast<NamespaceDecl>(getOutermostNamespace(FuncDecl));
50-
if (NS && NS->getName() == "__llvm_libc")
53+
if (NS && Result.SourceManager->isMacroBodyExpansion(NS->getLocation()) &&
54+
NS->getName().starts_with(RequiredNamespaceStart))
5155
return;
5256

5357
const DeclarationName &Name = FuncDecl->getDeclName();
5458
if (Name.isIdentifier() &&
5559
IgnoredFunctions.contains(Name.getAsIdentifierInfo()->getName()))
5660
return;
5761

58-
diag(UsageSiteExpr->getBeginLoc(), "%0 must resolve to a function declared "
59-
"within the '__llvm_libc' namespace")
60-
<< FuncDecl;
62+
diag(UsageSiteExpr->getBeginLoc(),
63+
"%0 must resolve to a function declared "
64+
"within the namespace defined by the '%1' macro")
65+
<< FuncDecl << RequiredNamespaceMacroName;
6166

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

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "ImplementationInNamespaceCheck.h"
10+
#include "NamespaceConstants.h"
1011
#include "clang/AST/ASTContext.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213

1314
using namespace clang::ast_matchers;
1415

1516
namespace clang::tidy::llvm_libc {
1617

17-
const static StringRef RequiredNamespaceStart = "__llvm_libc";
18-
const static StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE";
19-
2018
void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) {
2119
Finder->addMatcher(
2220
translationUnitDecl(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//===--- NamespaceConstants.h -----------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/ADT/StringRef.h"
10+
11+
namespace clang::tidy::llvm_libc {
12+
13+
const static StringRef RequiredNamespaceStart = "__llvm_libc";
14+
const static StringRef RequiredNamespaceMacroName = "LIBC_NAMESPACE";
15+
16+
} // namespace clang::tidy::llvm_libc

clang-tools-extra/docs/ReleaseNotes.rst

+6
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ Changes in existing checks
241241
<clang-tidy/checks/llvm/namespace-comment>` check to provide fixes for
242242
``inline`` namespaces in the same format as :program:`clang-format`.
243243

244+
- Improved :doc:`llvmlibc-callee-namespace
245+
<clang-tidy/checks/llvmlibc/callee-namespace>` to support
246+
customizable namespace. This matches the change made to implementation in
247+
namespace.
248+
244249
- Improved :doc:`llvmlibc-implementation-in-namespace
245250
<clang-tidy/checks/llvmlibc/implementation-in-namespace>` to support
246251
customizable namespace. This further allows for testing the libc when the
@@ -319,6 +324,7 @@ Changes in existing checks
319324
<clang-tidy/checks/readability/static-accessed-through-instance>` check to
320325
identify calls to static member functions with out-of-class inline definitions.
321326

327+
322328
Removed checks
323329
^^^^^^^^^^^^^^
324330

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

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
llvmlibc-callee-namespace
44
====================================
55

6-
Checks all calls resolve to functions within ``__llvm_libc`` namespace.
6+
Checks all calls resolve to functions within correct namespace.
77

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

10-
namespace __llvm_libc {
10+
// Implementation inside the LIBC_NAMESPACE namespace.
11+
// Correct if:
12+
// - LIBC_NAMESPACE is a macro
13+
// - LIBC_NAMESPACE expansion starts with `__llvm_libc`
14+
namespace LIBC_NAMESPACE {
1115

1216
// Allow calls with the fully qualified name.
13-
__llvm_libc::strlen("hello");
17+
LIBC_NAMESPACE::strlen("hello");
1418

1519
// Allow calls to compiler provided functions.
1620
(void)__builtin_abs(-1);
@@ -21,4 +25,4 @@ Checks all calls resolve to functions within ``__llvm_libc`` namespace.
2125
// Disallow calling into functions in the global namespace.
2226
::strlen("!");
2327

24-
} // namespace __llvm_libc
28+
} // namespace LIBC_NAMESPACE

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

+32-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
// RUN: %check_clang_tidy %s llvmlibc-callee-namespace %t
22

3+
#define OTHER_MACRO_NAMESPACE custom_namespace
4+
namespace OTHER_MACRO_NAMESPACE {
5+
void wrong_name_macro_func() {}
6+
}
7+
38
namespace __llvm_libc {
9+
void right_name_no_macro_func() {}
10+
}
11+
12+
#define LIBC_NAMESPACE __llvm_libc_xyz
13+
namespace LIBC_NAMESPACE {
414
namespace nested {
515
void nested_func() {}
616
} // namespace nested
@@ -22,12 +32,12 @@ struct global_struct {
2232
int operator()() const { return 0; }
2333
};
2434

25-
namespace __llvm_libc {
35+
namespace LIBC_NAMESPACE {
2636
void Test() {
2737
// Allow calls with the fully qualified name.
28-
__llvm_libc::libc_api_func();
29-
__llvm_libc::nested::nested_func();
30-
void (*qualifiedPtr)(void) = __llvm_libc::libc_api_func;
38+
LIBC_NAMESPACE::libc_api_func();
39+
LIBC_NAMESPACE::nested::nested_func();
40+
void (*qualifiedPtr)(void) = LIBC_NAMESPACE::libc_api_func;
3141
qualifiedPtr();
3242

3343
// Should not trigger on compiler provided function calls.
@@ -36,31 +46,41 @@ void Test() {
3646
// Bare calls are allowed as long as they resolve to the correct namespace.
3747
libc_api_func();
3848
nested::nested_func();
39-
void (*barePtr)(void) = __llvm_libc::libc_api_func;
49+
void (*barePtr)(void) = LIBC_NAMESPACE::libc_api_func;
4050
barePtr();
4151

4252
// Allow calling entities defined in the namespace.
43-
__llvm_libc::libc_api_struct{}();
53+
LIBC_NAMESPACE::libc_api_struct{}();
4454

4555
// Disallow calling into global namespace for implemented entrypoints.
4656
::libc_api_func();
47-
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'libc_api_func' must resolve to a function declared within the '__llvm_libc' namespace
48-
// CHECK-MESSAGES: :15:6: note: resolves to this declaration
57+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'libc_api_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro
58+
// CHECK-MESSAGES: :25:6: note: resolves to this declaration
4959

5060
// Disallow indirect references to functions in global namespace.
5161
void (*badPtr)(void) = ::libc_api_func;
5262
badPtr();
53-
// CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 'libc_api_func' must resolve to a function declared within the '__llvm_libc' namespace
54-
// CHECK-MESSAGES: :15:6: note: resolves to this declaration
63+
// CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 'libc_api_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro
64+
// CHECK-MESSAGES: :25:6: note: resolves to this declaration
5565

5666
// Allow calling into global namespace for specific functions.
5767
::malloc();
5868

5969
// Disallow calling on entities that are not in the namespace, but make sure
6070
// no crashes happen.
6171
global_struct{}();
62-
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'operator()' must resolve to a function declared within the '__llvm_libc' namespace
63-
// CHECK-MESSAGES: :22:7: note: resolves to this declaration
72+
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'operator()' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro
73+
// CHECK-MESSAGES: :32:7: note: resolves to this declaration
74+
75+
OTHER_MACRO_NAMESPACE::wrong_name_macro_func();
76+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'wrong_name_macro_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro
77+
// CHECK-MESSAGES: :3:31: note: expanded from macro 'OTHER_MACRO_NAMESPACE'
78+
// CHECK-MESSAGES: :5:8: note: resolves to this declaration
79+
80+
__llvm_libc::right_name_no_macro_func();
81+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'right_name_no_macro_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro
82+
// CHECK-MESSAGES: :9:8: note: resolves to this declaration
83+
6484
}
6585

6686
} // namespace __llvm_libc

0 commit comments

Comments
 (0)