r330808 - add check for long double for __builtin_dump_struct
Author: paulsemel Date: Wed Apr 25 03:09:20 2018 New Revision: 330808 URL: http://llvm.org/viewvc/llvm-project?rev=330808&view=rev Log: add check for long double for __builtin_dump_struct Modified: cfe/trunk/test/CodeGen/dump-struct-builtin.c Modified: cfe/trunk/test/CodeGen/dump-struct-builtin.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/dump-struct-builtin.c?rev=330808&r1=330807&r2=330808&view=diff == --- cfe/trunk/test/CodeGen/dump-struct-builtin.c (original) +++ cfe/trunk/test/CodeGen/dump-struct-builtin.c Wed Apr 25 03:09:20 2018 @@ -107,6 +107,12 @@ // CHECK-NEXT: [[FORMAT_U17:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%hhd\0A\00" // CHECK-NEXT: [[END_STRUCT_U17:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00" +// CHECK: @unit18.a = private unnamed_addr constant %struct.U18A { x86_fp80 0xK3FFF8FCD67FD3F5B6000 }, align 16 +// CHECK-NEXT: [[STRUCT_STR_U18:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U18A {\0A\00" +// CHECK-NEXT: [[FIELD_U18:@[0-9]+]] = private unnamed_addr constant [17 x i8] c"long double a : \00" +// CHECK-NEXT: [[FORMAT_U18:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%Lf\0A\00" +// CHECK-NEXT: [[END_STRUCT_U18:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00" + int printf(const char *fmt, ...) { return 0; } @@ -417,6 +423,24 @@ void unit17() { __builtin_dump_struct(&a, &printf); } +void unit18() { + struct U18A { +long double a; + }; + + struct U18A a = { + .a = 1.123456, + }; + + // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U18]], i32 0, i32 0)) + // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U18A, %struct.U18A* %a, i32 0, i32 0 + // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* [[FIELD_U18]], i32 0, i32 0)) + // CHECK: [[LOAD1:%[0-9]+]] = load x86_fp80, x86_fp80* [[RES1]], + // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[FORMAT_U18]], i32 0, i32 0), x86_fp80 [[LOAD1]]) + // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U18]], i32 0, i32 0) + __builtin_dump_struct(&a, &printf); +} + void test1() { struct T1A { int a; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXForRangeStmt should extend flow condition (PR #80989)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80989 >From 9cbe0ef60f0154cbbefaa7d3092d65e4a4ab4d2a Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 13:06:40 + Subject: [PATCH] [dataflow] CXXForRangeStmt should extend flow condition This is needed in order to correctly assume implicit iterator validity in the iterator checker. --- .../TypeErasedDataflowAnalysis.cpp| 9 +--- .../TypeErasedDataflowAnalysisTest.cpp| 21 +++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 4c88c46142d64d..f02c65094113ec 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -103,9 +103,12 @@ class TerminatorVisitor return {nullptr, false}; } - TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) { -// Don't do anything special for CXXForRangeStmt, because the condition -// (being implicitly generated) isn't visible from the loop body. + TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *S) { +// Even though the condition isn't visible from the loop body, analysis +// might depend on the implicit implicit statements implied by the loop. +auto *Cond = S->getCond(); +if (Cond != nullptr) + return extendFlowCondition(*Cond); return {nullptr, false}; } diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index 3bca9cced8d6f7..b940fb876710c2 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -1710,4 +1710,25 @@ TEST_F(TopTest, ForRangeStmtConverges) { // analysis converged. }); } + +TEST_F(TopTest, ForRangeStmtHasFlowCondition) { + std::string Code = R"( +#include +void target(bool Foo) { + std::array t; + for (auto& i : t) { +(void)0; +/*[[p1]]*/ + } +} + )"; + runDataflow(Code, + [](const llvm::StringMap> &Results, + const AnalysisOutputs &AO) { + ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); + const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); + ASSERT_TRUE(Env1.proves(Env1.arena().makeAtomRef(Env1.getFlowConditionToken(; + }); +} + } // namespace ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXForRangeStmt should extend flow condition (PR #80989)
@@ -1710,4 +1710,25 @@ TEST_F(TopTest, ForRangeStmtConverges) { // analysis converged. }); } + +TEST_F(TopTest, ForRangeStmtHasFlowCondition) { + std::string Code = R"( +#include +void target(bool Foo) { + std::array t; + for (auto& i : t) { +(void)0; +/*[[p1]]*/ + } +} + )"; + runDataflow(Code, + [](const llvm::StringMap> &Results, + const AnalysisOutputs &AO) { + ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); + const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); + ASSERT_TRUE(Env1.proves(Env1.arena().makeAtomRef(Env1.getFlowConditionToken(; + }); +} paulsemel wrote: Would this test work @martinboehme ? https://github.com/llvm/llvm-project/pull/80989 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel created https://github.com/llvm/llvm-project/pull/80970 None >From e56ced76e19d57a020030ab41a125012460d08d7 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 10:26:23 + Subject: [PATCH] [dataflow] Fix crash when InitListExpr is not a prvalue --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 6 ++ .../Analysis/FlowSensitive/TransferTest.cpp| 14 ++ 2 files changed, 20 insertions(+) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29c..dc0f1bd6dcc29 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -648,6 +648,12 @@ class TransferVisitor : public ConstStmtVisitor { QualType Type = S->getType(); if (!Type->isStructureOrClassType()) { + // It is possible that InitListExpr is not a prvalue, in which case + // `setValue` will fail. In this case, we can just let the next + // transfer function handle the value creation. + if (!S->isPRValue()) +return; + if (auto *Val = Env.createValue(Type)) Env.setValue(*S, *Val); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce..74e6f1abfa4ba 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,20 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, InitListExprAsXValue) { + // This is a crash repro. + std::string Code = R"( +void target() { + auto&& test{false}; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXForRangeStmt should extend flow condition (PR #80989)
https://github.com/paulsemel created https://github.com/llvm/llvm-project/pull/80989 This is needed in order to correctly assume implicit iterator validity in the iterator checker. >From b227aa82732cdc087ead5df62077055042d22696 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 13:06:40 + Subject: [PATCH] [dataflow] CXXForRangeStmt should extend flow condition This is needed in order to correctly assume implicit iterator validity in the iterator checker. --- .../FlowSensitive/TypeErasedDataflowAnalysis.cpp | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 4c88c46142d64d..f02c65094113ec 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -103,9 +103,12 @@ class TerminatorVisitor return {nullptr, false}; } - TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) { -// Don't do anything special for CXXForRangeStmt, because the condition -// (being implicitly generated) isn't visible from the loop body. + TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *S) { +// Even though the condition isn't visible from the loop body, analysis +// might depend on the implicit implicit statements implied by the loop. +auto *Cond = S->getCond(); +if (Cond != nullptr) + return extendFlowCondition(*Cond); return {nullptr, false}; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue (PR #80991)
https://github.com/paulsemel created https://github.com/llvm/llvm-project/pull/80991 Although in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated. >From 4aad70021b0cda8613f8944a6900fb71e55838e3 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 13:59:40 + Subject: [PATCH] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue Although in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated. --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 14 +++- .../Analysis/FlowSensitive/TransferTest.cpp | 36 +++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29ca..fb1c6848197339 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -535,7 +535,19 @@ class TransferVisitor : public ConstStmtVisitor { return; copyRecord(*LocSrc, *LocDst, Env); - Env.setStorageLocation(*S, *LocDst); + + // If the expr is a glvalue, we can reasonably assume the operator is + // returning T& and thus we can assign it `LocDst`. + if (S->isGLValue()) { +Env.setStorageLocation(*S, *LocDst); + } else if (S->getType()->isRecordType() && S->isPRValue()) { +// If the expr is a prvalue, we cannot really assume anything regarding +// the new value being created. We should just propagate it to ensure a +// `RecordValue` exist for it. +if (Env.getValue(*S) == nullptr) + refreshRecordValue(*S, Env); + } + return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce6..86f4081c798d55 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,42 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, CXXOperatorCallExprEqualReturnsVoid) { + // This is a crash repro. + std::string Code = R"( +struct B { + void operator=(B&& other); +}; +void target() { + B b; + b = B(); + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + +TEST(TransferTest, CXXOperatorCallExprEqualReturnsPRValue) { + // This is a crash repro. + std::string Code = R"( +struct B { + B operator=(B&& other); +}; +void target() { + B b; + b = B(); + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue (PR #80991)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80991 >From 0d03870ef82fac51387c353bbe4e095e431d7ce8 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 13:59:40 + Subject: [PATCH] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue Although in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated. --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 14 +++- .../Analysis/FlowSensitive/TransferTest.cpp | 36 +++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29c..d73c9d2513627 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -535,7 +535,19 @@ class TransferVisitor : public ConstStmtVisitor { return; copyRecord(*LocSrc, *LocDst, Env); - Env.setStorageLocation(*S, *LocDst); + + // If the expr is a glvalue, we can reasonably assume the operator is + // returning T& and thus we can assign it `LocDst`. + if (S->isGLValue()) { +Env.setStorageLocation(*S, *LocDst); + } else if (S->getType()->isRecordType()) { +// If the expr is a prvalue, we cannot really assume anything regarding +// the new value being created. We should just propagate it to ensure a +// `RecordValue` exist for it. +if (Env.getValue(*S) == nullptr) + refreshRecordValue(*S, Env); + } + return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce..4a4224b42b085 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,42 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, AssignmentOperatorReturnsVoid) { + // This is a crash repro. + std::string Code = R"( +struct S { + void operator=(S&& other); +}; +void target() { + S s; + s = S(); + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + +TEST(TransferTest, AssignmentOperatorReturnsByValue) { + // This is a crash repro. + std::string Code = R"( +struct S { + S operator=(S&& other); +}; +void target() { + S s; + s = S(); + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue (PR #80991)
@@ -535,7 +535,19 @@ class TransferVisitor : public ConstStmtVisitor { return; copyRecord(*LocSrc, *LocDst, Env); - Env.setStorageLocation(*S, *LocDst); + + // If the expr is a glvalue, we can reasonably assume the operator is + // returning T& and thus we can assign it `LocDst`. + if (S->isGLValue()) { +Env.setStorageLocation(*S, *LocDst); + } else if (S->getType()->isRecordType() && S->isPRValue()) { +// If the expr is a prvalue, we cannot really assume anything regarding +// the new value being created. We should just propagate it to ensure a +// `RecordValue` exist for it. +if (Env.getValue(*S) == nullptr) + refreshRecordValue(*S, Env); paulsemel wrote: Yes, similarly to `TransferCallExpr`, it ensures a `RecordValue` exists. This is just a short path for not having to call `TransferCallExpr`, since it is pretty much the only thing that will trigger if being called. https://github.com/llvm/llvm-project/pull/80991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue (PR #80991)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80991 >From 0d03870ef82fac51387c353bbe4e095e431d7ce8 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 13:59:40 + Subject: [PATCH 1/2] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue Although in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated. --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 14 +++- .../Analysis/FlowSensitive/TransferTest.cpp | 36 +++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29ca..d73c9d25136279 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -535,7 +535,19 @@ class TransferVisitor : public ConstStmtVisitor { return; copyRecord(*LocSrc, *LocDst, Env); - Env.setStorageLocation(*S, *LocDst); + + // If the expr is a glvalue, we can reasonably assume the operator is + // returning T& and thus we can assign it `LocDst`. + if (S->isGLValue()) { +Env.setStorageLocation(*S, *LocDst); + } else if (S->getType()->isRecordType()) { +// If the expr is a prvalue, we cannot really assume anything regarding +// the new value being created. We should just propagate it to ensure a +// `RecordValue` exist for it. +if (Env.getValue(*S) == nullptr) + refreshRecordValue(*S, Env); + } + return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce6..4a4224b42b0850 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,42 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, AssignmentOperatorReturnsVoid) { + // This is a crash repro. + std::string Code = R"( +struct S { + void operator=(S&& other); +}; +void target() { + S s; + s = S(); + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + +TEST(TransferTest, AssignmentOperatorReturnsByValue) { + // This is a crash repro. + std::string Code = R"( +struct S { + S operator=(S&& other); +}; +void target() { + S s; + s = S(); + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { >From 4165c1be301c1a61dda55358302436e696567e83 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Thu, 8 Feb 2024 15:02:04 +0100 Subject: [PATCH 2/2] Update clang/lib/Analysis/FlowSensitive/Transfer.cpp Co-authored-by: martinboehme --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index d73c9d25136279..fd439ef4e9ef0e 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -541,9 +541,9 @@ class TransferVisitor : public ConstStmtVisitor { if (S->isGLValue()) { Env.setStorageLocation(*S, *LocDst); } else if (S->getType()->isRecordType()) { -// If the expr is a prvalue, we cannot really assume anything regarding -// the new value being created. We should just propagate it to ensure a -// `RecordValue` exist for it. +// Make sure that we have a `RecordValue` for this expression so that +// `Environment::getResultObjectLocation()` is able to return a location +// for it. if (Env.getValue(*S) == nullptr) refreshRecordValue(*S, Env); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80970 >From 1ff7ea57e76041b25889685ead115a1b793d3921 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 10:26:23 + Subject: [PATCH] [dataflow] Fix crash when InitListExpr is not a prvalue --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 5 ++--- .../Analysis/FlowSensitive/TransferTest.cpp | 22 +++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29c..c299524a58d38 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -648,9 +648,8 @@ class TransferVisitor : public ConstStmtVisitor { QualType Type = S->getType(); if (!Type->isStructureOrClassType()) { - if (auto *Val = Env.createValue(Type)) -Env.setValue(*S, *Val); - + assert(S->getNumInits() == 1); + propagateValueOrStorageLocation(*S->getInit(0), *S, Env); return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce..cda92bc421f6c 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,28 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, InitListExprAsXValue) { + // This is a crash repro. + std::string Code = R"( +void target() { + bool&& Foo{false}; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); +ASSERT_THAT(FooDecl, NotNull()); +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); +const auto *FooVal = +dyn_cast_or_null(Env.getValue(*FooDecl)); +ASSERT_THAT(FooVal, NotNull()); +ASSERT_EQ(FooVal, &Env.getBoolLiteralValue(false)); + }); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
@@ -648,6 +648,12 @@ class TransferVisitor : public ConstStmtVisitor { QualType Type = S->getType(); if (!Type->isStructureOrClassType()) { + // It is possible that InitListExpr is not a prvalue, in which case + // `setValue` will fail. In this case, we can just let the next + // transfer function handle the value creation. + if (!S->isPRValue()) +return; + if (auto *Val = Env.createValue(Type)) Env.setValue(*S, *Val); paulsemel wrote: Done! https://github.com/llvm/llvm-project/pull/80970 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80970 >From 35fa8c1f4815bf2922ba9018d3f64b99428ecdc6 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 10:26:23 + Subject: [PATCH] [dataflow] Fix crash when InitListExpr is not a prvalue --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 7 +++--- .../Analysis/FlowSensitive/TransferTest.cpp | 22 +++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29ca..993fabca5e5e65 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -648,9 +648,10 @@ class TransferVisitor : public ConstStmtVisitor { QualType Type = S->getType(); if (!Type->isStructureOrClassType()) { - if (auto *Val = Env.createValue(Type)) -Env.setValue(*S, *Val); - + // Until array initialization is implemented, we don't need to care about + // cases where `getNumInits() > 1`. + if (S->getNumInits() == 1) +propagateValueOrStorageLocation(*S->getInit(0), *S, Env); return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce6..cda92bc421f6c6 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,28 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, InitListExprAsXValue) { + // This is a crash repro. + std::string Code = R"( +void target() { + bool&& Foo{false}; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); +ASSERT_THAT(FooDecl, NotNull()); +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); +const auto *FooVal = +dyn_cast_or_null(Env.getValue(*FooDecl)); +ASSERT_THAT(FooVal, NotNull()); +ASSERT_EQ(FooVal, &Env.getBoolLiteralValue(false)); + }); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel edited https://github.com/llvm/llvm-project/pull/80970 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] CXXOperatorCallExpr equal operator might not be a glvalue (PR #80991)
https://github.com/paulsemel closed https://github.com/llvm/llvm-project/pull/80991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80970 >From 35fa8c1f4815bf2922ba9018d3f64b99428ecdc6 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 10:26:23 + Subject: [PATCH 1/2] [dataflow] Fix crash when InitListExpr is not a prvalue --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 7 +++--- .../Analysis/FlowSensitive/TransferTest.cpp | 22 +++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29ca..993fabca5e5e65 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -648,9 +648,10 @@ class TransferVisitor : public ConstStmtVisitor { QualType Type = S->getType(); if (!Type->isStructureOrClassType()) { - if (auto *Val = Env.createValue(Type)) -Env.setValue(*S, *Val); - + // Until array initialization is implemented, we don't need to care about + // cases where `getNumInits() > 1`. + if (S->getNumInits() == 1) +propagateValueOrStorageLocation(*S->getInit(0), *S, Env); return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce6..cda92bc421f6c6 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2313,6 +2313,28 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, InitListExprAsXValue) { + // This is a crash repro. + std::string Code = R"( +void target() { + bool&& Foo{false}; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); +ASSERT_THAT(FooDecl, NotNull()); +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); +const auto *FooVal = +dyn_cast_or_null(Env.getValue(*FooDecl)); +ASSERT_THAT(FooVal, NotNull()); +ASSERT_EQ(FooVal, &Env.getBoolLiteralValue(false)); + }); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { >From 8b4d49dc9f22e804ee853eb7ea4980641d7f0da7 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Tue, 13 Feb 2024 12:40:45 +0100 Subject: [PATCH 2/2] Update clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Co-authored-by: martinboehme --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index cda92bc421f6c6..da76040b2116bd 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2325,13 +2325,9 @@ TEST(TransferTest, InitListExprAsXValue) { Code, [](const llvm::StringMap> &Results, ASTContext &ASTCtx) { -const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); -ASSERT_THAT(FooDecl, NotNull()); const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); -const auto *FooVal = -dyn_cast_or_null(Env.getValue(*FooDecl)); -ASSERT_THAT(FooVal, NotNull()); -ASSERT_EQ(FooVal, &Env.getBoolLiteralValue(false)); +const auto &FooVal = getValueForDecl(ASTCtx, Env, "Foo"); +ASSERT_TRUE(FooVal.formula().isLiteral(false)); }); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/80970 >From 584e875913dc2f3d667aae95f44225c1c0b3101a Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Wed, 7 Feb 2024 10:26:23 + Subject: [PATCH] [dataflow] Fix crash when InitListExpr is not a prvalue --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 7 --- .../Analysis/FlowSensitive/TransferTest.cpp| 18 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index f0b15f43b1f423..fc7395457f551d 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -664,9 +664,10 @@ class TransferVisitor : public ConstStmtVisitor { QualType Type = S->getType(); if (!Type->isStructureOrClassType()) { - if (auto *Val = Env.createValue(Type)) -Env.setValue(*S, *Val); - + // Until array initialization is implemented, we don't need to care about + // cases where `getNumInits() > 1`. + if (S->getNumInits() == 1) +propagateValueOrStorageLocation(*S->getInit(0), *S, Env); return; } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 4b3b3511f848e8..87e6e83d2e03a9 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2349,6 +2349,24 @@ TEST(TransferTest, AssignmentOperatorReturnsByValue) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, InitListExprAsXValue) { + // This is a crash repro. + std::string Code = R"( +void target() { + bool&& Foo{false}; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); +const auto &FooVal = getValueForDecl(ASTCtx, Env, "Foo"); +ASSERT_TRUE(FooVal.formula().isLiteral(false)); + }); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] fix assert in `Environment::getResultObjectLocation` (PR #79608)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/79608 >From 6af0f5971783214f6f3ce5f95aba97ed1c79824e Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Fri, 26 Jan 2024 15:29:58 + Subject: [PATCH 1/3] [dataflow] fix assert in `Environment::getResultObjectLocation` When calling `Environment::getResultObjectLocation` with a CXXOperatorCallExpr that is a prvalue, we just hit an assert because no record was ever created. --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 5 + 1 file changed, 5 insertions(+) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 2271a75fbcaf7..3b028a3200b72 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -536,6 +536,11 @@ class TransferVisitor : public ConstStmtVisitor { copyRecord(*LocSrc, *LocDst, Env); Env.setStorageLocation(*S, *LocDst); +} else { + // CXXOperatorCallExpr can be prvalues, in which case we must create a + // record for them in order for `Environment::getResultObjectLocation()` + // to be able to return a value. + VisitCallExpr(S); } } >From acca94eb5c2c3ce858a704384361f54c1ae7557c Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Tue, 30 Jan 2024 17:43:55 +0100 Subject: [PATCH 2/3] Update clang/lib/Analysis/FlowSensitive/Transfer.cpp Co-authored-by: martinboehme --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 3b028a3200b72..bb3aec763c29c 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -536,12 +536,13 @@ class TransferVisitor : public ConstStmtVisitor { copyRecord(*LocSrc, *LocDst, Env); Env.setStorageLocation(*S, *LocDst); -} else { - // CXXOperatorCallExpr can be prvalues, in which case we must create a - // record for them in order for `Environment::getResultObjectLocation()` - // to be able to return a value. - VisitCallExpr(S); + return; } + +// CXXOperatorCallExpr can be prvalues. Call `VisitCallExpr`() to create +// a `RecordValue` for them so that `Environment::getResultObjectLocation()` +// can return a value. +VisitCallExpr(S); } void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { >From 9a6a38339fa69baa4e4bc9dc601791dde154900c Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Tue, 30 Jan 2024 17:05:44 + Subject: [PATCH 3/3] add test --- .../Analysis/FlowSensitive/TransferTest.cpp | 35 +++ 1 file changed, 35 insertions(+) diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 268ea4c7431f6..6a357c47f0f60 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2735,6 +2735,41 @@ TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) { }); } +// This test ensures that CXXOperatorCallExpr returning prvalues are correctly +// handled by the transfer functions, especially that `getResultObjectLocation` +// correctly returns a storage location for those. +TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) { + std::string Code = R"( +struct A { + virtual ~A() = default; + A operator+(int a) { return A(); } +}; + +void target() { + A a; + a + 3; + (void)0; // [[p]] +} + )"; + using ast_matchers::cxxOperatorCallExpr; + using ast_matchers::match; + using ast_matchers::selectFirst; + using ast_matchers::traverse; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + +auto *CallExpr = selectFirst( +"call_expr", +match(traverse(TK_AsIs, cxxOperatorCallExpr().bind("call_expr")), + ASTCtx)); + +EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr); + }); +} + TEST(TransferTest, StaticCast) { std::string Code = R"( void target(int Foo) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] fix assert in `Environment::getResultObjectLocation` (PR #79608)
paulsemel wrote: The added test aborts (assert fails) without this patch. https://github.com/llvm/llvm-project/pull/79608 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] fix assert in `Environment::getResultObjectLocation` (PR #79608)
https://github.com/paulsemel updated https://github.com/llvm/llvm-project/pull/79608 >From 6af0f5971783214f6f3ce5f95aba97ed1c79824e Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Fri, 26 Jan 2024 15:29:58 + Subject: [PATCH 1/3] [dataflow] fix assert in `Environment::getResultObjectLocation` When calling `Environment::getResultObjectLocation` with a CXXOperatorCallExpr that is a prvalue, we just hit an assert because no record was ever created. --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 5 + 1 file changed, 5 insertions(+) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 2271a75fbcaf7..3b028a3200b72 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -536,6 +536,11 @@ class TransferVisitor : public ConstStmtVisitor { copyRecord(*LocSrc, *LocDst, Env); Env.setStorageLocation(*S, *LocDst); +} else { + // CXXOperatorCallExpr can be prvalues, in which case we must create a + // record for them in order for `Environment::getResultObjectLocation()` + // to be able to return a value. + VisitCallExpr(S); } } >From acca94eb5c2c3ce858a704384361f54c1ae7557c Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Tue, 30 Jan 2024 17:43:55 +0100 Subject: [PATCH 2/3] Update clang/lib/Analysis/FlowSensitive/Transfer.cpp Co-authored-by: martinboehme --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 3b028a3200b72..bb3aec763c29c 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -536,12 +536,13 @@ class TransferVisitor : public ConstStmtVisitor { copyRecord(*LocSrc, *LocDst, Env); Env.setStorageLocation(*S, *LocDst); -} else { - // CXXOperatorCallExpr can be prvalues, in which case we must create a - // record for them in order for `Environment::getResultObjectLocation()` - // to be able to return a value. - VisitCallExpr(S); + return; } + +// CXXOperatorCallExpr can be prvalues. Call `VisitCallExpr`() to create +// a `RecordValue` for them so that `Environment::getResultObjectLocation()` +// can return a value. +VisitCallExpr(S); } void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { >From 7375c69754a6ed203d6b5fe7aaaf4dc963fb034b Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Tue, 30 Jan 2024 17:05:44 + Subject: [PATCH 3/3] add test --- .../Analysis/FlowSensitive/TransferTest.cpp | 33 +++ 1 file changed, 33 insertions(+) diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 268ea4c7431f6..8bbb04024dcce 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2735,6 +2735,39 @@ TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) { }); } +// This test ensures that CXXOperatorCallExpr returning prvalues are correctly +// handled by the transfer functions, especially that `getResultObjectLocation` +// correctly returns a storage location for those. +TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) { + std::string Code = R"( +struct A { + A operator+(int); +}; + +void target() { + A a; + a + 3; + (void)0; // [[p]] +} + )"; + using ast_matchers::cxxOperatorCallExpr; + using ast_matchers::match; + using ast_matchers::selectFirst; + using ast_matchers::traverse; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + +auto *CallExpr = selectFirst( +"call_expr", +match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx)); + +EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr); + }); +} + TEST(TransferTest, StaticCast) { std::string Code = R"( void target(int Foo) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] fix assert in `Environment::getResultObjectLocation` (PR #79608)
https://github.com/paulsemel closed https://github.com/llvm/llvm-project/pull/79608 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] fix assert in `Environment::getResultObjectLocation` (PR #79608)
https://github.com/paulsemel created https://github.com/llvm/llvm-project/pull/79608 When calling `Environment::getResultObjectLocation` with a CXXOperatorCallExpr that is a prvalue, we just hit an assert because no record was ever created. >From 6af0f5971783214f6f3ce5f95aba97ed1c79824e Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Fri, 26 Jan 2024 15:29:58 + Subject: [PATCH] [dataflow] fix assert in `Environment::getResultObjectLocation` When calling `Environment::getResultObjectLocation` with a CXXOperatorCallExpr that is a prvalue, we just hit an assert because no record was ever created. --- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 5 + 1 file changed, 5 insertions(+) diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 2271a75fbcaf709..3b028a3200b72b2 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -536,6 +536,11 @@ class TransferVisitor : public ConstStmtVisitor { copyRecord(*LocSrc, *LocDst, Env); Env.setStorageLocation(*S, *LocDst); +} else { + // CXXOperatorCallExpr can be prvalues, in which case we must create a + // record for them in order for `Environment::getResultObjectLocation()` + // to be able to return a value. + VisitCallExpr(S); } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] bc37893 - [clang][dataflow] fix bug for transparent ListInitExpr handling
Author: Paul Semel Date: 2023-07-26T08:50:28Z New Revision: bc37893433d35b1448c5d4628d932fafec92efd0 URL: https://github.com/llvm/llvm-project/commit/bc37893433d35b1448c5d4628d932fafec92efd0 DIFF: https://github.com/llvm/llvm-project/commit/bc37893433d35b1448c5d4628d932fafec92efd0.diff LOG: [clang][dataflow] fix bug for transparent ListInitExpr handling This fixes the handling of "transparent" ListInitExpr, when they're only used as a copy constructor for records. Without the fix, the two tests are crashing the process. Added: Modified: clang/lib/Analysis/FlowSensitive/Transfer.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Removed: diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 39faeca4b45ce3..0b7c22fe24e301 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -637,6 +637,13 @@ class TransferVisitor : public ConstStmtVisitor { return; } +// In case the initializer list is transparent, we just need to propagate +// the value that it contains. +if (S->isSemanticForm() && S->isTransparent()) { + propagateValue(*S->getInit(0), *S, Env); + return; +} + std::vector Fields = getFieldsForInitListExpr(Type->getAsRecordDecl()); llvm::DenseMap FieldLocs; diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index edd015bbf10937..5acb28bd87abff 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2183,6 +2183,39 @@ TEST(TransferTest, CopyConstructorWithParens) { }); } +TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) { + std::string Code = R"( + struct A { +int Baz; + }; + void target() { +A Foo = {3}; +(void)Foo.Baz; +A Bar = {A(Foo)}; +// [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + +const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); + +const auto &FooLoc = +getLocForDecl(ASTCtx, Env, "Foo"); +const auto &BarLoc = +getLocForDecl(ASTCtx, Env, "Bar"); + +const auto *FooBazVal = +cast(getFieldValue(&FooLoc, *BazDecl, Env)); +const auto *BarBazVal = +cast(getFieldValue(&BarLoc, *BazDecl, Env)); +EXPECT_EQ(FooBazVal, BarBazVal); + }); +} + TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) { // This is a crash repro. std::string Code = R"( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 145f353 - [clang][dataflow] fix failing assert in copyRecord
Author: Paul Semel Date: 2023-07-26T08:52:06Z New Revision: 145f353fd67909e03c39b968b464ac625edde6cb URL: https://github.com/llvm/llvm-project/commit/145f353fd67909e03c39b968b464ac625edde6cb DIFF: https://github.com/llvm/llvm-project/commit/145f353fd67909e03c39b968b464ac625edde6cb.diff LOG: [clang][dataflow] fix failing assert in copyRecord When dealing with copy constructor, the compiler can emit an UncheckedDerivedToBase implicit cast for the CXXConstructorExpr of the base class. In such case, when trying to copy the src storage location to its destination, we will fail on the assert checking that location types are the same. When copying from derived to base class, it is acceptable to break that assumption to only copy common fields from the base class. Note: the provided test crashes the process without the changes made to copyRecord. Differential Revision: https://reviews.llvm.org/D155844 Added: Modified: clang/lib/Analysis/FlowSensitive/RecordOps.cpp clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp Removed: diff --git a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp index 60144531c25186..95693f2e933a49 100644 --- a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp @@ -17,18 +17,27 @@ void clang::dataflow::copyRecord(AggregateStorageLocation &Src, AggregateStorageLocation &Dst, Environment &Env) { + auto SrcType = Src.getType().getCanonicalType().getUnqualifiedType(); + auto DstType = Dst.getType().getCanonicalType().getUnqualifiedType(); + + auto SrcDecl = SrcType->getAsCXXRecordDecl(); + auto DstDecl = DstType->getAsCXXRecordDecl(); + + bool compatibleTypes = + SrcType == DstType || + (SrcDecl && DstDecl && SrcDecl->isDerivedFrom(DstDecl)); + (void)compatibleTypes; + LLVM_DEBUG({ -if (Dst.getType().getCanonicalType().getUnqualifiedType() != -Src.getType().getCanonicalType().getUnqualifiedType()) { +if (!compatibleTypes) { llvm::dbgs() << "Source type " << Src.getType() << "\n"; llvm::dbgs() << "Destination type " << Dst.getType() << "\n"; } }); - assert(Dst.getType().getCanonicalType().getUnqualifiedType() == - Src.getType().getCanonicalType().getUnqualifiedType()); + assert(compatibleTypes); - for (auto [Field, SrcFieldLoc] : Src.children()) { -StorageLocation *DstFieldLoc = Dst.getChild(*Field); + for (auto [Field, DstFieldLoc] : Dst.children()) { +StorageLocation *SrcFieldLoc = Src.getChild(*Field); assert(Field->getType()->isReferenceType() || (SrcFieldLoc != nullptr && DstFieldLoc != nullptr)); diff --git a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp index 2b4b64c74481fb..b4eb0f26bf76be 100644 --- a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp @@ -194,6 +194,40 @@ TEST(RecordOpsTest, RecordsEqual) { }); } +TEST(TransferTest, CopyRecordFromDerivedToBase) { + std::string Code = R"( +struct A { + int i; +}; + +struct B : public A { +}; + +void target(A a, B b) { + (void)a.i; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); + +const ValueDecl *IDecl = findValueDecl(ASTCtx, "i"); +auto &A = getLocForDecl(ASTCtx, Env, "a"); +auto &B = getLocForDecl(ASTCtx, Env, "b"); + +EXPECT_NE(Env.getValue(*A.getChild(*IDecl)), + Env.getValue(*B.getChild(*IDecl))); + +copyRecord(B, A, Env); + +EXPECT_EQ(Env.getValue(*A.getChild(*IDecl)), + Env.getValue(*B.getChild(*IDecl))); + }); +} + } // namespace } // namespace test } // namespace dataflow ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 96d035c - [clang][dataflow] unnamed bitfields should be discarded in InitListExpr
Author: Paul Semel Date: 2023-02-28T15:43:28Z New Revision: 96d035c1dcd795e3da76ef17796101006269f9c7 URL: https://github.com/llvm/llvm-project/commit/96d035c1dcd795e3da76ef17796101006269f9c7 DIFF: https://github.com/llvm/llvm-project/commit/96d035c1dcd795e3da76ef17796101006269f9c7.diff LOG: [clang][dataflow] unnamed bitfields should be discarded in InitListExpr Differential Revision: https://reviews.llvm.org/D144892 Added: Modified: clang/lib/Analysis/FlowSensitive/Transfer.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Removed: diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 389865771c16b..e427f1458a8db 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -732,7 +732,15 @@ class TransferVisitor : public ConstStmtVisitor { Env.setValue(Loc, *Val); if (Type->isStructureOrClassType()) { - for (auto It : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) { + // Unnamed bitfields are only used for padding and are not appearing in + // `InitListExpr`'s inits. However, those fields do appear in RecordDecl's + // field list, and we thus need to remove them before mapping inits to + // fields to avoid mapping inits to the wrongs fields. + std::vector Fields; + llvm::copy_if( + Type->getAsRecordDecl()->fields(), std::back_inserter(Fields), + [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); }); + for (auto It : llvm::zip(Fields, S->inits())) { const FieldDecl *Field = std::get<0>(It); assert(Field != nullptr); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 98021ce0d30b3..9c16335714c55 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -5080,4 +5080,28 @@ TEST(TransferTest, ContextSensitiveConstructorDefault) { {BuiltinOptions{ContextSensitiveOptions{}}}); } +TEST(TransferTest, UnnamedBitfieldInitializer) { + std::string Code = R"( +struct B {}; +struct A { + unsigned a; + unsigned : 4; + unsigned c; + B b; +}; +void target() { + A a = {}; + A test = a; + (void)test.c; +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +// This doesn't need a body because this test was crashing the framework +// before handling correctly Unnamed bitfields in `InitListExpr`. + }); +} + } // namespace ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] e6e753d - [clang][dataflow] Fix wrong assert for CXXConstructExpr
Author: Paul Semel Date: 2023-02-24T09:51:10Z New Revision: e6e753d173db14bb1273db65387dec696b7d7a48 URL: https://github.com/llvm/llvm-project/commit/e6e753d173db14bb1273db65387dec696b7d7a48 DIFF: https://github.com/llvm/llvm-project/commit/e6e753d173db14bb1273db65387dec696b7d7a48.diff LOG: [clang][dataflow] Fix wrong assert for CXXConstructExpr Differential Revision: https://reviews.llvm.org/D144546 Added: Modified: clang/lib/Analysis/FlowSensitive/Transfer.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Removed: diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 74dd59851ad44..389865771c16b 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -561,7 +561,9 @@ class TransferVisitor : public ConstStmtVisitor { assert(ConstructorDecl != nullptr); if (ConstructorDecl->isCopyOrMoveConstructor()) { - assert(S->getNumArgs() == 1); + // It is permissible for a copy/move constructor to have additional + // parameters as long as they have default arguments defined for them. + assert(S->getNumArgs() != 0); const Expr *Arg = S->getArg(0); assert(Arg != nullptr); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index f626eb0c01548..98021ce0d30b3 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2102,6 +2102,54 @@ TEST(TransferTest, CopyConstructor) { }); } +TEST(TransferTest, CopyConstructorWithDefaultArgument) { + std::string Code = R"( +struct A { + int Baz; + A() = default; + A(const A& a, bool def = true) { Baz = a.Baz; } +}; + +void target() { + A Foo; + (void)Foo.Baz; + A Bar = Foo; + // [[p]] +} + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { +ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); +const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + +const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); +ASSERT_THAT(FooDecl, NotNull()); + +const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); +ASSERT_THAT(BarDecl, NotNull()); + +const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); +ASSERT_THAT(BazDecl, NotNull()); + +const auto *FooLoc = cast( +Env.getStorageLocation(*FooDecl, SkipPast::None)); +const auto *BarLoc = cast( +Env.getStorageLocation(*BarDecl, SkipPast::None)); + +const auto *FooVal = cast(Env.getValue(*FooLoc)); +const auto *BarVal = cast(Env.getValue(*BarLoc)); +EXPECT_EQ(FooVal, BarVal); + +const auto *FooBazVal = +cast(Env.getValue(FooLoc->getChild(*BazDecl))); +const auto *BarBazVal = +cast(Env.getValue(BarLoc->getChild(*BazDecl))); +EXPECT_EQ(FooBazVal, BarBazVal); + }); +} + TEST(TransferTest, CopyConstructorWithParens) { std::string Code = R"( struct A { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [dataflow] Fix crash when InitListExpr is not a prvalue (PR #80970)
https://github.com/paulsemel closed https://github.com/llvm/llvm-project/pull/80970 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Fix casting in `ChromiumCheckModel`. (PR #101640)
https://github.com/paulsemel closed https://github.com/llvm/llvm-project/pull/101640 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits