xref: /llvm-project/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp (revision da95d926f6fce4ed9707c77908ad96624268f134)
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