<div dir="ltr">Looks like this broke the sphinx bot: <a href="http://lab.llvm.org:8011/builders/clang-tools-sphinx-docs/builds/65757/steps/docs-clang-tools-html/logs/stdio">http://lab.llvm.org:8011/builders/clang-tools-sphinx-docs/builds/65757/steps/docs-clang-tools-html/logs/stdio</a><div><br>Can you take a look?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 8, 2020 at 9:36 AM Aaron Ballman via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Frank Derry Wanye<br>
Date: 2020-09-08T09:35:14-04:00<br>
New Revision: 156b127945a8c923d141e608b7380427da024376<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/156b127945a8c923d141e608b7380427da024376" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/156b127945a8c923d141e608b7380427da024376</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/156b127945a8c923d141e608b7380427da024376.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/156b127945a8c923d141e608b7380427da024376.diff</a><br>
<br>
LOG: Add a new altera check for structure packing and alignment.<br>
<br>
The altera struct pack align lint check finds structs that are inefficiently<br>
packed or aligned and recommends packing/aligning of the structs using the<br>
packed and aligned attributes as needed in a warning.<br>
<br>
Added: <br>
clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp<br>
clang-tools-extra/clang-tidy/altera/CMakeLists.txt<br>
clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp<br>
clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.h<br>
clang-tools-extra/docs/clang-tidy/checks/altera-struct-pack-align.rst<br>
clang-tools-extra/test/clang-tidy/checkers/altera-struct-pack-align.cpp<br>
<br>
Modified: <br>
clang-tools-extra/clang-tidy/CMakeLists.txt<br>
clang-tools-extra/clang-tidy/ClangTidyForceLinker.h<br>
clang-tools-extra/docs/ReleaseNotes.rst<br>
clang-tools-extra/docs/clang-tidy/checks/list.rst<br>
clang-tools-extra/docs/clang-tidy/index.rst<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt b/clang-tools-extra/clang-tidy/CMakeLists.txt<br>
index 02573534ccae..923976197ebe 100644<br>
--- a/clang-tools-extra/clang-tidy/CMakeLists.txt<br>
+++ b/clang-tools-extra/clang-tidy/CMakeLists.txt<br>
@@ -46,6 +46,7 @@ endif()<br>
# If you add a check, also add it to ClangTidyForceLinker.h in this directory.<br>
add_subdirectory(android)<br>
add_subdirectory(abseil)<br>
+add_subdirectory(altera)<br>
add_subdirectory(boost)<br>
add_subdirectory(bugprone)<br>
add_subdirectory(cert)<br>
@@ -71,6 +72,7 @@ add_subdirectory(zircon)<br>
set(ALL_CLANG_TIDY_CHECKS<br>
clangTidyAndroidModule<br>
clangTidyAbseilModule<br>
+ clangTidyAlteraModule<br>
clangTidyBoostModule<br>
clangTidyBugproneModule<br>
clangTidyCERTModule<br>
<br>
diff --git a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h<br>
index 1d6bd2a4fd62..63e681f878db 100644<br>
--- a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h<br>
+++ b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h<br>
@@ -20,6 +20,11 @@ extern volatile int AbseilModuleAnchorSource;<br>
static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination =<br>
AbseilModuleAnchorSource;<br>
<br>
+// This anchor is used to force the linker to link the AlteraModule.<br>
+extern volatile int AlteraModuleAnchorSource;<br>
+static int LLVM_ATTRIBUTE_UNUSED AlteraModuleAnchorDestination =<br>
+ AlteraModuleAnchorSource;<br>
+<br>
// This anchor is used to force the linker to link the AndroidModule.<br>
extern volatile int AndroidModuleAnchorSource;<br>
static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination =<br>
<br>
diff --git a/clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp b/clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp<br>
new file mode 100644<br>
index 000000000000..d91f67ac1485<br>
--- /dev/null<br>
+++ b/clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp<br>
@@ -0,0 +1,39 @@<br>
+//===--- AlteraTidyModule.cpp - clang-tidy --------------------------------===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "../ClangTidy.h"<br>
+#include "../ClangTidyModule.h"<br>
+#include "../ClangTidyModuleRegistry.h"<br>
+#include "StructPackAlignCheck.h"<br>
+<br>
+using namespace clang::ast_matchers;<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace altera {<br>
+<br>
+class AlteraModule : public ClangTidyModule {<br>
+public:<br>
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {<br>
+ CheckFactories.registerCheck<StructPackAlignCheck>(<br>
+ "altera-struct-pack-align");<br>
+ }<br>
+};<br>
+<br>
+} // namespace altera<br>
+<br>
+// Register the AlteraTidyModule using this statically initialized variable.<br>
+static ClangTidyModuleRegistry::Add<altera::AlteraModule><br>
+ X("altera-module", "Adds Altera FPGA OpenCL lint checks.");<br>
+<br>
+// This anchor is used to force the linker to link in the generated object file<br>
+// and thus register the AlteraModule.<br>
+volatile int AlteraModuleAnchorSource = 0;<br>
+<br>
+} // namespace tidy<br>
+} // namespace clang<br>
<br>
diff --git a/clang-tools-extra/clang-tidy/altera/CMakeLists.txt b/clang-tools-extra/clang-tidy/altera/CMakeLists.txt<br>
new file mode 100644<br>
index 000000000000..45131c1809a2<br>
--- /dev/null<br>
+++ b/clang-tools-extra/clang-tidy/altera/CMakeLists.txt<br>
@@ -0,0 +1,15 @@<br>
+set(LLVM_LINK_COMPONENTS support)<br>
+<br>
+add_clang_library(clangTidyAlteraModule<br>
+ AlteraTidyModule.cpp<br>
+ StructPackAlignCheck.cpp<br>
+<br>
+ LINK_LIBS<br>
+ clangAnalysis<br>
+ clangAST<br>
+ clangASTMatchers<br>
+ clangBasic<br>
+ clangLex<br>
+ clangTidy<br>
+ clangTidyUtils<br>
+ )<br>
<br>
diff --git a/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp b/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp<br>
new file mode 100644<br>
index 000000000000..9f28a22a9d03<br>
--- /dev/null<br>
+++ b/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp<br>
@@ -0,0 +1,144 @@<br>
+//===--- StructPackAlignCheck.cpp - clang-tidy ----------------------------===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "StructPackAlignCheck.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/RecordLayout.h"<br>
+#include "clang/ASTMatchers/ASTMatchFinder.h"<br>
+#include <math.h><br>
+#include <sstream><br>
+<br>
+using namespace clang::ast_matchers;<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace altera {<br>
+<br>
+void StructPackAlignCheck::registerMatchers(MatchFinder *Finder) {<br>
+ Finder->addMatcher(recordDecl(isStruct(), isDefinition(),<br>
+ unless(isExpansionInSystemHeader()))<br>
+ .bind("struct"),<br>
+ this);<br>
+}<br>
+<br>
+CharUnits<br>
+StructPackAlignCheck::computeRecommendedAlignment(CharUnits MinByteSize) {<br>
+ CharUnits NewAlign = CharUnits::fromQuantity(1);<br>
+ if (!MinByteSize.isPowerOfTwo()) {<br>
+ int MSB = (int)MinByteSize.getQuantity();<br>
+ for (; MSB > 0; MSB /= 2) {<br>
+ NewAlign = NewAlign.alignTo(<br>
+ CharUnits::fromQuantity(((int)NewAlign.getQuantity()) * 2));<br>
+ // Abort if the computed alignment meets the maximum configured alignment.<br>
+ if (NewAlign.getQuantity() >= MaxConfiguredAlignment)<br>
+ break;<br>
+ }<br>
+ } else {<br>
+ NewAlign = MinByteSize;<br>
+ }<br>
+ return NewAlign;<br>
+}<br>
+<br>
+void StructPackAlignCheck::check(const MatchFinder::MatchResult &Result) {<br>
+ const auto *Struct = Result.Nodes.getNodeAs<RecordDecl>("struct");<br>
+<br>
+ // Do not trigger on templated struct declarations because the packing and<br>
+ // alignment requirements are unknown.<br>
+ if (Struct->isTemplated())<br>
+ return;<br>
+<br>
+ // Get sizing info for the struct.<br>
+ llvm::SmallVector<std::pair<unsigned int, unsigned int>, 10> FieldSizes;<br>
+ unsigned int TotalBitSize = 0;<br>
+ for (const FieldDecl *StructField : Struct->fields()) {<br>
+ // For each StructField, record how big it is (in bits).<br>
+ // Would be good to use a pair of <offset, size> to advise a better<br>
+ // packing order.<br>
+ unsigned int StructFieldWidth =<br>
+ (unsigned int)Result.Context<br>
+ ->getTypeInfo(StructField->getType().getTypePtr())<br>
+ .Width;<br>
+ FieldSizes.emplace_back(StructFieldWidth, StructField->getFieldIndex());<br>
+ // FIXME: Recommend a reorganization of the struct (sort by StructField<br>
+ // size, largest to smallest).<br>
+ TotalBitSize += StructFieldWidth;<br>
+ }<br>
+<br>
+ uint64_t CharSize = Result.Context->getCharWidth();<br>
+ CharUnits CurrSize = Result.Context->getASTRecordLayout(Struct).getSize();<br>
+ CharUnits MinByteSize =<br>
+ CharUnits::fromQuantity(ceil((float)TotalBitSize / CharSize));<br>
+ CharUnits MaxAlign = CharUnits::fromQuantity(<br>
+ ceil((float)Struct->getMaxAlignment() / CharSize));<br>
+ CharUnits CurrAlign =<br>
+ Result.Context->getASTRecordLayout(Struct).getAlignment();<br>
+ CharUnits NewAlign = computeRecommendedAlignment(MinByteSize);<br>
+<br>
+ bool IsPacked = Struct->hasAttr<PackedAttr>();<br>
+ bool NeedsPacking = (MinByteSize < CurrSize) && (MaxAlign != NewAlign) &&<br>
+ (CurrSize != NewAlign);<br>
+ bool NeedsAlignment = CurrAlign.getQuantity() != NewAlign.getQuantity();<br>
+<br>
+ if (!NeedsAlignment && !NeedsPacking)<br>
+ return;<br>
+<br>
+ // If it's using much more space than it needs, suggest packing.<br>
+ // (Do not suggest packing if it is currently explicitly aligned to what the<br>
+ // minimum byte size would suggest as the new alignment.)<br>
+ if (NeedsPacking && !IsPacked) {<br>
+ diag(Struct->getLocation(),<br>
+ "accessing fields in struct %0 is inefficient due to padding; only "<br>
+ "needs %1 bytes but is using %2 bytes")<br>
+ << Struct << (int)MinByteSize.getQuantity()<br>
+ << (int)CurrSize.getQuantity()<br>
+ << FixItHint::CreateInsertion(Struct->getEndLoc().getLocWithOffset(1),<br>
+ " __attribute__((packed))");<br>
+ diag(Struct->getLocation(),<br>
+ "use \"__attribute__((packed))\" to reduce the amount of padding "<br>
+ "applied to struct %0",<br>
+ DiagnosticIDs::Note)<br>
+ << Struct;<br>
+ }<br>
+<br>
+ FixItHint FixIt;<br>
+ AlignedAttr *Attribute = Struct->getAttr<AlignedAttr>();<br>
+ std::string NewAlignQuantity = std::to_string((int)NewAlign.getQuantity());<br>
+ if (Attribute) {<br>
+ std::ostringstream FixItString;<br>
+ FixItString << "aligned(" << NewAlignQuantity << ")";<br>
+ FixIt =<br>
+ FixItHint::CreateReplacement(Attribute->getRange(), FixItString.str());<br>
+ } else {<br>
+ std::ostringstream FixItString;<br>
+ FixItString << " __attribute__((aligned(" << NewAlignQuantity << ")))";<br>
+ FixIt = FixItHint::CreateInsertion(Struct->getEndLoc().getLocWithOffset(1),<br>
+ FixItString.str());<br>
+ }<br>
+<br>
+ // And suggest the minimum power-of-two alignment for the struct as a whole<br>
+ // (with and without packing).<br>
+ if (NeedsAlignment) {<br>
+ diag(Struct->getLocation(),<br>
+ "accessing fields in struct %0 is inefficient due to poor alignment; "<br>
+ "currently aligned to %1 bytes, but recommended alignment is %2 bytes")<br>
+ << Struct << (int)CurrAlign.getQuantity() << NewAlignQuantity << FixIt;<br>
+<br>
+ diag(Struct->getLocation(),<br>
+ "use \"__attribute__((aligned(%0)))\" to align struct %1 to %0 bytes",<br>
+ DiagnosticIDs::Note)<br>
+ << NewAlignQuantity << Struct;<br>
+ }<br>
+}<br>
+<br>
+void StructPackAlignCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {<br>
+ Options.store(Opts, "MaxConfiguredAlignment", MaxConfiguredAlignment);<br>
+}<br>
+<br>
+} // namespace altera<br>
+} // namespace tidy<br>
+} // namespace clang<br>
<br>
diff --git a/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.h b/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.h<br>
new file mode 100644<br>
index 000000000000..b903641247e3<br>
--- /dev/null<br>
+++ b/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.h<br>
@@ -0,0 +1,41 @@<br>
+//===--- StructPackAlignCheck.h - clang-tidy --------------------*- C++ -*-===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_STRUCTPACKALIGNCHECK_H<br>
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_STRUCTPACKALIGNCHECK_H<br>
+<br>
+#include "../ClangTidyCheck.h"<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace altera {<br>
+<br>
+/// Finds structs that are inefficiently packed or aligned, and recommends<br>
+/// packing and/or aligning of said structs as needed.<br>
+///<br>
+/// For the user-facing documentation see:<br>
+/// <a href="http://clang.llvm.org/extra/clang-tidy/checks/altera-struct-pack-align.html" rel="noreferrer" target="_blank">http://clang.llvm.org/extra/clang-tidy/checks/altera-struct-pack-align.html</a><br>
+class StructPackAlignCheck : public ClangTidyCheck {<br>
+public:<br>
+ StructPackAlignCheck(StringRef Name, ClangTidyContext *Context)<br>
+ : ClangTidyCheck(Name, Context),<br>
+ MaxConfiguredAlignment(Options.get("MaxConfiguredAlignment", 128)) {}<br>
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;<br>
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;<br>
+ void storeOptions(ClangTidyOptions::OptionMap &Opts);<br>
+<br>
+private:<br>
+ const unsigned MaxConfiguredAlignment;<br>
+ CharUnits computeRecommendedAlignment(CharUnits MinByteSize);<br>
+};<br>
+<br>
+} // namespace altera<br>
+} // namespace tidy<br>
+} // namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_STRUCTPACKALIGNCHECK_H<br>
<br>
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst<br>
index 781fef27c476..53c3894914e5 100644<br>
--- a/clang-tools-extra/docs/ReleaseNotes.rst<br>
+++ b/clang-tools-extra/docs/ReleaseNotes.rst<br>
@@ -67,6 +67,27 @@ The improvements are...<br>
Improvements to clang-tidy<br>
--------------------------<br>
<br>
+New modules<br>
+^^^^^^^^^^^<br>
+<br>
+- New :doc:`altera <clang-tidy/modules/altera>` module.<br>
+<br>
+ Includes checks related to OpenCL for FPGA coding guidelines, based on the<br>
+ `Altera SDK for OpenCL: Best Practices Guide<br>
+ <<a href="https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_optimization_guide.pdf" rel="noreferrer" target="_blank">https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_optimization_guide.pdf</a>>`_.<br>
+<br>
+New checks<br>
+^^^^^^^^^^<br>
+<br>
+- New :doc:`altera-struct-pack-align<br>
+ <clang-tidy/checks/altera-struct-pack-align>` check.<br>
+<br>
+ Finds structs that are inefficiently packed or aligned, and recommends<br>
+ packing and/or aligning of said structs as needed.<br>
+<br>
+- New :doc:`bugprone-misplaced-pointer-arithmetic-in-alloc<br>
+ <clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc>` check.<br>
+<br>
- New :doc:`bugprone-redundant-branch-condition<br>
<clang-tidy/checks/bugprone-redundant-branch-condition>` check.<br>
<br>
<br>
diff --git a/clang-tools-extra/docs/clang-tidy/checks/altera-struct-pack-align.rst b/clang-tools-extra/docs/clang-tidy/checks/altera-struct-pack-align.rst<br>
new file mode 100644<br>
index 000000000000..b03a4fcf7fcf<br>
--- /dev/null<br>
+++ b/clang-tools-extra/docs/clang-tidy/checks/altera-struct-pack-align.rst<br>
@@ -0,0 +1,54 @@<br>
+.. title:: clang-tidy - altera-struct-pack-align<br>
+<br>
+altera-struct-pack-align<br>
+========================<br>
+<br>
+Finds structs that are inefficiently packed or aligned, and recommends<br>
+packing and/or aligning of said structs as needed.<br>
+<br>
+Structs that are not packed take up more space than they should, and accessing<br>
+structs that are not well aligned is inefficient.<br>
+<br>
+Fix-its are provided to fix both of these issues by inserting and/or amending<br>
+relevant struct attributes.<br>
+<br>
+Based on the `Altera SDK for OpenCL: Best Practices Guide<br>
+<<a href="https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_optimization_guide.pdf" rel="noreferrer" target="_blank">https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_optimization_guide.pdf</a>>`_.<br>
+<br>
+.. code-block:: c++<br>
+<br>
+ // The following struct is originally aligned to 4 bytes, and thus takes up<br>
+ // 12 bytes of memory instead of 10. Packing the struct will make it use<br>
+ // only 10 bytes of memory, and aligning it to 16 bytes will make it<br>
+ // efficient to access.<br>
+ struct example {<br>
+ char a; // 1 byte<br>
+ double b; // 8 bytes<br>
+ char c; // 1 byte<br>
+ };<br>
+<br>
+ // The following struct is arranged in such a way that packing is not needed.<br>
+ // However, it is aligned to 4 bytes instead of 8, and thus needs to be<br>
+ // explicitly aligned.<br>
+ struct implicitly_packed_example {<br>
+ char a; // 1 byte<br>
+ char b; // 1 byte<br>
+ char c; // 1 byte<br>
+ char d; // 1 byte<br>
+ int e; // 4 bytes<br>
+ };<br>
+<br>
+ // The following struct is explicitly aligned and packed.<br>
+ struct good_example {<br>
+ char a; // 1 byte<br>
+ double b; // 8 bytes<br>
+ char c; // 1 byte<br>
+ } __attribute__((packed)) __attribute__((aligned(16));<br>
+<br>
+ // Explicitly aligning a struct to the wrong value will result in a warning.<br>
+ // The following example should be aligned to 16 bytes, not 32.<br>
+ struct badly_aligned_example {<br>
+ char a; // 1 byte<br>
+ double b; // 8 bytes<br>
+ char c; // 1 byte<br>
+ } __attribute__((packed)) __attribute__((aligned(32)));<br>
<br>
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst<br>
index 91414ee8c90f..c569ce704d97 100644<br>
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst<br>
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst<br>
@@ -30,6 +30,7 @@ Clang-Tidy Checks<br>
`abseil-time-comparison <abseil-time-comparison.html>`_, "Yes"<br>
`abseil-time-subtraction <abseil-time-subtraction.html>`_, "Yes"<br>
`abseil-upgrade-duration-conversions <abseil-upgrade-duration-conversions.html>`_, "Yes"<br>
+ `altera-struct-pack-align <altera-struct-pack-align.html>`_,<br>
`android-cloexec-accept <android-cloexec-accept.html>`_, "Yes"<br>
`android-cloexec-accept4 <android-cloexec-accept4.html>`_,<br>
`android-cloexec-creat <android-cloexec-creat.html>`_, "Yes"<br>
<br>
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst<br>
index b9a4a7d694b4..a85c72154178 100644<br>
--- a/clang-tools-extra/docs/clang-tidy/index.rst<br>
+++ b/clang-tools-extra/docs/clang-tidy/index.rst<br>
@@ -58,6 +58,7 @@ There are currently the following groups of checks:<br>
Name prefix Description<br>
====================== =========================================================<br>
``abseil-`` Checks related to Abseil library.<br>
+``altera-`` Checks related to OpenCL programming for FPGAs.<br>
``android-`` Checks related to Android.<br>
``boost-`` Checks related to Boost library.<br>
``bugprone-`` Checks that target bugprone code constructs.<br>
<br>
diff --git a/clang-tools-extra/test/clang-tidy/checkers/altera-struct-pack-align.cpp b/clang-tools-extra/test/clang-tidy/checkers/altera-struct-pack-align.cpp<br>
new file mode 100644<br>
index 000000000000..615b6cafe87a<br>
--- /dev/null<br>
+++ b/clang-tools-extra/test/clang-tidy/checkers/altera-struct-pack-align.cpp<br>
@@ -0,0 +1,101 @@<br>
+// RUN: %check_clang_tidy %s altera-struct-pack-align %t -- -header-filter=.*<br>
+<br>
+// Struct needs both alignment and packing<br>
+struct error {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+};<br>
+// CHECK-MESSAGES: :[[@LINE-5]]:8: warning: accessing fields in struct 'error' is inefficient due to padding; only needs 10 bytes but is using 24 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-6]]:8: note: use "__attribute__((packed))" to reduce the amount of padding applied to struct 'error'<br>
+// CHECK-MESSAGES: :[[@LINE-7]]:8: warning: accessing fields in struct 'error' is inefficient due to poor alignment; currently aligned to 8 bytes, but recommended alignment is 16 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-8]]:8: note: use "__attribute__((aligned(16)))" to align struct 'error' to 16 bytes<br>
+// CHECK-FIXES: __attribute__((packed))<br>
+// CHECK-FIXES: __attribute__((aligned(16)));<br>
+<br>
+// Struct is explicitly packed, but needs alignment<br>
+struct error_packed {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+} __attribute__((packed));<br>
+// CHECK-MESSAGES: :[[@LINE-5]]:8: warning: accessing fields in struct 'error_packed' is inefficient due to poor alignment; currently aligned to 1 bytes, but recommended alignment is 16 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-6]]:8: note: use "__attribute__((aligned(16)))" to align struct 'error_packed' to 16 bytes<br>
+// CHECK-FIXES: __attribute__((aligned(16)))<br>
+<br>
+// Struct is properly packed, but needs alignment<br>
+struct align_only {<br>
+ char a;<br>
+ char b;<br>
+ char c;<br>
+ char d;<br>
+ int e;<br>
+ double f;<br>
+};<br>
+// CHECK-MESSAGES: :[[@LINE-8]]:8: warning: accessing fields in struct 'align_only' is inefficient due to poor alignment; currently aligned to 8 bytes, but recommended alignment is 16 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-9]]:8: note: use "__attribute__((aligned(16)))" to align struct 'align_only' to 16 bytes<br>
+// CHECK-FIXES: __attribute__((aligned(16)));<br>
+<br>
+// Struct is perfectly packed but wrongly aligned<br>
+struct bad_align {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+} __attribute__((packed)) __attribute__((aligned(8)));<br>
+// CHECK-MESSAGES: :[[@LINE-5]]:8: warning: accessing fields in struct 'bad_align' is inefficient due to poor alignment; currently aligned to 8 bytes, but recommended alignment is 16 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-6]]:8: note: use "__attribute__((aligned(16)))" to align struct 'bad_align' to 16 bytes<br>
+// CHECK-FIXES: __attribute__((aligned(16)));<br>
+<br>
+struct bad_align2 {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+} __attribute__((packed)) __attribute__((aligned(32)));<br>
+// CHECK-MESSAGES: :[[@LINE-5]]:8: warning: accessing fields in struct 'bad_align2' is inefficient due to poor alignment; currently aligned to 32 bytes, but recommended alignment is 16 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-6]]:8: note: use "__attribute__((aligned(16)))" to align struct 'bad_align2' to 16 bytes<br>
+// CHECK-FIXES: __attribute__((aligned(16)));<br>
+<br>
+struct bad_align3 {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+} __attribute__((packed)) __attribute__((aligned(4)));<br>
+// CHECK-MESSAGES: :[[@LINE-5]]:8: warning: accessing fields in struct 'bad_align3' is inefficient due to poor alignment; currently aligned to 4 bytes, but recommended alignment is 16 bytes [altera-struct-pack-align]<br>
+// CHECK-MESSAGES: :[[@LINE-6]]:8: note: use "__attribute__((aligned(16)))" to align struct 'bad_align3' to 16 bytes<br>
+// CHECK-FIXES: __attribute__((aligned(16)));<br>
+<br>
+// Struct is both perfectly packed and aligned<br>
+struct success {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+} __attribute__((packed)) __attribute__((aligned(16)));<br>
+//Should take 10 bytes and be aligned to 16 bytes<br>
+<br>
+// Struct is properly packed, and explicitly aligned<br>
+struct success2 {<br>
+ int a;<br>
+ int b;<br>
+ int c;<br>
+} __attribute__((aligned(16)));<br>
+<br>
+// If struct is properly aligned, packing not needed<br>
+struct success3 {<br>
+ char a;<br>
+ double b;<br>
+ char c;<br>
+} __attribute__((aligned(16)));<br>
+<br>
+// If struct is templated, warnings should not be triggered<br>
+template <typename A, typename B><br>
+struct success4 {<br>
+ A a;<br>
+ B b;<br>
+ int c;<br>
+};<br>
+<br>
+// Warnings should not trigger on struct instantiations<br>
+void no_trigger_on_instantiation() {<br>
+ struct bad_align3 instantiated { 'a', 0.001, 'b' };<br>
+}<br>
+<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>