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