From 2045a44bd4aef7968ddc589004ee3d3ccd6d2bc7 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Wed, 26 Mar 2025 11:43:00 +0000
Subject: [PATCH 01/11] Restore deleted deviations suppression query

---
 .../deviations/DeviationsSuppression.qhelp    |  12 ++
 .../cpp/deviations/DeviationsSuppression.ql   | 120 ++++++++++++++++++
 .../DeviationsSuppression.expected            |   7 +
 .../DeviationsSuppression.qlref               |   1 +
 4 files changed, 140 insertions(+)
 create mode 100644 cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp
 create mode 100644 cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
 create mode 100644 cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
 create mode 100644 cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref

diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp
new file mode 100644
index 0000000000..0bf3a3a71b
--- /dev/null
+++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp
@@ -0,0 +1,12 @@
+<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
+<qhelp>
+    <overview>
+        <p>This query generates suppression information for rules that have an associated deviation record.</p>
+    </overview>
+    <references>
+        <li>
+            MISRA Compliance 2020 document:
+            <a href="https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf">Chapter 4.2 (page 12) - Deviations.</a>
+        </li>
+    </references>
+</qhelp>
\ No newline at end of file
diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
new file mode 100644
index 0000000000..9035b7d288
--- /dev/null
+++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
@@ -0,0 +1,120 @@
+/**
+ * @name Deviation suppression
+ * @description Generates information about files and locations where certain alerts should be considered suppressed by deviations.
+ * @kind alert-suppression
+ * @id cpp/coding-standards/deviation-suppression
+ */
+
+import cpp
+import Deviations
+
+/** Holds if `lineNumber` is an indexed line number in file `f`. */
+private predicate isLineNumber(File f, int lineNumber) {
+  exists(Location l | l.getFile() = f |
+    l.getStartLine() = lineNumber
+    or
+    l.getEndLine() = lineNumber
+  )
+}
+
+/** Gets the last line number in `f`. */
+private int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) }
+
+/** Gets the last column number on the last line of `f`. */
+int getLastColumnNumber(File f) {
+  result =
+    max(Location l |
+      l.getFile() = f and
+      l.getEndLine() = getLastLineNumber(f)
+    |
+      l.getEndColumn()
+    )
+}
+
+newtype TDeviationScope =
+  TDeviationRecordFileScope(DeviationRecord dr, File file) {
+    exists(string deviationPath |
+      dr.isDeviated(_, deviationPath) and
+      file.getRelativePath().prefix(deviationPath.length()) = deviationPath
+    )
+  } or
+  TDeviationRecordCommentScope(DeviationRecord dr, Comment c) { c = dr.getACodeIdentifierComment() }
+
+/** A deviation scope. */
+class DeviationScope extends TDeviationScope {
+  /** Gets the location at which this deviation was defined. */
+  abstract Locatable getDeviationDefinitionLocation();
+
+  /** Gets the Query being deviated. */
+  abstract Query getQuery();
+
+  abstract string toString();
+
+  abstract predicate hasLocationInfo(
+    string filepath, int startline, int startcolumn, int endline, int endcolumn
+  );
+}
+
+/** A deviation scope derived from a "path" entry in a `DeviationRecord`. */
+class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope {
+  private DeviationRecord getDeviationRecord() { this = TDeviationRecordFileScope(result, _) }
+
+  override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() }
+
+  private File getFile() { this = TDeviationRecordFileScope(_, result) }
+
+  override Query getQuery() { result = getDeviationRecord().getQuery() }
+
+  override predicate hasLocationInfo(
+    string filepath, int startline, int startcolumn, int endline, int endcolumn
+  ) {
+    // In an ideal world, we would produce a URL here that informed the AlertSuppression code that
+    // the whole file was suppressed. However, experimentation suggestions the alert suppression
+    // code only works with locations with lines and columns, so we generate a location that covers
+    // the whole "indexed" file, by finding the location indexed in the database with the latest
+    // line and column number.
+    exists(File f | f = getFile() |
+      f.getLocation().hasLocationInfo(filepath, _, _, _, _) and
+      startline = 1 and
+      startcolumn = 1 and
+      endline = getLastLineNumber(f) and
+      endcolumn = getLastColumnNumber(f)
+    )
+  }
+
+  override string toString() {
+    result = "Deviation of " + getDeviationRecord().getQuery() + " for " + getFile() + "."
+  }
+}
+
+/**
+ * A deviation scope derived from a comment corresponding to a "code-identifier" entry for a
+ * `DeviationRecord`.
+ */
+class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommentScope {
+  private DeviationRecord getDeviationRecord() { this = TDeviationRecordCommentScope(result, _) }
+
+  private Comment getComment() { this = TDeviationRecordCommentScope(_, result) }
+
+  override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() }
+
+  override Query getQuery() { result = getDeviationRecord().getQuery() }
+
+  override predicate hasLocationInfo(
+    string filepath, int startline, int startcolumn, int endline, int endcolumn
+  ) {
+    getComment().getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
+    startcolumn = 1
+  }
+
+  override string toString() {
+    result =
+      "Deviation of " + getDeviationRecord().getQuery() + " for comment " + getComment() + "."
+  }
+}
+
+from DeviationScope deviationScope
+select deviationScope.getDeviationDefinitionLocation(), // suppression comment
+  "// lgtm[" + deviationScope.getQuery().getQueryId() + "]", // text of suppression comment (excluding delimiters)
+  "lgtm[" + deviationScope.getQuery().getQueryId() + "]", // text of suppression annotation
+  deviationScope // scope of suppression
diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
new file mode 100644
index 0000000000..50ceb35b9d
--- /dev/null
+++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
@@ -0,0 +1,7 @@
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used for comment // a-0-4-2-deviation COMPLIANT[DEVIATED]. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. |
diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref
new file mode 100644
index 0000000000..6268ee7342
--- /dev/null
+++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref
@@ -0,0 +1 @@
+codingstandards/cpp/deviations/DeviationsSuppression.ql
\ No newline at end of file

From 1e4011f73443b8b080385dcea3a3abce7f2b7858 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Wed, 26 Mar 2025 11:46:30 +0000
Subject: [PATCH 02/11] Add change note.

---
 change_notes/2025-03-26-deviations-suppression.md | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 change_notes/2025-03-26-deviations-suppression.md

diff --git a/change_notes/2025-03-26-deviations-suppression.md b/change_notes/2025-03-26-deviations-suppression.md
new file mode 100644
index 0000000000..5dcb5e8dba
--- /dev/null
+++ b/change_notes/2025-03-26-deviations-suppression.md
@@ -0,0 +1 @@
+ - The `DeviationsSuppression.ql` query has been restored after being incorrectly deleted in a previous release.
\ No newline at end of file

From c25018fce4f419e5e770b8804fbd483b9705ccd3 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 31 Mar 2025 20:42:42 +0100
Subject: [PATCH 03/11] Re-add DeviationsSuppression.ql

This is required for our reporting scripts.

Changes implemented to support reporting of locations and
messages for new deviation formats.
---
 .../deviations/CodeIdentifierDeviation.qll    | 49 +++++++++++++++++--
 .../cpp/deviations/DeviationsSuppression.ql   | 25 ++++++----
 .../DeviationsSuppression.expected            |  2 +-
 3 files changed, 60 insertions(+), 16 deletions(-)

diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
index 310a2b678b..4b2f03cf98 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
+++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
@@ -226,8 +226,8 @@ class DeviationAttribute extends StdAttribute {
 
   DeviationRecord getADeviationRecord() { result = record }
 
-  pragma[nomagic]
-  Element getASuppressedElement() {
+  /** Gets the element to which this attribute was applied. */
+  Element getPrimarySuppressedElement() {
     result.(Type).getAnAttribute() = this
     or
     result.(Stmt).getAnAttribute() = this
@@ -235,6 +235,11 @@ class DeviationAttribute extends StdAttribute {
     result.(Variable).getAnAttribute() = this
     or
     result.(Function).getAnAttribute() = this
+  }
+
+  pragma[nomagic]
+  Element getASuppressedElement() {
+    result = this.getPrimarySuppressedElement()
     or
     result.(Expr).getEnclosingStmt() = this.getASuppressedElement()
     or
@@ -336,26 +341,60 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
     )
   }
 
+  predicate hasLocationInfo(
+    string filepath, int suppressedLine, int suppressedColumn, int endline, int endcolumn
+  ) {
+    exists(Comment commentMarker |
+      this = TSingleLineDeviation(_, commentMarker, filepath, suppressedLine) and
+      suppressedColumn = 1 and
+      endline = suppressedLine
+    |
+      if commentMarker instanceof DeviationEndOfLineMarker
+      then endcolumn = commentMarker.(DeviationEndOfLineMarker).getLocation().getEndColumn()
+      else
+        // Find the last column for a location on the next line
+        endcolumn =
+          max(Location l |
+            l.hasLocationInfo(filepath, _, _, _, _) and
+            l.getEndLine() = suppressedLine
+          |
+            l.getEndColumn()
+          )
+    )
+    or
+    this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline) and
+    suppressedColumn = 1 and
+    endcolumn = 1
+    or
+    exists(DeviationAttribute attribute |
+      this = TCodeIdentifierDeviation(_, attribute) and
+      attribute
+          .getPrimarySuppressedElement()
+          .getLocation()
+          .hasLocationInfo(filepath, suppressedLine, suppressedColumn, endline, endcolumn)
+    )
+  }
+
   string toString() {
     exists(string filepath |
       exists(int suppressedLine |
         this = TSingleLineDeviation(_, _, filepath, suppressedLine) and
         result =
-          "Deviation record " + getADeviationRecord() + " applied to " + filepath + " Line " +
+          "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " +
             suppressedLine
       )
       or
       exists(int suppressedStartLine, int suppressedEndLine |
         this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and
         result =
-          "Deviation record " + getADeviationRecord() + " applied to " + filepath + " Line" +
+          "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " +
             suppressedStartLine + ":" + suppressedEndLine
       )
     )
     or
     exists(DeviationAttribute attribute |
       this = TCodeIdentifierDeviation(_, attribute) and
-      result = "Deviation record " + getADeviationRecord() + " applied to " + attribute
+      result = "Deviation of " + getADeviationRecord().getQuery() + " applied to " + attribute
     )
   }
 }
diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
index 9035b7d288..f29c068983 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
+++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
@@ -38,7 +38,9 @@ newtype TDeviationScope =
       file.getRelativePath().prefix(deviationPath.length()) = deviationPath
     )
   } or
-  TDeviationRecordCommentScope(DeviationRecord dr, Comment c) { c = dr.getACodeIdentifierComment() }
+  TDeviationRecordCodeIdentiferDeviationScope(DeviationRecord dr, CodeIdentifierDeviation c) {
+    c = dr.getACodeIdentifierDeviation()
+  }
 
 /** A deviation scope. */
 class DeviationScope extends TDeviationScope {
@@ -91,10 +93,16 @@ class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope
  * A deviation scope derived from a comment corresponding to a "code-identifier" entry for a
  * `DeviationRecord`.
  */
-class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommentScope {
-  private DeviationRecord getDeviationRecord() { this = TDeviationRecordCommentScope(result, _) }
+class DeviationRecordCommentScope extends DeviationScope,
+  TDeviationRecordCodeIdentiferDeviationScope
+{
+  private DeviationRecord getDeviationRecord() {
+    this = TDeviationRecordCodeIdentiferDeviationScope(result, _)
+  }
 
-  private Comment getComment() { this = TDeviationRecordCommentScope(_, result) }
+  private CodeIdentifierDeviation getCodeIdentifierDeviation() {
+    this = TDeviationRecordCodeIdentiferDeviationScope(_, result)
+  }
 
   override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() }
 
@@ -103,14 +111,11 @@ class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommen
   override predicate hasLocationInfo(
     string filepath, int startline, int startcolumn, int endline, int endcolumn
   ) {
-    getComment().getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
-    startcolumn = 1
+    getCodeIdentifierDeviation()
+        .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
   }
 
-  override string toString() {
-    result =
-      "Deviation of " + getDeviationRecord().getQuery() + " for comment " + getComment() + "."
-  }
+  override string toString() { result = getCodeIdentifierDeviation().toString() }
 }
 
 from DeviationScope deviationScope
diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
index 50ceb35b9d..1d8a87d359 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
+++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
@@ -1,4 +1,4 @@
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used for comment // a-0-4-2-deviation COMPLIANT[DEVIATED]. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |

From ddd28e6dc4274c3c1ce1ee313ed3692c28ce7744 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 31 Mar 2025 20:47:06 +0100
Subject: [PATCH 04/11] Test new deviation formats for DeviationSuppressions.ql

---
 .../DeviationsSuppression.expected            |  6 ++++-
 .../deviations_report_deviated/main.cpp       | 25 +++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
index 1d8a87d359..73f564c13c 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
+++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
@@ -1,7 +1,11 @@
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:14:1:14:65 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 14 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:18:1:18:40 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 18 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. |
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:39:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. |
diff --git a/cpp/common/test/deviations/deviations_report_deviated/main.cpp b/cpp/common/test/deviations/deviations_report_deviated/main.cpp
index c59dea5609..7891faea18 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/main.cpp
+++ b/cpp/common/test/deviations/deviations_report_deviated/main.cpp
@@ -10,5 +10,30 @@ int main(int argc, char **argv) {
   getX();         // NON_COMPLIANT
   long double d1; // NON_COMPLIANT (A0-4-2)
   long double d2; // a-0-4-2-deviation COMPLIANT[DEVIATED]
+
+  long double d3; // codeql::autosar_deviation(a-0-4-2-deviation)
+                  // COMPLIANT[DEVIATED]
+  long double d4; // NON_COMPLIANT (A0-4-2)
+  // codeql::autosar_deviation_next_line(a-0-4-2-deviation)
+  long double d5; // COMPLIANT[DEVIATED]
+  long double d6; // NON_COMPLIANT (A0-4-2)
+
+  // codeql::autosar_deviation_begin(a-0-4-2-deviation)
+  long double d7; // COMPLIANT[DEVIATED]
+  getX();         // NON_COMPLIANT (A0-1-2)
+  long double d8; // COMPLIANT[DEVIATED]
+  getX();         // NON_COMPLIANT (A0-1-2)
+  long double d9; // COMPLIANT[DEVIATED]
+  // codeql::autosar_deviation_end(a-0-4-2-deviation)
+  long double d10; // NON_COMPLIANT (A0-4-2)
+  // codeql::autosar_deviation_begin(a-0-4-2-deviation)
+  long double d11; // COMPLIANT[DEVIATED]
+  getX();          // NON_COMPLIANT (A0-1-2)
+  long double d12; // COMPLIANT[DEVIATED]
+  getX();          // NON_COMPLIANT (A0-1-2)
+  long double d13; // COMPLIANT[DEVIATED]
+  // codeql::autosar_deviation_end(a-0-4-2-deviation)
+  long double d14; // NON_COMPLIANT (A0-4-2)
+  getX();          // NON_COMPLIANT (A0-1-2)
   return 0;
 }
\ No newline at end of file

From d8ac07f96918e85310d5baa0dcbe34f25b57e163 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 21 Apr 2025 23:07:01 +0100
Subject: [PATCH 05/11] Add missing results

---
 .../deviations_report_deviated/UnusedReturnValue.expected    | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected
index 7b8860d5a3..ab75d81f6f 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected
+++ b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected
@@ -1,3 +1,8 @@
 | main.cpp:10:3:10:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX |
+| main.cpp:23:3:23:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX |
+| main.cpp:25:3:25:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX |
+| main.cpp:31:3:31:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX |
+| main.cpp:33:3:33:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX |
+| main.cpp:37:3:37:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX |
 | nested/nested2/test2.h:5:3:5:6 | call to getZ | Return value from call to $@ is unused. | nested/nested2/test2.h:1:5:1:8 | getZ | getZ |
 | nested/test.h:5:3:5:6 | call to getY | Return value from call to $@ is unused. | nested/test.h:1:5:1:8 | getY | getY |

From 52e64673fee3cf653027a2924b5d3095bf81b457 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 21 Apr 2025 23:17:15 +0100
Subject: [PATCH 06/11] Add comment

---
 .../cpp/deviations/CodeIdentifierDeviation.qll               | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
index 4b2f03cf98..b7a144f429 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
+++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
@@ -341,6 +341,11 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
     )
   }
 
+  /**
+   * Holds for the region matched by this code identifier deviation.
+   *
+   * Note: this is not the location of the marker itself.
+   */
   predicate hasLocationInfo(
     string filepath, int suppressedLine, int suppressedColumn, int endline, int endcolumn
   ) {

From 184e5d3ed5bde1cd8ae5895cff70254a0ae36104 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 21 Apr 2025 23:22:27 +0100
Subject: [PATCH 07/11] Extract common library for location handling

---
 .../src/codingstandards/cpp/Locations.qll     | 24 ++++++++++++++
 .../cpp/deviations/DeviationsSuppression.ql   | 31 +++----------------
 2 files changed, 28 insertions(+), 27 deletions(-)
 create mode 100644 cpp/common/src/codingstandards/cpp/Locations.qll

diff --git a/cpp/common/src/codingstandards/cpp/Locations.qll b/cpp/common/src/codingstandards/cpp/Locations.qll
new file mode 100644
index 0000000000..83dd0448af
--- /dev/null
+++ b/cpp/common/src/codingstandards/cpp/Locations.qll
@@ -0,0 +1,24 @@
+import cpp
+
+/** Holds if `lineNumber` is an indexed line number in file `f`. */
+predicate isLineNumber(File f, int lineNumber) {
+  exists(Location l | l.getFile() = f |
+    l.getStartLine() = lineNumber
+    or
+    l.getEndLine() = lineNumber
+  )
+}
+
+/** Gets the last line number in `f`. */
+int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) }
+
+/** Gets the last column number on the last line of `f`. */
+int getLastColumnNumber(File f) {
+  result =
+    max(Location l |
+      l.getFile() = f and
+      l.getEndLine() = getLastLineNumber(f)
+    |
+      l.getEndColumn()
+    )
+}
diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
index f29c068983..94f45c74b3 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
+++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql
@@ -7,29 +7,7 @@
 
 import cpp
 import Deviations
