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