[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)); +