1 //===--- HeaderGuardCheck.cpp - clang-tidy --------------------------------===//
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 "HeaderGuardCheck.h"
10 #include "clang/Tooling/Tooling.h"
11
12 namespace clang {
13 namespace tidy {
14 namespace llvm_check {
15
LLVMHeaderGuardCheck(StringRef Name,ClangTidyContext * Context)16 LLVMHeaderGuardCheck::LLVMHeaderGuardCheck(StringRef Name,
17 ClangTidyContext *Context)
18 : HeaderGuardCheck(Name, Context) {}
19
getHeaderGuard(StringRef Filename,StringRef OldGuard)20 std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename,
21 StringRef OldGuard) {
22 std::string Guard = tooling::getAbsolutePath(Filename);
23
24 // Sanitize the path. There are some rules for compatibility with the historic
25 // style in include/llvm and include/clang which we want to preserve.
26
27 // We don't want _INCLUDE_ in our guards.
28 size_t PosInclude = Guard.rfind("include/");
29 if (PosInclude != StringRef::npos)
30 Guard = Guard.substr(PosInclude + std::strlen("include/"));
31
32 // For clang we drop the _TOOLS_.
33 size_t PosToolsClang = Guard.rfind("tools/clang/");
34 if (PosToolsClang != StringRef::npos)
35 Guard = Guard.substr(PosToolsClang + std::strlen("tools/"));
36
37 // Unlike LLVM svn, LLVM git monorepo is named llvm-project, so we replace
38 // "/llvm-project/" with the cannonical "/llvm/".
39 const static StringRef LLVMProject = "/llvm-project/";
40 size_t PosLLVMProject = Guard.rfind(std::string(LLVMProject));
41 if (PosLLVMProject != StringRef::npos)
42 Guard = Guard.replace(PosLLVMProject, LLVMProject.size(), "/llvm/");
43
44 // The remainder is LLVM_FULL_PATH_TO_HEADER_H
45 size_t PosLLVM = Guard.rfind("llvm/");
46 if (PosLLVM != StringRef::npos)
47 Guard = Guard.substr(PosLLVM);
48
49 std::replace(Guard.begin(), Guard.end(), '/', '_');
50 std::replace(Guard.begin(), Guard.end(), '.', '_');
51 std::replace(Guard.begin(), Guard.end(), '-', '_');
52
53 // The prevalent style in clang is LLVM_CLANG_FOO_BAR_H
54 if (StringRef(Guard).startswith("clang"))
55 Guard = "LLVM_" + Guard;
56
57 // The prevalent style in flang is FORTRAN_FOO_BAR_H
58 if (StringRef(Guard).startswith("flang"))
59 Guard = "FORTRAN" + Guard.substr(sizeof("flang") - 1);
60
61 return StringRef(Guard).upper();
62 }
63
64 } // namespace llvm_check
65 } // namespace tidy
66 } // namespace clang
67