clang-tools  15.0.0git
CalleeNamespaceCheck.cpp
Go to the documentation of this file.
1 //===-- CalleeNamespaceCheck.cpp ------------------------------------------===//
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 "CalleeNamespaceCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 #include "llvm/ADT/StringSet.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace llvm_libc {
20 
21 // Gets the outermost namespace of a DeclContext, right under the Translation
22 // Unit.
23 const DeclContext *getOutermostNamespace(const DeclContext *Decl) {
24  const DeclContext *Parent = Decl->getParent();
25  if (Parent->isTranslationUnit())
26  return Decl;
28 }
29 
30 void CalleeNamespaceCheck::registerMatchers(MatchFinder *Finder) {
31  Finder->addMatcher(
32  declRefExpr(to(functionDecl().bind("func"))).bind("use-site"), this);
33 }
34 
35 // A list of functions that are exempted from this check. The __errno_location
36 // function is for setting errno, which is allowed in libc, and the other
37 // functions are specifically allowed to be external so that they can be
38 // intercepted.
39 static const llvm::StringSet<> IgnoredFunctions = {
40  "__errno_location", "malloc", "calloc", "realloc", "free", "aligned_alloc"};
41 
42 void CalleeNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
43  const auto *UsageSiteExpr = Result.Nodes.getNodeAs<DeclRefExpr>("use-site");
44  const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("func");
45 
46  // Ignore compiler builtin functions.
47  if (FuncDecl->getBuiltinID() != 0)
48  return;
49 
50  // If the outermost namespace of the function is __llvm_libc, we're good.
51  const auto *NS = dyn_cast<NamespaceDecl>(getOutermostNamespace(FuncDecl));
52  if (NS && NS->getName() == "__llvm_libc")
53  return;
54 
55  const DeclarationName &Name = FuncDecl->getDeclName();
56  if (Name.isIdentifier() &&
57  IgnoredFunctions.contains(Name.getAsIdentifierInfo()->getName()))
58  return;
59 
60  diag(UsageSiteExpr->getBeginLoc(), "%0 must resolve to a function declared "
61  "within the '__llvm_libc' namespace")
62  << FuncDecl;
63 
64  diag(FuncDecl->getLocation(), "resolves to this declaration",
65  clang::DiagnosticIDs::Note);
66 }
67 
68 } // namespace llvm_libc
69 } // namespace tidy
70 } // namespace clang
clang::clangd::check
bool check(llvm::StringRef File, llvm::Optional< Range > LineRange, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:273
clang::tidy::llvm_libc::IgnoredFunctions
static const llvm::StringSet IgnoredFunctions
Definition: CalleeNamespaceCheck.cpp:39
clang::ast_matchers
Definition: AbseilMatcher.h:14
CalleeNamespaceCheck.h
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
Name
Token Name
Definition: MacroToEnumCheck.cpp:89
Parent
const Node * Parent
Definition: ExtractFunction.cpp:157
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::llvm_libc::getOutermostNamespace
const DeclContext * getOutermostNamespace(const DeclContext *Decl)
Definition: CalleeNamespaceCheck.cpp:23