diff options
author | martinboehme <mboehme@google.com> | 2024-06-26 15:01:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-26 15:01:57 +0200 |
commit | dfe80a73223edff5c53f8be7925d302883cb40bc (patch) | |
tree | 9a8399f61d6c6769b0179c25bb6f14841fa49c2e /clang/unittests | |
parent | 6f8efc76c9b9d1fc02f043cb908a8aa655290a61 (diff) | |
download | llvm-dfe80a73223edff5c53f8be7925d302883cb40bc.zip llvm-dfe80a73223edff5c53f8be7925d302883cb40bc.tar.gz llvm-dfe80a73223edff5c53f8be7925d302883cb40bc.tar.bz2 |
[clang][dataflow] Teach `AnalysisASTVisitor` that `typeid()` can be evaluated. (#96731)
We were previously treating the operand of `typeid()` as being
definitely
unevaluated, but it can be evaluated if it is a glvalue of polymorphic
type.
This patch includes a test that fails without the fix.
Diffstat (limited to 'clang/unittests')
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index cfbc64c..2ce8339 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -1637,6 +1637,49 @@ TEST(TransferTest, StructModeledFieldsWithAccessor) { }); } +TEST(TransferTest, StructModeledFieldsInTypeid) { + // Test that we model fields mentioned inside a `typeid()` expression only if + // that expression is potentially evaluated -- i.e. if the expression inside + // `typeid()` is a glvalue of polymorphic type (see + // `CXXTypeidExpr::isPotentiallyEvaluated()` and [expr.typeid]p3). + std::string Code = R"( + // Definitions needed for `typeid`. + namespace std { + class type_info {}; + class bad_typeid {}; + } // namespace std + + struct NonPolymorphic {}; + + struct Polymorphic { + virtual ~Polymorphic() = default; + }; + + struct S { + NonPolymorphic *NonPoly; + Polymorphic *Poly; + }; + + void target(S &s) { + typeid(*s.NonPoly); + typeid(*s.Poly); + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"); + std::vector<const ValueDecl *> Fields; + for (auto [Field, _] : SLoc.children()) + Fields.push_back(Field); + EXPECT_THAT(Fields, + UnorderedElementsAre(findValueDecl(ASTCtx, "Poly"))); + }); +} + TEST(TransferTest, StructModeledFieldsWithComplicatedInheritance) { std::string Code = R"( struct Base1 { |