-
-/** Holds if `lineNumber` is an indexed line number in file `f`. */
-private predicate isLineNumber(File f, int lineNumber) {
-  exists(Location l | l.getFile() = f |
-    l.getStartLine() = lineNumber
-    or
-    l.getEndLine() = lineNumber
-  )
-}
-
-/** Gets the last line number in `f`. */
-private int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) }
-
-/** Gets the last column number on the last line of `f`. */
-int getLastColumnNumber(File f) {
-  result =
-    max(Location l |
-      l.getFile() = f and
-      l.getEndLine() = getLastLineNumber(f)
-    |
-      l.getEndColumn()
-    )
-}
+import codingstandards.cpp.Locations
 
 newtype TDeviationScope =
   TDeviationRecordFileScope(DeviationRecord dr, File file) {
@@ -71,10 +49,9 @@ class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope
     string filepath, int startline, int startcolumn, int endline, int endcolumn
   ) {
     // In an ideal world, we would produce a URL here that informed the AlertSuppression code that
-    // the whole file was suppressed. However, experimentation suggestions the alert suppression
-    // code only works with locations with lines and columns, so we generate a location that covers
-    // the whole "indexed" file, by finding the location indexed in the database with the latest
-    // line and column number.
+    // the whole file was suppressed. However, the alert suppression code only works with locations
+    // with lines and columns, so we generate a location that covers the whole "indexed" file, by
+    // finding the location indexed in the database with the latest line and column number.
     exists(File f | f = getFile() |
       f.getLocation().hasLocationInfo(filepath, _, _, _, _) and
       startline = 1 and

From 126ed553e5026853250e3c62e59768eb3abd540b Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 21 Apr 2025 23:30:54 +0100
Subject: [PATCH 08/11] Add getLastColumnNumber to shared library

---
 cpp/common/src/codingstandards/cpp/Locations.qll         | 6 ++++++
 .../cpp/deviations/CodeIdentifierDeviation.qll           | 9 ++-------
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/cpp/common/src/codingstandards/cpp/Locations.qll b/cpp/common/src/codingstandards/cpp/Locations.qll
index 83dd0448af..800f44d18a 100644
--- a/cpp/common/src/codingstandards/cpp/Locations.qll
+++ b/cpp/common/src/codingstandards/cpp/Locations.qll
@@ -22,3 +22,9 @@ int getLastColumnNumber(File f) {
       l.getEndColumn()
     )
 }
+
+/** Gets the last column number on the given line of `filepath`. */
+bindingset[filepath, lineNumber]
+int getLastColumnNumber(string filepath, int lineNumber) {
+  result = max(Location l | l.hasLocationInfo(filepath, _, _, lineNumber, _) | l.getEndColumn())
+}
diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
index b7a144f429..137a2a72d7 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
+++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
@@ -32,6 +32,7 @@
 
 import cpp
 import Deviations
+import codingstandards.cpp.Locations
 
 string supportedStandard() { result = ["misra", "autosar", "cert"] }
 
@@ -358,13 +359,7 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
       then endcolumn = commentMarker.(DeviationEndOfLineMarker).getLocation().getEndColumn()
       else
         // Find the last column for a location on the next line
-        endcolumn =
-          max(Location l |
-            l.hasLocationInfo(filepath, _, _, _, _) and
-            l.getEndLine() = suppressedLine
-          |
-            l.getEndColumn()
-          )
+        endcolumn = getLastColumnNumber(filepath, suppressedLine)
     )
     or
     this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline) and

From 5ad61ee4e441007828e966df4c61d3ad658a62e8 Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 21 Apr 2025 23:42:01 +0100
Subject: [PATCH 09/11] Deviations: Include the final line in ranges

The deviated locations now include the line with the _end marker,
for any element before the marker.
---
 .../deviations/CodeIdentifierDeviation.qll    | 38 ++++++++++++-------
 .../DeviationsSuppression.expected            |  4 +-
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
index 137a2a72d7..e177b84046 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
+++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
@@ -295,11 +295,11 @@ newtype TCodeIndentifierDeviation =
   } or
   TMultiLineDeviation(
     DeviationRecord record, DeviationBegin beginComment, DeviationEnd endComment, string filepath,
-    int suppressedStartLine, int suppressedEndLine
+    int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn
   ) {
     isDeviationRangePaired(record, beginComment, endComment) and
     beginComment.getLocation().hasLocationInfo(filepath, suppressedStartLine, _, _, _) and
-    endComment.getLocation().hasLocationInfo(filepath, suppressedEndLine, _, _, _)
+    endComment.getLocation().hasLocationInfo(filepath, _, _, suppressedEndLine, suppressedEndColumn)
   } or
   TCodeIdentifierDeviation(DeviationRecord record, DeviationAttribute attribute) {
     attribute.getADeviationRecord() = record
@@ -310,7 +310,7 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
   DeviationRecord getADeviationRecord() {
     this = TSingleLineDeviation(result, _, _, _)
     or
-    this = TMultiLineDeviation(result, _, _, _, _, _)
+    this = TMultiLineDeviation(result, _, _, _, _, _, _)
     or
     this = TCodeIdentifierDeviation(result, _)
   }
@@ -321,18 +321,27 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
   bindingset[e]
   pragma[inline_late]
   predicate isElementMatching(Element e) {
-    exists(string filepath, int elementLocationStart |
-      e.getLocation().hasLocationInfo(filepath, elementLocationStart, _, _, _)
+    exists(string filepath, int elementLocationStart, int elementLocationColumnStart |
+      e.getLocation()
+          .hasLocationInfo(filepath, elementLocationStart, elementLocationColumnStart, _, _)
     |
       exists(int suppressedLine |
         this = TSingleLineDeviation(_, _, filepath, suppressedLine) and
         suppressedLine = elementLocationStart
       )
       or
-      exists(int suppressedStartLine, int suppressedEndLine |
-        this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and
-        suppressedStartLine < elementLocationStart and
+      exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn |
+        this =
+          TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine,
+            suppressedEndColumn) and
+        suppressedStartLine < elementLocationStart
+      |
+        // Element starts before the end line of the suppression
         suppressedEndLine > elementLocationStart
+        or
+        // Element exists on the same line as the suppression, and occurs before it
+        suppressedEndLine = elementLocationStart and
+        elementLocationColumnStart < suppressedEndColumn
       )
     )
     or
@@ -362,9 +371,8 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
         endcolumn = getLastColumnNumber(filepath, suppressedLine)
     )
     or
-    this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline) and
-    suppressedColumn = 1 and
-    endcolumn = 1
+    this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline, endcolumn) and
+    suppressedColumn = 1
     or
     exists(DeviationAttribute attribute |
       this = TCodeIdentifierDeviation(_, attribute) and
@@ -384,11 +392,13 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
             suppressedLine
       )
       or
-      exists(int suppressedStartLine, int suppressedEndLine |
-        this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and
+      exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn |
+        this =
+          TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine,
+            suppressedEndColumn) and
         result =
           "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " +
-            suppressedStartLine + ":" + suppressedEndLine
+            suppressedStartLine + ":" + suppressedEndLine + " (Column " + suppressedEndColumn + ")"
       )
     )
     or
diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
index 73f564c13c..2192b36279 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
+++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
@@ -1,8 +1,8 @@
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:14:1:14:65 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 14 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:18:1:18:40 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 18 |
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 |
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 (Column 53) |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 (Column 53) |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:39:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |

From 6a5f0950ec571b46088b0f96e57fa0dbff346cac Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Mon, 21 Apr 2025 23:56:29 +0100
Subject: [PATCH 10/11] Deviations: Store start columns for comment ranges

---
 .../deviations/CodeIdentifierDeviation.qll    | 58 ++++++++++++-------
 .../DeviationsSuppression.expected            |  7 ++-
 .../deviations_report_deviated/main.cpp       |  5 ++
 3 files changed, 47 insertions(+), 23 deletions(-)

diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
index e177b84046..00e02d5712 100644
--- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
+++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll
@@ -295,10 +295,13 @@ newtype TCodeIndentifierDeviation =
   } or
   TMultiLineDeviation(
     DeviationRecord record, DeviationBegin beginComment, DeviationEnd endComment, string filepath,
-    int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn
+    int suppressedStartLine, int suppressedStartColumn, int suppressedEndLine,
+    int suppressedEndColumn
   ) {
     isDeviationRangePaired(record, beginComment, endComment) and
-    beginComment.getLocation().hasLocationInfo(filepath, suppressedStartLine, _, _, _) and
+    beginComment
+        .getLocation()
+        .hasLocationInfo(filepath, suppressedStartLine, suppressedStartColumn, _, _) and
     endComment.getLocation().hasLocationInfo(filepath, _, _, suppressedEndLine, suppressedEndColumn)
   } or
   TCodeIdentifierDeviation(DeviationRecord record, DeviationAttribute attribute) {
@@ -310,7 +313,7 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
   DeviationRecord getADeviationRecord() {
     this = TSingleLineDeviation(result, _, _, _)
     or
-    this = TMultiLineDeviation(result, _, _, _, _, _, _)
+    this = TMultiLineDeviation(result, _, _, _, _, _, _, _)
     or
     this = TCodeIdentifierDeviation(result, _)
   }
@@ -330,18 +333,29 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
         suppressedLine = elementLocationStart
       )
       or
-      exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn |
-        this =
-          TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine,
-            suppressedEndColumn) and
-        suppressedStartLine < elementLocationStart
+      exists(
+        int suppressedStartLine, int suppressedStartColumn, int suppressedEndLine,
+        int suppressedEndColumn
       |
-        // Element starts before the end line of the suppression
-        suppressedEndLine > elementLocationStart
-        or
-        // Element exists on the same line as the suppression, and occurs before it
-        suppressedEndLine = elementLocationStart and
-        elementLocationColumnStart < suppressedEndColumn
+        this =
+          TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedStartColumn,
+            suppressedEndLine, suppressedEndColumn) and
+        (
+          // Element starts on a line after the begin marker of the suppression
+          suppressedStartLine < elementLocationStart
+          or
+          // Element exists on the same line as the begin marker, and occurs after it
+          suppressedStartLine = elementLocationStart and
+          suppressedStartColumn < elementLocationColumnStart
+        ) and
+        (
+          // Element starts on a line before the end marker of the suppression
+          suppressedEndLine > elementLocationStart
+          or
+          // Element exists on the same line as the end marker of the suppression, and occurs before it
+          suppressedEndLine = elementLocationStart and
+          elementLocationColumnStart < suppressedEndColumn
+        )
       )
     )
     or
@@ -371,8 +385,8 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
         endcolumn = getLastColumnNumber(filepath, suppressedLine)
     )
     or
-    this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline, endcolumn) and
-    suppressedColumn = 1
+    this =
+      TMultiLineDeviation(_, _, _, filepath, suppressedLine, suppressedColumn, endline, endcolumn)
     or
     exists(DeviationAttribute attribute |
       this = TCodeIdentifierDeviation(_, attribute) and
@@ -392,13 +406,17 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation {
             suppressedLine
       )
       or
-      exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn |
+      exists(
+        int suppressedStartLine, int suppressedStartColumn, int suppressedEndLine,
+        int suppressedEndColumn
+      |
         this =
-          TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine,
-            suppressedEndColumn) and
+          TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedStartColumn,
+            suppressedEndLine, suppressedEndColumn) and
         result =
           "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " +
-            suppressedStartLine + ":" + suppressedEndLine + " (Column " + suppressedEndColumn + ")"
+            suppressedStartLine + ":" + suppressedStartColumn + ":" + suppressedEndLine + ":" +
+            suppressedEndColumn
       )
     )
     or
diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
index 2192b36279..35fca84928 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
+++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected
@@ -1,11 +1,12 @@
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:14:1:14:65 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 14 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:18:1:18:40 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 18 |
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 (Column 53) |
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 (Column 53) |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:3:27:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:3:27:53 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:3:35:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:3:35:53 |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:40:39:41:99 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 40:39:41:99 |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. |
-| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:39:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |
+| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:44:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. |
 | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. |
diff --git a/cpp/common/test/deviations/deviations_report_deviated/main.cpp b/cpp/common/test/deviations/deviations_report_deviated/main.cpp
index 7891faea18..d2f58d9db1 100644
--- a/cpp/common/test/deviations/deviations_report_deviated/main.cpp
+++ b/cpp/common/test/deviations/deviations_report_deviated/main.cpp
@@ -35,5 +35,10 @@ int main(int argc, char **argv) {
   // codeql::autosar_deviation_end(a-0-4-2-deviation)
   long double d14; // NON_COMPLIANT (A0-4-2)
   getX();          // NON_COMPLIANT (A0-1-2)
+
+  // clang-format off
+  long double d15; /* NON_COMPLIANT*/ /* codeql::autosar_deviation_begin(a-0-4-2-deviation) */ long double d16; // COMPLIANT[DEVIATED]
+  long double d17; /* COMPLIANT[DEVIATED] */ /* codeql::autosar_deviation_end(a-0-4-2-deviation) */ long double d18; // NON_COMPLIANT
+  // clang-format on
   return 0;
 }
\ No newline at end of file

From 8c2da1cd439f6f5df31f1756842b64832da6feae Mon Sep 17 00:00:00 2001
From: Luke Cartey <lcartey@github.com>
Date: Tue, 22 Apr 2025 00:01:48 +0100
Subject: [PATCH 11/11] Deviations: Expand testing for ranges

Ensure begin/end column code works as expected
---
 .../TypeLongDoubleUsed.expected               |  2 +
 .../deviations/deviations_basic_test/main.cpp |  5 +++
 .../TypeLongDoubleUsed.expected               | 18 +++++++++
 .../TypeLongDoubleUsed.ql                     | 38 +++++++++++++++++++
 4 files changed, 63 insertions(+)
 create mode 100644 cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected
 create mode 100644 cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql

diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected
index f2cfd03dc6..afc613642a 100644
--- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected
+++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected
@@ -10,3 +10,5 @@
 | main.cpp:21:15:21:16 | d6 | Use of long double type. |
 | main.cpp:30:15:30:17 | d10 | Use of long double type. |
 | main.cpp:38:15:38:17 | d14 | Use of long double type. |
+| main.cpp:42:15:42:17 | d15 | Use of long double type. |
+| main.cpp:43:113:43:115 | d18 | Use of long double type. |
diff --git a/cpp/common/test/deviations/deviations_basic_test/main.cpp b/cpp/common/test/deviations/deviations_basic_test/main.cpp
index aa389ed0ad..17126364f4 100644
--- a/cpp/common/test/deviations/deviations_basic_test/main.cpp
+++ b/cpp/common/test/deviations/deviations_basic_test/main.cpp
@@ -37,5 +37,10 @@ int main(int argc, char **argv) {
   // codeql::autosar_deviation_end(a-0-4-2-deviation)
   long double d14; // NON_COMPLIANT (A0-4-2)
   getX();          // NON_COMPLIANT (A0-1-2)
+
+  // clang-format off
+  long double d15; /* NON_COMPLIANT*/ /* codeql::autosar_deviation_begin(a-0-4-2-deviation) */ long double d16; // COMPLIANT[DEVIATED]
+  long double d17; /* COMPLIANT[DEVIATED] */ /* codeql::autosar_deviation_end(a-0-4-2-deviation) */ long double d18; // NON_COMPLIANT
+  // clang-format on
   return 0;
 }
\ No newline at end of file
diff --git a/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected
new file mode 100644
index 0000000000..e9099fa64a
--- /dev/null
+++ b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected
@@ -0,0 +1,18 @@
+| main.cpp:11:15:11:16 | d1 | Use of long double type. |
+| main.cpp:12:15:12:16 | d2 | Use of long double type. |
+| main.cpp:14:15:14:16 | d3 | Use of long double type. |
+| main.cpp:16:15:16:16 | d4 | Use of long double type. |
+| main.cpp:18:15:18:16 | d5 | Use of long double type. |
+| main.cpp:19:15:19:16 | d6 | Use of long double type. |
+| main.cpp:22:15:22:16 | d7 | Use of long double type. |
+| main.cpp:24:15:24:16 | d8 | Use of long double type. |
+| main.cpp:26:15:26:16 | d9 | Use of long double type. |
+| main.cpp:28:15:28:17 | d10 | Use of long double type. |
+| main.cpp:30:15:30:17 | d11 | Use of long double type. |
+| main.cpp:32:15:32:17 | d12 | Use of long double type. |
+| main.cpp:34:15:34:17 | d13 | Use of long double type. |
+| main.cpp:36:15:36:17 | d14 | Use of long double type. |
+| main.cpp:40:15:40:17 | d15 | Use of long double type. |
+| main.cpp:40:108:40:110 | d16 | Use of long double type. |
+| main.cpp:41:15:41:17 | d17 | Use of long double type. |
+| main.cpp:41:113:41:115 | d18 | Use of long double type. |
diff --git a/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql
new file mode 100644
index 0000000000..0ff7b93251
--- /dev/null
+++ b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql
@@ -0,0 +1,38 @@
+/**
+ * @id cpp/autosar/type-long-double-used
+ * @name A0-4-2: Type long double shall not be used
+ * @description The type long double has an implementation-defined width and therefore shall not be
+ *              used.
+ * @kind problem
+ * @precision very-high
+ * @problem.severity warning
+ * @tags external/autosar/id/a0-4-2
+ *       correctness
+ *       readability
+ *       external/autosar/allocated-target/implementation
+ *       external/autosar/enforcement/automated
+ *       external/autosar/obligation/required
+ */
+
+import cpp
+import codingstandards.cpp.CodingStandards
+import codingstandards.cpp.exclusions.cpp.RuleMetadata
+
+predicate isUsingLongDouble(ClassTemplateInstantiation c) {
+  c.getATemplateArgument() instanceof LongDoubleType or
+  isUsingLongDouble(c.getATemplateArgument())
+}
+
+from Variable v
+where
+  not isExcluded(v, BannedTypesPackage::typeLongDoubleUsedQuery()) and
+  (
+    v.getUnderlyingType() instanceof LongDoubleType and
+    not v.isFromTemplateInstantiation(_)
+    or
+    exists(ClassTemplateInstantiation c |
+      c = v.getType() and
+      isUsingLongDouble(c)
+    )
+  )
+select v, "Use of long double type."