| //===--- KernelNameRestrictionCheck.cpp - clang-tidy ----------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "KernelNameRestrictionCheck.h" |
| #include "clang/Frontend/CompilerInstance.h" |
| #include "clang/Lex/PPCallbacks.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include <string> |
| #include <vector> |
| |
| using namespace clang::ast_matchers; |
| |
| namespace clang { |
| namespace tidy { |
| namespace altera { |
| |
| namespace { |
| |
| class KernelNameRestrictionPPCallbacks : public PPCallbacks { |
| public: |
| explicit KernelNameRestrictionPPCallbacks(ClangTidyCheck &Check, |
| const SourceManager &SM) |
| : Check(Check), SM(SM) {} |
| |
| void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, |
| StringRef FileName, bool IsAngled, |
| CharSourceRange FileNameRange, const FileEntry *File, |
| StringRef SearchPath, StringRef RelativePath, |
| const Module *Imported, |
| SrcMgr::CharacteristicKind FileType) override; |
| |
| void EndOfMainFile() override; |
| |
| private: |
| /// Returns true if the name of the file with path FilePath is 'kernel.cl', |
| /// 'verilog.cl', or 'vhdl.cl'. The file name check is case insensitive. |
| bool fileNameIsRestricted(StringRef FilePath); |
| |
| struct IncludeDirective { |
| SourceLocation Loc; // Location in the include directive. |
| StringRef FileName; // Filename as a string. |
| }; |
| |
| std::vector<IncludeDirective> IncludeDirectives; |
| ClangTidyCheck &Check; |
| const SourceManager &SM; |
| }; |
| |
| } // namespace |
| |
| void KernelNameRestrictionCheck::registerPPCallbacks(const SourceManager &SM, |
| Preprocessor *PP, |
| Preprocessor *) { |
| PP->addPPCallbacks( |
| std::make_unique<KernelNameRestrictionPPCallbacks>(*this, SM)); |
| } |
| |
| void KernelNameRestrictionPPCallbacks::InclusionDirective( |
| SourceLocation HashLoc, const Token &, StringRef FileName, bool, |
| CharSourceRange, const FileEntry *, StringRef, StringRef, const Module *, |
| SrcMgr::CharacteristicKind) { |
| IncludeDirective ID = {HashLoc, FileName}; |
| IncludeDirectives.push_back(std::move(ID)); |
| } |
| |
| bool KernelNameRestrictionPPCallbacks::fileNameIsRestricted( |
| StringRef FileName) { |
| return FileName.equals_insensitive("kernel.cl") || |
| FileName.equals_insensitive("verilog.cl") || |
| FileName.equals_insensitive("vhdl.cl"); |
| } |
| |
| void KernelNameRestrictionPPCallbacks::EndOfMainFile() { |
| |
| // Check main file for restricted names. |
| const FileEntry *Entry = SM.getFileEntryForID(SM.getMainFileID()); |
| StringRef FileName = llvm::sys::path::filename(Entry->getName()); |
| if (fileNameIsRestricted(FileName)) |
| Check.diag(SM.getLocForStartOfFile(SM.getMainFileID()), |
| "compiling '%0' may cause additional compilation errors due " |
| "to the name of the kernel source file; consider renaming the " |
| "included kernel source file") |
| << FileName; |
| |
| if (IncludeDirectives.empty()) |
| return; |
| |
| // Check included files for restricted names. |
| for (const IncludeDirective &ID : IncludeDirectives) { |
| StringRef FileName = llvm::sys::path::filename(ID.FileName); |
| if (fileNameIsRestricted(FileName)) |
| Check.diag(ID.Loc, |
| "including '%0' may cause additional compilation errors due " |
| "to the name of the kernel source file; consider renaming the " |
| "included kernel source file") |
| << FileName; |
| } |
| } |
| |
| } // namespace altera |
| } // namespace tidy |
| } // namespace clang |