aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests
diff options
context:
space:
mode:
authormartinboehme <mboehme@google.com>2024-06-26 15:01:57 +0200
committerGitHub <noreply@github.com>2024-06-26 15:01:57 +0200
commitdfe80a73223edff5c53f8be7925d302883cb40bc (patch)
tree9a8399f61d6c6769b0179c25bb6f14841fa49c2e /clang/unittests
parent6f8efc76c9b9d1fc02f043cb908a8aa655290a61 (diff)
downloadllvm-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.cpp43
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 {