[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-19 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

I was also implementing this and run into an issue, so I looked into your 
implementation and you have exactly same issue as I do, following code will 
fail:
```c++
namespace std {
template  consteval bool is_within_lifetime(const T * ptr) noexcept 
{
return __builtin_is_within_lifetime(ptr);
}
}

constexpr bool test_union(int * i) { // <-- note the constexpr here
  return std::is_within_lifetime(i);
}

static_assert([] consteval {
  union { int i; char c; } u = {.i = 10};
  return test_union(&u.i);
}());
```

with error: 
```
./builtin-is-within-lifetime-call.cpp:8:10: error: call to consteval function 
'std::is_within_lifetime' is not a constant expression
8 |   return std::is_within_lifetime(i);
  |  ^
./builtin-is-within-lifetime-call.cpp:8:34: note: function parameter 'i' with 
unknown value cannot be used in a constant expression
8 |   return std::is_within_lifetime(i);
  |  ^
./builtin-is-within-lifetime-call.cpp:7:33: note: declared here
7 | constexpr bool test_union(int * i) { // <-- note the constexpr here
  | ^
1 error generated.
```

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-19 Thread Hana Dusíková via cfe-commits


@@ -17264,3 +17288,76 @@ bool Expr::tryEvaluateStrLen(uint64_t &Result, 
ASTContext &Ctx) const {
   EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
   return EvaluateBuiltinStrLen(this, Result, Info);
 }
+
+namespace {
+struct IsWithinLifetimeHandler {
+  EvalInfo &Info;
+  static constexpr AccessKinds AccessKind = AccessKinds::AK_IsWithinLifetime;
+  using result_type = std::optional;
+  std::optional failed() { return std::nullopt; }
+  template 
+  std::optional found(T &Subobj, QualType SubobjType) {
+return true;
+  }
+};
+
+std::optional EvaluateBuiltinIsWithinLifetime(IntExprEvaluator &IEE,
+const CallExpr *E) {
+  EvalInfo &Info = IEE.Info;
+  // Sometimes this is called during some sorts of constant folding / early
+  // evaluation. These are meant for non-constant expressions and are not
+  // necessary since this consteval builtin will never be evaluated at runtime.
+  // Just fail to evaluate when not in a constant context.
+  if (!Info.InConstantContext)
+return std::nullopt;
+  assert(E->getBuiltinCallee() == Builtin::BI__builtin_is_within_lifetime);
+  const Expr *Arg = E->getArg(0);
+  if (Arg->isValueDependent())
+return std::nullopt;
+  LValue Val;
+  if (!EvaluatePointer(Arg, Val, Info))
+return std::nullopt;
+
+  auto Error = [&](int Diag) {
+const auto *Callee = Info.CurrentCall->getCallee();
+bool CalledFromStd = Callee && Callee->isInStdNamespace() &&
+ Callee->getIdentifier() &&
+ Callee->getIdentifier()->isStr("is_within_lifetime");
+Info.report(CalledFromStd ? Info.CurrentCall->getCallRange().getBegin()
+  : E->getExprLoc(),
+diag::err_invalid_is_within_lifetime)
+<< (CalledFromStd ? "std::is_within_lifetime"
+  : "__builtin_is_within_lifetime")
+<< Diag;
+return std::nullopt;
+  };
+  // C++2c [meta.const.eval]p4:
+  //   During the evaluation of an expression E as a core constant expression, 
a
+  //   call to this function is ill-formed unless p points to an object that is
+  //   usable in constant expressions or whose complete object's lifetime began
+  //   within E.
+
+  // Make sure it points to an object
+  // nullptr does not point to an object
+  if (Val.isNullPointer() || Val.getLValueBase().isNull())
+return Error(0);
+  QualType T = Val.getLValueBase().getType();
+  if (T->isFunctionType())
+return Error(1);
+  assert(T->isObjectType());
+  // Hypothetical array element is not an object
+  if (Val.getLValueDesignator().isOnePastTheEnd())
+return Error(2);
+  assert(Val.getLValueDesignator().isValidSubobject() &&
+ "Unchecked case for valid subobject");
+  // All other ill-formed values should have failed EvaluatePointer, so the
+  // object should be a pointer to an object that is usable in a constant
+  // expression or whose complete lifetime began within the expression
+  CompleteObject CO =
+  findCompleteObject(Info, E, AccessKinds::AK_IsWithinLifetime, Val, T);
+  if (!CO)
+return false;
+  IsWithinLifetimeHandler handler{Info};
+  return findSubobject(Info, E, CO, Val.getLValueDesignator(), handler);

hanickadot wrote:

associated with previous comment ... you are returning `false` but `.failure()` 
will return std::nullopt, so be aware :)

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-19 Thread Hana Dusíková via cfe-commits


@@ -3760,6 +3765,9 @@ findSubobject(EvalInfo &Info, const Expr *E, const 
CompleteObject &Obj,
 if ((O->isAbsent() && !(handler.AccessKind == AK_Construct && I == N)) ||
 (O->isIndeterminate() &&
  !isValidIndeterminateAccess(handler.AccessKind))) {
+  // Object has ended lifetime since pointer was formed
+  if (handler.AccessKind == AK_IsWithinLifetime)
+return false;

hanickadot wrote:

AFAIK you can't use `bool` here, it will be problem when `findSubobject` will 
be used with non-compatible return type

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-19 Thread Hana Dusíková via cfe-commits


@@ -3927,6 +3935,9 @@ findSubobject(EvalInfo &Info, const Expr *E, const 
CompleteObject &Obj,
 // Placement new onto an inactive union member makes it active.
 O->setUnion(Field, APValue());
   } else {
+// Pointer to/into inactive union member: Not within lifetime
+if (handler.AccessKind == AK_IsWithinLifetime)
+  return false;

hanickadot wrote:

same here

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


[clang] [clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) (PR #98756)

2024-07-29 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98756

From e21d8acf36c188056bc2f08b60470fdd6d62cf7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 20:59:22 +0200
Subject: [PATCH] [clang] constexpr atomic builtins (__c11_atomic_OP and
 __atomic_OP)

---
 clang/include/clang/Basic/Builtins.td |  80 +--
 clang/lib/AST/ExprConstant.cpp| 539 ++
 .../SemaCXX/atomic-constexpr-c11-builtins.cpp | 326 +++
 .../SemaCXX/atomic-constexpr-gcc-builtins.cpp | 504 
 4 files changed, 1409 insertions(+), 40 deletions(-)
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-c11-builtins.cpp
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-gcc-builtins.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 4133f6ff40cf3..fdb87e88b0e2a 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,133 +1785,133 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
-  le

[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-22 Thread Hana Dusíková via cfe-commits

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/99773

From ebf1c6996f18cbd706ec3d76a1887c58c9ce3230 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 20 Jul 2024 20:12:45 +0200
Subject: [PATCH 1/2] [clang-tidy] `bugprone-exception-escape` didn't detech
 catching of an exception with pointer type by `void *` exception handler

---
 .../clang-tidy/utils/ExceptionAnalyzer.cpp | 10 +-
 clang-tools-extra/docs/ReleaseNotes.rst|  4 
 .../checkers/bugprone/exception-escape.cpp | 18 ++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp 
b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index 6ae46e2b1262a..9bfb7e2677533 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -141,7 +141,10 @@ bool isStandardPointerConvertible(QualType From, QualType 
To) {
 if (RD->isCompleteDefinition() &&
 isBaseOf(From->getPointeeType().getTypePtr(),
  To->getPointeeType().getTypePtr())) {
-  return true;
+  // If B is an inaccessible or ambiguous base class of D, a program
+  // that necessitates this conversion is ill-formed
+  return isUnambiguousPublicBaseClass(From->getPointeeType().getTypePtr(),
+  To->getPointeeType().getTypePtr());
 }
   }
 
@@ -375,10 +378,7 @@ bool ExceptionAnalyzer::ExceptionInfo::filterByCatch(
 isPointerOrPointerToMember(ExceptionCanTy->getTypePtr())) {
   // A standard pointer conversion not involving conversions to pointers to
   // private or protected or ambiguous classes ...
-  if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy) &&
-  isUnambiguousPublicBaseClass(
-  ExceptionCanTy->getTypePtr()->getPointeeType().getTypePtr(),
-  HandlerCanTy->getTypePtr()->getPointeeType().getTypePtr())) {
+  if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy)) {
 TypesToDelete.push_back(ExceptionTy);
   }
   // A function pointer conversion ...
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index a23483e6df6d2..30228828686da 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -245,6 +245,10 @@ Changes in existing checks
   where source is already a ``void``` pointer, making middle ``void`` pointer
   casts bug-free.
 
+- Improved :doc:`exception-escape 
`
+  check to correctly detect exception handler of type ``CV void *`` as 
catching all 
+  ``CV`` compatible pointer types.
+
 - Improved :doc:`bugprone-forwarding-reference-overload
   `
   check to ignore deleted constructors which won't hide other overloads.
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
index f5e74df1621ce..26c443b139629 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
@@ -756,3 +756,21 @@ struct test_implicit_throw {
 };
 
 }}
+
+void pointer_exception_can_not_escape_with_const_void_handler() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown 
in function 'pointer_exception_can_not_escape_with_const_void_handler' which 
should not throw exceptions
+  const int value = 42;
+  try {
+throw &value;
+  } catch (const void *) {
+  }
+}
+
+void pointer_exception_can_not_escape_with_void_handler() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown 
in function 'pointer_exception_can_not_escape_with_void_handler' which should 
not throw exceptions
+  int value = 42;
+  try {
+throw &value;
+  } catch (void *) {
+  }
+}

From 1363d619a264f3e4633870d950e26bd3ba59692f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dus=C3=ADkov=C3=A1?= 
Date: Mon, 22 Jul 2024 20:45:42 +0200
Subject: [PATCH 2/2] Update clang-tools-extra/docs/ReleaseNotes.rst

Co-authored-by: Piotr Zegar 
---
 clang-tools-extra/docs/ReleaseNotes.rst | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 30228828686da..233fb0e01be86 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -245,9 +245,9 @@ Changes in existing checks
   where source is already a ``void``` pointer, making middle ``void`` pointer
   casts bug-free.
 
-- Improved :doc:`exception-escape 
`
-  check to correctly detect exception handler of type ``CV void *`` as 
catching all 
-  ``CV`` compatible pointer types.
+- Improved :doc:`bugprone-exception-escape
+  `  check to correctly detect 
exception 
+  handl

[clang] [clang] Implement function pointer signing and authenticated function calls (PR #93906)

2024-07-21 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

When this change is building at Compiler Explorer I noticed it spams build 
output with warnings:
```
In file included from /root/llvm-project/clang/include/clang/AST/Type.h:31,
 from 
/root/llvm-project/clang/include/clang/AST/DeclarationName.h:16,
 from /root/llvm-project/clang/include/clang/AST/DeclBase.h:19,
 from /root/llvm-project/clang/include/clang/AST/Decl.h:20,
 from 
/root/llvm-project/clang/tools/libclang/CXExtractAPI.cpp:20:
/root/llvm-project/clang/include/clang/Basic/PointerAuthOptions.h:61:8: 
warning: 'clang::PointerAuthSchema::TheKind' is too small to hold all values of 
'enum class clang::PointerAuthSchema::Kind'
   61 |   Kind TheKind : 2;
  |^~~
/root/llvm-project/clang/include/clang/Basic/PointerAuthOptions.h:65:29: 
warning: 'clang::PointerAuthSchema::SelectedAuthenticationMode' is too small to 
hold all values of 'enum class clang::PointerAuthenticationMode'
   65 |   PointerAuthenticationMode SelectedAuthenticationMode : 2;
  | ^~
/root/llvm-project/clang/include/clang/Basic/PointerAuthOptions.h:66:18: 
warning: 'clang::PointerAuthSchema::DiscriminationKind' is too small to hold 
all values of 'enum class clang::PointerAuthSchema::Discrimination'
   66 |   Discrimination DiscriminationKind : 2;
  |  ^~
  ```
compiler-explorar pipe line builds it with GCC 9.2

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/99773

From ebf1c6996f18cbd706ec3d76a1887c58c9ce3230 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 20 Jul 2024 20:12:45 +0200
Subject: [PATCH] [clang-tidy] `bugprone-exception-escape` didn't detech
 catching of an exception with pointer type by `void *` exception handler

---
 .../clang-tidy/utils/ExceptionAnalyzer.cpp | 10 +-
 clang-tools-extra/docs/ReleaseNotes.rst|  4 
 .../checkers/bugprone/exception-escape.cpp | 18 ++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp 
b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index 6ae46e2b1262a..9bfb7e2677533 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -141,7 +141,10 @@ bool isStandardPointerConvertible(QualType From, QualType 
To) {
 if (RD->isCompleteDefinition() &&
 isBaseOf(From->getPointeeType().getTypePtr(),
  To->getPointeeType().getTypePtr())) {
-  return true;
+  // If B is an inaccessible or ambiguous base class of D, a program
+  // that necessitates this conversion is ill-formed
+  return isUnambiguousPublicBaseClass(From->getPointeeType().getTypePtr(),
+  To->getPointeeType().getTypePtr());
 }
   }
 
@@ -375,10 +378,7 @@ bool ExceptionAnalyzer::ExceptionInfo::filterByCatch(
 isPointerOrPointerToMember(ExceptionCanTy->getTypePtr())) {
   // A standard pointer conversion not involving conversions to pointers to
   // private or protected or ambiguous classes ...
-  if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy) &&
-  isUnambiguousPublicBaseClass(
-  ExceptionCanTy->getTypePtr()->getPointeeType().getTypePtr(),
-  HandlerCanTy->getTypePtr()->getPointeeType().getTypePtr())) {
+  if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy)) {
 TypesToDelete.push_back(ExceptionTy);
   }
   // A function pointer conversion ...
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index a23483e6df6d2..30228828686da 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -245,6 +245,10 @@ Changes in existing checks
   where source is already a ``void``` pointer, making middle ``void`` pointer
   casts bug-free.
 
+- Improved :doc:`exception-escape 
`
+  check to correctly detect exception handler of type ``CV void *`` as 
catching all 
+  ``CV`` compatible pointer types.
+
 - Improved :doc:`bugprone-forwarding-reference-overload
   `
   check to ignore deleted constructors which won't hide other overloads.
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
index f5e74df1621ce..26c443b139629 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
@@ -756,3 +756,21 @@ struct test_implicit_throw {
 };
 
 }}
+
+void pointer_exception_can_not_escape_with_const_void_handler() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown 
in function 'pointer_exception_can_not_escape_with_const_void_handler' which 
should not throw exceptions
+  const int value = 42;
+  try {
+throw &value;
+  } catch (const void *) {
+  }
+}
+
+void pointer_exception_can_not_escape_with_void_handler() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown 
in function 'pointer_exception_can_not_escape_with_void_handler' which should 
not throw exceptions
+  int value = 42;
+  try {
+throw &value;
+  } catch (void *) {
+  }
+}

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-21 Thread Hana Dusíková via cfe-commits


@@ -518,6 +518,10 @@ Changes in existing checks
   usages of ``std::string_view::compare``. Added a `StringLikeClasses` option
   to detect usages of ``compare`` method in custom string-like classes.
 
+- Improved :doc:`exception-escape 
`

hanickadot wrote:

Oh, silly me. I'm used to add release notes to  clang where they are added at 
the end of release notes. Will fix.

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-20 Thread Hana Dusíková via cfe-commits

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-20 Thread Hana Dusíková via cfe-commits

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-20 Thread Hana Dusíková via cfe-commits

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


[clang-tools-extra] [clang-tidy] `bugprone-exception-escape` didn't detech catching of an exception with pointer type by `void *` exception handler (PR #99773)

2024-07-20 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot created 
https://github.com/llvm/llvm-project/pull/99773

As in title, code which check eligibility of exceptions with pointer types to 
be handled by exception handler of type `void *` disallowed this case. It was 
check:

```c++
if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy) &&
  isUnambiguousPublicBaseClass(
  ExceptionCanTy->getTypePtr()->getPointeeType().getTypePtr(),
  HandlerCanTy->getTypePtr()->getPointeeType().getTypePtr())) {
```

but in `isUnambiguousPublicBaseClass` there was code which looked for 
definitions:

```c++
bool isUnambiguousPublicBaseClass(const Type *DerivedType,
  const Type *BaseType) {
  const auto *DerivedClass =
  DerivedType->getCanonicalTypeUnqualified()->getAsCXXRecordDecl();
  const auto *BaseClass =
  BaseType->getCanonicalTypeUnqualified()->getAsCXXRecordDecl();
  if (!DerivedClass || !BaseClass)
return false;
```

This code disallowed usage of `void *` type which was correctly detected in 
`isStandardPointerConvertible`.

AFAIK this seems like misinterpretation of specification:

> 14.4 Handling an exception
> a standard [pointer conversion](https://eel.is/c++draft/conv.ptr) not 
> involving conversions to pointers to private or protected or ambiguous classes
(https://eel.is/c++draft/except.handle#3.3.1)

and 

> 7.3.12 Pointer conversions
> ... If B is an inaccessible 
> ([[class.access]](https://eel.is/c++draft/class.access)) or ambiguous 
> ([[class.member.lookup]](https://eel.is/c++draft/class.member.lookup)) base 
> class of D, a program that necessitates this conversion is 
> ill-formed[.](https://eel.is/c++draft/conv.ptr#3.sentence-2) ...
(https://eel.is/c++draft/conv.ptr#3)

14.4 is carving out private, protected, and ambiguous base classes, but they 
are already carved out in 7.3.12 and implemented in 
`isStandardPointerConvertible`



From 3ea4f5d28e3183243f9aa9da1c264e5d70b16563 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 20 Jul 2024 20:12:45 +0200
Subject: [PATCH] [clang-tidy] `bugprone-exception-escape` didn't detech
 catching of an exception with pointer type by `void *` exception handler

---
 .../clang-tidy/utils/ExceptionAnalyzer.cpp | 10 +-
 clang-tools-extra/docs/ReleaseNotes.rst|  4 
 .../checkers/bugprone/exception-escape.cpp | 18 ++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp 
b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index 6ae46e2b1262a..9bfb7e2677533 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -141,7 +141,10 @@ bool isStandardPointerConvertible(QualType From, QualType 
To) {
 if (RD->isCompleteDefinition() &&
 isBaseOf(From->getPointeeType().getTypePtr(),
  To->getPointeeType().getTypePtr())) {
-  return true;
+  // If B is an inaccessible or ambiguous base class of D, a program
+  // that necessitates this conversion is ill-formed
+  return isUnambiguousPublicBaseClass(From->getPointeeType().getTypePtr(),
+  To->getPointeeType().getTypePtr());
 }
   }
 
@@ -375,10 +378,7 @@ bool ExceptionAnalyzer::ExceptionInfo::filterByCatch(
 isPointerOrPointerToMember(ExceptionCanTy->getTypePtr())) {
   // A standard pointer conversion not involving conversions to pointers to
   // private or protected or ambiguous classes ...
-  if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy) &&
-  isUnambiguousPublicBaseClass(
-  ExceptionCanTy->getTypePtr()->getPointeeType().getTypePtr(),
-  HandlerCanTy->getTypePtr()->getPointeeType().getTypePtr())) {
+  if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy)) {
 TypesToDelete.push_back(ExceptionTy);
   }
   // A function pointer conversion ...
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index a23483e6df6d2..8e8c0cd0cc3d8 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -518,6 +518,10 @@ Changes in existing checks
   usages of ``std::string_view::compare``. Added a `StringLikeClasses` option
   to detect usages of ``compare`` method in custom string-like classes.
 
+- Improved :doc:`exception-escape 
`
+  check to correctly detect exception handler of type `CV void *` as catching 
all 
+  `CV` compatible pointer types.
+
 Removed checks
 ^^
 
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
index f5e74df1621ce..26c443b139629 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
+++ b/clang-tools-ext

[clang] [clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) (PR #98756)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98756

From f308fee20b44b1a7f83ca0038acf7b43fdd46fa9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 20:59:22 +0200
Subject: [PATCH] [clang] constexpr atomic builtins (__c11_atomic_OP and
 __atomic_OP)

---
 clang/include/clang/Basic/Builtins.td |  80 +--
 clang/lib/AST/ExprConstant.cpp| 539 ++
 .../SemaCXX/atomic-constexpr-c11-builtins.cpp | 326 +++
 .../SemaCXX/atomic-constexpr-gcc-builtins.cpp | 504 
 4 files changed, 1409 insertions(+), 40 deletions(-)
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-c11-builtins.cpp
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-gcc-builtins.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..10a3f8e83cd59 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,133 +1785,133 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
-  le

[clang] [clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) (PR #98756)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98756

From 76fe494219d085247e537b3633c321ffe2917226 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 20:10:26 +0200
Subject: [PATCH 1/2] [clang] constexpr atomic builtins (__c11_atomic_OP and
 __atomic_OP)

---
 clang/include/clang/Basic/Builtins.td |  84 +--
 clang/lib/AST/ExprConstant.cpp| 528 ++
 .../SemaCXX/atomic-constexpr-c11-builtins.cpp | 288 ++
 .../SemaCXX/atomic-constexpr-gcc-builtins.cpp | 494 
 4 files changed, 1352 insertions(+), 42 deletions(-)
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-c11-builtins.cpp
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-gcc-builtins.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..0716cf02f5110 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,157 +1785,157 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
- 

[clang] [clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) (PR #98756)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98756

From 76fe494219d085247e537b3633c321ffe2917226 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 20:10:26 +0200
Subject: [PATCH] [clang] constexpr atomic builtins (__c11_atomic_OP and
 __atomic_OP)

---
 clang/include/clang/Basic/Builtins.td |  84 +--
 clang/lib/AST/ExprConstant.cpp| 528 ++
 .../SemaCXX/atomic-constexpr-c11-builtins.cpp | 288 ++
 .../SemaCXX/atomic-constexpr-gcc-builtins.cpp | 494 
 4 files changed, 1352 insertions(+), 42 deletions(-)
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-c11-builtins.cpp
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-gcc-builtins.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..0716cf02f5110 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,157 +1785,157 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
-  let

[clang] [clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) (PR #98756)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot created 
https://github.com/llvm/llvm-project/pull/98756

This implements clang support for P3309 constexpr std::atomic & std::atomic_ref 
(currently in LWG) by allowing constant evaluation of clang's __c11_atomic_OP 
and GCC's __atomic_OP builtins.

From e42b4a8877fed0096e44961235a61192ecb8e620 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 20:10:26 +0200
Subject: [PATCH] [clang] constexpr atomic builtins (__c11_atomic_OP and
 __atomic_OP)

---
 clang/include/clang/Basic/Builtins.td |  84 +--
 clang/lib/AST/ExprConstant.cpp| 553 +-
 .../SemaCXX/atomic-constexpr-c11-builtins.cpp | 288 +
 .../SemaCXX/atomic-constexpr-gcc-builtins.cpp | 494 
 4 files changed, 1371 insertions(+), 48 deletions(-)
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-c11-builtins.cpp
 create mode 100644 clang/test/SemaCXX/atomic-constexpr-gcc-builtins.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..0716cf02f5110 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,157 +1785,157 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [

[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

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


[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98738

From c691efa7649c990814bb363511106457e306aefa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 14:28:07 +0200
Subject: [PATCH] [clang] [libc++] atomic constexpr support

---
 clang/include/clang/Basic/Builtins.td |  84 ++--
 clang/lib/AST/ExprConstant.cpp| 449 +-
 libcxx/include/__atomic/atomic.h  |  89 +++--
 libcxx/include/__atomic/atomic_base.h |  76 ++--
 libcxx/include/__atomic/atomic_flag.h |  56 ++-
 libcxx/include/__atomic/atomic_ref.h  | 314 ++-
 libcxx/include/__atomic/cxx_atomic_impl.h |  77 ++--
 7 files changed, 871 insertions(+), 274 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..0716cf02f5110 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,157 +1785,157 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
-  let Attributes = [CustomTypeChec

[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98738

From 83645b161f62bbff2baf5a90eef2c6cd1b280180 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 13:12:24 +0200
Subject: [PATCH] [clang] [libc++] atomic constexpr support

---
 clang/include/clang/Basic/Builtins.td |  84 ++--
 clang/lib/AST/ExprConstant.cpp| 446 +-
 libcxx/include/__atomic/atomic.h  |  89 +++--
 libcxx/include/__atomic/atomic_base.h |  76 ++--
 libcxx/include/__atomic/atomic_flag.h |  56 ++-
 libcxx/include/__atomic/atomic_ref.h  | 324 +++-
 libcxx/include/__atomic/cxx_atomic_impl.h |  77 ++--
 7 files changed, 873 insertions(+), 279 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..0716cf02f5110 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,157 +1785,157 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
-  let Attributes = [CustomTypeChe

[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

@philnik777 I would rather not, at least for the review, manipulating two 
branches will be cumbersome. I can split it before merging, but as I don't 
expect this to happen soon, it should be fine.

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


[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/98738

From 63cefb0634ece515cbc1939c56d4fa2f0ef1eccf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jul 2024 13:12:24 +0200
Subject: [PATCH] [clang] [libc++] atomic constexpr support

---
 clang/include/clang/Basic/Builtins.td |  84 ++---
 clang/lib/AST/ExprConstant.cpp| 413 ++
 libcxx/include/__atomic/atomic.h  |  89 ++---
 libcxx/include/__atomic/atomic_base.h |  76 ++--
 libcxx/include/__atomic/atomic_flag.h |  56 +--
 libcxx/include/__atomic/atomic_ref.h  | 380 ++--
 libcxx/include/__atomic/cxx_atomic_impl.h |  79 +++--
 7 files changed, 896 insertions(+), 281 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f5b15cf90d1f8..0716cf02f5110 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1682,97 +1682,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate {
 // C11 _Atomic operations for .
 def C11AtomicInit : AtomicBuiltin {
   let Spellings = ["__c11_atomic_init"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicLoad : AtomicBuiltin {
   let Spellings = ["__c11_atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicStore : AtomicBuiltin {
   let Spellings = ["__c11_atomic_store"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicExchange : AtomicBuiltin {
   let Spellings = ["__c11_atomic_exchange"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeStrong : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_strong"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicCompareExchangeWeak : AtomicBuiltin {
   let Spellings = ["__c11_atomic_compare_exchange_weak"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAdd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_add"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchSub : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_sub"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchAnd : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_and"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchOr : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_or"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchXor : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_xor"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchNand : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_nand"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMax : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_max"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicFetchMin : AtomicBuiltin {
   let Spellings = ["__c11_atomic_fetch_min"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def C11AtomicThreadFence : Builtin {
   let Spellings = ["__c11_atomic_thread_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
 def C11AtomicSignalFence : Builtin {
   let Spellings = ["__c11_atomic_signal_fence"];
-  let Attributes = [NoThrow];
+  let Attributes = [NoThrow, Constexpr];
   let Prototype = "void(int)";
 }
 
@@ -1785,157 +1785,157 @@ def C11AtomicIsLockFree : Builtin {
 // GNU atomic builtins.
 def AtomicLoad : AtomicBuiltin {
   let Spellings = ["__atomic_load"];
-  let Attributes = [CustomTypeChecking];
+  let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
 def AtomicLoadN : AtomicBuiltin {
   let Spellings = ["__atomic_load_n"];
-  let Attributes = [CustomT

[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

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


[clang] [libcxx] [clang] [libc++] P3309 constexpr atomic and atomic ref [WIP] (PR #98738)

2024-07-13 Thread Hana Dusíková via cfe-commits

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


[clang] [Coverage] Suppress covmap and profdata for system headers. (PR #97952)

2024-07-07 Thread Hana Dusíková via cfe-commits

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

LGTM

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-06-13 Thread Hana Dusíková via cfe-commits

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


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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-06-13 Thread Hana Dusíková via cfe-commits


@@ -2122,20 +2135,70 @@ struct CounterCoverageMappingBuilder
  subtractCounters(ParentCount, TrueCount));
   }
 
-  void createDecision(const BinaryOperator *E) {
+  void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
 unsigned NumConds = MCDCBuilder.getTotalConditionsAndReset(E);
 if (NumConds == 0)
   return;
 
+// Extract [ID, Conds] to construct the graph.
+llvm::SmallVector CondIDs(NumConds);
+for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
+  if (SR.isMCDCBranch()) {
+auto [ID, Conds] = SR.getMCDCBranchParams();
+CondIDs[ID] = Conds;
+  }
+}
+
+// Construct the graph and calculate `Indices`.
+mcdc::TVIdxBuilder Builder(CondIDs);
+unsigned NumTVs = Builder.NumTestVectors;
+unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
+assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);

hanickadot wrote:

Than I would probably make it `!=`

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-06-13 Thread Hana Dusíková via cfe-commits


@@ -2122,20 +2135,70 @@ struct CounterCoverageMappingBuilder
  subtractCounters(ParentCount, TrueCount));
   }
 
-  void createDecision(const BinaryOperator *E) {
+  void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
 unsigned NumConds = MCDCBuilder.getTotalConditionsAndReset(E);
 if (NumConds == 0)
   return;
 
+// Extract [ID, Conds] to construct the graph.
+llvm::SmallVector CondIDs(NumConds);
+for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
+  if (SR.isMCDCBranch()) {
+auto [ID, Conds] = SR.getMCDCBranchParams();
+CondIDs[ID] = Conds;
+  }
+}
+
+// Construct the graph and calculate `Indices`.
+mcdc::TVIdxBuilder Builder(CondIDs);
+unsigned NumTVs = Builder.NumTestVectors;
+unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
+assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);

hanickadot wrote:

should it be `<=` or `<`?

I'm asking because `MaxTVs` seems like a count, not id

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-06-13 Thread Hana Dusíková via cfe-commits

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-06-13 Thread Hana Dusíková via cfe-commits


@@ -14416,7 +14416,7 @@ Syntax:
 ::
 
   declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr , i64 ,
-i32 )
+i32 )

hanickadot wrote:

I saw a pattern across whole PR where you replace bytes with bits ... is it 
intentional here to have the argument unused instead of something like 
 ?

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-06-13 Thread Hana Dusíková via cfe-commits


@@ -484,10 +484,31 @@ MC/DC Instrumentation
 -
 
 When instrumenting for Modified Condition/Decision Coverage (MC/DC) using the
-clang option ``-fcoverage-mcdc``, users are limited to at most **six** 
leaf-level
-conditions in a boolean expression.  A warning will be generated for boolean
-expressions that contain more than six, and they will not be instrumented for
-MC/DC.
+clang option ``-fcoverage-mcdc``, there are two hard limits.
+
+The maximum number of terms is limited to 32767, which is practical for
+handwritten expressions. To be more restrictive in order to enforce coding 
rules,
+use ``-Xclang -fmcdc-max-conditions=n``. Expressions with exceeded condition
+counts ``n`` will generate warnings.

hanickadot wrote:

add something like _"and the expression will be removed from MCDC coverage"_

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


[clang] [Coverage][Expansion] handle nested macros in scratch space (PR #89869)

2024-05-23 Thread Hana Dusíková via cfe-commits

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

lgtm

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


[clang] [Coverage] Rework !SystemHeadersCoverage (PR #91446)

2024-05-20 Thread Hana Dusíková via cfe-commits

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

LGTM

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

> @hanickadot Your comments to `llvm/CoverageMapping.cpp` are not for this PR. 
> See #80676 .
> 
> They are my preferences.

Didn't know the context, I saw it green as added. Just ignore it.

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits


@@ -223,9 +223,130 @@ Expected CounterMappingContext::evaluate(const 
Counter &C) const {
   return LastPoppedValue;
 }
 
+mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl &NextIDs,
+ int Offset)
+: Indices(NextIDs.size()) {
+  // Construct Nodes and set up each InCount
+  auto N = NextIDs.size();
+  SmallVector Nodes(N);
+  for (unsigned ID = 0; ID < N; ++ID) {
+for (unsigned C = 0; C < 2; ++C) {
+#ifndef NDEBUG
+  Indices[ID][C] = INT_MIN;
+#endif
+  auto NextID = NextIDs[ID][C];
+  Nodes[ID].NextIDs[C] = NextID;
+  if (NextID >= 0)
+++Nodes[NextID].InCount;
+}
+  }
+
+  // Sort key ordered by <-Width, Ord>
+  SmallVector>
+  Decisions;
+
+  // Traverse Nodes to assign Idx
+  SmallVector Q;
+  assert(Nodes[0].InCount == 0);
+  Nodes[0].Width = 1;
+  Q.push_back(0);
+
+  unsigned Ord = 0;
+  while (!Q.empty()) {
+auto IID = Q.begin();
+int ID = *IID;
+Q.erase(IID);
+auto &Node = Nodes[ID];
+assert(Node.Width > 0);
+
+for (unsigned I = 0; I < 2; ++I) {
+  auto NextID = Node.NextIDs[I];
+  assert(NextID != 0 && "NextID should not point to the top");
+  if (NextID < 0) {
+// Decision
+Decisions.emplace_back(-Node.Width, Ord++, ID, I);
+assert(Ord == Decisions.size());
+continue;
+  }
+
+  // Inter Node
+  auto &NextNode = Nodes[NextID];
+  assert(NextNode.InCount > 0);
+
+  // Assign Idx
+  assert(Indices[ID][I] == INT_MIN);
+  Indices[ID][I] = NextNode.Width;
+  auto NextWidth = int64_t(NextNode.Width) + Node.Width;
+  if (NextWidth > HardMaxTVs) {
+NumTestVectors = HardMaxTVs; // Overflow
+return;
+  }
+  NextNode.Width = NextWidth;
+
+  // Ready if all incomings are processed.
+  // Or NextNode.Width hasn't been confirmed yet.
+  if (--NextNode.InCount == 0)
+Q.push_back(NextID);
+}
+  }
+
+  std::sort(Decisions.begin(), Decisions.end());
+
+  // Assign TestVector Indices in Decision Nodes
+  int64_t CurIdx = 0;
+  for (auto [NegWidth, Ord, ID, C] : Decisions) {
+int Width = -NegWidth;

hanickadot wrote:

change it also here if you change Decision to a smallvector of defined struct 

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits


@@ -223,9 +223,130 @@ Expected CounterMappingContext::evaluate(const 
Counter &C) const {
   return LastPoppedValue;
 }
 
+mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl &NextIDs,
+ int Offset)
+: Indices(NextIDs.size()) {
+  // Construct Nodes and set up each InCount
+  auto N = NextIDs.size();
+  SmallVector Nodes(N);
+  for (unsigned ID = 0; ID < N; ++ID) {
+for (unsigned C = 0; C < 2; ++C) {
+#ifndef NDEBUG
+  Indices[ID][C] = INT_MIN;
+#endif
+  auto NextID = NextIDs[ID][C];
+  Nodes[ID].NextIDs[C] = NextID;
+  if (NextID >= 0)
+++Nodes[NextID].InCount;
+}
+  }
+
+  // Sort key ordered by <-Width, Ord>
+  SmallVector>
+  Decisions;
+
+  // Traverse Nodes to assign Idx
+  SmallVector Q;
+  assert(Nodes[0].InCount == 0);
+  Nodes[0].Width = 1;
+  Q.push_back(0);
+
+  unsigned Ord = 0;
+  while (!Q.empty()) {
+auto IID = Q.begin();
+int ID = *IID;
+Q.erase(IID);
+auto &Node = Nodes[ID];
+assert(Node.Width > 0);
+
+for (unsigned I = 0; I < 2; ++I) {
+  auto NextID = Node.NextIDs[I];
+  assert(NextID != 0 && "NextID should not point to the top");
+  if (NextID < 0) {
+// Decision
+Decisions.emplace_back(-Node.Width, Ord++, ID, I);

hanickadot wrote:

The negation shouldn't be here. It's error prone.

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits


@@ -1959,9 +2013,44 @@ struct CounterCoverageMappingBuilder
subtractCounters(ParentCount, TrueCount));
   }
 
+  void RewindDecision(unsigned Since) {
+#ifndef NDEBUG
+llvm::DenseSet SeenIDs;
+#endif
+unsigned NConds = 0;

hanickadot wrote:

move the `NConds` into `ifndef NDEBUG` block as it's just a sanity check

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits


@@ -223,9 +223,130 @@ Expected CounterMappingContext::evaluate(const 
Counter &C) const {
   return LastPoppedValue;
 }
 
+mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl &NextIDs,
+ int Offset)
+: Indices(NextIDs.size()) {
+  // Construct Nodes and set up each InCount
+  auto N = NextIDs.size();
+  SmallVector Nodes(N);
+  for (unsigned ID = 0; ID < N; ++ID) {
+for (unsigned C = 0; C < 2; ++C) {
+#ifndef NDEBUG
+  Indices[ID][C] = INT_MIN;
+#endif
+  auto NextID = NextIDs[ID][C];
+  Nodes[ID].NextIDs[C] = NextID;
+  if (NextID >= 0)
+++Nodes[NextID].InCount;
+}
+  }
+
+  // Sort key ordered by <-Width, Ord>
+  SmallVector>
+  Decisions;

hanickadot wrote:

I think this would be better as a defined struct with defined `operator<`, as 
this mandates inserting `-Width`  and negating it when reading just for sorting 
purposes. It will be error prone for future someone editing this code.

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot requested changes to this pull request.


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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits


@@ -723,7 +737,15 @@ struct MCDCCoverageBuilder {
 if (I == CondIDs.end())
   return -1;
 else
-  return I->second;
+  return I->second.ID;
+  }
+
+  void ccc(const Expr *CondExpr, mcdc::ConditionIDs IDs) {

hanickadot wrote:

this should be named differently, based on name I don't understand what it is 
doing

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


[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

2024-02-20 Thread Hana Dusíková via cfe-commits

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


[clang] [clang][CodeCoverage] Fix CoverageMapping for binary conditionals ops (PR #82141)

2024-02-18 Thread Hana Dusíková via cfe-commits


@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false 
-fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping 
-emit-llvm-only %s | FileCheck %s
+
+// CHECK-LABEL:   binary_conditional:
+// CHECK-NEXT:  File 0, [[@LINE+4]]:31 -> {{[0-9]+}}:2 = #0
+// CHECK-NEXT:  File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:8 = #0
+// CHECK-NEXT:  Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:8 = #1, 
(#0 - #1)
+// CHECK-NEXT:  File 0, [[@LINE+2]]:13 -> [[@LINE+2]]:14 = (#0 - #1)
+int binary_conditional(int x) {
+  x = x ? : 4;
+  int y = x;
+  return y;
+}
+
+// CHECK-LABEL:   tenary_conditional:
+// CHECK-NEXT:  File 0, [[@LINE+6]]:31 -> {{[0-9]+}}:2 = #0
+// CHECK-NEXT:  File 0, [[@LINE+6]]:7 -> [[@LINE+6]]:8 = #0
+// CHECK-NEXT:  Branch,File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:8 = #1, 
(#0 - #1)
+// CHECK-NEXT:  Gap,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #1
+// CHECK-NEXT:  File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:12 = #1
+// CHECK-NEXT:  File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:16 = (#0 - #1)
+int tenary_conditional(int x) {

hanickadot wrote:

Typo: s/tenary/ternary/

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


[clang] [clang][CodeCoverage] Fix CoverageMapping for binary conditionals ops (PR #82141)

2024-02-18 Thread Hana Dusíková via cfe-commits

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

Small typo in test. Otherwise LGTM

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


[clang] [clang][CodeCoverage] Fix CoverageMapping for binary conditionals ops (PR #82141)

2024-02-18 Thread Hana Dusíková via cfe-commits

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/80292

From 886cd32ef022fcb7c5a4604c5238074a54f78b96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Thu, 1 Feb 2024 22:20:44 +0100
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..f7f73546af017 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue =
+S->getCond()
+->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
+.getBoolValue();
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..445cdfc20e2af 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+  if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+  if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+  if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/80292

From af3118a1bbc071ec5d3a9d5b43cce66b0fe828e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Thu, 1 Feb 2024 22:20:44 +0100
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..f7f73546af017 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue =
+S->getCond()
+->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
+.getBoolValue();
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..445cdfc20e2af 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+  if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+  if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+  if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);

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


[llvm] [mlir] [clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/80292

From 4b2d3b7b8f04510f791e4d3cc68b2de5a273c735 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Thu, 1 Feb 2024 22:20:44 +0100
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..f7f73546af017 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue =
+S->getCond()
+->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
+.getBoolValue();
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..445cdfc20e2af 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+  if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+  if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+  if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits


@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+if constexpr (false_value{}) { };

hanickadot wrote:

Thanks!

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/80292

From 4b2d3b7b8f04510f791e4d3cc68b2de5a273c735 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Thu, 1 Feb 2024 22:20:44 +0100
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..f7f73546af017 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue =
+S->getCond()
+->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
+.getBoolValue();
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..445cdfc20e2af 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+  if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+  if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+  if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

> Changes LGTM, but please add a release note to `clang/docs/ReleaseNotes.rst` 
> so users know about the fix.
> 
> Thank you for the fix!

Even if it's a fix for recent PR I did few days ago?

Also, how do I get this into release branch (the previous change is there)?

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/80292

From f1dfd7fb2713f879de3532c903217b911b81db34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Thu, 1 Feb 2024 22:20:44 +0100
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..f7f73546af017 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue =
+S->getCond()
+->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
+.getBoolValue();
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..4de1467aa7ee3 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+   if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);

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


[openmp] [clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits


@@ -1808,12 +1808,24 @@ struct CounterCoverageMappingBuilder
 }
   }
 
+private:
+  static bool evaluateConstantCondition(const Expr *Condition) {
+if (const auto *Expr = dyn_cast(Condition))
+  return Expr->getResultAsAPSInt().getExtValue();
+
+if (const auto *Expr = dyn_cast(Condition))
+  return evaluateConstantCondition(Expr->getSubExpr()); // recursion
+
+assert(false && "Unexpected node in 'if constexpr' condition");
+return false;
+  }
+
+public:

hanickadot wrote:

Thanks!

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


[openmp] [clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits


@@ -1808,12 +1808,24 @@ struct CounterCoverageMappingBuilder
 }
   }
 
+private:
+  static bool evaluateConstantCondition(const Expr *Condition) {
+if (const auto *Expr = dyn_cast(Condition))
+  return Expr->getResultAsAPSInt().getExtValue();
+
+if (const auto *Expr = dyn_cast(Condition))
+  return evaluateConstantCondition(Expr->getSubExpr()); // recursion
+
+assert(false && "Unexpected node in 'if constexpr' condition");
+return false;
+  }
+
+public:

hanickadot wrote:

Ok it seems to work :)

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


[openmp] [clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/80292

From 84817eb419dfe0a66e8b4b1d21cf67cbc6b20199 Mon Sep 17 00:00:00 2001
From: Alexandre Ganea <37383324+aga...@users.noreply.github.com>
Date: Thu, 1 Feb 2024 08:14:05 -0500
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 openmp/cmake/HandleOpenMPOptions.cmake   |  8 +++
 3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..f7f73546af017 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue =
+S->getCond()
+->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
+.getBoolValue();
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..4de1467aa7ee3 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+   if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);
diff --git a/openmp/cmake/HandleOpenMPOptions.cmake 
b/openmp/cmake/HandleOpenMPOptions.cmake
index 201aeabbd3df9..71346201129b6 100644
--- a/openmp/cmake/HandleOpenMPOptions.cmake
+++ b/openmp/cmake/HandleOpenMPOptions.cmake
@@ -9,6 +9,14 @@ if (NOT COMMAND append_if)
   endfunction()
 endif()
 
+if (NOT COMMAND append)
+  function(append value)
+foreach(variable ${ARGN})
+  set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
+endforeach(variable)
+  endfunction()
+endif()
+
 # MSVC and clang-cl in compatibility mode map -Wall to -Weverything.
 # TODO: LLVM adds /W4 instead, check if that works for the OpenMP runtimes.
 if (NOT MSVC)

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits


@@ -1808,12 +1808,24 @@ struct CounterCoverageMappingBuilder
 }
   }
 
+private:
+  static bool evaluateConstantCondition(const Expr *Condition) {
+if (const auto *Expr = dyn_cast(Condition))
+  return Expr->getResultAsAPSInt().getExtValue();
+
+if (const auto *Expr = dyn_cast(Condition))
+  return evaluateConstantCondition(Expr->getSubExpr()); // recursion
+
+assert(false && "Unexpected node in 'if constexpr' condition");
+return false;
+  }
+
+public:

hanickadot wrote:

I'm still a bit new here and I'm confused... `CoverageMappingGen.cpp` doesn't 
have any mention of ASTContext which is an argument for functions mentioned by 
@efriedma-quic is there an easy way how to get it. Or do I need to go another 
direction?

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


[clang] [coverage] fix crash in code coverage and `if constexpr` with `ExprWithCleanups` (PR #80292)

2024-02-01 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot created 
https://github.com/llvm/llvm-project/pull/80292

Fixes https://github.com/llvm/llvm-project/issues/80285

From 84c3e120e04394d024851f30044de591cf1599e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Thu, 1 Feb 2024 14:34:16 +0100
Subject: [PATCH] [coverage] fix crash in code coverage and `if constexpr` with
 `ExprWithCleanups`

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 16 +++--
 clang/test/CoverageMapping/if.cpp| 29 
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8b5e6c4ad8272..6640fe6f41fd1 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1808,12 +1808,24 @@ struct CounterCoverageMappingBuilder
 }
   }
 
+private:
+  static bool evaluateConstantCondition(const Expr *Condition) {
+if (const auto *Expr = dyn_cast(Condition))
+  return Expr->getResultAsAPSInt().getExtValue();
+
+if (const auto *Expr = dyn_cast(Condition))
+  return evaluateConstantCondition(Expr->getSubExpr()); // recursion
+
+assert(false && "Unexpected node in 'if constexpr' condition");
+return false;
+  }
+
+public:
   void coverIfConstexpr(const IfStmt *S) {
 assert(S->isConstexpr());
 
 // evaluate constant condition...
-const auto *E = cast(S->getCond());
-const bool isTrue = E->getResultAsAPSInt().getExtValue();
+const bool isTrue = evaluateConstantCondition(S->getCond());
 
 extendRegion(S);
 
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index 3045ffe43948c..4de1467aa7ee3 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) {   
// CHECK-NEXT: [[@LINE
   return i;
 }
 
+struct false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+template  struct dependable_false_value {
+  constexpr operator bool() {
+return false;
+  }
+};
+
+// GH-80285
+void should_not_crash() {
+if constexpr (false_value{}) { };
+}
+
+template  void should_not_crash_dependable() {
+if constexpr (dependable_false_value{}) { };
+}
+
+void should_not_crash_with_template_instance() {
+  should_not_crash_dependable();
+}
+
+void should_not_crash_with_requires_expr() {
+   if constexpr (requires {42;}) { };
+}
+
 int instantiate_consteval(int i) {
   i *= check_consteval_with_else_discarded_then(i);
   i *= check_notconsteval_with_else_discarded_else(i);

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From e2e0ecab6693547938274ffa0a7f517cedf52205 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/9] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/9] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits


@@ -1700,43 +1776,116 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  markSkipped(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+markSkipped(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  markSkipped(S->getIfLoc(), Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  markSkipped(startOfSkipped, getStart(Init));
+  propagateCounts(ParentCount, Init);
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(Init);

hanickadot wrote:

test added :) it catched a crash as for some reason `using foo = int` there 
doesn't have right source location

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


[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/8] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e8..0f0f0459406fb32 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations o

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/7] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e8..0f0f0459406fb32 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations o

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/6] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e8..0f0f0459406fb32 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations o

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits


@@ -1251,6 +1264,69 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {

hanickadot wrote:

it's a pattern used thru whole `CoverageMappingGen.cpp` file, it's copied and 
modified existing functions for calculating Gap regions, so I would rather not

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


[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/5] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits


@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }

hanickadot wrote:

SkippedRegions are also created by preprocessor for comments and whitespaces, 
then they are squeezed out of line with any coverage. This patch allows making 
them also while walking AST and fixes `LineCoverageStats` to properly show such 
lines as mapped.

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits


@@ -1700,43 +1776,116 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  markSkipped(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+markSkipped(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  markSkipped(S->getIfLoc(), Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  markSkipped(startOfSkipped, getStart(Init));
+  propagateCounts(ParentCount, Init);
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(Init);

hanickadot wrote:

yes, and it will be dealt as with declaration, in `propagateCounts` it will 
recurse into it

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/7] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/6] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-22 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/5] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/4] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/3] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e8..0f0f0459406fb32 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations o

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits


@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,

hanickadot wrote:

this is modified function `findGapAreaBetween` but we need to start at 
StartingLoc, not after

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits


@@ -1700,43 +1777,116 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  markSkipped(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+markSkipped(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  markSkipped(S->getIfLoc(), Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  markSkipped(startOfSkipped, getStart(Init));
+  propagateCounts(ParentCount, Init);
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(Init);
+}
+
+if (isTrue) {
+  // ignore ')'
+  markSkipped(startOfSkipped, getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else)
+// ignore 'else '
+markSkipped(getEnd(Then), getEnd(Else));
+} else {
+  // ignore ')  [else]'
+  markSkipped(startOfSkipped, Else ? getStart(Else) : getEnd(Then));
+
+  if (Else) {
+propagateCounts(ParentCount, Else);
+  }
+}
+  }
+
   void VisitIfStmt(const IfStmt *S) {
+// "if constexpr" and "if consteval" are not normal conditional statements,
+// they should behave more like a preprocessor conditions
+if (S->isConsteval())
+  return CoverIfConsteval(S);
+else if (S->isConstexpr())
+  return CoverIfConstexpr(S);

hanickadot wrote:

I did this dispatch here to keep `if` part clean, as `if consteval` and `if 
constexpr` have closer to "preprocessor" than runtime `if`.

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits


@@ -90,10 +90,10 @@ bool for_7(bool a) {   // MCDC: Decision,File 0, 
[[@LINE+1]]:10 -> [[@LINE+1
 }  // CHECK: Branch,File 0, [[@LINE-1]]:15 -> 
[[@LINE-1]]:19 = 0, 0
 
 // CHECK-LABEL: _Z5for_8b:
-bool for_8(bool a) {   // MCDC: Decision,File 0, [[@LINE+3]]:17 -> 
[[@LINE+3]]:30 = M:0, C:2
-   // CHECK: Branch,File 0, [[@LINE+2]]:17 -> 
[[@LINE+2]]:21 = 0, 0
-   // CHECK: Branch,File 0, [[@LINE+1]]:25 -> 
[[@LINE+1]]:30 = 0, 0
-  if constexpr (true && false)

hanickadot wrote:

`if constexpr` is not a branch now

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH 1/2] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of 

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

I kept the whitespace in front of `if constexpr` and `if consteval` marked as 
uncovered in case whole region containing the ifs is uncovered. It's an 
esthetic thing and I will do it with a next patch to limit scope of this one.

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


[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

I deleted the screenshot showing skipped whitespace regions as I reverted that 
part of the patch.

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


[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From ae319fd34659c1373ce573346b93ffaa290a3312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Mon, 22 Jan 2024 00:00:43 +0100
Subject: [PATCH] [coverage] skipping code coverage for 'if constexpr' and 'if
 consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 212 +++---
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 138 
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 +-
 5 files changed, 317 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..0f0f0459406fb3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,70 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Find a valid range starting with \p StartingLoc and ending before \p
+  /// BeforeLoc.
+  std::optional findAreaStartingFromTo(SourceLocation StartingLoc,
+SourceLocation BeforeLoc) {
+// If StartingLoc is in function-like macro, use its start location.
+if (StartingLoc.isMacroID()) {
+  FileID FID = SM.getFileID(StartingLoc);
+  const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+  if (EI->isFunctionMacroExpansion())
+StartingLoc = EI->getExpansionLocStart();
+}
+
+size_t StartDepth = locationDepth(StartingLoc);
+size_t EndDepth = locationDepth(BeforeLoc);
+while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+  bool UnnestStart = StartDepth >= EndDepth;
+  bool UnnestEnd = EndDepth >= StartDepth;
+  if (UnnestEnd) {
+assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+  BeforeLoc));
+
+BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+assert(BeforeLoc.isValid());
+EndDepth--;
+  }
+  if (UnnestStart) {
+assert(SM.isWrittenInSameFile(StartingLoc,
+  getStartOfFileOrMacro(StartingLoc)));
+
+StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+assert(StartingLoc.isValid());
+StartDepth--;
+  }
+}
+// If the start and end locations of the 

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 587228bf8c59813f70b9cfbc42a88076027e1422 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sun, 21 Jan 2024 23:13:55 +0100
Subject: [PATCH 1/3] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 167 ++
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 119 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 ++-
 5 files changed, 253 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e8..ff5bc6941cc5c85 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,23 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1700,43 +1730,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 587228bf8c59813f70b9cfbc42a88076027e1422 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sun, 21 Jan 2024 23:13:55 +0100
Subject: [PATCH 1/2] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 167 ++
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 119 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 ++-
 5 files changed, 253 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..ff5bc6941cc5c8 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,23 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1700,43 +1730,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+  

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 587228bf8c59813f70b9cfbc42a88076027e1422 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sun, 21 Jan 2024 23:13:55 +0100
Subject: [PATCH] [coverage] skipping code coverage for 'if constexpr' and 'if
 consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 167 ++
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 119 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  14 +-
 .../ProfileData/CoverageMappingTest.cpp   |  24 ++-
 5 files changed, 253 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e8..ff5bc6941cc5c85 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,12 +119,16 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch, or anything skipped but not empty line / comments)
+  bool SkippedRegion;
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
   bool GapRegion = false)
-  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) 
{
-  }
+  : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(Counter Count, std::optional FalseCount,
   MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ class SourceMappingRegion {
   std::optional LocEnd,
   bool GapRegion = false)
   : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
-LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+SkippedRegion(false) {}
 
   SourceMappingRegion(MCDCParameters MCDCParams,
   std::optional LocStart,
   std::optional LocEnd)
   : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
-GapRegion(false) {}
+GapRegion(false), SkippedRegion(false) {}
 
   const Counter &getCounter() const { return Count; }
 
@@ -174,6 +179,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1264,23 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1700,43 +1730,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 91fb9a16769253658d4f770b326cae9e9fe0eef9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sun, 21 Jan 2024 23:07:15 +0100
Subject: [PATCH 1/2] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 158 ++
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 119 -
 .../ProfileData/Coverage/CoverageMapping.cpp  |  12 +-
 .../ProfileData/CoverageMappingTest.cpp   |  21 ++-
 5 files changed, 243 insertions(+), 75 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..89afecaa48edc3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1263,23 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1700,43 +1729,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  find

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-21 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 91fb9a16769253658d4f770b326cae9e9fe0eef9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sun, 21 Jan 2024 23:07:15 +0100
Subject: [PATCH] [coverage] skipping code coverage for 'if constexpr' and 'if
 consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 158 ++
 .../CoverageMapping/branch-constfolded.cpp|   8 +-
 clang/test/CoverageMapping/if.cpp | 119 -
 .../ProfileData/Coverage/CoverageMapping.cpp  |  12 +-
 .../ProfileData/CoverageMappingTest.cpp   |  21 ++-
 5 files changed, 243 insertions(+), 75 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4a44d113ddec9e..89afecaa48edc3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1251,6 +1263,23 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1700,43 +1729,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  findGapA

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

I was able to get rid of empty regions in front of `if constexpr` by checking 
if the region contains only whitespace characters in llvm-cov (not happy about 
it) so if someone know better. Please do help me.

![coverage-before 
copy](https://github.com/llvm/llvm-project/assets/6557263/fa36f22b-5a0f-4252-8b63-4ccb6275e80f)


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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From efcab4def5ed135f84791d5569081cbe750f57d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jan 2024 23:27:07 +0100
Subject: [PATCH 1/2] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 164 +++---
 .../ProfileData/Coverage/CoverageMapping.cpp  |  65 ++-
 2 files changed, 200 insertions(+), 29 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f4a..7e02c4fbac1efb 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1252,6 +1264,29 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+// const std::optional Gap = findGapAreaBetween(AfterLoc,
+// BeforeLoc);
+//
+// if (Gap) {
+//   markSkipArea(Gap->getBegin(), Gap->getEnd());
+// }
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1701,43 +1736,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  fin

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From efcab4def5ed135f84791d5569081cbe750f57d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jan 2024 23:27:07 +0100
Subject: [PATCH] [coverage] skipping code coverage for 'if constexpr' and 'if
 consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 164 +++---
 .../ProfileData/Coverage/CoverageMapping.cpp  |  65 ++-
 2 files changed, 200 insertions(+), 29 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f4a..7e02c4fbac1efb 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1252,6 +1264,29 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+// const std::optional Gap = findGapAreaBetween(AfterLoc,
+// BeforeLoc);
+//
+// if (Gap) {
+//   markSkipArea(Gap->getBegin(), Gap->getEnd());
+// }
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1701,43 +1736,118 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  propagateCounts(ParentCount, Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+propagateCounts(ParentCount, Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Init = S->getInit();
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// I'm using 'propagateCounts' later as new region is better and allows me
+// to properly calculate line coverage in llvm-cov utility
+const Counter ParentCount = getRegion().getCounter();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (Init) {
+  // don't mark initialisation as ignored
+  findGap

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

I need to skip the whitespace before `if constexpr` and `if consteval` (in 
circles).
![coverage-before-after](https://github.com/llvm/llvm-project/assets/6557263/77a58cea-47c7-472a-91d0-6d1c2e34a3c6)


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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 7e09f8a2dc9026047d34e0d6f4f55df9ab196fc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jan 2024 14:54:21 +0100
Subject: [PATCH 1/3] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 154 ++
 .../ProfileData/Coverage/CoverageMapping.cpp  |  15 +-
 2 files changed, 138 insertions(+), 31 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f4a..c476ffa6305da2 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1252,6 +1264,29 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+// const std::optional Gap = findGapAreaBetween(AfterLoc,
+// BeforeLoc);
+//
+// if (Gap) {
+//   markSkipArea(Gap->getBegin(), Gap->getEnd());
+// }
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1701,43 +1736,108 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  Visit(Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+Visit(Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (S->getInit()) {
+  // don't mark initialisation as ignored
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, 
getStart(S->getInit()));
+  Visit(S->getInit());
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(S->getInit());
+}
+
+if (isTrue) {
+  // ignore ')'
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, getStart(Then));
+  Visit(Then);
+
+  if (Else)
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+} else {
+  // ignore ')  

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 7e09f8a2dc9026047d34e0d6f4f55df9ab196fc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jan 2024 14:54:21 +0100
Subject: [PATCH 1/2] [coverage] skipping code coverage for 'if constexpr' and
 'if consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 154 ++
 .../ProfileData/Coverage/CoverageMapping.cpp  |  15 +-
 2 files changed, 138 insertions(+), 31 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f4a..c476ffa6305da2 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1252,6 +1264,29 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+// const std::optional Gap = findGapAreaBetween(AfterLoc,
+// BeforeLoc);
+//
+// if (Gap) {
+//   markSkipArea(Gap->getBegin(), Gap->getEnd());
+// }
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1701,43 +1736,108 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  Visit(Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+Visit(Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (S->getInit()) {
+  // don't mark initialisation as ignored
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, 
getStart(S->getInit()));
+  Visit(S->getInit());
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(S->getInit());
+}
+
+if (isTrue) {
+  // ignore ')'
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, getStart(Then));
+  Visit(Then);
+
+  if (Else)
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+} else {
+  // ignore ')  

[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

(still needs some polishing)
![coverage-compare](https://github.com/llvm/llvm-project/assets/6557263/b62fae27-ca7a-4f48-9d16-d04a25262ea6)


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


[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

![coverage-change](https://github.com/llvm/llvm-project/assets/6557263/f4d8ea72-a197-4fe5-8f1e-254e44fde0c1)


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


[llvm] [clang] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

hanickadot wrote:

![coverage-change-if-constexpr](https://github.com/llvm/llvm-project/assets/6557263/7c579d4f-0f14-4c7e-b9af-b0ec15b389ee)


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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/78033

From 7e09f8a2dc9026047d34e0d6f4f55df9ab196fc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jan 2024 14:54:21 +0100
Subject: [PATCH] [coverage] skipping code coverage for 'if constexpr' and 'if
 consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 154 ++
 .../ProfileData/Coverage/CoverageMapping.cpp  |  15 +-
 2 files changed, 138 insertions(+), 31 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f4a..c476ffa6305da2 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1252,6 +1264,29 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+// const std::optional Gap = findGapAreaBetween(AfterLoc,
+// BeforeLoc);
+//
+// if (Gap) {
+//   markSkipArea(Gap->getBegin(), Gap->getEnd());
+// }
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1701,43 +1736,108 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  Visit(Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+Visit(Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (S->getInit()) {
+  // don't mark initialisation as ignored
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, 
getStart(S->getInit()));
+  Visit(S->getInit());
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(S->getInit());
+}
+
+if (isTrue) {
+  // ignore ')'
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, getStart(Then));
+  Visit(Then);
+
+  if (Else)
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+} else {
+  // ignore ')  [els

[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

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


[clang] [llvm] [coverage] skipping code coverage for 'if constexpr' and 'if consteval' [WIP] (PR #78033)

2024-01-13 Thread Hana Dusíková via cfe-commits

https://github.com/hanickadot created 
https://github.com/llvm/llvm-project/pull/78033

`if constexpr` and `if consteval` conditional statements code coverage should 
behave more like a preprocesor `#if`-s than normal ConditionalStmt. This PR 
should fix that.

From 50856e444d4fd9dc92dab34ed8ad302671ce3716 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= 
Date: Sat, 13 Jan 2024 14:41:21 +0100
Subject: [PATCH] [coverage] skipping code coverage for 'if constexpr' and 'if
 consteval'

---
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 151 ++
 .../ProfileData/Coverage/CoverageMapping.cpp  |  12 +-
 2 files changed, 132 insertions(+), 31 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f4a..7e3d2b76b8646b 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -119,6 +119,10 @@ class SourceMappingRegion {
   /// as the line execution count if there are no other regions on the line.
   bool GapRegion;
 
+  /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+  /// branch)
+  bool SkippedRegion{false};
+
 public:
   SourceMappingRegion(Counter Count, std::optional LocStart,
   std::optional LocEnd,
@@ -174,6 +178,10 @@ class SourceMappingRegion {
 
   void setGap(bool Gap) { GapRegion = Gap; }
 
+  bool isSkipped() const { return SkippedRegion; }
+
+  void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +476,10 @@ class CoverageMappingBuilder {
 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
 SR.LineEnd, SR.ColumnEnd));
+  } else if (Region.isSkipped()) {
+MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+*CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+SR.ColumnEnd));
   } else if (Region.isBranch()) {
 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
 Region.getCounter(), Region.getFalseCounter(),
@@ -1252,6 +1264,29 @@ struct CounterCoverageMappingBuilder
 popRegions(Index);
   }
 
+  /// Emit a skip region between \p StartLoc and \p EndLoc with the given 
count.
+  void markSkipArea(SourceLocation StartLoc, SourceLocation EndLoc) {
+if (StartLoc == EndLoc)
+  return;
+assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+handleFileExit(StartLoc);
+size_t Index = pushRegion({}, StartLoc, EndLoc);
+getRegion().setSkipped(true);
+handleFileExit(EndLoc);
+popRegions(Index);
+  }
+
+  void findGapAreaBetweenAndMarkSkipArea(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+// const std::optional Gap = findGapAreaBetween(AfterLoc,
+// BeforeLoc);
+//
+// if (Gap) {
+//   markSkipArea(Gap->getBegin(), Gap->getEnd());
+// }
+markSkipArea(AfterLoc, BeforeLoc);
+  }
+
   /// Keep counts of breaks and continues inside loops.
   struct BreakContinue {
 Counter BreakCount;
@@ -1701,43 +1736,106 @@ struct CounterCoverageMappingBuilder
 Visit(S->getSubStmt());
   }
 
+  void CoverIfConsteval(const IfStmt *S) {
+assert(S->isConsteval());
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+extendRegion(S);
+
+if (S->isNegatedConsteval()) {
+  // ignore 'if consteval'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(), getStart(Then));
+  Visit(Then);
+
+  if (Else) {
+// ignore 'else '
+findGapAreaBetweenAndMarkSkipArea(getEnd(Then), getEnd(Else));
+  }
+} else {
+  assert(S->isNonNegatedConsteval());
+  // ignore 'if consteval  [else]'
+  findGapAreaBetweenAndMarkSkipArea(S->getIfLoc(),
+Else ? getStart(Else) : getEnd(Then));
+
+  if (Else)
+Visit(Else);
+}
+  }
+
+  void CoverIfConstexpr(const IfStmt *S) {
+assert(S->isConstexpr());
+
+// evaluate constant condition...
+const auto *E = dyn_cast(S->getCond());
+assert(E != nullptr);
+const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+extendRegion(S);
+
+const auto *Then = S->getThen();
+const auto *Else = S->getElse();
+
+// ignore 'if constexpr ('
+SourceLocation startOfSkipped = S->getIfLoc();
+
+if (S->getInit()) {
+  // don't mark initialisation as ignored
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, 
getStart(S->getInit()));
+  Visit(S->getInit());
+  // ignore after initialisation: '; )'...
+  startOfSkipped = getEnd(S->getInit());
+}
+
+if (isTrue) {
+  // ignore ')'
+  findGapAreaBetweenAndMarkSkipArea(startOfSkipped, getStart(Then));
+  

  1   2   >