23
23
#include " llvm/ADT/DenseSet.h"
24
24
#include " llvm/ADT/MapVector.h"
25
25
#include " llvm/ADT/STLExtras.h"
26
+ #include " llvm/ADT/ScopeExit.h"
26
27
#include " llvm/Support/ErrorHandling.h"
27
28
#include < cassert>
28
29
#include < utility>
@@ -79,7 +80,6 @@ static bool equateUnknownValues(Value::Kind K) {
79
80
switch (K) {
80
81
case Value::Kind::Integer:
81
82
case Value::Kind::Pointer:
82
- case Value::Kind::Record:
83
83
return true ;
84
84
default :
85
85
return false ;
@@ -144,25 +144,7 @@ static Value *joinDistinctValues(QualType Type, Value &Val1,
144
144
return &A.makeBoolValue (JoinedVal);
145
145
}
146
146
147
- Value *JoinedVal = nullptr ;
148
- if (auto *RecordVal1 = dyn_cast<RecordValue>(&Val1)) {
149
- auto *RecordVal2 = cast<RecordValue>(&Val2);
150
-
151
- if (&RecordVal1->getLoc () == &RecordVal2->getLoc ())
152
- // `RecordVal1` and `RecordVal2` may have different properties associated
153
- // with them. Create a new `RecordValue` with the same location but
154
- // without any properties so that we soundly approximate both values. If a
155
- // particular analysis needs to join properties, it should do so in
156
- // `DataflowAnalysis::join()`.
157
- JoinedVal = &JoinedEnv.create <RecordValue>(RecordVal1->getLoc ());
158
- else
159
- // If the locations for the two records are different, need to create a
160
- // completely new value.
161
- JoinedVal = JoinedEnv.createValue (Type);
162
- } else {
163
- JoinedVal = JoinedEnv.createValue (Type);
164
- }
165
-
147
+ Value *JoinedVal = JoinedEnv.createValue (Type);
166
148
if (JoinedVal)
167
149
Model.join (Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv);
168
150
@@ -627,7 +609,6 @@ void Environment::initialize() {
627
609
auto &ThisLoc =
628
610
cast<RecordStorageLocation>(createStorageLocation (ThisPointeeType));
629
611
setThisPointeeStorageLocation (ThisLoc);
630
- refreshRecordValue (ThisLoc, *this );
631
612
// Initialize fields of `*this` with values, but only if we're not
632
613
// analyzing a constructor; after all, it's the constructor's job to do
633
614
// this (and we want to be able to test that).
@@ -794,10 +775,6 @@ void Environment::popCall(const CXXConstructExpr *Call,
794
775
// See also comment in `popCall(const CallExpr *, const Environment &)` above.
795
776
this ->LocToVal = std::move (CalleeEnv.LocToVal );
796
777
this ->FlowConditionToken = std::move (CalleeEnv.FlowConditionToken );
797
-
798
- if (Value *Val = CalleeEnv.getValue (*CalleeEnv.ThisPointeeLoc )) {
799
- setValue (*Call, *Val);
800
- }
801
778
}
802
779
803
780
bool Environment::equivalentTo (const Environment &Other,
@@ -1021,24 +998,23 @@ void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
1021
998
}
1022
999
1023
1000
void Environment::setValue (const StorageLocation &Loc, Value &Val) {
1024
- assert (!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)-> getLoc () == &Loc);
1025
-
1001
+ // Records should not be associated with values.
1002
+ assert (!isa<RecordStorageLocation>(Loc));
1026
1003
LocToVal[&Loc] = &Val;
1027
1004
}
1028
1005
1029
1006
void Environment::setValue (const Expr &E, Value &Val) {
1030
1007
const Expr &CanonE = ignoreCFGOmittedNodes (E);
1031
1008
1032
- if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) {
1033
- assert (&RecordVal->getLoc () == &getResultObjectLocation (CanonE));
1034
- (void )RecordVal;
1035
- }
1036
-
1037
1009
assert (CanonE.isPRValue ());
1010
+ // Records should not be associated with values.
1011
+ assert (!CanonE.getType ()->isRecordType ());
1038
1012
ExprToVal[&CanonE] = &Val;
1039
1013
}
1040
1014
1041
1015
Value *Environment::getValue (const StorageLocation &Loc) const {
1016
+ // Records should not be associated with values.
1017
+ assert (!isa<RecordStorageLocation>(Loc));
1042
1018
return LocToVal.lookup (&Loc);
1043
1019
}
1044
1020
@@ -1050,6 +1026,9 @@ Value *Environment::getValue(const ValueDecl &D) const {
1050
1026
}
1051
1027
1052
1028
Value *Environment::getValue (const Expr &E) const {
1029
+ // Records should not be associated with values.
1030
+ assert (!E.getType ()->isRecordType ());
1031
+
1053
1032
if (E.isPRValue ()) {
1054
1033
auto It = ExprToVal.find (&ignoreCFGOmittedNodes (E));
1055
1034
return It == ExprToVal.end () ? nullptr : It->second ;
@@ -1078,6 +1057,7 @@ Value *Environment::createValueUnlessSelfReferential(
1078
1057
int &CreatedValuesCount) {
1079
1058
assert (!Type.isNull ());
1080
1059
assert (!Type->isReferenceType ());
1060
+ assert (!Type->isRecordType ());
1081
1061
1082
1062
// Allow unlimited fields at depth 1; only cap at deeper nesting levels.
1083
1063
if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
@@ -1106,15 +1086,6 @@ Value *Environment::createValueUnlessSelfReferential(
1106
1086
return &arena ().create <PointerValue>(PointeeLoc);
1107
1087
}
1108
1088
1109
- if (Type->isRecordType ()) {
1110
- CreatedValuesCount++;
1111
- auto &Loc = cast<RecordStorageLocation>(createStorageLocation (Type));
1112
- initializeFieldsWithValues (Loc, Loc.getType (), Visited, Depth,
1113
- CreatedValuesCount);
1114
-
1115
- return &refreshRecordValue (Loc, *this );
1116
- }
1117
-
1118
1089
return nullptr ;
1119
1090
}
1120
1091
@@ -1124,20 +1095,23 @@ Environment::createLocAndMaybeValue(QualType Ty,
1124
1095
int Depth, int &CreatedValuesCount) {
1125
1096
if (!Visited.insert (Ty.getCanonicalType ()).second )
1126
1097
return createStorageLocation (Ty.getNonReferenceType ());
1127
- Value *Val = createValueUnlessSelfReferential (
1128
- Ty.getNonReferenceType (), Visited, Depth, CreatedValuesCount);
1129
- Visited.erase (Ty.getCanonicalType ());
1098
+ auto EraseVisited = llvm::make_scope_exit (
1099
+ [&Visited, Ty] { Visited.erase (Ty.getCanonicalType ()); });
1130
1100
1131
1101
Ty = Ty.getNonReferenceType ();
1132
1102
1133
- if (Val == nullptr )
1134
- return createStorageLocation (Ty);
1135
-
1136
- if (Ty-> isRecordType ())
1137
- return cast<RecordValue>(Val)-> getLoc ();
1103
+ if (Ty-> isRecordType ()) {
1104
+ auto &Loc = cast<RecordStorageLocation>( createStorageLocation (Ty) );
1105
+ initializeFieldsWithValues (Loc, Ty, Visited, Depth, CreatedValuesCount);
1106
+ return Loc;
1107
+ }
1138
1108
1139
1109
StorageLocation &Loc = createStorageLocation (Ty);
1140
- setValue (Loc, *Val);
1110
+
1111
+ if (Value *Val = createValueUnlessSelfReferential (Ty, Visited, Depth,
1112
+ CreatedValuesCount))
1113
+ setValue (Loc, *Val);
1114
+
1141
1115
return Loc;
1142
1116
}
1143
1117
@@ -1149,10 +1123,11 @@ void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
1149
1123
auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) {
1150
1124
if (FieldType->isRecordType ()) {
1151
1125
auto &FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc);
1152
- setValue (FieldRecordLoc, create<RecordValue>(FieldRecordLoc));
1153
1126
initializeFieldsWithValues (FieldRecordLoc, FieldRecordLoc.getType (),
1154
1127
Visited, Depth + 1 , CreatedValuesCount);
1155
1128
} else {
1129
+ if (getValue (FieldLoc) != nullptr )
1130
+ return ;
1156
1131
if (!Visited.insert (FieldType.getCanonicalType ()).second )
1157
1132
return ;
1158
1133
if (Value *Val = createValueUnlessSelfReferential (
@@ -1210,7 +1185,6 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
1210
1185
auto &RecordLoc = cast<RecordStorageLocation>(Loc);
1211
1186
if (!InitExpr)
1212
1187
initializeFieldsWithValues (RecordLoc);
1213
- refreshRecordValue (RecordLoc, *this );
1214
1188
} else {
1215
1189
Value *Val = nullptr ;
1216
1190
if (InitExpr)
@@ -1407,25 +1381,5 @@ RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) {
1407
1381
}
1408
1382
}
1409
1383
1410
- RecordValue &refreshRecordValue (RecordStorageLocation &Loc, Environment &Env) {
1411
- auto &NewVal = Env.create <RecordValue>(Loc);
1412
- Env.setValue (Loc, NewVal);
1413
- return NewVal;
1414
- }
1415
-
1416
- RecordValue &refreshRecordValue (const Expr &Expr, Environment &Env) {
1417
- assert (Expr.getType ()->isRecordType ());
1418
-
1419
- if (Expr.isPRValue ())
1420
- refreshRecordValue (Env.getResultObjectLocation (Expr), Env);
1421
-
1422
- if (auto *Loc = Env.get <RecordStorageLocation>(Expr))
1423
- refreshRecordValue (*Loc, Env);
1424
-
1425
- auto &NewVal = *cast<RecordValue>(Env.createValue (Expr.getType ()));
1426
- Env.setStorageLocation (Expr, NewVal.getLoc ());
1427
- return NewVal;
1428
- }
1429
-
1430
1384
} // namespace dataflow
1431
1385
} // namespace clang
0 commit comments