Index: clang-tools-extra/clang-tidy/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/CMakeLists.txt +++ clang-tools-extra/clang-tidy/CMakeLists.txt @@ -41,6 +41,7 @@ # If you add a check, also add it to ClangTidyForceLinker.h in this directory. add_subdirectory(android) add_subdirectory(abseil) +add_subdirectory(altera) add_subdirectory(boost) add_subdirectory(bugprone) add_subdirectory(cert) @@ -65,6 +66,7 @@ set(ALL_CLANG_TIDY_CHECKS clangTidyAndroidModule clangTidyAbseilModule + clangTidyAlteraModule clangTidyBoostModule clangTidyBugproneModule clangTidyCERTModule Index: clang-tools-extra/clang-tidy/ClangTidyForceLinker.h =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyForceLinker.h +++ clang-tools-extra/clang-tidy/ClangTidyForceLinker.h @@ -25,6 +25,11 @@ static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination = AbseilModuleAnchorSource; +// This anchor is used to force the linker to link the AlteraModule. +extern volatile int AlteraModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED AlteraModuleAnchorDestination = + AlteraModuleAnchorSource; + // This anchor is used to force the linker to link the BoostModule. extern volatile int BoostModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination = Index: clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp @@ -0,0 +1,39 @@ +//===--- AlteraTidyModule.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 "../ClangTidy.h" +#include "../ClangTidyModule.h" +#include "../ClangTidyModuleRegistry.h" +#include "KernelNameRestrictionCheck.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace altera { + +class AlteraModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "altera-kernel-name-restriction"); + } +}; + +} // namespace altera + +// Register the AlteraTidyModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add + X("altera-module", "Adds Altera FPGA OpenCL lint checks."); + +// This anchor is used to force the linker to link in the generated object file +// and thus register the AlteraModule. +volatile int AlteraModuleAnchorSource = 0; + +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/altera/CMakeLists.txt =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/altera/CMakeLists.txt @@ -0,0 +1,15 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangTidyAlteraModule + AlteraTidyModule.cpp + KernelNameRestrictionCheck.cpp + + LINK_LIBS + clangAnalysis + clangAST + clangASTMatchers + clangBasic + clangLex + clangTidy + clangTidyUtils + ) Index: clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.h @@ -0,0 +1,36 @@ +//===--- KernelNameRestrictionCheck.h - clang-tidy --------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_KERNEL_NAME_RESTRICTION_CHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_KERNEL_NAME_RESTRICTION_CHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace altera { + +/// Flags kernel files that are named `kernel.cl`, `Verilog.cl` or `VHDL.cl` as +/// warnings, since this may lead to intermediate files being generated that +/// have the same names as certain internal files, leading to compiler errors. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/altera-kernel-name-restriction.html +class KernelNameRestrictionCheck : public ClangTidyCheck { +public: + KernelNameRestrictionCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; +}; + +} // namespace altera +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_KERNEL_NAME_RESTRICTION_CHECK_H Index: clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp @@ -0,0 +1,97 @@ +//===--- 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: + 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 *ModuleExpanderPP) { + PP->addPPCallbacks( + std::make_unique(*this, SM)); +} + +void KernelNameRestrictionPPCallbacks::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) { + IncludeDirective ID = {HashLoc, FileName}; + IncludeDirectives.push_back(std::move(ID)); +} + +void KernelNameRestrictionPPCallbacks::EndOfMainFile() { + if (IncludeDirectives.empty()) + return; + + // Check included files for restricted names. + for (const IncludeDirective &ID : IncludeDirectives) { + StringRef FilePath = ID.Filename; + StringRef FileName = FilePath.substr(FilePath.find_last_of("/\\") + 1); + if (FileName.equals_lower("kernel.cl") || + FileName.equals_lower("verilog.cl") || + FileName.equals_lower("vhdl.cl")) + Check.diag(ID.Loc, + "The imported kernel source file is named 'kernel.cl'," + "'Verilog.cl', or 'VHDL.cl', which could cause compilation " + "errors."); + } + + // Check main file for restricted names. + const FileEntry *Entry = SM.getFileEntryForID(SM.getMainFileID()); + StringRef FilePath = Entry->getName(); + StringRef FileName = FilePath.substr(FilePath.find_last_of("/\\") + 1); + if (FileName.equals_lower("kernel.cl") || + FileName.equals_lower("verilog.cl") || FileName.equals_lower("vhdl.cl")) + Check.diag(SM.getLocForStartOfFile(SM.getMainFileID()), + "Naming your OpenCL kernel source file 'kernel.cl', 'Verilog.cl'" + ", or 'VHDL.cl' could cause compilation errors."); +} + +} // namespace altera +} // namespace tidy +} // namespace clang Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -67,9 +67,24 @@ Improvements to clang-tidy -------------------------- +New modules +^^^^^^^^^^^ + +- New :doc:`altera ` module. + + Includes checks related to OpenCL for FPGA coding guidelines, based on the + `Altera SDK for OpenCL: Best Practices Guide + `_. + New checks ^^^^^^^^^^ +- New :doc:`altera-kernel-name-restriction + ` check. + + Finds kernel files and include directives whose filename is `kernel.cl`, + `Verilog.cl`, or `VHDL.cl`. + - New :doc:`bugprone-misplaced-pointer-arithmetic-in-alloc ` check. Index: clang-tools-extra/docs/clang-tidy/checks/altera-kernel-name-restriction.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/altera-kernel-name-restriction.rst @@ -0,0 +1,15 @@ +.. title:: clang-tidy - altera-kernel-name-restriction + +altera-kernel-name-restriction +============================ + +Finds kernel files and include directives whose filename is `kernel.cl`, +`Verilog.cl`, or `VHDL.cl`. + +Such kernel file names cause the offline compiler to generate intermediate +design files that have the same names as certain internal files, which +leads to a compilation error. + +Based on the `Guidelines for Naming the Kernel` section in the +`Intel FPGA SDK for OpenCL Pro Edition: Programming Guide +`_. Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -29,6 +29,7 @@ `abseil-time-comparison `_, "Yes" `abseil-time-subtraction `_, "Yes" `abseil-upgrade-duration-conversions `_, "Yes" + `altera-kernel-name-restriction `_, `android-cloexec-accept `_, "Yes" `android-cloexec-accept4 `_, `android-cloexec-creat `_, "Yes" Index: clang-tools-extra/docs/clang-tidy/index.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/index.rst +++ clang-tools-extra/docs/clang-tidy/index.rst @@ -58,6 +58,7 @@ Name prefix Description ====================== ========================================================= ``abseil-`` Checks related to Abseil library. +``altera-`` Checks related to OpenCL programming for FPGAs. ``android-`` Checks related to Android. ``boost-`` Checks related to Boost library. ``bugprone-`` Checks that target bugprone code constructs. Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/KERNEL.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/KERNEL.cl @@ -0,0 +1 @@ +const int KERNELINT2 = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/VHDL.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/VHDL.cl @@ -0,0 +1 @@ +const int VHDLINT = 3; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/Verilog.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/Verilog.cl @@ -0,0 +1 @@ +const int VERILOGINT = 2; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/kernel.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/kernel.h @@ -0,0 +1 @@ +const int KERNELINT3 = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/kernel.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/kernel.cl @@ -0,0 +1 @@ +const int KERNELINT = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/other_Verilog.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/other_Verilog.cl @@ -0,0 +1 @@ +const int OTHERVERILOGINT = 2; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/otherdir/vhdl.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/otherdir/vhdl.cl @@ -0,0 +1 @@ +const int OTHERDIRVHDLINT = 3; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/otherthing.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/otherthing.cl @@ -0,0 +1 @@ +const int OTHERTHINGINT = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/some/dir/kernel.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/some/dir/kernel.cl @@ -0,0 +1 @@ +const int SOMEDIRKERNELINT = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/some_kernel.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/some_kernel.cl @@ -0,0 +1 @@ +const int SOMEKERNELINT = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/somedir/verilog.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/somedir/verilog.cl @@ -0,0 +1 @@ +const int SOMEDIRVERILOGINT = 2; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/thing.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/thing.h @@ -0,0 +1 @@ +const int THINGINT = 1; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vERILOG.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vERILOG.cl @@ -0,0 +1 @@ +const int VERILOGINT2 = 2; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/verilog.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/verilog.h @@ -0,0 +1 @@ +const int VERILOGINT3 = 2; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vhdl.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vhdl.h @@ -0,0 +1 @@ +const int VHDLINT3 = 3; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vhdl.CL =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vhdl.CL @@ -0,0 +1 @@ +const int VHDLINT2 = 3; Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vhdl_number_two.cl =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/Inputs/altera-kernel-name-restriction/vhdl_number_two.cl @@ -0,0 +1 @@ +const int VHDLNUMBERTWOINT = 3; Index: clang-tools-extra/test/clang-tidy/checkers/altera-kernel-name-restriction.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/altera-kernel-name-restriction.cpp @@ -0,0 +1,42 @@ +// RUN: %check_clang_tidy %s altera-kernel-name-restriction %t -- -- -I%S/Inputs/altera-kernel-name-restriction + +// These are the banned kernel filenames, and should trigger warnings +#include "kernel.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] +#include "Verilog.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] +#include "VHDL.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] + +// The warning should be triggered regardless of capitalization +#include "KERNEL.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] +#include "vERILOG.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] +#include "vhdl.CL" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] + +// The warning should be triggered if the names are within a directory +#include "some/dir/kernel.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] +#include "somedir/verilog.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] +#include "otherdir/vhdl.cl" +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: The imported kernel source file is named 'kernel.cl','Verilog.cl', or 'VHDL.cl', which could cause compilation errors. [altera-kernel-name-restriction] + +// There are no FIX-ITs for the altera-kernel-name-restriction lint check + +// The following include directives shouldn't trigger the warning +#include "otherthing.cl" +#include "thing.h" + +// It doesn't make sense to have kernel.h, verilog.h, or vhdl.h as filenames without the corresponding .cl files, +// but the Altera Programming Guide doesn't explicitly forbid it +#include "kernel.h" +#include "verilog.h" +#include "vhdl.h" + +// The files can still have the forbidden names in them, so long as they're not the entire file name +#include "some_kernel.cl" +#include "other_Verilog.cl" +#include "vhdl_number_two.cl"