1 //===--- KernelNameRestrictionCheck.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 "KernelNameRestrictionCheck.h"
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/Lex/PPCallbacks.h"
12 #include "clang/Lex/Preprocessor.h"
13 #include <string>
14 #include <vector>
15
16 using namespace clang::ast_matchers;
17
18 namespace clang::tidy::altera {
19
20 namespace {
21
22 class KernelNameRestrictionPPCallbacks : public PPCallbacks {
23 public:
KernelNameRestrictionPPCallbacks(ClangTidyCheck & Check,const SourceManager & SM)24 explicit KernelNameRestrictionPPCallbacks(ClangTidyCheck &Check,
25 const SourceManager &SM)
26 : Check(Check), SM(SM) {}
27
28 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
29 StringRef FileName, bool IsAngled,
30 CharSourceRange FileNameRange,
31 OptionalFileEntryRef File, StringRef SearchPath,
32 StringRef RelativePath, const Module *SuggestedModule,
33 bool ModuleImported,
34 SrcMgr::CharacteristicKind FileType) override;
35
36 void EndOfMainFile() override;
37
38 private:
39 /// Returns true if the name of the file with path FileName is 'kernel.cl',
40 /// 'verilog.cl', or 'vhdl.cl'. The file name check is case insensitive.
41 bool fileNameIsRestricted(StringRef FileName);
42
43 struct IncludeDirective {
44 SourceLocation Loc; // Location in the include directive.
45 StringRef FileName; // Filename as a string.
46 };
47
48 std::vector<IncludeDirective> IncludeDirectives;
49 ClangTidyCheck &Check;
50 const SourceManager &SM;
51 };
52
53 } // namespace
54
registerPPCallbacks(const SourceManager & SM,Preprocessor * PP,Preprocessor *)55 void KernelNameRestrictionCheck::registerPPCallbacks(const SourceManager &SM,
56 Preprocessor *PP,
57 Preprocessor *) {
58 PP->addPPCallbacks(
59 std::make_unique<KernelNameRestrictionPPCallbacks>(*this, SM));
60 }
61
InclusionDirective(SourceLocation HashLoc,const Token &,StringRef FileName,bool,CharSourceRange,OptionalFileEntryRef,StringRef,StringRef,const Module *,bool,SrcMgr::CharacteristicKind)62 void KernelNameRestrictionPPCallbacks::InclusionDirective(
63 SourceLocation HashLoc, const Token &, StringRef FileName, bool,
64 CharSourceRange, OptionalFileEntryRef, StringRef, StringRef, const Module *,
65 bool, SrcMgr::CharacteristicKind) {
66 IncludeDirective ID = {HashLoc, FileName};
67 IncludeDirectives.push_back(std::move(ID));
68 }
69
fileNameIsRestricted(StringRef FileName)70 bool KernelNameRestrictionPPCallbacks::fileNameIsRestricted(
71 StringRef FileName) {
72 return FileName.equals_insensitive("kernel.cl") ||
73 FileName.equals_insensitive("verilog.cl") ||
74 FileName.equals_insensitive("vhdl.cl");
75 }
76
EndOfMainFile()77 void KernelNameRestrictionPPCallbacks::EndOfMainFile() {
78
79 // Check main file for restricted names.
80 OptionalFileEntryRef Entry = SM.getFileEntryRefForID(SM.getMainFileID());
81 StringRef FileName = llvm::sys::path::filename(Entry->getName());
82 if (fileNameIsRestricted(FileName))
83 Check.diag(SM.getLocForStartOfFile(SM.getMainFileID()),
84 "compiling '%0' may cause additional compilation errors due "
85 "to the name of the kernel source file; consider renaming the "
86 "included kernel source file")
87 << FileName;
88
89 if (IncludeDirectives.empty())
90 return;
91
92 // Check included files for restricted names.
93 for (const IncludeDirective &ID : IncludeDirectives) {
94 StringRef FileName = llvm::sys::path::filename(ID.FileName);
95 if (fileNameIsRestricted(FileName))
96 Check.diag(ID.Loc,
97 "including '%0' may cause additional compilation errors due "
98 "to the name of the kernel source file; consider renaming the "
99 "included kernel source file")
100 << FileName;
101 }
102 }
103
104 } // namespace clang::tidy::altera
105