[clang] [analyzer] Add std::variant checker (PR #66481)

2023-11-07 Thread Gábor Spaits via cfe-commits

spaits wrote:

gentle ping @steakhal

https://github.com/llvm/llvm-project/pull/66481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

https://github.com/spaits created 
https://github.com/llvm/llvm-project/pull/75076

`PRValueHandler`'s handle function is only called from Tracker's track 
function. In `Tracker::track` the
`ExprNode` parameter passed to `PRValueHandler::handle` is already the 
`ExplodedNode` for the tracked expression. We do not need to calculate that 
again.

From f3d7181073996dd94e6d0b7ac403e9a3d97f4e0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 16:59:16 +0100
Subject: [PATCH] [Analyzer][NFC] Remove redundant function call

PRValueHandler's handle function is only called from
Tracker's track function. In Tracker::track the
ExprNode parameter passed to PRValueHandler::handle
is already the ExplodedNode for the tracked expression.
We do not need to calculate that again.
---
 .../lib/StaticAnalyzer/Core/BugReporterVisitors.cpp  | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a9d130c240aec..4a1607530dbd82 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2565,21 +2565,17 @@ class PRValueHandler final : public ExpressionHandler {
   using ExpressionHandler::ExpressionHandler;
 
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
- const ExplodedNode *ExprNode,
+ const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-if (!E->isPRValue())
-  return {};
-
-const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
-if (!RVNode)
+if (!E->isPRValue() || !RVNode)
   return {};
 
 Tracker::Result CombinedResult;
 Tracker &Parent = getParentTracker();
 
-const auto track = [&CombinedResult, &Parent, ExprNode,
+const auto track = [&CombinedResult, &Parent, RVNode,
 Opts](const Expr *Inner) {
-  CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
+  CombinedResult.combineWith(Parent.track(Inner, RVNode, Opts));
 };
 
 // FIXME: Initializer lists can appear in many different contexts

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

spaits wrote:

It is a great idea to use assertions here. It is exactly the context in which 
they should be used. I will add that. Thank you for the review.

I have also thought about a possible different caller but I think it is very 
unlikely. These `ExpressionHandler`s are basically visitor like classes for 
this tracking mechanism, if I am correct. Their purpose is to track other 
values or append `BugReporterVisitor`s to the `PathSensitiveBugReport`.

https://github.com/llvm/llvm-project/pull/75076
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/75076

From f3d7181073996dd94e6d0b7ac403e9a3d97f4e0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 16:59:16 +0100
Subject: [PATCH 1/2] [Analyzer][NFC] Remove redundant function call

PRValueHandler's handle function is only called from
Tracker's track function. In Tracker::track the
ExprNode parameter passed to PRValueHandler::handle
is already the ExplodedNode for the tracked expression.
We do not need to calculate that again.
---
 .../lib/StaticAnalyzer/Core/BugReporterVisitors.cpp  | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a9d130c240aec..4a1607530dbd82 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2565,21 +2565,17 @@ class PRValueHandler final : public ExpressionHandler {
   using ExpressionHandler::ExpressionHandler;
 
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
- const ExplodedNode *ExprNode,
+ const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-if (!E->isPRValue())
-  return {};
-
-const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
-if (!RVNode)
+if (!E->isPRValue() || !RVNode)
   return {};
 
 Tracker::Result CombinedResult;
 Tracker &Parent = getParentTracker();
 
-const auto track = [&CombinedResult, &Parent, ExprNode,
+const auto track = [&CombinedResult, &Parent, RVNode,
 Opts](const Expr *Inner) {
-  CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
+  CombinedResult.combineWith(Parent.track(Inner, RVNode, Opts));
 };
 
 // FIXME: Initializer lists can appear in many different contexts

From d3b3bbce9ee6fa107c6bfa183dd7885f191300d6 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 19:14:36 +0100
Subject: [PATCH 2/2] Add assertion to check if RVNode node for E

---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a1607530dbd82..745a9f34f6a61d 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2567,6 +2567,8 @@ class PRValueHandler final : public ExpressionHandler {
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
  const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
+assert(RVNode->getStmtForDiagnostics() == E && "RVNode must be the 
ExplodedNode for the tracked expression.");
+
 if (!E->isPRValue() || !RVNode)
   return {};
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/75076

From f3d7181073996dd94e6d0b7ac403e9a3d97f4e0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 16:59:16 +0100
Subject: [PATCH 1/2] [Analyzer][NFC] Remove redundant function call

PRValueHandler's handle function is only called from
Tracker's track function. In Tracker::track the
ExprNode parameter passed to PRValueHandler::handle
is already the ExplodedNode for the tracked expression.
We do not need to calculate that again.
---
 .../lib/StaticAnalyzer/Core/BugReporterVisitors.cpp  | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a9d130c240aec..4a1607530dbd82 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2565,21 +2565,17 @@ class PRValueHandler final : public ExpressionHandler {
   using ExpressionHandler::ExpressionHandler;
 
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
- const ExplodedNode *ExprNode,
+ const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-if (!E->isPRValue())
-  return {};
-
-const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
-if (!RVNode)
+if (!E->isPRValue() || !RVNode)
   return {};
 
 Tracker::Result CombinedResult;
 Tracker &Parent = getParentTracker();
 
-const auto track = [&CombinedResult, &Parent, ExprNode,
+const auto track = [&CombinedResult, &Parent, RVNode,
 Opts](const Expr *Inner) {
-  CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
+  CombinedResult.combineWith(Parent.track(Inner, RVNode, Opts));
 };
 
 // FIXME: Initializer lists can appear in many different contexts

From 0f36d7e1947380c39f062840ad75bf7bfd8b0bbd Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 19:14:36 +0100
Subject: [PATCH 2/2] Add assertion to check if RVNode node for E

---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a1607530dbd82..df2be72531e35f 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2567,6 +2567,9 @@ class PRValueHandler final : public ExpressionHandler {
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
  const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
+assert(RVNode->getStmtForDiagnostics() == E &&
+   "RVNode must be the ExplodedNode for the tracked expression.");
+
 if (!E->isPRValue() || !RVNode)
   return {};
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/75076

From f3d7181073996dd94e6d0b7ac403e9a3d97f4e0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 16:59:16 +0100
Subject: [PATCH 1/3] [Analyzer][NFC] Remove redundant function call

PRValueHandler's handle function is only called from
Tracker's track function. In Tracker::track the
ExprNode parameter passed to PRValueHandler::handle
is already the ExplodedNode for the tracked expression.
We do not need to calculate that again.
---
 .../lib/StaticAnalyzer/Core/BugReporterVisitors.cpp  | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a9d130c240ae..4a1607530dbd8 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2565,21 +2565,17 @@ class PRValueHandler final : public ExpressionHandler {
   using ExpressionHandler::ExpressionHandler;
 
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
- const ExplodedNode *ExprNode,
+ const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-if (!E->isPRValue())
-  return {};
-
-const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
-if (!RVNode)
+if (!E->isPRValue() || !RVNode)
   return {};
 
 Tracker::Result CombinedResult;
 Tracker &Parent = getParentTracker();
 
-const auto track = [&CombinedResult, &Parent, ExprNode,
+const auto track = [&CombinedResult, &Parent, RVNode,
 Opts](const Expr *Inner) {
-  CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
+  CombinedResult.combineWith(Parent.track(Inner, RVNode, Opts));
 };
 
 // FIXME: Initializer lists can appear in many different contexts

From 0f36d7e1947380c39f062840ad75bf7bfd8b0bbd Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 19:14:36 +0100
Subject: [PATCH 2/3] Add assertion to check if RVNode node for E

---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a1607530dbd8..df2be72531e35 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2567,6 +2567,9 @@ class PRValueHandler final : public ExpressionHandler {
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
  const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
+assert(RVNode->getStmtForDiagnostics() == E &&
+   "RVNode must be the ExplodedNode for the tracked expression.");
+
 if (!E->isPRValue() || !RVNode)
   return {};
 

From 10cdc26eeb9925cd11bb85f25509ad1a751c99db Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 19:35:39 +0100
Subject: [PATCH 3/3] Move RVNode nullptr check

---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index df2be72531e35..fb8630884d994 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2567,10 +2567,14 @@ class PRValueHandler final : public ExpressionHandler {
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
  const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
+
+if (!RVNode)
+  return {};
+
 assert(RVNode->getStmtForDiagnostics() == E &&
"RVNode must be the ExplodedNode for the tracked expression.");
 
-if (!E->isPRValue() || !RVNode)
+if (!E->isPRValue())
   return {};
 
 Tracker::Result CombinedResult;

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits


@@ -2565,21 +2565,20 @@ class PRValueHandler final : public ExpressionHandler {
   using ExpressionHandler::ExpressionHandler;
 
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
- const ExplodedNode *ExprNode,
+ const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-if (!E->isPRValue())
-  return {};
+assert(RVNode->getStmtForDiagnostics() == E &&

spaits wrote:

Moved nullptr check before call.

https://github.com/llvm/llvm-project/pull/75076
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

spaits wrote:

My rationale behind this change is that, as I mentioned this class is for a 
very specific purpose. It is a module of sub-system, not a generic "library" 
class that is intended to be used from anywhere, so this class would not really 
make sense to be used anywhere else.

If we take a look at the definition of the `ExpressionHandler` base class in 
`BugReporterVisitor.h`, then we can see that the third argument should be the 
node where the evaluation of the expression happens. We should not look for 
that node in the function. It is not the function's responsibility but the 
caller's responsibility.
```C++
  /// Handle the given expression from the given node.
  ///
  /// \param E The expression value which we are tracking
  /// \param Original A node "downstream" where the tracking started.
  /// \param ExprNode A node where the evaluation of \c E actually happens.
  /// \param Opts Tracking options specifying how we are tracking the value.
  virtual Tracker::Result handle(const Expr *E, const ExplodedNode *Original,
 const ExplodedNode *ExprNode,
 TrackingOptions Opts) = 0;
```
So there is already a written precondition for that parameter. I think the best 
way to express this precondition in C++17 is an assertion. If the user of the 
function call it incorrectly they should be warned as strongly as possible. 
With the least amount of runtime cost. Now we could save the cost for building 
a call stack, a comparison, a conditional jump based on the result of the 
previous comparison and also the deconstruction of the stack.

I also respect and accept your opinions and understand why you prefer that 
extra function call.

I will wait a bit with this PR. If no one else will review it in the next few 
weeks I will just abort it.

Thank you for your time and effort.

https://github.com/llvm/llvm-project/pull/75076
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-11 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/75076

From f3d7181073996dd94e6d0b7ac403e9a3d97f4e0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 16:59:16 +0100
Subject: [PATCH 1/3] [Analyzer][NFC] Remove redundant function call

PRValueHandler's handle function is only called from
Tracker's track function. In Tracker::track the
ExprNode parameter passed to PRValueHandler::handle
is already the ExplodedNode for the tracked expression.
We do not need to calculate that again.
---
 .../lib/StaticAnalyzer/Core/BugReporterVisitors.cpp  | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a9d130c240aec..4a1607530dbd82 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2565,21 +2565,17 @@ class PRValueHandler final : public ExpressionHandler {
   using ExpressionHandler::ExpressionHandler;
 
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
- const ExplodedNode *ExprNode,
+ const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-if (!E->isPRValue())
-  return {};
-
-const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
-if (!RVNode)
+if (!E->isPRValue() || !RVNode)
   return {};
 
 Tracker::Result CombinedResult;
 Tracker &Parent = getParentTracker();
 
-const auto track = [&CombinedResult, &Parent, ExprNode,
+const auto track = [&CombinedResult, &Parent, RVNode,
 Opts](const Expr *Inner) {
-  CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
+  CombinedResult.combineWith(Parent.track(Inner, RVNode, Opts));
 };
 
 // FIXME: Initializer lists can appear in many different contexts

From 0f36d7e1947380c39f062840ad75bf7bfd8b0bbd Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 19:14:36 +0100
Subject: [PATCH 2/3] Add assertion to check if RVNode node for E

---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 4a1607530dbd82..df2be72531e35f 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2567,6 +2567,9 @@ class PRValueHandler final : public ExpressionHandler {
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
  const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
+assert(RVNode->getStmtForDiagnostics() == E &&
+   "RVNode must be the ExplodedNode for the tracked expression.");
+
 if (!E->isPRValue() || !RVNode)
   return {};
 

From 3bce8ce37cff49e482700684462193adb8326df9 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Mon, 11 Dec 2023 19:35:39 +0100
Subject: [PATCH 3/3] Move RVNode nullptr check

---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index df2be72531e35f..4dbbd2024577e1 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2567,12 +2567,13 @@ class PRValueHandler final : public ExpressionHandler {
   Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
  const ExplodedNode *RVNode,
  TrackingOptions Opts) override {
-assert(RVNode->getStmtForDiagnostics() == E &&
-   "RVNode must be the ExplodedNode for the tracked expression.");
 
 if (!E->isPRValue() || !RVNode)
   return {};
 
+assert(RVNode->getStmtForDiagnostics() == E &&
+   "RVNode must be the ExplodedNode for the tracked expression.");
+
 Tracker::Result CombinedResult;
 Tracker &Parent = getParentTracker();
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::variant checker (PR #66481)

2023-11-16 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,104 @@
+//===- TaggedUnionModeling.h -*- 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_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/FoldingSet.h"
+#include 
+
+namespace clang {
+namespace ento {
+namespace tagged_union_modeling {
+
+// The implementation of all these functions can be found in the file
+// StdVariantChecker.cpp under the same directory as this file.
+CallEventRef<> getCaller(const CallEvent &Call, CheckerContext &C);
+bool isCopyConstructorCall(const CallEvent &Call);
+bool isCopyAssignmentCall(const CallEvent &Call);
+bool isMoveAssignmentCall(const CallEvent &Call);
+bool isMoveConstructorCall(const CallEvent &Call);
+bool isStdType(const Type *Type, const std::string &TypeName);
+bool isStdVariant(const Type *Type);
+bool calledFromSystemHeader(const CallEvent &Call, CheckerContext &C);

spaits wrote:

There are functions I did not move into CallEvent because they are called on a 
CallEvent, cast it to a subclass, then tell things about it. It would not be 
nice to have a function like this in the CallEvent super class. But if you 
think I should move them there then I can do that.

https://github.com/llvm/llvm-project/pull/66481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::variant checker (PR #66481)

2023-11-20 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/66481

From 1948d226de16bda2899ca562276370d20ceba236 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 15 Sep 2023 10:21:30 +0200
Subject: [PATCH 1/7] [analyzer] Add std::variant checker

Adding a checker that checks for bad std::variant type access.
---
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../Checkers/StdVariantChecker.cpp| 327 
 .../Checkers/TaggedUnionModeling.h| 104 +
 .../Inputs/system-header-simulator-cxx.h  | 122 ++
 .../diagnostics/explicit-suppression.cpp  |   2 +-
 clang/test/Analysis/std-variant-checker.cpp   | 358 ++
 7 files changed, 917 insertions(+), 1 deletion(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/TaggedUnionModeling.h
 create mode 100644 clang/test/Analysis/std-variant-checker.cpp

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index be813bde8be41ea..a93e97348606f28 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -318,6 +318,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdVariantChecker : Checker<"StdVariant">,
+  HelpText<"Check for bad type access for std::variant.">,
+  Documentation;
+
 } // end "alpha.core"
 
 
//===--===//
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index d849649c96a0d13..4443ffd09293881 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -108,6 +108,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
   StdLibraryFunctionsChecker.cpp
+  StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
   StreamChecker.cpp
   StringChecker.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
new file mode 100644
index 000..680c5567431bbfb
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
@@ -0,0 +1,327 @@
+//===- StdVariantChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/AST/Type.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include 
+#include 
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType)
+
+namespace clang {
+namespace ento {
+namespace tagged_union_modeling {
+
+// Returns the CallEvent representing the caller of the function
+// It is needed because the CallEvent class does not contain enough information
+// to tell who called it. Checker context is needed.
+CallEventRef<> getCaller(const CallEvent &Call, const ProgramStateRef &State) {
+  const auto *CallLocationContext = Call.getLocationContext();
+  if (!CallLocationContext || CallLocationContext->inTopFrame())
+return nullptr;
+
+  const auto *CallStackFrameContext = CallLocationContext->getStackFrame();
+  if (!CallStackFrameContext)
+return nullptr;
+
+  CallEventManager &CEMgr = State->getStateManager().getCallEventManager();
+  return CEMgr.getCaller(CallStackFrameContext, State);
+}
+
+const CXXConstructorDecl *
+getConstructorDeclarationForCall(const CallEvent &Call) {
+  const auto *ConstructorCall = dyn_cast(&Call);
+  if (!ConstructorCall)
+return nullptr;
+
+  return ConstructorCall->getDecl();
+}
+
+bool isCopyConstructorCall(const CallEvent &Call) {
+  if (const CXXConstructorDecl *ConstructorDecl =
+  getConstructorDeclarationForCall(Call))
+return ConstructorDecl->isCopyConstructor();
+  return false;
+}
+
+bool isCopyAssignmentCall(const CallE

[clang] [analyzer] Add std::variant checker (PR #66481)

2023-11-21 Thread Gábor Spaits via cfe-commits

spaits wrote:

@steakhal I talked with @DonatNagyE and @dkrupp . We came to the conclusion, 
that the checker is only an alpha checker, would also not mean breaking changes 
to the analyzer and would not bring false positives. It also has been reviewed 
by @DonatNagyE . I would like to merge it in this form and later iterate on it. 
Would it be okay for you? 

https://github.com/llvm/llvm-project/pull/66481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::variant checker (PR #66481)

2023-11-21 Thread Gábor Spaits via cfe-commits

https://github.com/spaits closed https://github.com/llvm/llvm-project/pull/66481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::variant checker (PR #66481)

2023-11-02 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,327 @@
+//===- StdVariantChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/AST/Type.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include 
+#include 
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType)
+
+namespace clang {
+namespace ento {
+namespace tagged_union_modeling {
+
+// Returns the CallEvent representing the caller of the function
+// It is needed because the CallEvent class does not contain enough information
+// to tell who called it. Checker context is needed.
+CallEventRef<> getCaller(const CallEvent &Call, const ProgramStateRef &State) {

spaits wrote:

I moved this function into the `CallEvent` class.

https://github.com/llvm/llvm-project/pull/66481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits created 
https://github.com/llvm/llvm-project/pull/76501

Add a short documentation for `StdVariantChecker`.

From f7f26c38d1d363bf1dd097dc73e004970dfb32df Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 12 
 1 file changed, 12 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 81d40395067c9a..1e5ba013f85d67 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,18 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if the active value accessed in an ``std::variant`` instance.
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From e885006a873e4bd8eb4618c270bac72c11446f06 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 12 
 1 file changed, 12 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 81d40395067c9a..6e8052a0afacf8 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,18 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if the active value accessed in an ``std::variant`` instance.
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From e885006a873e4bd8eb4618c270bac72c11446f06 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH 1/2] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 12 
 1 file changed, 12 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 81d40395067c9a..6e8052a0afacf8 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,18 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if the active value accessed in an ``std::variant`` instance.
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

From 67e647998a6a5b3e135c4fc760f545e73ad6b04c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 16:20:14 +0100
Subject: [PATCH 2/2] Update clang/docs/analyzer/checkers.rst

Co-authored-by: whisperity 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 6e8052a0afacf8..8e6029406202bf 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2103,7 +2103,7 @@ Check if the active value accessed in an ``std::variant`` 
instance.
 .. code-block:: cpp
 
  void test() {
-   std::variant  v = 25;
+   std::variant v = 25;
char c = stg::get(v); // warn
  }
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From c1884cc4d17c446491777baa43e3996aae22ad0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 81d40395067c9a..272e1965335ed3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

spaits wrote:

Added some more explanation. I will continue using "Check if" since the other 
descriptions that I saw stared like that (or "Check for").

https://github.com/llvm/llvm-project/pull/76501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From c1884cc4d17c446491777baa43e3996aae22ad0d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH 1/2] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 81d40395067c9a..272e1965335ed3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

From 240c34c0f9e11b5059cc57b44fd776584d2e768a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 16:41:07 +0100
Subject: [PATCH 2/2] Update clang/docs/analyzer/checkers.rst

Co-authored-by: DonatNagyE 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 272e1965335ed3..7f5572c8c9c10c 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2100,7 +2100,7 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 alpha.core.StdVariant (C++)
 """
 Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
-In case of bad variant type access(the accessed type differs from the active 
type)
+In case of bad variant type access (the accessed type differs from the active 
type)
 a warning is emitted. Currently this checker does not take exception handling 
into account.
 
 .. code-block:: cpp

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From 682bed6d800133a2d1f21bd49491d002ec8c6b54 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..06c08e14a8f136 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From e0dabac5d84c291da39646efda189f6cdbcc369b Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..06c08e14a8f136 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2097,6 +2097,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
 
 .. _alpha-core-TestAfterDivZero:
 
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
+.. _alpha-core-StdVariant:
+
 alpha.core.TestAfterDivZero (C)
 """
 Check for division by variable that is later compared against 0.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From daec81389ccaa23f6f8c75abac9a2f827d4c0fcd Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/analyzer/checkers.rst | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..94c712f63d5ba3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdVariant:
+
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
 .. _alpha-core-TestAfterDivZero:
 
 alpha.core.TestAfterDivZero (C)

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From b271420a6e4ed23abf2749d767f986aa16d9fe9d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH] [analyzer] Add documentation for std::variant checker

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/docs/analyzer/checkers.rst | 15 +++
 2 files changed, 16 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e21ec78a1e8a77..bf63cc981eb32d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1072,6 +1072,7 @@ New features
 
 - Added a new experimental checker ``alpha.core.StdVariant`` to detect variant
   accesses via wrong alternatives.
+  `Documentation 
`__.
   (`#66481 `_)
 
 - Added a new experimental checker ``alpha.cplusplus.ArrayDelete`` to detect
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..94c712f63d5ba3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdVariant:
+
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
 .. _alpha-core-TestAfterDivZero:
 
 alpha.core.TestAfterDivZero (C)

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From b271420a6e4ed23abf2749d767f986aa16d9fe9d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH 1/2] [analyzer] Add documentation for std::variant checker

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/docs/analyzer/checkers.rst | 15 +++
 2 files changed, 16 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e21ec78a1e8a77..bf63cc981eb32d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1072,6 +1072,7 @@ New features
 
 - Added a new experimental checker ``alpha.core.StdVariant`` to detect variant
   accesses via wrong alternatives.
+  `Documentation 
`__.
   (`#66481 `_)
 
 - Added a new experimental checker ``alpha.cplusplus.ArrayDelete`` to detect
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..94c712f63d5ba3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdVariant:
+
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
 .. _alpha-core-TestAfterDivZero:
 
 alpha.core.TestAfterDivZero (C)

From 450fd58fd64e64b2a0df6cb90b6c232b2d84ece6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:39 +0100
Subject: [PATCH 2/2] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 94c712f63d5ba3..7903ad75bcb831 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2101,7 +2101,7 @@ alpha.core.StdVariant (C++)
 """
 Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
 In case of bad variant type access(the accessed type differs from the active 
type)
-a warning is emitted. Currently this checker does not take exception handling 
into account.
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
 
 .. code-block:: cpp
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From b271420a6e4ed23abf2749d767f986aa16d9fe9d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH 1/3] [analyzer] Add documentation for std::variant checker

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/docs/analyzer/checkers.rst | 15 +++
 2 files changed, 16 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e21ec78a1e8a77..bf63cc981eb32d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1072,6 +1072,7 @@ New features
 
 - Added a new experimental checker ``alpha.core.StdVariant`` to detect variant
   accesses via wrong alternatives.
+  `Documentation 
`__.
   (`#66481 `_)
 
 - Added a new experimental checker ``alpha.cplusplus.ArrayDelete`` to detect
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..94c712f63d5ba3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdVariant:
+
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
 .. _alpha-core-TestAfterDivZero:
 
 alpha.core.TestAfterDivZero (C)

From 450fd58fd64e64b2a0df6cb90b6c232b2d84ece6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:39 +0100
Subject: [PATCH 2/3] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 94c712f63d5ba3..7903ad75bcb831 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2101,7 +2101,7 @@ alpha.core.StdVariant (C++)
 """
 Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
 In case of bad variant type access(the accessed type differs from the active 
type)
-a warning is emitted. Currently this checker does not take exception handling 
into account.
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
 
 .. code-block:: cpp
 

From 6ba5052007ef724e90f6665d6df350ee6d9aa1f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:46 +0100
Subject: [PATCH 3/3] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 7903ad75bcb831..eb01fcf8020802 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2107,7 +2107,7 @@ a warning is emitted. Currently, this checker does not 
take exception handling i
 
  void test() {
std::variant  v = 25;
-   char c = stg::get(v); // warn
+   char c = stg::get(v); // warn: "int" is the active alternative
  }
 
 .. _alpha-core-TestAfterDivZero:

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From b271420a6e4ed23abf2749d767f986aa16d9fe9d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH 1/4] [analyzer] Add documentation for std::variant checker

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/docs/analyzer/checkers.rst | 15 +++
 2 files changed, 16 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e21ec78a1e8a77..bf63cc981eb32d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1072,6 +1072,7 @@ New features
 
 - Added a new experimental checker ``alpha.core.StdVariant`` to detect variant
   accesses via wrong alternatives.
+  `Documentation 
`__.
   (`#66481 `_)
 
 - Added a new experimental checker ``alpha.cplusplus.ArrayDelete`` to detect
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..94c712f63d5ba3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdVariant:
+
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
 .. _alpha-core-TestAfterDivZero:
 
 alpha.core.TestAfterDivZero (C)

From 450fd58fd64e64b2a0df6cb90b6c232b2d84ece6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:39 +0100
Subject: [PATCH 2/4] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 94c712f63d5ba3..7903ad75bcb831 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2101,7 +2101,7 @@ alpha.core.StdVariant (C++)
 """
 Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
 In case of bad variant type access(the accessed type differs from the active 
type)
-a warning is emitted. Currently this checker does not take exception handling 
into account.
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
 
 .. code-block:: cpp
 

From 6ba5052007ef724e90f6665d6df350ee6d9aa1f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:46 +0100
Subject: [PATCH 3/4] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 7903ad75bcb831..eb01fcf8020802 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2107,7 +2107,7 @@ a warning is emitted. Currently, this checker does not 
take exception handling i
 
  void test() {
std::variant  v = 25;
-   char c = stg::get(v); // warn
+   char c = stg::get(v); // warn: "int" is the active alternative
  }
 
 .. _alpha-core-TestAfterDivZero:

From 7615eaab9fda0799543a7b708a68694ea5d774a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 18:22:51 +0100
Subject: [PATCH 4/4] Update checkers.rst

Co-authored-by: whisperity 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index eb01fcf8020802..cce1af65cc608b 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2106,7 +2106,7 @@ a warning is emitted. Currently, this checker does not 
take exception handling i
 .. code-block:: cpp
 
  void test() {
-   std::variant  v = 25;
+   std::variant v = 25;
char c = stg::get(v); // warn: "int" is the active alternative
  }
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76501

From b271420a6e4ed23abf2749d767f986aa16d9fe9d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Thu, 28 Dec 2023 14:17:55 +0100
Subject: [PATCH 1/5] [analyzer] Add documentation for std::variant checker

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/docs/analyzer/checkers.rst | 15 +++
 2 files changed, 16 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e21ec78a1e8a77..bf63cc981eb32d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1072,6 +1072,7 @@ New features
 
 - Added a new experimental checker ``alpha.core.StdVariant`` to detect variant
   accesses via wrong alternatives.
+  `Documentation 
`__.
   (`#66481 `_)
 
 - Added a new experimental checker ``alpha.cplusplus.ArrayDelete`` to detect
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 64a4752695f11f..94c712f63d5ba3 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,21 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdVariant:
+
+alpha.core.StdVariant (C++)
+"""
+Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
+In case of bad variant type access(the accessed type differs from the active 
type)
+a warning is emitted. Currently this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void test() {
+   std::variant  v = 25;
+   char c = stg::get(v); // warn
+ }
+
 .. _alpha-core-TestAfterDivZero:
 
 alpha.core.TestAfterDivZero (C)

From 450fd58fd64e64b2a0df6cb90b6c232b2d84ece6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:39 +0100
Subject: [PATCH 2/5] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 94c712f63d5ba3..7903ad75bcb831 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2101,7 +2101,7 @@ alpha.core.StdVariant (C++)
 """
 Check if a value of active type is retrieved from an ``std::variant`` instance 
with ``std::get``.
 In case of bad variant type access(the accessed type differs from the active 
type)
-a warning is emitted. Currently this checker does not take exception handling 
into account.
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
 
 .. code-block:: cpp
 

From 6ba5052007ef724e90f6665d6df350ee6d9aa1f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 17:11:46 +0100
Subject: [PATCH 3/5] Update clang/docs/analyzer/checkers.rst

Co-authored-by: Balazs Benics 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 7903ad75bcb831..eb01fcf8020802 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2107,7 +2107,7 @@ a warning is emitted. Currently, this checker does not 
take exception handling i
 
  void test() {
std::variant  v = 25;
-   char c = stg::get(v); // warn
+   char c = stg::get(v); // warn: "int" is the active alternative
  }
 
 .. _alpha-core-TestAfterDivZero:

From 7615eaab9fda0799543a7b708a68694ea5d774a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 18:22:51 +0100
Subject: [PATCH 4/5] Update checkers.rst

Co-authored-by: whisperity 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index eb01fcf8020802..cce1af65cc608b 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2106,7 +2106,7 @@ a warning is emitted. Currently, this checker does not 
take exception handling i
 .. code-block:: cpp
 
  void test() {
-   std::variant  v = 25;
+   std::variant v = 25;
char c = stg::get(v); // warn: "int" is the active alternative
  }
 

From be919aa74856eee9b1316bc79e13fbbfc081c671 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?=
 <48805437+spa...@users.noreply.github.com>
Date: Thu, 28 Dec 2023 18:23:12 +0100
Subject: [PATCH 5/5] Update checkers.rst

Co-authored-by: DonatNagyE 
---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insert

[clang] [Analyzer][NFC] Remove redundant function call (PR #75076)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits closed https://github.com/llvm/llvm-project/pull/75076
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

spaits wrote:

I will merge the PR when the CI builds have finished. Thank you for reviewing.

https://github.com/llvm/llvm-project/pull/76501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add documentation for std::variant checker (PR #76501)

2023-12-28 Thread Gábor Spaits via cfe-commits

https://github.com/spaits closed https://github.com/llvm/llvm-project/pull/76501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-29 Thread Gábor Spaits via cfe-commits

https://github.com/spaits created 
https://github.com/llvm/llvm-project/pull/76580

Add a checker to detect bad `std::any` type accesses.
It warns, when the active type is different from the requested type when 
calling `std::any_cast`:
```cpp
void anyCast() {
  std::any a = 5;
  char c = std::any_cast(a); // // warn: "int" is the active alternative
 }
```
It also warns, when the `std::any` instance is empty:
```cpp
 void noTypeHeld() {
  std::any a;
  int i = std::any_cast(a); // warn: any 'a' is empty
 }
```
This checker works in a similar way to `std::variant` checker: Recognizes when 
the active type of an `std::any` instance changes and stores this information. 
Later on, when the data hold in this instance is accessed with `std::any_cast` 
it is checked if the active type is retrieved or not. If not then a warning is 
emitted.

This checker does not produce false positives. It is conservative: if there is 
no information of the `std::any` instance or the already recorded information 
becomes invalid no report will be emitted. 

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"

[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-29 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 1/7] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Progr

[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-29 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};

spaits wrote:

Added longer description and made it const.

https://github.com/llvm/llvm-project/pull/76580
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-29 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  ProgramStateRef
+  checkRegionChanges(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef ExplicitRegions,
+ ArrayRef Regions,
+ const LocationContext *LCtx, const CallEvent *Call) const 
{
+if (!Call)
+  return State;
+
+return removeInformationStoredForDeadInstances(*Call, 
State,
+   Regions);
+  }
+
+  bool evalCall(const CallEvent &Call, CheckerContext &C) const {
+// Do not take implementation details into consideration
+if (Call.isCalledFromSystemHeader())
+  return false;
+
+if (AnyCast.matches(Call))
+  return handleAnyCastCall(Call, C);
+
+if (AnyReset.matches(Call)) {
+  const auto *AsMemberCall = dyn_cast(&Call);
+  if (!AsMemberCall)
+return false;
+
+  const auto *ThisMemRegion = AsMemberCall->getCXXThisVal().getAsRegion();
+  if (!ThisMemRegion)
+return false;
+
+  setNullTypeAny(ThisMemRegion, C);
+  return true;
+}
+
+bool IsAnyConstructor =
+isa(Call) && AnyConstructor.matches(Call);
+bool IsAnyAssignmentOperatorCall =
+isa(Call) && AnyAsOp.matches(Call);
+
+if (IsAnyConstructor || IsAnyAssignmentOperatorCall) {
+  auto State = C.getState();
+  SVal ThisSVal = [&]() {
+if (IsAnyConstructor) {
+  const auto *AsConstructorCall = dyn_cast(&Call);
+  return AsConstructorCall->getCXXThisVal();
+}
+if (IsAnyAssignmentOperatorCall) {
+  const auto *AsMemberOpCall = dyn_cast(&Call);
+  return AsMemberOpCall->getCXXThisVal();
+}
+llvm_unreachable("We must have an assignment operator or constructor");
+  }();
+
+  // default constructor call
+  // in this case the any holds a null type
+  if (Call.getNumArgs() == 0) {
+const auto *ThisMemRegion = ThisSVal.getAsRegion();
+setNullTypeAny(ThisMemRegion, C);
+return true;
+  }
+
+  if (Call.getNumArgs() != 1)
+return false;
+
+  handleConstructorAndAssignment(Call, C, ThisSVal);
+  return true;
+}
+return false;
+  }
+
+private:
+  // When an std::any is rested or default constructed it has a null type.
+  // We represent it by storing a null QualType.
+  void setNullTypeAny(const MemRegion *Mem, CheckerContext &C) const {
+auto State = C.getState();
+State = State->set(Mem, QualType{});
+C.addTransition(State);
+  }

spaits wrote:

Now `setNullTypeAny` return a `ProgramStateRef` in which the type for that 
instance is null. Later the caller of the function can decide what to do with 
that.

The reason for storing null types is the possibility of an empty `std::any` 
instance. This is how the checker represents that. There is no type in the 
instance.

https://github.com/llvm/llvm-project/pull/76580
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-29 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  ProgramStateRef
+  checkRegionChanges(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef ExplicitRegions,
+ ArrayRef Regions,
+ const LocationContext *LCtx, const CallEvent *Call) const 
{
+if (!Call)
+  return State;
+
+return removeInformationStoredForDeadInstances(*Call, 
State,
+   Regions);
+  }
+
+  bool evalCall(const CallEvent &Call, CheckerContext &C) const {
+// Do not take implementation details into consideration
+if (Call.isCalledFromSystemHeader())
+  return false;
+
+if (AnyCast.matches(Call))
+  return handleAnyCastCall(Call, C);
+
+if (AnyReset.matches(Call)) {
+  const auto *AsMemberCall = dyn_cast(&Call);
+  if (!AsMemberCall)
+return false;
+
+  const auto *ThisMemRegion = AsMemberCall->getCXXThisVal().getAsRegion();
+  if (!ThisMemRegion)
+return false;
+
+  setNullTypeAny(ThisMemRegion, C);
+  return true;
+}
+
+bool IsAnyConstructor =
+isa(Call) && AnyConstructor.matches(Call);
+bool IsAnyAssignmentOperatorCall =
+isa(Call) && AnyAsOp.matches(Call);
+
+if (IsAnyConstructor || IsAnyAssignmentOperatorCall) {
+  auto State = C.getState();
+  SVal ThisSVal = [&]() {
+if (IsAnyConstructor) {
+  const auto *AsConstructorCall = dyn_cast(&Call);
+  return AsConstructorCall->getCXXThisVal();
+}
+if (IsAnyAssignmentOperatorCall) {
+  const auto *AsMemberOpCall = dyn_cast(&Call);
+  return AsMemberOpCall->getCXXThisVal();
+}
+llvm_unreachable("We must have an assignment operator or constructor");
+  }();
+
+  // default constructor call
+  // in this case the any holds a null type
+  if (Call.getNumArgs() == 0) {
+const auto *ThisMemRegion = ThisSVal.getAsRegion();
+setNullTypeAny(ThisMemRegion, C);
+return true;
+  }
+
+  if (Call.getNumArgs() != 1)
+return false;
+
+  handleConstructorAndAssignment(Call, C, ThisSVal);
+  return true;
+}
+return false;
+  }
+
+private:
+  // When an std::any is rested or default constructed it has a null type.
+  // We represent it by storing a null QualType.
+  void setNullTypeAny(const MemRegion *Mem, CheckerContext &C) const {
+auto State = C.getState();
+State = State->set(Mem, QualType{});
+C.addTransition(State);
+  }
+
+  // this function name is terrible
+  bool handleAnyCastCall(const CallEvent &Call, CheckerContext &C) const {
+auto State = C.getState();
+
+if (Call.getNumArgs() != 1)
+  return false;
+
+auto ArgSVal = Call.getArgSVal(0);
+
+// The argument is aether a const reference or a right value reference
+//  We need the type referred
+const auto *ArgType = ArgSVal.getType(C.getASTContext())
+  .getTypePtr()
+  ->getPointeeType()
+  .getTypePtr();
+if (!isStdAny(ArgType))
+  return false;
+
+const auto *AnyMemRegion = ArgSVal.getAsRegion();
+
+if (!State->contains(AnyMemRegion))
+  return false;
+
+// get the type we are trying to get from any
+const CallExpr *CE = cast(Call.getOriginExpr());
+const FunctionDecl *FD = CE->getDirectCallee();
+if (FD->getTemplateSpecializationArgs()->size() < 1)

[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-30 Thread Gábor Spaits via cfe-commits


@@ -58,6 +58,14 @@ void wontConfuseStdGets() {
 
////
 // std::get
 
////
+void stdGetType2() {

spaits wrote:

Oh, this test is not relevant. It is basically the same as the one after it. I 
was just doing some debugging to see how CSA handles different kinds of object 
constructions and forgot to remove it. I will remove it.

https://github.com/llvm/llvm-project/pull/76580
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-30 Thread Gábor Spaits via cfe-commits


@@ -87,6 +85,28 @@ bool isStdVariant(const Type *Type) {
   return isStdType(Type, llvm::StringLiteral("variant"));
 }
 
+bool isStdAny(const Type *Type) {
+  return isStdType(Type, llvm::StringLiteral("any"));
+}
+
+bool isVowel(char a) {
+  switch (a) {
+  case 'a':
+  case 'e':
+  case 'i':
+  case 'o':
+  case 'u':
+return true;
+  default:
+return false;
+  }
+}
+
+llvm::StringRef indefiniteArticleBasedOnVowel(char a) {
+  if (isVowel(a))
+return "an";
+  return "a";
+}

spaits wrote:

I like the new sentence you suggested. I will replace the current warning text 
for this checker and for `std::variant` checker too.

https://github.com/llvm/llvm-project/pull/76580
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2023-12-30 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,200 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};

spaits wrote:

I have not implemented the modeling of these functions yet. Looking at the 
semantics of these functions I should really do some modeling of them or at 
least "turn off" the checker when a one of these functions are used.

https://github.com/llvm/llvm-project/pull/76580
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-02 Thread Gábor Spaits via cfe-commits


@@ -87,6 +85,28 @@ bool isStdVariant(const Type *Type) {
   return isStdType(Type, llvm::StringLiteral("variant"));
 }
 
+bool isStdAny(const Type *Type) {
+  return isStdType(Type, llvm::StringLiteral("any"));
+}
+
+bool isVowel(char a) {
+  switch (a) {
+  case 'a':
+  case 'e':
+  case 'i':
+  case 'o':
+  case 'u':
+return true;
+  default:
+return false;
+  }
+}
+
+llvm::StringRef indefiniteArticleBasedOnVowel(char a) {
+  if (isVowel(a))
+return "an";
+  return "a";
+}

spaits wrote:

I think a good solution would be just to use the current text, but instead of 
deciding the indefinite article dynamically, we could just use `a(n)`. I think 
with this solution we would have correct grammar and a short warning. What do 
you think?

https://github.com/llvm/llvm-project/pull/76580
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-03 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 1/8] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Progr

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-03 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 1/9] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Progr

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-03 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/10] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-03 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/11] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-03 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/12] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-04 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/15] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-04 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/16] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-04 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From 98b52eb390438402562de96a74771b0132fc71cb Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/18] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-04 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From a19329050600d4d89cc698b686d7aaa13e0c22c2 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/18] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-10 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From a19329050600d4d89cc698b686d7aaa13e0c22c2 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/19] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-10 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/76580

From a19329050600d4d89cc698b686d7aaa13e0c22c2 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Fri, 29 Dec 2023 17:54:34 +0100
Subject: [PATCH 01/20] [analyzer] Add std::any checker

---
 clang/docs/analyzer/checkers.rst  |  21 ++
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   4 +
 .../StaticAnalyzer/Checkers/CMakeLists.txt|   1 +
 .../StaticAnalyzer/Checkers/StdAnyChecker.cpp | 201 ++
 .../Checkers/StdVariantChecker.cpp|  46 ++--
 .../Checkers/TaggedUnionModeling.h|   9 +-
 .../Inputs/system-header-simulator-cxx.h  |  59 +
 clang/test/Analysis/std-any-checker.cpp   | 170 +++
 clang/test/Analysis/std-variant-checker.cpp   |   8 +
 9 files changed, 490 insertions(+), 29 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
 create mode 100644 clang/test/Analysis/std-any-checker.cpp

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index bb637cf1b8007b..867bdfc9012253 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2095,6 +2095,27 @@ This checker is a part of ``core.StackAddressEscape``, 
but is temporarily disabl
  //   returned block
  }
 
+.. _alpha-core-StdAny:
+
+alpha.core.StdAny (C++)
+"""
+Check if a value of active type is retrieved from an ``std::any`` instance 
with ``std::any_cats``
+or if the ``std::any`` instance holds type. In case of bad any type access
+(the accessed type differs from the active type, or the instance has no stored 
value)
+a warning is emitted. Currently, this checker does not take exception handling 
into account.
+
+.. code-block:: cpp
+
+ void anyCast() {
+  std::any a = 5;
+  char c = std::any_cast(a); // // warn: "int" is the active alternative
+ }
+
+ void noTypeHeld() {
+  std::any a;
+  int i = std::any_cast(a); // warn: any 'a' is empty
+ }
+
 .. _alpha-core-StdVariant:
 
 alpha.core.StdVariant (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d2..954584fadb225d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -321,6 +321,10 @@ def C11LockChecker : Checker<"C11Lock">,
   Dependencies<[PthreadLockBase]>,
   Documentation;
 
+def StdAnyChecker : Checker<"StdAny">,
+  HelpText<"Check for bad type access for std::any.">,
+  Documentation;
+
 def StdVariantChecker : Checker<"StdVariant">,
   HelpText<"Check for bad type access for std::variant.">,
   Documentation;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 4443ffd0929388..4e3475ff7f37da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -107,6 +107,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrChecker.cpp
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
+  StdAnyChecker.cpp
   StdLibraryFunctionsChecker.cpp
   StdVariantChecker.cpp
   STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
new file mode 100644
index 00..647ee72e555140
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StdAnyChecker.cpp
@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  Pro

[clang] [analyzer] Add std::any checker (PR #76580)

2024-01-10 Thread Gábor Spaits via cfe-commits


@@ -0,0 +1,201 @@
+//===- StdAnyChecker.cpp -*- 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
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(AnyHeldTypeMap, const MemRegion *, QualType)
+
+class StdAnyChecker : public Checker {
+  CallDescription AnyConstructor{{"std", "any", "any"}};
+  CallDescription AnyAsOp{{"std", "any", "operator="}};
+  CallDescription AnyReset{{"std", "any", "reset"}, 0, 0};
+  CallDescription AnyCast{{"std", "any_cast"}, 1, 1};
+
+  BugType BadAnyType{this, "BadAnyType", "BadAnyType"};
+  BugType NullAnyType{this, "NullAnyType", "NullAnyType"};
+
+public:
+  ProgramStateRef
+  checkRegionChanges(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef ExplicitRegions,
+ ArrayRef Regions,
+ const LocationContext *LCtx, const CallEvent *Call) const 
{
+if (!Call)
+  return State;
+
+return removeInformationStoredForDeadInstances(*Call, 
State,
+   Regions);
+  }
+
+  bool evalCall(const CallEvent &Call, CheckerContext &C) const {
+// Do not take implementation details into consideration
+if (Call.isCalledFromSystemHeader())
+  return false;
+
+if (AnyCast.matches(Call))
+  return handleAnyCastCall(Call, C);
+
+if (AnyReset.matches(Call)) {
+  const auto *AsMemberCall = dyn_cast(&Call);
+  if (!AsMemberCall)
+return false;
+
+  const auto *ThisMemRegion = AsMemberCall->getCXXThisVal().getAsRegion();
+  if (!ThisMemRegion)
+return false;
+
+  setNullTypeAny(ThisMemRegion, C);
+  return true;
+}
+
+bool IsAnyConstructor =
+isa(Call) && AnyConstructor.matches(Call);
+bool IsAnyAssignmentOperatorCall =
+isa(Call) && AnyAsOp.matches(Call);
+
+if (IsAnyConstructor || IsAnyAssignmentOperatorCall) {
+  auto State = C.getState();
+  SVal ThisSVal = [&]() {
+if (IsAnyConstructor) {
+  const auto *AsConstructorCall = dyn_cast(&Call);
+  return AsConstructorCall->getCXXThisVal();
+}
+if (IsAnyAssignmentOperatorCall) {
+  const auto *AsMemberOpCall = dyn_cast(&Call);
+  return AsMemberOpCall->getCXXThisVal();
+}
+llvm_unreachable("We must have an assignment operator or constructor");
+  }();
+
+  // default constructor call
+  // in this case the any holds a null type
+  if (Call.getNumArgs() == 0) {
+const auto *ThisMemRegion = ThisSVal.getAsRegion();
+setNullTypeAny(ThisMemRegion, C);
+return true;
+  }
+
+  if (Call.getNumArgs() != 1)
+return false;
+
+  handleConstructorAndAssignment(Call, C, ThisSVal);
+  return true;
+}
+return false;
+  }
+
+private:
+  // When an std::any is rested or default constructed it has a null type.
+  // We represent it by storing a null QualType.
+  void setNullTypeAny(const MemRegion *Mem, CheckerContext &C) const {
+auto State = C.getState();
+State = State->set(Mem, QualType{});
+C.addTransition(State);
+  }
+
+  // this function name is terrible
+  bool handleAnyCastCall(const CallEvent &Call, CheckerContext &C) const {
+auto State = C.getState();
+
+if (Call.getNumArgs() != 1)
+  return false;
+
+auto ArgSVal = Call.getArgSVal(0);
+
+// The argument is aether a const reference or a right value reference
+//  We need the type referred
+const auto *ArgType = ArgSVal.getType(C.getASTContext())
+  .getTypePtr()
+  ->getPointeeType()
+  .getTypePtr();

spaits wrote:

I changed the code so it uses the `Expr` instead of `SVal`. I removed the 
checking that is responsible to tell if the argument is a reference or pointer. 
I think it is not likely, that the user defines their own `std::any_cast`.

When `std::any_cast` is used with a `std::any *` arg no exception will be throw 
(see https://en.cppreference.com/w/cpp/util

[clang] [analyzer] Improve some comments in ArrayBoundCheckerV2 (NFC) (PR #83545)

2024-03-01 Thread Gábor Spaits via cfe-commits


@@ -301,21 +301,27 @@ compareValueToThreshold(ProgramStateRef State, NonLoc 
Value, NonLoc Threshold,
   // calling `evalBinOpNN`:
   if (isNegative(SVB, State, Value) && isUnsigned(SVB, Threshold)) {
 if (CheckEquality) {
-  // negative_value == unsigned_value is always false
+  // negative_value == unsigned_threshold is always false
   return {nullptr, State};
 }
-// negative_value < unsigned_value is always false
+// negative_value < unsigned_threshold is always true
 return {State, nullptr};
   }
   if (isUnsigned(SVB, Value) && isNegative(SVB, State, Threshold)) {
-// unsigned_value == negative_value and unsigned_value < negative_value are
-// both always false
+// unsigned_value == negative_threshold and
+// unsigned_value < negative_threshold are both always false

spaits wrote:

Just a minor nit: Wouldn't it be better to write `<=`?

https://github.com/llvm/llvm-project/pull/83545
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Improve some comments in ArrayBoundCheckerV2 (NFC) (PR #83545)

2024-03-02 Thread Gábor Spaits via cfe-commits


@@ -301,21 +301,27 @@ compareValueToThreshold(ProgramStateRef State, NonLoc 
Value, NonLoc Threshold,
   // calling `evalBinOpNN`:
   if (isNegative(SVB, State, Value) && isUnsigned(SVB, Threshold)) {
 if (CheckEquality) {
-  // negative_value == unsigned_value is always false
+  // negative_value == unsigned_threshold is always false
   return {nullptr, State};
 }
-// negative_value < unsigned_value is always false
+// negative_value < unsigned_threshold is always true
 return {State, nullptr};
   }
   if (isUnsigned(SVB, Value) && isNegative(SVB, State, Threshold)) {
-// unsigned_value == negative_value and unsigned_value < negative_value are
-// both always false
+// unsigned_value == negative_threshold and
+// unsigned_value < negative_threshold are both always false

spaits wrote:

Oh. I understand.

https://github.com/llvm/llvm-project/pull/83545
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Improve some comments in ArrayBoundCheckerV2 (NFC) (PR #83545)

2024-03-03 Thread Gábor Spaits via cfe-commits

https://github.com/spaits approved this pull request.


https://github.com/llvm/llvm-project/pull/83545
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits created 
https://github.com/llvm/llvm-project/pull/79371

This pull request would solve https://github.com/llvm/llvm-project/issues/78449 
.
There is also a discussion about this on stackoverflow: 
https://stackoverflow.com/questions/77832658/stdtype-identity-to-support-several-variadic-argument-lists
 .

The following program is well formed:
```cpp
#include 

template 
struct args_tag
{
using type = std::common_type_t;
};

template 
void bar(args_tag, std::type_identity_t..., int, 
std::type_identity_t...) {}

// example
int main() {
bar(args_tag{}, 4, 8, 15, 16, 23);
}
```

but Clang rejects it, while GCC and MSVC doesn't. The reason for this is that, 
in `Sema::DeduceTemplateArguments` we are not prepared for this case. 

The logic that handles substitution when we have explicit template arguments 
does not work here, since the types of the pack are not pushed to `ParamTypes` 
before the loop starts that does the deduction.
The other "candidate" that would may handle this case would be the loop that 
does the deduction for trailing packs, but we are not dealing with trailing 
packs here.

The solution proposed in this PR works similar to the trailing pack deduction. 
The main difference here is the end of the deduction cycle.
When a non-trailing template pack argument is found, whose type is not 
explicitly specified and the next type is not a pack type, the length of the 
previously deduced pack is retrieved (let that length be `s`). After that the 
next `s` arguments are processed in the same way as in the case of non trailing 
packs.

There is another possible approach that would be less efficient. In the loop 
when we get to an element of `ParamTypes` that is a pack and could be 
substituted because the type is deduced from a previous argument, then `s` 
number of arg types would be inserted before the current element of 
`ParamTypes` type. Then we would "cancel" the processing of the current 
element, first process the previously inserted elements and the after that 
re-process the current element.
Basically we would do what `SubstituteExplicitTemplateArguments` does but 
during deduction.

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH] [Sema]Substitue template parameter packs when deduced from
 function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpan

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/2] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/3] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb82

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/4] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb82

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-24 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/5] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits


@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced
+// perviously we substitute the pack here in a similar fashion as seen
+// above with the trailing parameter packs. The main difference here is
+// that, in this case we are not processing all of the remaining
+// arguments. We are only process as many arguments as much we have in
+// the already deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;

spaits wrote:

I think it could be. In that case that every template packs that are needed by 
the dependent name are all expanded. For example this could happen when we use 
explicitly specified template arguments.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/6] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits


@@ -431,6 +442,17 @@ namespace deduction_after_explicit_pack {
 i(0, 1, 2, 3, 4, 5); // expected-error {{no match}}
   }
 
+  template 
+  void bar(args_tag, type_identity_t..., int mid, 
type_identity_t...) {}

spaits wrote:

It could work. It would cost only condition being removed. I deliberately put 
in the condition that disables this. Should I enable it?

I think enabling it would be standard compliant, but I played it safe and stuck 
to the example seen in the issue.  

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/7] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb82

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/8] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/9] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6cbb

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits


@@ -858,6 +859,30 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(), [&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {
+return DeducedFromEarlierParameter;
+  }
+

spaits wrote:

This code at the this state(the state in which you wrote this comment) is more 
complicated then it should be. I was able to make it more simple.

I gave a new name to this function, that describes better what this function 
does.

We are using the `Saved` packs here that are only modified in the constructors. 
The `Saved` packs are the previously deduced packs.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits


@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced
+// perviously we substitute the pack here in a similar fashion as seen
+// above with the trailing parameter packs. The main difference here is
+// that, in this case we are not processing all of the remaining
+// arguments. We are only process as many arguments as much we have in
+// the already deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;

spaits wrote:

I did some optimization and this part of the code is not needed anymore.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/10] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 52de421b998481105e5522a04ad9e39a4a6c

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

spaits wrote:

Thank you @cor3ntin for reviewing my PR.

I addressed all of your comments.

- I fixed the types.
- I added support for deduction of non-trailing packs when there is no 
separator type.
- Simplified the code. This simplification has affect on the code you asked 
about.

Could you please review my recent changes?

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From c00b8bd525b6acab45009188a7b9d1cb8c7eb30d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/10] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 1105354e001b41cac22836e0ac1df9eb8e33

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

spaits wrote:

> I don't see the release note, and there is a typo in the PR entry that should 
> be fixed.
> 
> Else just 1 nit.

Oh sorry I forgot about the release note. I will update that.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From c00b8bd525b6acab45009188a7b9d1cb8c7eb30d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/11] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 1105354e001b41cac22836e0ac1df9eb8e3331

[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From c00b8bd525b6acab45009188a7b9d1cb8c7eb30d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/12] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 1105354e001b41cac22836e0ac1df9eb8e3331

[clang] [Sema] Substitue parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From a27fe8c4179a58a741121eec9e8368c9ab44d7cc Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/12] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 44771539c48b3d5418c3726999b78b70b9a059

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

spaits wrote:

@cor3ntin @erichkeane
Thank you for checking the updates on my PR.
I fixed the typo and added the release notes.


https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From a27fe8c4179a58a741121eec9e8368c9ab44d7cc Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/13] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 44771539c48b3d5418c3726999b78b70b9a059

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

spaits wrote:

> > @cor3ntin @erichkeane Thank you for checking the updates on my PR. I fixed 
> > the typo and added the release notes. Also rebased the branch.
> 
> Looks like the release notes change failed CI.

Not my changes. This was commited 3 hours ago: 
https://github.com/spaits/llvm-project/commit/c92ad411f2f94d8521cd18abcb37285f9a390ecb
 .
In this commit the author has forgot to close a `` .

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits


@@ -431,6 +442,17 @@ namespace deduction_after_explicit_pack {
 i(0, 1, 2, 3, 4, 5); // expected-error {{no match}}
   }
 
+  template 
+  void bar(args_tag, type_identity_t..., int mid, 
type_identity_t...) {}

spaits wrote:

I added a test for this.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-25 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From 38107a96c18fc5d008873fbac5257f0f476799f3 Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/13] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From dd404c09cc572499558d784093ada299070546

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

spaits wrote:

It looks like libc++ test suites are failing. Looking at the logs from the CI I 
can not really figure out what is the exact reason.
I could only deduce that the failing test case is 
`libcxx/gdb/gdb_pretty_printer_test.sh.cpp`. This case seems to be related to 
`libcxx/selftest/convenience_substitutions/build_run.sh.cpp`. I will try to 
figure out how to set up my environment to run these tests.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From 3e0c3db0d8500e5f2111e3603da3d8f2b1cd261d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/13] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 59a01f3be41a1d8efa11e0e31448887b5517

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

spaits wrote:

I did some more digging. I saw that the test in the CI fails with permission 
errors.

```
| No symbol table is loaded.  Use the "file" command.
| warning: opening /proc/PID/mem file for lwp 4103309.4103309 failed: 
Permission denied (13)
| Traceback (most recent call last):
|   File 
"/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-h5ngp-1/llvm-project/clang-ci/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py",
 line 123, in 
| gdb.execute("run")
| gdb.error: Warning:
| Cannot insert breakpoint 1.
| Cannot access memory at address 0x637c
```

I thought that maybe the problem is that, the program to be debugged by `dbg` 
does not compile with the compiler that includes my changes. I decided to just 
compile the test file with my modified compiler. I copied the test file. 
Removed one include that is only needed for manual debugging and recreated the 
command used in the CI as much as I could. The command looks like this now:
```
/home/spaits/repo/llvm-project/build/bin/clang++ -pthread 
--target=x86_64-unknown-linux-gnu /home/spaits/cpp/deb.cpp -o 
/home/spaits/cpp/deb.out -std=c++26 -Werror -Wall -Wctad-maybe-unsupported 
-Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument 
-Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment 
-Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor 
-Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare 
-Wunused-variable -Wunused-parameter -Wunreachable-code 
-Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions 
-Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete 
-Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 
-D_LIBCPP_ENABLE_EXPERIMENTAL 
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety 
-Wuser-defined-warnings -g   -lc++ -latomic
0 spaits@work-laptop:~/cpp$ 
```
Because of the GCC 13+ prereq. I did not build libc++ for my self, but used the 
one available on my machine.
This way the file has compiled successfully.

I will still try to run the tests myself.

Until that if you have any idea what should I, do what wen possibly wrong pleas 
share that with me.

Thanks.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From 3e0c3db0d8500e5f2111e3603da3d8f2b1cd261d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/14] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 59a01f3be41a1d8efa11e0e31448887b55178f

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From 3e0c3db0d8500e5f2111e3603da3d8f2b1cd261d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/15] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 59a01f3be41a1d8efa11e0e31448887b55178f

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits


@@ -431,6 +442,17 @@ namespace deduction_after_explicit_pack {
 i(0, 1, 2, 3, 4, 5); // expected-error {{no match}}
   }
 
+  template 
+  void bar(args_tag, type_identity_t..., int mid, 
type_identity_t...) {}

spaits wrote:

Added the test. It also works.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits


@@ -858,6 +859,27 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  // Return the size of the saved packs if all of them has the same size.
+  std::optional getSavedPackSizeIfAllEqual() const {
+if (Packs.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)

spaits wrote:

The reason I added them is because I wanted to be careful. What if someone 
constructs a `PackDeductionScope` with a non pack `TemplateArgument`.

Should I replace them with insertions?

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

https://github.com/spaits edited https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-26 Thread Gábor Spaits via cfe-commits

https://github.com/spaits updated 
https://github.com/llvm/llvm-project/pull/79371

From 3e0c3db0d8500e5f2111e3603da3d8f2b1cd261d Mon Sep 17 00:00:00 2001
From: Gabor Spaits 
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 01/16] [Sema]Substitue template parameter packs when deduced
 from function parameter

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a..46fa9eece3747a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
 // Save the deduced template argument for the parameter pack expanded
 // by this pack expansion, then clear out the deduction.
+DeducedFromEarlierParameter = !Deduced[Index].isNull();
 DeducedPack Pack(Index);
 Pack.Saved = Deduced[Index];
 Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  std::optional getSavedPackSize(unsigned Index,
+   TemplateArgument Pattern) const {
+
+SmallVector Unexpanded;
+S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+if (Unexpanded.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+  return {};
+unsigned PackSize = Packs[0].Saved.pack_size();
+
+if (std::all_of(Packs.begin() + 1, Packs.end(),
+[&PackSize](auto P) {
+  return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+}))
+  return PackSize;
+return {};
+  }
+
+  /// Determine whether this pack has already been deduced from a previous
+  /// argument.
+  bool isDeducedFromEarlierParameter() const {return 
DeducedFromEarlierParameter;}
+
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
   bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
 NewPack = Pack.DeferredDeduction;
 Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
   }
-
   NamedDecl *Param = TemplateParams->getParam(Pack.Index);
   if (Result.isNull()) {
 Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
   bool DeducePackIfNotAlreadyDeduced = false;
+  bool DeducedFromEarlierParameter = false;
+
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional FixedNumExpansions;
 
+
   SmallVector Packs;
 };
 
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult 
Sema::DeduceTemplateArguments(
   // corresponding argument is a list?
   PackScope.nextPackElement();
 }
+  } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa(ParamTypes[ParamIdx + 1])) {
+// [temp.deduct.general#3]
+// When all template arguments have been deduced
+// or obtained from default template arguments, all uses of template
+// parameters in the template parameter list of the template are
+// replaced with the corresponding deduced or default argument values
+//
+// If we have a trailing parameter pack, that has been deduced 
perviously
+// we substitute the pack here in a similar fashion as seen above with
+// the trailing parameter packs. The main difference here is that, in
+// this case we are not processing all of the remaining arguments. We
+// are only process as many arguments as much we have in the already
+// deduced parameter.
+SmallVector Unexpanded;
+collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+if (Unexpanded.size() == 0)
+  continue;
+
+std::optional ArgPosAfterSubstitution =
+PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+   ParamPattern);
+if (!ArgPosAfterSubstitution)
+  continue;
+
+unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+  ParamTypesForArgChecking.push_back(ParamPattern);
+  if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+   
/*ExplicitObjetArgument=*/false))
+return Result;
+
+  PackScope.nextPackElement();
+}
   }
 }
 

From 59a01f3be41a1d8efa11e0e31448887b55178f

[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-27 Thread Gábor Spaits via cfe-commits


@@ -858,6 +859,27 @@ class PackDeductionScope {
   Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
   }
 
+  // Return the size of the saved packs if all of them has the same size.
+  std::optional getSavedPackSizeIfAllEqual() const {
+if (Packs.size() == 0 ||
+Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)

spaits wrote:

Removed this precondition. I have also removed a redundant condition from the 
checking of the equivalence of pack sizes.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-27 Thread Gábor Spaits via cfe-commits

spaits wrote:

Thank you for reviewing.

Before merge we should take a look at the CI.

It still fails for libc++ 26 suite, with the same reason as before.

I wanted to reproduce the issue. I built libc++ with the clang++ I compiled:
```
cmake -S "../runtimes" -GNinja \
  -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \
  -DLIBCXX_CXX_ABI=libcxxabi \
  -DCMAKE_BUILD_TYPE=Debug \
  -DLIBCXX_TEST_PARAMS="std=c++26" \
  -DLIBCXXABI_TEST_PARAMS="std=c++26" \
  -DCMAKE_CXX_COMPILER=/home/spaits/repo/llvm-project/build/bin/clang++ 
\
  -DLLVM_DIR=/home/spaits/repo/llvm-project/build/lib/cmake/llvm
```
Then I run the test:
```
 /home/spaits/repo/llvm-project/build/bin/llvm-lit -a 
/home/spaits/repo/llvm-project/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp
```

Everything worked fine for me.
I don't know why the CI always fails for my PR with the same reason. It looks 
like an env issue in the CI, but it can not be that since other PRs are getting 
green runs.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-27 Thread Gábor Spaits via cfe-commits

spaits wrote:

@cor3ntin I see that you have CI runs that fail with exactly the same reason as 
my runs: 
https://buildkite.com/llvm-project/clang-ci/builds/10874#018d49c2-1224-4939-9430-0e5a2be796a9
 .

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-27 Thread Gábor Spaits via cfe-commits

spaits wrote:

> It's unrelated to your changes. Configuration issue on the CI, probably

Okay. Then I will merge this.

Thank you very much for reviewing my PR and helping me.

https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Substitute parameter packs when deduced from function arguments (PR #79371)

2024-01-27 Thread Gábor Spaits via cfe-commits

https://github.com/spaits closed https://github.com/llvm/llvm-project/pull/79371
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   >