//===--- 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 #include 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 IncludeDirectives; ClangTidyCheck &Check; const SourceManager &SM; }; } // namespace void KernelNameRestrictionCheck::registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *) { PP->addPPCallbacks( std::make_unique(*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_lower("kernel.cl") || FileName.equals_lower("verilog.cl") || FileName.equals_lower("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