diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 68e6457419ab1..426ac39b8767e 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1566,6 +1566,15 @@ struct CounterCoverageMappingBuilder // Lambdas are treated as their own functions for now, so we shouldn't // propagate counts into them. } + + void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { + // Just visit syntatic expression as this is what users actually write. + VisitStmt(POE->getSyntacticForm()); + } + + void VisitOpaqueValueExpr(const OpaqueValueExpr* OVE) { + Visit(OVE->getSourceExpr()); + } }; } // end anonymous namespace diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp index de3554c100b96..f477db980e7f4 100644 --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -1,6 +1,14 @@ -// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++2b -triple %itanium_abi_triple -main-file-name if.cpp %s | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++2b -triple %itanium_abi_triple -main-file-name if.cpp %s | FileCheck %s int nop() { return 0; } +struct S { + int i; + int putprop(int j) { + i = j; + return i; + } + __declspec(property(put = putprop)) int the_prop; +}; // CHECK-LABEL: _Z3foov: // CHECK-NEXT: [[@LINE+3]]:12 -> [[@LINE+8]]:2 = #0 @@ -70,7 +78,17 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = constexpr int c_i = check_consteval(0); check_consteval(i); - return 0; + // GH-45481 + S s; + s.the_prop = 0? 1 : 2; // CHECK-NEXT: File 0, [[@LINE]]:16 -> [[@LINE]]:17 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:17 = 0, 0 + // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:18 -> [[@LINE-2]]:19 = #7 + // CHECK-NEXT: File 0, [[@LINE-3]]:19 -> [[@LINE-3]]:20 = #7 + // CHECK-NEXT: File 0, [[@LINE-4]]:23 -> [[@LINE-4]]:24 = (#0 - #7) + if (s.the_prop = 1) { // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:21 = #0 + return 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:21 = #8, (#0 - #8) + } // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:22 -> [[@LINE-2]]:23 = #8 + // CHECK-NEXT: File 0, [[@LINE-3]]:23 -> [[@LINE-1]]:4 = #8 } #define FOO true diff --git a/clang/test/CoverageMapping/strong_order.cpp b/clang/test/CoverageMapping/strong_order.cpp new file mode 100644 index 0000000000000..ebda311d2489b --- /dev/null +++ b/clang/test/CoverageMapping/strong_order.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++2b -triple %itanium_abi_triple -main-file-name if.cpp %s + +// No crash for following example. +// See https://github.com/llvm/llvm-project/issues/45481 +namespace std { +class strong_ordering; + +// Mock how STD defined unspecified parameters for the operators below. +struct _CmpUnspecifiedParam { + consteval + _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} +}; + +struct strong_ordering { + signed char value; + + friend constexpr bool operator==(strong_ordering v, + _CmpUnspecifiedParam) noexcept { + return v.value == 0; + } + friend constexpr bool operator<(strong_ordering v, + _CmpUnspecifiedParam) noexcept { + return v.value < 0; + } + friend constexpr bool operator>(strong_ordering v, + _CmpUnspecifiedParam) noexcept { + return v.value > 0; + } + friend constexpr bool operator>=(strong_ordering v, + _CmpUnspecifiedParam) noexcept { + return v.value >= 0; + } + static const strong_ordering equal, greater, less; +}; +constexpr strong_ordering strong_ordering::equal = {0}; +constexpr strong_ordering strong_ordering::greater = {1}; +constexpr strong_ordering strong_ordering::less = {-1}; +} // namespace std + +struct S { + friend bool operator<(const S&, const S&); + friend bool operator==(const S&, const S&); +}; + +struct MyStruct { + friend bool operator==(MyStruct const& lhs, MyStruct const& rhs) = delete; + friend std::strong_ordering operator<=>(MyStruct const& lhs, MyStruct const& rhs) = default; + S value; +}; + +void foo(MyStruct bar){ + (void)(bar <=> bar); +}