mboehme created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
mboehme requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

- Both of these constructs are used to represent structs, classes, and unions; 
Clang uses the collective term "record" for these.

- The term "aggregate" in `AggregateStorageLocation` implies that, at some 
point, the intention may have been to use it also for arrays, but it don't 
think it's possible to use it for arrays. Records and arrays are very different 
and therefore need to be modeled differently. Records have a fixed set of named 
fields, which can have different type; arrays have a variable number of 
elements, but they all have the same type.

- Futhermore, "aggregate" has a very specific meaning in C++ 
(https://en.cppreference.com/w/cpp/language/aggregate_initialization). 
Aggregates of class type may not have any user-declared or inherited 
constructors, no private or protected non-static data members, no virtual 
member functions, and so on, but we use `AggregateStorageLocations` to model 
all objects of class type.

In addition, for consistency, we also rename the following:

- `getAggregateLoc()` (in `RecordValue`, formerly known as `StructValue`) to 
simply `getLoc()`.

- `refreshStructValue()` to `refreshRecordValue()`

We keep the old names around as deprecated synonyms to enable clients to be
migrated to the new names.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156788

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/RecordOps.h
  clang/include/clang/Analysis/FlowSensitive/StorageLocation.h
  clang/include/clang/Analysis/FlowSensitive/Value.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
  clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/RecordOps.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.h
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
  clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -415,7 +415,7 @@
     if (const auto *E = selectFirst<CXXConstructExpr>(
             "call", match(cxxConstructExpr(HasSpecialBoolType).bind("call"), *S,
                           getASTContext()))) {
-      cast<StructValue>(Env.getValue(*E))
+      cast<RecordValue>(Env.getValue(*E))
           ->setProperty("is_set", Env.getBoolLiteralValue(false));
     } else if (const auto *E = selectFirst<CXXMemberCallExpr>(
                    "call", match(cxxMemberCallExpr(callee(cxxMethodDecl(ofClass(
@@ -423,9 +423,9 @@
                                      .bind("call"),
                                  *S, getASTContext()))) {
       auto &ObjectLoc =
-          *cast<AggregateStorageLocation>(getImplicitObjectLocation(*E, Env));
+          *cast<RecordStorageLocation>(getImplicitObjectLocation(*E, Env));
 
-      refreshStructValue(ObjectLoc, Env)
+      refreshRecordValue(ObjectLoc, Env)
           .setProperty("is_set", Env.getBoolLiteralValue(true));
     }
   }
@@ -572,7 +572,7 @@
         *S, getASTContext());
     if (const auto *E = selectFirst<CXXConstructExpr>(
             "construct", Matches)) {
-      cast<StructValue>(Env.getValue(*E))
+      cast<RecordValue>(Env.getValue(*E))
           ->setProperty("has_value", Env.getBoolLiteralValue(false));
     } else if (const auto *E =
                    selectFirst<CXXOperatorCallExpr>("operator", Matches)) {
@@ -580,7 +580,7 @@
       auto *Object = E->getArg(0);
       assert(Object != nullptr);
 
-      refreshStructValue(*Object, Env)
+      refreshRecordValue(*Object, Env)
           .setProperty("has_value", Env.getBoolLiteralValue(true));
     }
   }
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -164,10 +164,10 @@
         auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl));
         ASSERT_THAT(FooValue, NotNull());
 
-        EXPECT_TRUE(isa<AggregateStorageLocation>(FooValue->getPointeeLoc()));
+        EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc()));
         auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc());
         ASSERT_THAT(FooPointeeValue, NotNull());
-        EXPECT_TRUE(isa<StructValue>(FooPointeeValue));
+        EXPECT_TRUE(isa<RecordValue>(FooPointeeValue));
       });
 }
 
@@ -215,9 +215,9 @@
         ASSERT_THAT(UnmodeledDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *UnmodeledLoc = FooLoc->getChild(*UnmodeledDecl);
-        ASSERT_TRUE(isa<AggregateStorageLocation>(UnmodeledLoc));
+        ASSERT_TRUE(isa<RecordStorageLocation>(UnmodeledLoc));
         EXPECT_THAT(Env.getValue(*UnmodeledLoc), IsNull());
 
         const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab");
@@ -262,7 +262,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
       });
 }
@@ -305,7 +305,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
       });
 }
@@ -369,7 +369,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
       });
 }
@@ -396,10 +396,10 @@
         ASSERT_THAT(FooDecl, NotNull());
 
         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
-        ASSERT_TRUE(isa_and_nonnull<AggregateStorageLocation>(FooLoc));
+        ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
 
         const Value *FooReferentVal = Env.getValue(*FooLoc);
-        EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
+        EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal));
       });
 }
 
@@ -483,20 +483,20 @@
     ASSERT_THAT(BazPtrDecl, NotNull());
 
     const auto &FooLoc =
-        *cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+        *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
 
     const auto &BarLoc =
-        *cast<AggregateStorageLocation>(FooLoc.getChild(*BarDecl));
+        *cast<RecordStorageLocation>(FooLoc.getChild(*BarDecl));
 
     const auto &FooReferentLoc =
-        *cast<AggregateStorageLocation>(BarLoc.getChild(*FooRefDecl));
+        *cast<RecordStorageLocation>(BarLoc.getChild(*FooRefDecl));
     EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull());
     EXPECT_THAT(getFieldValue(&FooReferentLoc, *BarDecl, Env), IsNull());
 
     const auto &FooPtrVal =
         *cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env));
     const auto &FooPtrPointeeLoc =
-        cast<AggregateStorageLocation>(FooPtrVal.getPointeeLoc());
+        cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull());
     EXPECT_THAT(getFieldValue(&FooPtrPointeeLoc, *BarDecl, Env), IsNull());
 
@@ -535,10 +535,10 @@
 
         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
-        EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
+        EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
 
         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
-        EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
+        EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
       });
 }
 
@@ -638,19 +638,19 @@
             *cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto &FooVal = *cast<PointerValue>(Env.getValue(FooLoc));
         const auto &FooPointeeVal =
-            *cast<StructValue>(Env.getValue(FooVal.getPointeeLoc()));
+            *cast<RecordValue>(Env.getValue(FooVal.getPointeeLoc()));
 
         const auto &BarVal =
             *cast<PointerValue>(getFieldValue(&FooPointeeVal, *BarDecl, Env));
         const auto &BarPointeeVal =
-            *cast<StructValue>(Env.getValue(BarVal.getPointeeLoc()));
+            *cast<RecordValue>(Env.getValue(BarVal.getPointeeLoc()));
 
         EXPECT_THAT(getFieldValue(&BarPointeeVal, *FooRefDecl, Env), NotNull());
 
         const auto &FooPtrVal = *cast<PointerValue>(
             getFieldValue(&BarPointeeVal, *FooPtrDecl, Env));
         const auto &FooPtrPointeeLoc =
-            cast<AggregateStorageLocation>(FooPtrVal.getPointeeLoc());
+            cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
 
         EXPECT_THAT(getFieldValue(&BarPointeeVal, *BazRefDecl, Env), NotNull());
@@ -1044,7 +1044,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
       });
 }
@@ -1069,10 +1069,10 @@
         ASSERT_THAT(FooDecl, NotNull());
 
         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
-        ASSERT_TRUE(isa_and_nonnull<AggregateStorageLocation>(FooLoc));
+        ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
 
         const Value *FooReferentVal = Env.getValue(*FooLoc);
-        EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
+        EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal));
       });
 }
 
@@ -1100,10 +1100,10 @@
 
         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
-        EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
+        EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
 
         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
-        EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
+        EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
       });
 }
 
@@ -1142,7 +1142,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarVal =
             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
 
@@ -1273,7 +1273,7 @@
         ASSERT_THAT(APublicDecl, NotNull());
 
         ASSERT_TRUE(
-            isa<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)));
+            isa<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)));
       });
 }
 
@@ -1304,9 +1304,9 @@
   ASSERT_THAT(BarDecl, NotNull());
 
   const auto &FooLoc =
-      *cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
-  const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
-  EXPECT_EQ(&FooVal.getAggregateLoc(), &FooLoc);
+      *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
+  const auto &FooVal = *cast<RecordValue>(Env.getValue(FooLoc));
+  EXPECT_EQ(&FooVal.getLoc(), &FooLoc);
 }
 
 TEST(TransferTest, DerivedBaseMemberStructDefault) {
@@ -1383,7 +1383,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarVal =
             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
 
@@ -1473,7 +1473,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarReferentVal =
             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
 
@@ -1543,8 +1543,8 @@
         ASSERT_THAT(BazDecl, NotNull());
 
         const auto *QuxLoc =
-            cast<AggregateStorageLocation>(ThisLoc->getChild(*QuxDecl));
-        EXPECT_THAT(dyn_cast<StructValue>(Env.getValue(*QuxLoc)), NotNull());
+            cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
+        EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
 
         const auto *BazVal =
             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
@@ -1614,8 +1614,8 @@
         ASSERT_THAT(BazDecl, NotNull());
 
         const auto *QuxLoc =
-            cast<AggregateStorageLocation>(ThisLoc->getChild(*QuxDecl));
-        EXPECT_THAT(dyn_cast<StructValue>(Env.getValue(*QuxLoc)), NotNull());
+            cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
+        EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
 
         const auto *BazVal =
             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
@@ -1897,7 +1897,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
       });
 }
@@ -1930,7 +1930,7 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
       },
       LangStandard::lang_cxx14);
@@ -1970,9 +1970,9 @@
           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
 
           const auto *FooLoc1 =
-              cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl));
+              cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
           const auto *BarLoc1 =
-              cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl));
+              cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
 
           const auto *FooBazVal1 =
@@ -1987,12 +1987,12 @@
           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
 
           const auto *FooLoc2 =
-              cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl));
+              cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
           const auto *BarLoc2 =
-              cast<AggregateStorageLocation>(Env2.getStorageLocation(*BarDecl));
+              cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
 
-          const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
-          const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
+          const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
+          const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2));
           EXPECT_NE(FooVal2, BarVal2);
 
           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
@@ -2009,9 +2009,9 @@
           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
 
           const auto *FooLoc3 =
-              cast<AggregateStorageLocation>(Env3.getStorageLocation(*FooDecl));
+              cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
           const auto *BarLoc3 =
-              cast<AggregateStorageLocation>(Env3.getStorageLocation(*BarDecl));
+              cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
 
           const auto *FooBazVal3 =
@@ -2076,13 +2076,13 @@
               getEnvironmentAtAnnotation(Results, "after_copy");
 
           const auto *FooLoc =
-              cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+              cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
           const auto *BarLoc =
-              cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
+              cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
 
-          // `Foo` and `Bar` have different `StructValue`s associated with them.
-          const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
-          const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
+          // `Foo` and `Bar` have different `RecordValue`s associated with them.
+          const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
+          const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
           EXPECT_NE(FooVal, BarVal);
 
           // But the records compare equal.
@@ -2102,9 +2102,9 @@
               getEnvironmentAtAnnotation(Results, "after_update");
 
           const auto *FooLoc =
-              cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+              cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
           const auto *BarLoc =
-              cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
+              cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
 
           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
 
@@ -2149,9 +2149,9 @@
         ASSERT_THAT(BazDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
 
         const auto *FooBazVal =
@@ -2192,9 +2192,9 @@
         ASSERT_THAT(BazDecl, NotNull());
 
         const auto *FooLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarLoc =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
+            cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
 
         const auto *FooBazVal =
@@ -2226,9 +2226,9 @@
         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
 
         const auto &FooLoc =
-            getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "Foo");
+            getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
         const auto &BarLoc =
-            getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "Bar");
+            getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
 
         const auto *FooBazVal =
             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
@@ -2300,14 +2300,14 @@
         ASSERT_THAT(BazDecl, NotNull());
 
         const auto *FooLoc1 =
-            cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl));
+            cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
         const auto *BarLoc1 =
-            cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl));
+            cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
 
         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
 
-        const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
-        const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
+        const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
+        const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
         EXPECT_NE(FooVal1, BarVal1);
 
         const auto *FooBazVal1 =
@@ -2317,8 +2317,8 @@
         EXPECT_NE(FooBazVal1, BarBazVal1);
 
         const auto *FooLoc2 =
-            cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl));
-        const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
+            cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
+        const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
         EXPECT_NE(FooVal2, BarVal1);
         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
 
@@ -2357,7 +2357,7 @@
         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
         ASSERT_THAT(BazDecl, NotNull());
 
-        const auto &FooVal = *cast<StructValue>(Env.getValue(*FooDecl));
+        const auto &FooVal = *cast<RecordValue>(Env.getValue(*FooDecl));
         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
         EXPECT_EQ(BarVal, getFieldValue(&FooVal, *BazDecl, Env));
       });
@@ -2530,7 +2530,7 @@
         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
 
         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
-        EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc));
+        EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
 
         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
@@ -2716,10 +2716,10 @@
         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
         ASSERT_THAT(BazDecl, NotNull());
 
-        const auto *FooVal = cast<StructValue>(Env.getValue(*FooDecl));
-        const auto *BarVal = cast<StructValue>(Env.getValue(*BarDecl));
+        const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
+        const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
 
-        const auto *BazVal = dyn_cast<StructValue>(Env.getValue(*BazDecl));
+        const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
         ASSERT_THAT(BazVal, NotNull());
 
         EXPECT_NE(BazVal, FooVal);
@@ -2857,11 +2857,11 @@
           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
 
-          const auto *QuuxVal = cast<StructValue>(Env.getValue(*QuuxDecl));
+          const auto *QuuxVal = cast<RecordValue>(Env.getValue(*QuuxDecl));
           ASSERT_THAT(QuuxVal, NotNull());
 
           const auto *BazVal =
-              cast<StructValue>(getFieldValue(QuuxVal, *BazDecl, Env));
+              cast<RecordValue>(getFieldValue(QuuxVal, *BazDecl, Env));
           ASSERT_THAT(BazVal, NotNull());
 
           EXPECT_EQ(getFieldValue(QuuxVal, *BarDecl, Env), BarArgVal);
@@ -2871,7 +2871,7 @@
           // Check that fields initialized in an initializer list are always
           // modeled in other instances of the same type.
           const auto &OtherBVal =
-              getValueForDecl<StructValue>(ASTCtx, Env, "OtherB");
+              getValueForDecl<RecordValue>(ASTCtx, Env, "OtherB");
           EXPECT_THAT(OtherBVal.getChild(*BarDecl), NotNull());
           EXPECT_THAT(OtherBVal.getChild(*BazDecl), NotNull());
           EXPECT_THAT(OtherBVal.getChild(*QuxDecl), NotNull());
@@ -2899,7 +2899,7 @@
         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
 
         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
-        auto &SLoc = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s");
+        auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
 
         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
       });
@@ -2926,7 +2926,7 @@
         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
 
-        auto &SLoc = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s");
+        auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
 
         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
         auto &I1Value =
@@ -2972,7 +2972,7 @@
         }
         ASSERT_THAT(FooDecl, NotNull());
 
-        const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
+        const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
             Env.getStorageLocation(*BazDecl));
         ASSERT_THAT(BazLoc, NotNull());
         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
@@ -3540,7 +3540,7 @@
 
         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
 
-        const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl));
+        const auto *A2Val = cast<RecordValue>(Env.getValue(*A2Decl));
         EXPECT_EQ(getFieldValue(A2Val, *FooDecl, Env), BarVal);
       });
 }
@@ -5449,7 +5449,7 @@
     void target() {
       Outer *p = new Outer;
       // Access the fields to make sure the analysis actually generates children
-      // for them in the `AggregateStorageLoc` and `StructValue`.
+      // for them in the `RecordStorageLocation` and `RecordValue`.
       p->OuterField.InnerField;
       // [[after_new]]
     }
@@ -5466,9 +5466,9 @@
 
         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
 
-        auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc());
+        auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
         auto &OuterFieldLoc =
-            *cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField));
+            *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
 
         // Values for the struct and all fields exist after the new.
@@ -5574,9 +5574,8 @@
         const IndirectFieldDecl *IndirectField =
             findIndirectFieldDecl(ASTCtx, "b");
 
-        auto *S =
-            cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl));
-        auto &AnonStruct = *cast<AggregateStorageLocation>(
+        auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
+        auto &AnonStruct = *cast<RecordStorageLocation>(
             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
 
         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
@@ -5606,8 +5605,8 @@
             findIndirectFieldDecl(ASTCtx, "b");
 
         auto *ThisLoc =
-            cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
-        auto &AnonStruct = *cast<AggregateStorageLocation>(ThisLoc->getChild(
+            cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
+        auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
             *cast<ValueDecl>(IndirectField->chain().front())));
 
         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
@@ -5639,8 +5638,8 @@
             findIndirectFieldDecl(ASTCtx, "i");
 
         auto *ThisLoc =
-            cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
-        auto &AnonStruct = *cast<AggregateStorageLocation>(ThisLoc->getChild(
+            cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
+        auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
             *cast<ValueDecl>(IndirectField->chain().front())));
 
         ASSERT_EQ(AnonStruct.getChild(*IDecl),
Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h
===================================================================
--- clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -453,7 +453,7 @@
 
 /// Returns the value of a `Field` on the record referenced by `Loc.`
 /// Returns null if `Loc` is null.
-inline Value *getFieldValue(const AggregateStorageLocation *Loc,
+inline Value *getFieldValue(const RecordStorageLocation *Loc,
                             const ValueDecl &Field, const Environment &Env) {
   if (Loc == nullptr)
     return nullptr;
@@ -469,7 +469,7 @@
 /// Note: This function currently does not use the `Env` parameter, but it will
 /// soon be needed to look up the `Value` when `setChild()` changes to return a
 /// `StorageLocation *`.
-inline Value *getFieldValue(const StructValue *Struct, const ValueDecl &Field,
+inline Value *getFieldValue(const RecordValue *Struct, const ValueDecl &Field,
                             const Environment &Env) {
   if (Struct == nullptr)
     return nullptr;
Index: clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
@@ -58,10 +58,10 @@
         const ValueDecl *InnerDecl = findValueDecl(ASTCtx, "inner");
         const ValueDecl *InnerIntDecl = findValueDecl(ASTCtx, "inner_int");
 
-        auto &S1 = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s1");
-        auto &S2 = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s2");
-        auto &Inner1 = *cast<AggregateStorageLocation>(S1.getChild(*InnerDecl));
-        auto &Inner2 = *cast<AggregateStorageLocation>(S2.getChild(*InnerDecl));
+        auto &S1 = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s1");
+        auto &S2 = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s2");
+        auto &Inner1 = *cast<RecordStorageLocation>(S1.getChild(*InnerDecl));
+        auto &Inner2 = *cast<RecordStorageLocation>(S2.getChild(*InnerDecl));
 
         EXPECT_NE(getFieldValue(&S1, *OuterIntDecl, Env),
                   getFieldValue(&S2, *OuterIntDecl, Env));
@@ -69,8 +69,8 @@
         EXPECT_NE(getFieldValue(&Inner1, *InnerIntDecl, Env),
                   getFieldValue(&Inner2, *InnerIntDecl, Env));
 
-        auto *S1Val = cast<StructValue>(Env.getValue(S1));
-        auto *S2Val = cast<StructValue>(Env.getValue(S2));
+        auto *S1Val = cast<RecordValue>(Env.getValue(S1));
+        auto *S2Val = cast<RecordValue>(Env.getValue(S2));
         EXPECT_NE(S1Val, S2Val);
 
         S1Val->setProperty("prop", Env.getBoolLiteralValue(true));
@@ -83,8 +83,8 @@
         EXPECT_EQ(getFieldValue(&Inner1, *InnerIntDecl, Env),
                   getFieldValue(&Inner2, *InnerIntDecl, Env));
 
-        S1Val = cast<StructValue>(Env.getValue(S1));
-        S2Val = cast<StructValue>(Env.getValue(S2));
+        S1Val = cast<RecordValue>(Env.getValue(S1));
+        S2Val = cast<RecordValue>(Env.getValue(S2));
         EXPECT_NE(S1Val, S2Val);
 
         EXPECT_EQ(S2Val->getProperty("prop"), &Env.getBoolLiteralValue(true));
@@ -118,11 +118,11 @@
         const ValueDecl *InnerDecl = findValueDecl(ASTCtx, "inner");
         const ValueDecl *InnerIntDecl = findValueDecl(ASTCtx, "inner_int");
 
-        auto &S1 = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s1");
-        auto &S2 = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s2");
-        auto &Inner2 = *cast<AggregateStorageLocation>(S2.getChild(*InnerDecl));
+        auto &S1 = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s1");
+        auto &S2 = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s2");
+        auto &Inner2 = *cast<RecordStorageLocation>(S2.getChild(*InnerDecl));
 
-        cast<StructValue>(Env.getValue(S1))
+        cast<RecordValue>(Env.getValue(S1))
             ->setProperty("prop", Env.getBoolLiteralValue(true));
 
         // Strategy: Create two equal records, then verify each of the various
@@ -163,14 +163,14 @@
         EXPECT_TRUE(recordsEqual(S1, S2, Env));
 
         // S1 and S2 have the same property with different values.
-        cast<StructValue>(Env.getValue(S2))
+        cast<RecordValue>(Env.getValue(S2))
             ->setProperty("prop", Env.getBoolLiteralValue(false));
         EXPECT_FALSE(recordsEqual(S1, S2, Env));
         copyRecord(S1, S2, Env);
         EXPECT_TRUE(recordsEqual(S1, S2, Env));
 
         // S1 has a property that S2 doesn't have.
-        cast<StructValue>(Env.getValue(S1))
+        cast<RecordValue>(Env.getValue(S1))
             ->setProperty("other_prop", Env.getBoolLiteralValue(false));
         EXPECT_FALSE(recordsEqual(S1, S2, Env));
         // We modified S1 this time, so need to copy back the other way.
@@ -178,7 +178,7 @@
         EXPECT_TRUE(recordsEqual(S1, S2, Env));
 
         // S2 has a property that S1 doesn't have.
-        cast<StructValue>(Env.getValue(S2))
+        cast<RecordValue>(Env.getValue(S2))
             ->setProperty("other_prop", Env.getBoolLiteralValue(false));
         EXPECT_FALSE(recordsEqual(S1, S2, Env));
         copyRecord(S1, S2, Env);
@@ -186,9 +186,9 @@
 
         // S1 and S2 have the same number of properties, but with different
         // names.
-        cast<StructValue>(Env.getValue(S1))
+        cast<RecordValue>(Env.getValue(S1))
             ->setProperty("prop1", Env.getBoolLiteralValue(false));
-        cast<StructValue>(Env.getValue(S2))
+        cast<RecordValue>(Env.getValue(S2))
             ->setProperty("prop2", Env.getBoolLiteralValue(false));
         EXPECT_FALSE(recordsEqual(S1, S2, Env));
       });
@@ -215,8 +215,8 @@
         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
 
         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
-        auto &A = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "a");
-        auto &B = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "b");
+        auto &A = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "a");
+        auto &B = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "b");
 
         EXPECT_NE(Env.getValue(*A.getChild(*IDecl)),
                   Env.getValue(*B.getChild(*IDecl)));
Index: clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -91,7 +91,7 @@
   // Verify that the struct and the field (`R`) with first appearance of the
   // type is created successfully.
   Environment Env(DAContext, *Fun);
-  StructValue *SVal = cast<StructValue>(Env.createValue(Ty));
+  RecordValue *SVal = cast<RecordValue>(Env.createValue(Ty));
   PointerValue *PV = cast_or_null<PointerValue>(getFieldValue(SVal, *R, Env));
   EXPECT_THAT(PV, NotNull());
 }
@@ -171,7 +171,7 @@
   // Verify that the `X` field of `S` is populated when analyzing the
   // constructor, even though it is not referenced directly in the constructor.
   Environment Env(DAContext, *Constructor);
-  auto *Val = cast<StructValue>(Env.createValue(QTy));
+  auto *Val = cast<RecordValue>(Env.createValue(QTy));
   EXPECT_THAT(getFieldValue(Val, *XDecl, Env), NotNull());
 }
 
@@ -215,8 +215,8 @@
   // Verify the global variable is populated when we analyze `Target`.
   Environment Env(DAContext, *Fun);
   const auto *GlobalLoc =
-      cast<AggregateStorageLocation>(Env.getStorageLocation(*GlobalDecl));
-  const auto *GlobalVal = cast<StructValue>(Env.getValue(*GlobalLoc));
+      cast<RecordStorageLocation>(Env.getStorageLocation(*GlobalDecl));
+  const auto *GlobalVal = cast<RecordValue>(Env.getValue(*GlobalLoc));
   auto *BarVal = getFieldValue(GlobalVal, *BarDecl, Env);
   EXPECT_TRUE(isa<IntegerValue>(BarVal));
 }
@@ -253,7 +253,7 @@
   EXPECT_THAT(Env.getValue(*Var), NotNull());
 }
 
-TEST_F(EnvironmentTest, RefreshStructValue) {
+TEST_F(EnvironmentTest, RefreshRecordValue) {
   using namespace ast_matchers;
 
   std::string Code = R"cc(
@@ -280,7 +280,7 @@
 
   Environment Env(DAContext, *Target);
   EXPECT_THAT(Env.getStorageLocation(*DRE), IsNull());
-  refreshStructValue(*DRE, Env);
+  refreshRecordValue(*DRE, Env);
   EXPECT_THAT(Env.getStorageLocation(*DRE), NotNull());
 }
 
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -376,7 +376,7 @@
   assert(InitExpr != nullptr);
 
   const FieldDecl *Member = nullptr;
-  AggregateStorageLocation *ParentLoc = &ThisLoc;
+  RecordStorageLocation *ParentLoc = &ThisLoc;
   StorageLocation *MemberLoc = nullptr;
   if (Init->isMemberInitializer()) {
     Member = Init->getMember();
@@ -387,7 +387,7 @@
     MemberLoc = &ThisLoc;
     for (const auto *I : IndirectField->chain()) {
       Member = cast<FieldDecl>(I);
-      ParentLoc = cast<AggregateStorageLocation>(MemberLoc);
+      ParentLoc = cast<RecordStorageLocation>(MemberLoc);
       MemberLoc = ParentLoc->getChild(*Member);
     }
   }
@@ -398,8 +398,8 @@
   // to simply use `Environment::createObject()` here, the same way that we do
   // this in `TransferVisitor::VisitInitListExpr()`. However, this would require
   // us to be able to build a list of fields that we then use to initialize an
-  // `AggregateStorageLocation` -- and the problem is that, when we get here,
-  // the `AggregateStorageLocation` already exists. We should explore if there's
+  // `RecordStorageLocation` -- and the problem is that, when we get here,
+  // the `RecordStorageLocation` already exists. We should explore if there's
   // anything that we can do to change this.
   if (Member->getType()->isReferenceType()) {
     auto *InitExprLoc = Env.getStorageLocation(*InitExpr);
@@ -409,13 +409,13 @@
     ParentLoc->setChild(*Member, InitExprLoc);
   } else if (auto *InitExprVal = Env.getValue(*InitExpr)) {
     if (Member->getType()->isRecordType()) {
-      auto *InitValStruct = cast<StructValue>(InitExprVal);
+      auto *InitValStruct = cast<RecordValue>(InitExprVal);
       // FIXME: Rather than performing a copy here, we should really be
       // initializing the field in place. This would require us to propagate the
       // storage location of the field to the AST node that creates the
-      // `StructValue`.
-      copyRecord(InitValStruct->getAggregateLoc(),
-                 *cast<AggregateStorageLocation>(MemberLoc), Env);
+      // `RecordValue`.
+      copyRecord(InitValStruct->getLoc(),
+                 *cast<RecordStorageLocation>(MemberLoc), Env);
     } else {
       Env.setValue(*MemberLoc, *InitExprVal);
     }
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -435,7 +435,7 @@
       }
     }
 
-    AggregateStorageLocation *BaseLoc = getBaseObjectLocation(*S, Env);
+    RecordStorageLocation *BaseLoc = getBaseObjectLocation(*S, Env);
     if (BaseLoc == nullptr)
       return;
 
@@ -464,7 +464,7 @@
       assert(Arg != nullptr);
 
       auto *ArgLoc =
-          cast_or_null<AggregateStorageLocation>(Env.getStorageLocation(*Arg));
+          cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg));
       if (ArgLoc == nullptr)
         return;
 
@@ -472,9 +472,9 @@
         if (Value *Val = Env.getValue(*ArgLoc))
           Env.setValue(*S, *Val);
       } else {
-        auto &Val = *cast<StructValue>(Env.createValue(S->getType()));
+        auto &Val = *cast<RecordValue>(Env.createValue(S->getType()));
         Env.setValue(*S, Val);
-        copyRecord(*ArgLoc, Val.getAggregateLoc(), Env);
+        copyRecord(*ArgLoc, Val.getLoc(), Env);
       }
       return;
     }
@@ -483,9 +483,8 @@
     // of records, and we currently can't create values for arrays. So check if
     // we've got a record type.
     if (S->getType()->isRecordType()) {
-      auto &InitialVal = *cast<StructValue>(Env.createValue(S->getType()));
-      copyRecord(InitialVal.getAggregateLoc(), Env.getResultObjectLocation(*S),
-                 Env);
+      auto &InitialVal = *cast<RecordValue>(Env.createValue(S->getType()));
+      copyRecord(InitialVal.getLoc(), Env.getResultObjectLocation(*S), Env);
     }
 
     transferInlineCall(S, ConstructorDecl);
@@ -511,9 +510,9 @@
         return;
 
       auto *LocSrc =
-          cast_or_null<AggregateStorageLocation>(Env.getStorageLocation(*Arg1));
+          cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg1));
       auto *LocDst =
-          cast_or_null<AggregateStorageLocation>(Env.getStorageLocation(*Arg0));
+          cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg0));
 
       if (LocSrc != nullptr && LocDst != nullptr) {
         copyRecord(*LocSrc, *LocDst, Env);
@@ -573,8 +572,8 @@
     if (SubExprVal == nullptr)
       return;
 
-    if (StructValue *StructVal = dyn_cast<StructValue>(SubExprVal)) {
-      Env.setStorageLocation(*S, StructVal->getAggregateLoc());
+    if (RecordValue *RecordVal = dyn_cast<RecordValue>(SubExprVal)) {
+      Env.setStorageLocation(*S, RecordVal->getLoc());
       return;
     }
 
@@ -638,14 +637,13 @@
     }
 
     auto &Loc =
-        Env.getDataflowAnalysisContext()
-            .arena()
-            .create<AggregateStorageLocation>(Type, std::move(FieldLocs));
-    StructValue &StructVal = Env.create<StructValue>(Loc);
+        Env.getDataflowAnalysisContext().arena().create<RecordStorageLocation>(
+            Type, std::move(FieldLocs));
+    RecordValue &RecordVal = Env.create<RecordValue>(Loc);
 
-    Env.setValue(Loc, StructVal);
+    Env.setValue(Loc, RecordVal);
 
-    Env.setValue(*S, StructVal);
+    Env.setValue(*S, RecordVal);
 
     // FIXME: Implement array initialization.
   }
Index: clang/lib/Analysis/FlowSensitive/RecordOps.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/RecordOps.cpp
+++ clang/lib/Analysis/FlowSensitive/RecordOps.cpp
@@ -14,9 +14,8 @@
 
 #define DEBUG_TYPE "dataflow"
 
-void clang::dataflow::copyRecord(AggregateStorageLocation &Src,
-                                 AggregateStorageLocation &Dst,
-                                 Environment &Env) {
+void clang::dataflow::copyRecord(RecordStorageLocation &Src,
+                                 RecordStorageLocation &Dst, Environment &Env) {
   auto SrcType = Src.getType().getCanonicalType().getUnqualifiedType();
   auto DstType = Dst.getType().getCanonicalType().getUnqualifiedType();
 
@@ -43,8 +42,8 @@
            (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
 
     if (Field->getType()->isRecordType()) {
-      copyRecord(cast<AggregateStorageLocation>(*SrcFieldLoc),
-                 cast<AggregateStorageLocation>(*DstFieldLoc), Env);
+      copyRecord(cast<RecordStorageLocation>(*SrcFieldLoc),
+                 cast<RecordStorageLocation>(*DstFieldLoc), Env);
     } else if (Field->getType()->isReferenceType()) {
       Dst.setChild(*Field, SrcFieldLoc);
     } else {
@@ -55,10 +54,10 @@
     }
   }
 
-  StructValue *SrcVal = cast_or_null<StructValue>(Env.getValue(Src));
-  StructValue *DstVal = cast_or_null<StructValue>(Env.getValue(Dst));
+  RecordValue *SrcVal = cast_or_null<RecordValue>(Env.getValue(Src));
+  RecordValue *DstVal = cast_or_null<RecordValue>(Env.getValue(Dst));
 
-  DstVal = &Env.create<StructValue>(Dst);
+  DstVal = &Env.create<RecordValue>(Dst);
   Env.setValue(Dst, *DstVal);
 
   if (SrcVal == nullptr)
@@ -70,9 +69,9 @@
   }
 }
 
-bool clang::dataflow::recordsEqual(const AggregateStorageLocation &Loc1,
+bool clang::dataflow::recordsEqual(const RecordStorageLocation &Loc1,
                                    const Environment &Env1,
-                                   const AggregateStorageLocation &Loc2,
+                                   const RecordStorageLocation &Loc2,
                                    const Environment &Env2) {
   LLVM_DEBUG({
     if (Loc2.getType().getCanonicalType().getUnqualifiedType() !=
@@ -91,8 +90,8 @@
            (FieldLoc1 != nullptr && FieldLoc2 != nullptr));
 
     if (Field->getType()->isRecordType()) {
-      if (!recordsEqual(cast<AggregateStorageLocation>(*FieldLoc1), Env1,
-                        cast<AggregateStorageLocation>(*FieldLoc2), Env2))
+      if (!recordsEqual(cast<RecordStorageLocation>(*FieldLoc1), Env1,
+                        cast<RecordStorageLocation>(*FieldLoc2), Env2))
         return false;
     } else if (Field->getType()->isReferenceType()) {
       if (FieldLoc1 != FieldLoc2)
@@ -104,10 +103,10 @@
 
   llvm::StringMap<Value *> Props1, Props2;
 
-  if (StructValue *Val1 = cast_or_null<StructValue>(Env1.getValue(Loc1)))
+  if (RecordValue *Val1 = cast_or_null<RecordValue>(Env1.getValue(Loc1)))
     for (const auto &[Name, Value] : Val1->properties())
       Props1[Name] = Value;
-  if (StructValue *Val2 = cast_or_null<StructValue>(Env2.getValue(Loc2)))
+  if (RecordValue *Val2 = cast_or_null<RecordValue>(Env2.getValue(Loc2)))
     for (const auto &[Name, Value] : Val2->properties())
       Props2[Name] = Value;
 
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -256,9 +256,9 @@
 /// Creates a symbolic value for an `optional` value at an existing storage
 /// location. Uses `HasValueVal` as the symbolic value of the "has_value"
 /// property.
-StructValue &createOptionalValue(AggregateStorageLocation &Loc,
+RecordValue &createOptionalValue(RecordStorageLocation &Loc,
                                  BoolValue &HasValueVal, Environment &Env) {
-  auto &OptionalVal = Env.create<StructValue>(Loc);
+  auto &OptionalVal = Env.create<RecordValue>(Loc);
   Env.setValue(Loc, OptionalVal);
   setHasValue(OptionalVal, HasValueVal);
   return OptionalVal;
@@ -335,7 +335,7 @@
     // the check, like another optional or a boolean that influences control
     // flow.
     if (ValueLoc.getType()->isRecordType()) {
-      refreshStructValue(cast<AggregateStorageLocation>(ValueLoc), Env);
+      refreshRecordValue(cast<RecordStorageLocation>(ValueLoc), Env);
       return &ValueLoc;
     } else {
       auto *ValueVal = Env.createValue(ValueLoc.getType());
@@ -356,7 +356,7 @@
   // example:
   //
   //   void target(optional<int> oo, bool b) {
-  //     // `oo` is associated with a `StructValue` here, which we will call
+  //     // `oo` is associated with a `RecordValue` here, which we will call
   //     // `OptionalVal`.
   //
   //     // The `has_value` property is set on `OptionalVal` (but not the
@@ -532,15 +532,13 @@
   if (State.Env.getValue(*E) != nullptr)
     return;
 
-  AggregateStorageLocation *Loc = nullptr;
+  RecordStorageLocation *Loc = nullptr;
   if (E->isPRValue()) {
     Loc = &State.Env.getResultObjectLocation(*E);
   } else {
-    Loc = cast_or_null<AggregateStorageLocation>(
-        State.Env.getStorageLocation(*E));
+    Loc = cast_or_null<RecordStorageLocation>(State.Env.getStorageLocation(*E));
     if (Loc == nullptr) {
-      Loc =
-          &cast<AggregateStorageLocation>(State.Env.createStorageLocation(*E));
+      Loc = &cast<RecordStorageLocation>(State.Env.createStorageLocation(*E));
       State.Env.setStorageLocation(*E, *Loc);
     }
   }
@@ -550,7 +548,7 @@
 
 void constructOptionalValue(const Expr &E, Environment &Env,
                             BoolValue &HasValueVal) {
-  AggregateStorageLocation &Loc = Env.getResultObjectLocation(E);
+  RecordStorageLocation &Loc = Env.getResultObjectLocation(E);
   Env.setValue(E, createOptionalValue(Loc, HasValueVal, Env));
 }
 
@@ -598,7 +596,7 @@
                         LatticeTransferState &State) {
   assert(E->getNumArgs() > 0);
 
-  if (auto *Loc = cast<AggregateStorageLocation>(
+  if (auto *Loc = cast<RecordStorageLocation>(
           State.Env.getStorageLocation(*E->getArg(0)))) {
     createOptionalValue(*Loc, HasValueVal, State.Env);
 
@@ -623,8 +621,8 @@
   transferAssignment(E, State.Env.getBoolLiteralValue(false), State);
 }
 
-void transferSwap(AggregateStorageLocation *Loc1,
-                  AggregateStorageLocation *Loc2, Environment &Env) {
+void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,
+                  Environment &Env) {
   // We account for cases where one or both of the optionals are not modeled,
   // either lacking associated storage locations, or lacking values associated
   // to such storage locations.
@@ -661,7 +659,7 @@
                       const MatchFinder::MatchResult &,
                       LatticeTransferState &State) {
   assert(E->getNumArgs() == 1);
-  auto *OtherLoc = cast_or_null<AggregateStorageLocation>(
+  auto *OtherLoc = cast_or_null<RecordStorageLocation>(
       State.Env.getStorageLocation(*E->getArg(0)));
   transferSwap(getImplicitObjectLocation(*E, State.Env), OtherLoc, State.Env);
 }
@@ -669,9 +667,9 @@
 void transferStdSwapCall(const CallExpr *E, const MatchFinder::MatchResult &,
                          LatticeTransferState &State) {
   assert(E->getNumArgs() == 2);
-  auto *Arg0Loc = cast_or_null<AggregateStorageLocation>(
+  auto *Arg0Loc = cast_or_null<RecordStorageLocation>(
       State.Env.getStorageLocation(*E->getArg(0)));
-  auto *Arg1Loc = cast_or_null<AggregateStorageLocation>(
+  auto *Arg1Loc = cast_or_null<RecordStorageLocation>(
       State.Env.getStorageLocation(*E->getArg(1)));
   transferSwap(Arg0Loc, Arg1Loc, State.Env);
 }
@@ -848,7 +846,7 @@
           isOptionalMemberCallWithNameMatcher(hasName("emplace")),
           [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &,
              LatticeTransferState &State) {
-            if (AggregateStorageLocation *Loc =
+            if (RecordStorageLocation *Loc =
                     getImplicitObjectLocation(*E, State.Env)) {
               createOptionalValue(*Loc, State.Env.getBoolLiteralValue(true),
                                   State.Env);
@@ -860,7 +858,7 @@
           isOptionalMemberCallWithNameMatcher(hasName("reset")),
           [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &,
              LatticeTransferState &State) {
-            if (AggregateStorageLocation *Loc =
+            if (RecordStorageLocation *Loc =
                     getImplicitObjectLocation(*E, State.Env)) {
               createOptionalValue(*Loc, State.Env.getBoolLiteralValue(false),
                                   State.Env);
@@ -1032,7 +1030,7 @@
       if (isa<TopBoolValue>(CurrentHasVal))
         return &Current;
     }
-    return &createOptionalValue(cast<StructValue>(Current).getAggregateLoc(),
+    return &createOptionalValue(cast<RecordValue>(Current).getLoc(),
                                 CurrentEnv.makeTopBoolValue(), CurrentEnv);
   case ComparisonResult::Unknown:
     return nullptr;
Index: clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
+++ clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
@@ -103,9 +103,8 @@
       JOS.attributeObject(
           "pointee", [&] { dump(cast<PointerValue>(V).getPointeeLoc()); });
       break;
-    case Value::Kind::Struct:
-      for (const auto &Child :
-           cast<StructValue>(V).getAggregateLoc().children())
+    case Value::Kind::Record:
+      for (const auto &Child : cast<RecordValue>(V).getLoc().children())
         JOS.attributeObject("f:" + Child.first->getNameAsString(), [&] {
           if (Child.second)
             if (Value *Val = Env.getValue(*Child.second))
Index: clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
+++ clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
@@ -28,8 +28,8 @@
     return "Integer";
   case Value::Kind::Pointer:
     return "Pointer";
-  case Value::Kind::Struct:
-    return "Struct";
+  case Value::Kind::Record:
+    return "Record";
   case Value::Kind::AtomicBool:
     return "AtomicBool";
   case Value::Kind::TopBool:
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -69,7 +69,7 @@
     switch (Val1.getKind()) {
     case Value::Kind::Integer:
     case Value::Kind::Pointer:
-    case Value::Kind::Struct:
+    case Value::Kind::Record:
       // FIXME: this choice intentionally introduces unsoundness to allow
       // for convergence. Once we have widening support for the
       // reference/pointer and struct built-in models, this should be
@@ -120,19 +120,19 @@
   }
 
   Value *MergedVal = nullptr;
-  if (auto *StructVal1 = dyn_cast<StructValue>(&Val1)) {
-    [[maybe_unused]] auto *StructVal2 = cast<StructValue>(&Val2);
+  if (auto *RecordVal1 = dyn_cast<RecordValue>(&Val1)) {
+    [[maybe_unused]] auto *RecordVal2 = cast<RecordValue>(&Val2);
 
     // Values to be merged are always associated with the same location in
-    // `LocToVal`. The location stored in `StructVal` should therefore also
+    // `LocToVal`. The location stored in `RecordVal` should therefore also
     // be the same.
-    assert(&StructVal1->getAggregateLoc() == &StructVal2->getAggregateLoc());
+    assert(&RecordVal1->getLoc() == &RecordVal2->getLoc());
 
-    // `StructVal1` and `StructVal2` may have different properties associated
-    // with them. Create a new `StructValue` without any properties so that we
+    // `RecordVal1` and `RecordVal2` may have different properties associated
+    // with them. Create a new `RecordValue` without any properties so that we
     // soundly approximate both values. If a particular analysis needs to merge
     // properties, it should do so in `DataflowAnalysis::merge()`.
-    MergedVal = &MergedEnv.create<StructValue>(StructVal1->getAggregateLoc());
+    MergedVal = &MergedEnv.create<RecordValue>(RecordVal1->getLoc());
   } else {
     MergedVal = MergedEnv.createValue(Type);
   }
@@ -320,7 +320,7 @@
     if (MethodDecl && !MethodDecl->isStatic()) {
       QualType ThisPointeeType = MethodDecl->getThisObjectType();
       ThisPointeeLoc =
-          &cast<StructValue>(createValue(ThisPointeeType))->getAggregateLoc();
+          &cast<RecordValue>(createValue(ThisPointeeType))->getLoc();
     }
   }
 }
@@ -337,7 +337,7 @@
     if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
       if (!isa<CXXThisExpr>(Arg))
           Env.ThisPointeeLoc =
-              cast<AggregateStorageLocation>(getStorageLocation(*Arg));
+              cast<RecordStorageLocation>(getStorageLocation(*Arg));
       // Otherwise (when the argument is `this`), retain the current
       // environment's `ThisPointeeLoc`.
     }
@@ -634,18 +634,18 @@
   return getStorageLocationInternal(E);
 }
 
-AggregateStorageLocation *Environment::getThisPointeeStorageLocation() const {
+RecordStorageLocation *Environment::getThisPointeeStorageLocation() const {
   return ThisPointeeLoc;
 }
 
-AggregateStorageLocation &
+RecordStorageLocation &
 Environment::getResultObjectLocation(const Expr &RecordPRValue) {
   assert(RecordPRValue.getType()->isRecordType());
   assert(RecordPRValue.isPRValue());
 
   if (StorageLocation *ExistingLoc = getStorageLocationInternal(RecordPRValue))
-    return *cast<AggregateStorageLocation>(ExistingLoc);
-  auto &Loc = cast<AggregateStorageLocation>(
+    return *cast<RecordStorageLocation>(ExistingLoc);
+  auto &Loc = cast<RecordStorageLocation>(
       DACtx->getStableStorageLocation(RecordPRValue));
   setStorageLocationInternal(RecordPRValue, Loc);
   return Loc;
@@ -656,8 +656,7 @@
 }
 
 void Environment::setValue(const StorageLocation &Loc, Value &Val) {
-  assert(!isa<StructValue>(&Val) ||
-         &cast<StructValue>(&Val)->getAggregateLoc() == &Loc);
+  assert(!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)->getLoc() == &Loc);
 
   LocToVal[&Loc] = &Val;
 }
@@ -665,16 +664,16 @@
 void Environment::setValue(const Expr &E, Value &Val) {
   assert(E.isPRValue());
 
-  if (auto *StructVal = dyn_cast<StructValue>(&Val)) {
+  if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) {
     if ([[maybe_unused]] auto *ExistingVal =
-            cast_or_null<StructValue>(getValue(E)))
-      assert(&ExistingVal->getAggregateLoc() == &StructVal->getAggregateLoc());
+            cast_or_null<RecordValue>(getValue(E)))
+      assert(&ExistingVal->getLoc() == &RecordVal->getLoc());
     if ([[maybe_unused]] StorageLocation *ExistingLoc =
             getStorageLocationInternal(E))
-      assert(ExistingLoc == &StructVal->getAggregateLoc());
+      assert(ExistingLoc == &RecordVal->getLoc());
     else
-      setStorageLocationInternal(E, StructVal->getAggregateLoc());
-    setValue(StructVal->getAggregateLoc(), Val);
+      setStorageLocationInternal(E, RecordVal->getLoc());
+    setValue(RecordVal->getLoc(), Val);
     return;
   }
 
@@ -774,15 +773,15 @@
                                           CreatedValuesCount)});
     }
 
-    AggregateStorageLocation &Loc =
-        arena().create<AggregateStorageLocation>(Type, std::move(FieldLocs));
-    StructValue &StructVal = create<StructValue>(Loc);
+    RecordStorageLocation &Loc =
+        arena().create<RecordStorageLocation>(Type, std::move(FieldLocs));
+    RecordValue &RecordVal = create<RecordValue>(Loc);
 
-    // As we already have a storage location for the `StructValue`, we can and
+    // As we already have a storage location for the `RecordValue`, we can and
     // should associate them in the environment.
-    setValue(Loc, StructVal);
+    setValue(Loc, RecordVal);
 
-    return &StructVal;
+    return &RecordVal;
   }
 
   return nullptr;
@@ -804,7 +803,7 @@
     return createStorageLocation(Ty);
 
   if (Ty->isRecordType())
-    return cast<StructValue>(Val)->getAggregateLoc();
+    return cast<RecordValue>(Val)->getLoc();
 
   StorageLocation &Loc = createStorageLocation(Ty);
   setValue(Loc, *Val);
@@ -850,7 +849,7 @@
     Val = createValue(Ty);
 
   if (Ty->isRecordType())
-    return cast<StructValue>(Val)->getAggregateLoc();
+    return cast<RecordValue>(Val)->getLoc();
 
   StorageLocation &Loc =
       D ? createStorageLocation(*D) : createStorageLocation(Ty);
@@ -893,32 +892,31 @@
   dump(llvm::dbgs());
 }
 
-AggregateStorageLocation *
-getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
-                          const Environment &Env) {
+RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
+                                                 const Environment &Env) {
   Expr *ImplicitObject = MCE.getImplicitObjectArgument();
   if (ImplicitObject == nullptr)
     return nullptr;
   if (ImplicitObject->getType()->isPointerType()) {
     if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*ImplicitObject)))
-      return &cast<AggregateStorageLocation>(Val->getPointeeLoc());
+      return &cast<RecordStorageLocation>(Val->getPointeeLoc());
     return nullptr;
   }
-  return cast_or_null<AggregateStorageLocation>(
+  return cast_or_null<RecordStorageLocation>(
       Env.getStorageLocation(*ImplicitObject));
 }
 
-AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
-                                                const Environment &Env) {
+RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
+                                             const Environment &Env) {
   Expr *Base = ME.getBase();
   if (Base == nullptr)
     return nullptr;
   if (ME.isArrow()) {
     if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*Base)))
-      return &cast<AggregateStorageLocation>(Val->getPointeeLoc());
+      return &cast<RecordStorageLocation>(Val->getPointeeLoc());
     return nullptr;
   }
-  return cast_or_null<AggregateStorageLocation>(Env.getStorageLocation(*Base));
+  return cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Base));
 }
 
 std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) {
@@ -933,37 +931,36 @@
   return Fields;
 }
 
-StructValue &refreshStructValue(AggregateStorageLocation &Loc,
-                                Environment &Env) {
-  auto &NewVal = Env.create<StructValue>(Loc);
+RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) {
+  auto &NewVal = Env.create<RecordValue>(Loc);
   Env.setValue(Loc, NewVal);
   return NewVal;
 }
 
-StructValue &refreshStructValue(const Expr &Expr, Environment &Env) {
+RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) {
   assert(Expr.getType()->isRecordType());
 
   if (Expr.isPRValue()) {
-    if (auto *ExistingVal = cast_or_null<StructValue>(Env.getValue(Expr))) {
-      auto &NewVal = Env.create<StructValue>(ExistingVal->getAggregateLoc());
+    if (auto *ExistingVal = cast_or_null<RecordValue>(Env.getValue(Expr))) {
+      auto &NewVal = Env.create<RecordValue>(ExistingVal->getLoc());
       Env.setValue(Expr, NewVal);
       return NewVal;
     }
 
-    auto &NewVal = *cast<StructValue>(Env.createValue(Expr.getType()));
+    auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType()));
     Env.setValue(Expr, NewVal);
     return NewVal;
   }
 
-  if (auto *Loc = cast_or_null<AggregateStorageLocation>(
-          Env.getStorageLocation(Expr))) {
-    auto &NewVal = Env.create<StructValue>(*Loc);
+  if (auto *Loc =
+          cast_or_null<RecordStorageLocation>(Env.getStorageLocation(Expr))) {
+    auto &NewVal = Env.create<RecordValue>(*Loc);
     Env.setValue(*Loc, NewVal);
     return NewVal;
   }
 
-  auto &NewVal = *cast<StructValue>(Env.createValue(Expr.getType()));
-  Env.setStorageLocation(Expr, NewVal.getAggregateLoc());
+  auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType()));
+  Env.setStorageLocation(Expr, NewVal.getLoc());
   return NewVal;
 }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -67,7 +67,7 @@
       else
         FieldLocs.insert({Field, &createStorageLocation(
                                      Field->getType().getNonReferenceType())});
-    return arena().create<AggregateStorageLocation>(Type, std::move(FieldLocs));
+    return arena().create<RecordStorageLocation>(Type, std::move(FieldLocs));
   }
   return arena().create<ScalarStorageLocation>(Type);
 }
Index: clang/include/clang/Analysis/FlowSensitive/Value.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/Value.h
+++ clang/include/clang/Analysis/FlowSensitive/Value.h
@@ -35,7 +35,9 @@
   enum class Kind {
     Integer,
     Pointer,
-    Struct,
+    Record,
+    // Deprecated synonym for `Record`
+    Struct = Record,
 
     // TODO: Top values should not be need to be type-specific.
     TopBool,
@@ -184,13 +186,13 @@
 /// In C++, prvalues of class type serve only a limited purpose: They can only
 /// be used to initialize a result object. It is not possible to access member
 /// variables or call member functions on a prvalue of class type.
-/// Correspondingly, `StructValue` also serves only two limited purposes:
+/// Correspondingly, `RecordValue` also serves only two limited purposes:
 /// - It conveys a prvalue of class type from the place where the object is
 ///   constructed to the result object that it initializes.
 ///
 ///   When creating a prvalue of class type, we already need a storage location
 ///   for `this`, even though prvalues are otherwise not associated with storage
-///   locations. `StructValue` is therefore essentially a wrapper for a storage
+///   locations. `RecordValue` is therefore essentially a wrapper for a storage
 ///   location, which is then used to set the storage location for the result
 ///   object when we process the AST node for that result object.
 ///
@@ -198,43 +200,49 @@
 ///      MyStruct S = MyStruct(3);
 ///
 ///   In this example, `MyStruct(3) is a prvalue, which is modeled as a
-///   `StructValue` that wraps an `AbstractStorageLocation`. This
-//    `AbstractStorageLocation` is then used as the storage location for `S`.
+///   `RecordValue` that wraps a `RecordStorageLocation`. This
+//    `RecordStorageLocation` is then used as the storage location for `S`.
 ///
 /// - It allows properties to be associated with an object of class type.
 ///   Note that when doing so, you should avoid mutating the properties of an
-///   existing `StructValue` in place, as these changes would be visible to
-///   other `Environment`s that share the same `StructValue`. Instead, associate
-///   a new `StructValue` with the `AggregateStorageLocation` and set the
-///   properties on this new `StructValue`. (See also `refreshStructValue()` in
+///   existing `RecordValue` in place, as these changes would be visible to
+///   other `Environment`s that share the same `RecordValue`. Instead, associate
+///   a new `RecordValue` with the `RecordStorageLocation` and set the
+///   properties on this new `RecordValue`. (See also `refreshRecordValue()` in
 ///   DataflowEnvironment.h, which makes this easy.)
 ///   Note also that this implies that it is common for the same
-///   `AggregateStorageLocation` to be associated with different `StructValue`s
+///   `RecordStorageLocation` to be associated with different `RecordValue`s
 ///   in different environments.
-/// Over time, we may eliminate `StructValue` entirely. See also the discussion
+/// Over time, we may eliminate `RecordValue` entirely. See also the discussion
 /// here: https://reviews.llvm.org/D155204#inline-1503204
-class StructValue final : public Value {
+class RecordValue final : public Value {
 public:
-  explicit StructValue(AggregateStorageLocation &Loc)
-      : Value(Kind::Struct), Loc(Loc) {}
+  explicit RecordValue(RecordStorageLocation &Loc)
+      : Value(Kind::Record), Loc(Loc) {}
 
   static bool classof(const Value *Val) {
-    return Val->getKind() == Kind::Struct;
+    return Val->getKind() == Kind::Record;
   }
 
-  /// Returns the storage location that this `StructValue` is associated with.
-  AggregateStorageLocation &getAggregateLoc() const { return Loc; }
+  /// Returns the storage location that this `RecordValue` is associated with.
+  RecordStorageLocation &getLoc() const { return Loc; }
+
+  /// Deprecated synonym for `getLoc()`.
+  RecordStorageLocation &getAggregateLoc() const { return Loc; }
 
   /// Convenience function that returns the child storage location for `Field`.
-  /// See also the documentation for `AggregateStorageLocation::getChild()`.
+  /// See also the documentation for `RecordStorageLocation::getChild()`.
   StorageLocation *getChild(const ValueDecl &Field) const {
     return Loc.getChild(Field);
   }
 
 private:
-  AggregateStorageLocation &Loc;
+  RecordStorageLocation &Loc;
 };
 
+/// Deprecated synonym for `RecordValue`.
+using StructValue = RecordValue;
+
 raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
 
 } // namespace dataflow
Index: clang/include/clang/Analysis/FlowSensitive/StorageLocation.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/StorageLocation.h
+++ clang/include/clang/Analysis/FlowSensitive/StorageLocation.h
@@ -31,7 +31,12 @@
 /// values is stored in the environment.
 class StorageLocation {
 public:
-  enum class Kind { Scalar, Aggregate };
+  enum class Kind {
+    Scalar,
+    Record,
+    // Deprecated synonym for `Record`
+    Aggregate = Record,
+  };
 
   StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) {
     assert(Type.isNull() || !Type->isReferenceType());
@@ -66,11 +71,11 @@
   }
 };
 
-/// A storage location which is subdivided into smaller storage locations that
-/// can be traced independently by abstract interpretation. For example: a
-/// struct with public members. The child map is flat, so when used for a struct
-/// or class type, all accessible members of base struct and class types are
-/// directly accesible as children of this location.
+/// A storage location for a record (struct, class, or union).
+///
+/// Contains storage locations for all modeled fields of the record (also
+/// referred to as "children"). The child map is flat, so accessible members of
+/// the base class are directly accesible as children of this location.
 ///
 /// The storage location for a field of reference type may be null. This
 /// typically occurs in one of two situations:
@@ -82,16 +87,15 @@
 /// FIXME: Currently, the storage location of unions is modelled the same way as
 /// that of structs or classes. Eventually, we need to change this modelling so
 /// that all of the members of a given union have the same storage location.
-class AggregateStorageLocation final : public StorageLocation {
+class RecordStorageLocation final : public StorageLocation {
 public:
   using FieldToLoc = llvm::DenseMap<const ValueDecl *, StorageLocation *>;
 
-  explicit AggregateStorageLocation(QualType Type)
-      : AggregateStorageLocation(Type, FieldToLoc()) {}
+  explicit RecordStorageLocation(QualType Type)
+      : RecordStorageLocation(Type, FieldToLoc()) {}
 
-  AggregateStorageLocation(QualType Type, FieldToLoc TheChildren)
-      : StorageLocation(Kind::Aggregate, Type),
-        Children(std::move(TheChildren)) {
+  RecordStorageLocation(QualType Type, FieldToLoc TheChildren)
+      : StorageLocation(Kind::Record, Type), Children(std::move(TheChildren)) {
     assert(!Type.isNull());
     assert(Type->isRecordType());
     assert([this] {
@@ -104,7 +108,7 @@
   }
 
   static bool classof(const StorageLocation *Loc) {
-    return Loc->getKind() == Kind::Aggregate;
+    return Loc->getKind() == Kind::Record;
   }
 
   /// Returns the child storage location for `D`.
@@ -133,7 +137,7 @@
 
   /// Changes the child storage location for a field `D` of reference type.
   /// All other fields cannot change their storage location and always retain
-  /// the storage location passed to the `AggregateStorageLocation` constructor.
+  /// the storage location passed to the `RecordStorageLocation` constructor.
   ///
   /// Requirements:
   ///
@@ -151,6 +155,9 @@
   FieldToLoc Children;
 };
 
+/// Deprecated synonym for `RecordStorageLocation`.
+using AggregateStorageLocation = RecordStorageLocation;
+
 } // namespace dataflow
 } // namespace clang
 
Index: clang/include/clang/Analysis/FlowSensitive/RecordOps.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/RecordOps.h
+++ clang/include/clang/Analysis/FlowSensitive/RecordOps.h
@@ -22,23 +22,23 @@
 /// Copies a record (struct, class, or union) from `Src` to `Dst`.
 ///
 /// This performs a deep copy, i.e. it copies every field and recurses on
-/// fields of record type. It also copies properties from the `StructValue`
-/// associated with `Src` to the `StructValue` associated with `Dst` (if these
-/// `StructValue`s exist).
+/// fields of record type. It also copies properties from the `RecordValue`
+/// associated with `Src` to the `RecordValue` associated with `Dst` (if these
+/// `RecordValue`s exist).
 ///
-/// If there is a `StructValue` associated with `Dst` in the environment, this
-/// function creates a new `StructValue` and associates it with `Dst`; clients
-/// need to be aware of this and must not assume that the `StructValue`
+/// If there is a `RecordValue` associated with `Dst` in the environment, this
+/// function creates a new `RecordValue` and associates it with `Dst`; clients
+/// need to be aware of this and must not assume that the `RecordValue`
 /// associated with `Dst` remains the same after the call.
 ///
-/// We create a new `StructValue` rather than modifying properties on the old
-/// `StructValue` because the old `StructValue` may be shared with other
+/// We create a new `RecordValue` rather than modifying properties on the old
+/// `RecordValue` because the old `RecordValue` may be shared with other
 /// `Environment`s, and we don't want changes to properties to be visible there.
 ///
 /// Requirements:
 ///
 ///  `Src` and `Dst` must have the same canonical unqualified type.
-void copyRecord(AggregateStorageLocation &Src, AggregateStorageLocation &Dst,
+void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst,
                 Environment &Env);
 
 /// Returns whether the records `Loc1` and `Loc2` are equal.
@@ -49,8 +49,8 @@
 ///
 /// This performs a deep comparison, i.e. it compares every field and recurses
 /// on fields of record type. Fields of reference type compare equal if they
-/// refer to the same storage location. If `StructValue`s are associated with
-/// `Loc1` and `Loc2`, it also compares the properties on those `StructValue`s.
+/// refer to the same storage location. If `RecordValue`s are associated with
+/// `Loc1` and `Loc2`, it also compares the properties on those `RecordValue`s.
 ///
 /// Note on how to interpret the result:
 /// - If this returns true, the records are guaranteed to be equal at runtime.
@@ -60,12 +60,11 @@
 /// Requirements:
 ///
 ///  `Src` and `Dst` must have the same canonical unqualified type.
-bool recordsEqual(const AggregateStorageLocation &Loc1, const Environment &Env1,
-                  const AggregateStorageLocation &Loc2,
-                  const Environment &Env2);
+bool recordsEqual(const RecordStorageLocation &Loc1, const Environment &Env1,
+                  const RecordStorageLocation &Loc2, const Environment &Env2);
 
-inline bool recordsEqual(const AggregateStorageLocation &Loc1,
-                         const AggregateStorageLocation &Loc2,
+inline bool recordsEqual(const RecordStorageLocation &Loc1,
+                         const RecordStorageLocation &Loc2,
                          const Environment &Env) {
   return recordsEqual(Loc1, Env, Loc2, Env);
 }
Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -76,7 +76,7 @@
     virtual ComparisonResult compare(QualType Type, const Value &Val1,
                                      const Environment &Env1, const Value &Val2,
                                      const Environment &Env2) {
-      // FIXME: Consider adding QualType to StructValue and removing the Type
+      // FIXME: Consider adding QualType to RecordValue and removing the Type
       // argument here.
       return ComparisonResult::Unknown;
     }
@@ -300,7 +300,7 @@
   /// Returns the storage location assigned to the `this` pointee in the
   /// environment or null if the `this` pointee has no assigned storage location
   /// in the environment.
-  AggregateStorageLocation *getThisPointeeStorageLocation() const;
+  RecordStorageLocation *getThisPointeeStorageLocation() const;
 
   /// Returns the location of the result object for a record-type prvalue.
   ///
@@ -325,7 +325,7 @@
   ///
   /// Requirements:
   ///  `E` must be a prvalue of record type.
-  AggregateStorageLocation &getResultObjectLocation(const Expr &RecordPRValue);
+  RecordStorageLocation &getResultObjectLocation(const Expr &RecordPRValue);
 
   /// Returns the return value of the current function. This can be null if:
   /// - The function has a void return type
@@ -385,8 +385,8 @@
   /// non-pointer/non-reference type.
   ///
   /// If `Type` is a class, struct, or union type, calls `setValue()` to
-  /// associate the `StructValue` with its storage location
-  /// (`StructValue::getAggregateLoc()`).
+  /// associate the `RecordValue` with its storage location
+  /// (`RecordValue::getLoc()`).
   ///
   /// If `Type` is one of the following types, this function will always return
   /// a non-null pointer:
@@ -448,10 +448,10 @@
   ///
   ///  `E` must be a prvalue
   ///  `Val` must not be a `ReferenceValue`
-  ///  If `Val` is a `StructValue`, its `AggregateStorageLocation` must be the
-  ///  same as that of any `StructValue` that has already been associated with
+  ///  If `Val` is a `RecordValue`, its `RecordStorageLocation` must be the
+  ///  same as that of any `RecordValue` that has already been associated with
   ///  `E`. This is to guarantee that the result object initialized by a prvalue
-  ///  `StructValue` has a durable storage location.
+  ///  `RecordValue` has a durable storage location.
   void setValue(const Expr &E, Value &Val);
 
   /// Deprecated synonym for `setValue()`.
@@ -662,7 +662,7 @@
   StorageLocation *ReturnLoc = nullptr;
   // The storage location of the `this` pointee. Should only be null if the
   // function being analyzed is only a function and not a method.
-  AggregateStorageLocation *ThisPointeeLoc = nullptr;
+  RecordStorageLocation *ThisPointeeLoc = nullptr;
 
   // Maps from program declarations and statements to storage locations that are
   // assigned to them. Unlike the maps in `DataflowAnalysisContext`, these
@@ -681,36 +681,44 @@
 /// `CXXMemberCallExpr`, or null if none is defined in the environment.
 /// Dereferences the pointer if the member call expression was written using
 /// `->`.
-AggregateStorageLocation *
-getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env);
+RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
+                                                 const Environment &Env);
 
 /// Returns the storage location for the base object of a `MemberExpr`, or null
 /// if none is defined in the environment. Dereferences the pointer if the
 /// member expression was written using `->`.
-AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
-                                                const Environment &Env);
+RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
+                                             const Environment &Env);
 
 /// Returns the fields of `RD` that are initialized by an `InitListExpr`, in the
 /// order in which they appear in `InitListExpr::inits()`.
 std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD);
 
-/// Associates a new `StructValue` with `Loc` and returns the new value.
+/// Associates a new `RecordValue` with `Loc` and returns the new value.
 /// It is not defined whether the field values remain the same or not.
 ///
 /// This function is primarily intended for use by checks that set custom
-/// properties on `StructValue`s to model the state of these values. Such checks
-/// should avoid modifying the properties of an existing `StructValue` because
+/// properties on `RecordValue`s to model the state of these values. Such checks
+/// should avoid modifying the properties of an existing `RecordValue` because
 /// these changes would be visible to other `Environment`s that share the same
-/// `StructValue`. Instead, call `refreshStructValue()`, then set the properties
-/// on the new `StructValue` that it returns. Typical usage:
+/// `RecordValue`. Instead, call `refreshRecordValue()`, then set the properties
+/// on the new `RecordValue` that it returns. Typical usage:
 ///
-///   refreshStructValue(Loc, Env).setProperty("my_prop", MyPropValue);
-StructValue &refreshStructValue(AggregateStorageLocation &Loc,
-                                Environment &Env);
+///   refreshRecordValue(Loc, Env).setProperty("my_prop", MyPropValue);
+RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env);
 
-/// Associates a new `StructValue` with `Expr` and returns the new value.
+/// Associates a new `RecordValue` with `Expr` and returns the new value.
 /// See also documentation for the overload above.
-StructValue &refreshStructValue(const Expr &Expr, Environment &Env);
+RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env);
+
+/// Deprecated synonym for `refreshRecordValue()`.
+inline RecordValue &refreshStructValue(RecordStorageLocation &Loc,
+                                       Environment &Env) {
+  return refreshRecordValue(Loc, Env);
+}
+inline RecordValue &refreshStructValue(const Expr &Expr, Environment &Env) {
+  return refreshRecordValue(Expr, Env);
+}
 
 } // namespace dataflow
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D156788: [clang][dat... Martin Böhme via Phabricator via cfe-commits

Reply via email to