mboehme updated this revision to Diff 534891. mboehme added a comment. Undo all of the non-test changes. This patch now only introduces a test that we can access fields of anonymous structs.
I realized based on gribozavr2's comment that we shouldn't be lumping all fields of anonymous records into the parent record, as this goes against the grain of the Clang AST and, for example, requires special-case code in `MemberExpr`. Instead, I realized that everything essentially already works -- anonymous records were already being correctly added as fields of their parent record. The only thing that needs to be fixed is handling `IndirectFieldDecl` correctly when transferring `CXXCtorInitializer`. This will come in a followup patch. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153409/new/ https://reviews.llvm.org/D153409 Files: clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp clang/unittests/Analysis/FlowSensitive/TestingSupport.h clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -5434,4 +5434,38 @@ }); } +// Check that fields of anonymous records are modeled. +TEST(TransferTest, AnonymousStruct) { + std::string Code = R"( + struct S { + struct { + bool b; + }; + }; + void target() { + S s; + s.b = true; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); + const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); + const IndirectFieldDecl *IndirectField = + findIndirectFieldDecl(ASTCtx, "b"); + + auto *S = + cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl)); + auto &AnonStruct = cast<AggregateStorageLocation>( + S->getChild(*cast<ValueDecl>(IndirectField->chain().front()))); + + auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl))); + ASSERT_TRUE(Env.flowConditionImplies(*B)); + }); +} + } // namespace Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h =================================================================== --- clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -428,6 +428,14 @@ /// `Name` must be unique in `ASTCtx`. const ValueDecl *findValueDecl(ASTContext &ASTCtx, llvm::StringRef Name); +/// Returns the `IndirectFieldDecl` for the given identifier. +/// +/// Requirements: +/// +/// `Name` must be unique in `ASTCtx`. +const IndirectFieldDecl *findIndirectFieldDecl(ASTContext &ASTCtx, + llvm::StringRef Name); + /// Returns the storage location (of type `LocT`) for the given identifier. /// `LocT` must be a subclass of `StorageLocation` and must be of the /// appropriate type. Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp +++ clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp @@ -154,9 +154,19 @@ } const ValueDecl *test::findValueDecl(ASTContext &ASTCtx, llvm::StringRef Name) { - auto TargetNodes = match(valueDecl(hasName(Name)).bind("v"), ASTCtx); + auto TargetNodes = match( + valueDecl(unless(indirectFieldDecl()), hasName(Name)).bind("v"), ASTCtx); assert(TargetNodes.size() == 1 && "Name must be unique"); auto *const Result = selectFirst<ValueDecl>("v", TargetNodes); assert(Result != nullptr); return Result; } + +const IndirectFieldDecl *test::findIndirectFieldDecl(ASTContext &ASTCtx, + llvm::StringRef Name) { + auto TargetNodes = match(indirectFieldDecl(hasName(Name)).bind("i"), ASTCtx); + assert(TargetNodes.size() == 1 && "Name must be unique"); + const auto *Result = selectFirst<IndirectFieldDecl>("i", TargetNodes); + assert(Result != nullptr); + return Result; +}
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -5434,4 +5434,38 @@ }); } +// Check that fields of anonymous records are modeled. +TEST(TransferTest, AnonymousStruct) { + std::string Code = R"( + struct S { + struct { + bool b; + }; + }; + void target() { + S s; + s.b = true; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); + const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); + const IndirectFieldDecl *IndirectField = + findIndirectFieldDecl(ASTCtx, "b"); + + auto *S = + cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl)); + auto &AnonStruct = cast<AggregateStorageLocation>( + S->getChild(*cast<ValueDecl>(IndirectField->chain().front()))); + + auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl))); + ASSERT_TRUE(Env.flowConditionImplies(*B)); + }); +} + } // namespace Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h =================================================================== --- clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -428,6 +428,14 @@ /// `Name` must be unique in `ASTCtx`. const ValueDecl *findValueDecl(ASTContext &ASTCtx, llvm::StringRef Name); +/// Returns the `IndirectFieldDecl` for the given identifier. +/// +/// Requirements: +/// +/// `Name` must be unique in `ASTCtx`. +const IndirectFieldDecl *findIndirectFieldDecl(ASTContext &ASTCtx, + llvm::StringRef Name); + /// Returns the storage location (of type `LocT`) for the given identifier. /// `LocT` must be a subclass of `StorageLocation` and must be of the /// appropriate type. Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp +++ clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp @@ -154,9 +154,19 @@ } const ValueDecl *test::findValueDecl(ASTContext &ASTCtx, llvm::StringRef Name) { - auto TargetNodes = match(valueDecl(hasName(Name)).bind("v"), ASTCtx); + auto TargetNodes = match( + valueDecl(unless(indirectFieldDecl()), hasName(Name)).bind("v"), ASTCtx); assert(TargetNodes.size() == 1 && "Name must be unique"); auto *const Result = selectFirst<ValueDecl>("v", TargetNodes); assert(Result != nullptr); return Result; } + +const IndirectFieldDecl *test::findIndirectFieldDecl(ASTContext &ASTCtx, + llvm::StringRef Name) { + auto TargetNodes = match(indirectFieldDecl(hasName(Name)).bind("i"), ASTCtx); + assert(TargetNodes.size() == 1 && "Name must be unique"); + const auto *Result = selectFirst<IndirectFieldDecl>("i", TargetNodes); + assert(Result != nullptr); + return Result; +}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits