https://github.com/martinboehme created https://github.com/llvm/llvm-project/pull/91172
- **Reapply "[clang][dataflow] Don't propagate result objects in unevaluated contexts (#90438)"** - **fixup! Reapply "[clang][dataflow] Don't propagate result objects in unevaluated contexts (#90438)"** >From af6de532e14c6b3bf89f238533dea197fbc8114a Mon Sep 17 00:00:00 2001 From: Martin Braenne <mboe...@google.com> Date: Mon, 6 May 2024 06:46:33 +0000 Subject: [PATCH 1/2] Reapply "[clang][dataflow] Don't propagate result objects in unevaluated contexts (#90438)" This reverts commit 2252c5c42b95dd12dda0c7fb1b2811f943b21949. --- .../FlowSensitive/DataflowEnvironment.cpp | 11 ++++ .../Analysis/FlowSensitive/TransferTest.cpp | 52 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index d79e734402892a..cb6c8b2ef1072b 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -350,6 +350,17 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> { return RecursiveASTVisitor<ResultObjectVisitor>::TraverseDecl(D); } + // Don't traverse expressions in unevaluated contexts, as we don't model + // fields that are only used in these. + // Note: The operand of the `noexcept` operator is an unevaluated operand, but + // nevertheless it appears in the Clang CFG, so we don't exclude it here. + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; } + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; } + bool TraverseCXXTypeidExpr(CXXTypeidExpr *) { return true; } + bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) { + return true; + } + bool TraverseBindingDecl(BindingDecl *BD) { // `RecursiveASTVisitor` doesn't traverse holding variables for // `BindingDecl`s by itself, so we need to tell it to. diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 0b441faa6c76da..91bd496226caf2 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -3400,6 +3400,58 @@ TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) { + // This is a crash repro. + // We used to crash because when propagating result objects, we would visit + // unevaluated contexts, but we don't model fields used only in these. + + auto testFunction = [](llvm::StringRef Code, llvm::StringRef TargetFun) { + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) {}, + LangStandard::lang_gnucxx17, + /* ApplyBuiltinTransfer= */ true, TargetFun); + }; + + std::string Code = R"cc( + // Definitions needed for `typeid`. + namespace std { + class type_info {}; + class bad_typeid {}; + } // namespace std + + struct S1 {}; + struct S2 { S1 s1; }; + + // We test each type of unevaluated context from a different target + // function. Some types of unevaluated contexts may actually cause the + // field `s1` to be modeled, and we don't want this to "pollute" the tests + // for the other unevaluated contexts. + void decltypeTarget() { + decltype(S2{}) Dummy; + } + void typeofTarget() { + typeof(S2{}) Dummy; + } + void typeidTarget() { + typeid(S2{}); + } + void sizeofTarget() { + sizeof(S2{}); + } + void noexceptTarget() { + noexcept(S2{}); + } + )cc"; + + testFunction(Code, "decltypeTarget"); + testFunction(Code, "typeofTarget"); + testFunction(Code, "typeidTarget"); + testFunction(Code, "sizeofTarget"); + testFunction(Code, "noexceptTarget"); +} + TEST(TransferTest, StaticCast) { std::string Code = R"( void target(int Foo) { >From 77222057b948a668aebda9cbd0b6fd41e01a21a2 Mon Sep 17 00:00:00 2001 From: Martin Braenne <mboe...@google.com> Date: Mon, 6 May 2024 08:11:11 +0000 Subject: [PATCH 2/2] fixup! Reapply "[clang][dataflow] Don't propagate result objects in unevaluated contexts (#90438)" --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 91bd496226caf2..6743e778a2ffeb 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -3435,7 +3435,9 @@ TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) { typeof(S2{}) Dummy; } void typeidTarget() { +#if __has_feature(cxx_rtti) typeid(S2{}); +#endif } void sizeofTarget() { sizeof(S2{}); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits