@@ -2166,6 +2166,152 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const {
2166
2166
return false ;
2167
2167
}
2168
2168
2169
+ bool QualType::unionHasUniqueObjectRepresentations (
2170
+ const ASTContext &Context) const {
2171
+ assert ((*this )->isUnionType () && " must be union type" );
2172
+ CharUnits UnionSize = Context.getTypeSizeInChars (*this );
2173
+ const RecordDecl *Union = getTypePtr ()->getAs <RecordType>()->getDecl ();
2174
+
2175
+ for (const auto *Field : Union->fields ()) {
2176
+ if (!Field->getType ().hasUniqueObjectRepresentations (Context))
2177
+ return false ;
2178
+ CharUnits FieldSize = Context.getTypeSizeInChars (Field->getType ());
2179
+ if (FieldSize != UnionSize)
2180
+ return false ;
2181
+ }
2182
+ return true ;
2183
+ }
2184
+
2185
+ bool isStructEmpty (QualType Ty) {
2186
+ assert (Ty.getTypePtr ()->isStructureOrClassType () &&
2187
+ " Must be struct or class" );
2188
+ const RecordDecl *RD = Ty.getTypePtr ()->getAs <RecordType>()->getDecl ();
2189
+
2190
+ if (!RD->field_empty ())
2191
+ return false ;
2192
+
2193
+ if (const CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RD)) {
2194
+ return ClassDecl->isEmpty ();
2195
+ }
2196
+
2197
+ return true ;
2198
+ }
2199
+
2200
+ bool QualType::structHasUniqueObjectRepresentations (
2201
+ const ASTContext &Context) const {
2202
+ assert ((*this )->isStructureOrClassType () && " Must be struct or class" );
2203
+ const RecordDecl *RD = getTypePtr ()->getAs <RecordType>()->getDecl ();
2204
+
2205
+ if (isStructEmpty (*this ))
2206
+ return false ;
2207
+
2208
+ // Check base types.
2209
+ CharUnits BaseSize{};
2210
+ if (const CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RD)) {
2211
+ for (const auto Base : ClassDecl->bases ()) {
2212
+ if (Base.isVirtual ())
2213
+ return false ;
2214
+
2215
+ // Empty bases are permitted, otherwise ensure base has unique
2216
+ // representation. Also, Empty Base Optimization means that an
2217
+ // Empty base takes up 0 size.
2218
+ if (!isStructEmpty (Base.getType ())) {
2219
+ if (!Base.getType ().structHasUniqueObjectRepresentations (Context))
2220
+ return false ;
2221
+ BaseSize += Context.getTypeSizeInChars (Base.getType ());
2222
+ }
2223
+ }
2224
+ }
2225
+
2226
+ CharUnits StructSize = Context.getTypeSizeInChars (*this );
2227
+
2228
+ // This struct obviously has bases that keep it from being 'empty', so
2229
+ // checking fields is no longer required. Ensure that the struct size
2230
+ // is the sum of the bases.
2231
+ if (RD->field_empty ())
2232
+ return StructSize == BaseSize;
2233
+ ;
2234
+
2235
+ CharUnits CurOffset =
2236
+ Context.toCharUnitsFromBits (Context.getFieldOffset (*RD->field_begin ()));
2237
+
2238
+ // If the first field isn't at the sum of the size of the bases, there
2239
+ // is padding somewhere.
2240
+ if (BaseSize != CurOffset)
2241
+ return false ;
2242
+
2243
+ for (const auto *Field : RD->fields ()) {
2244
+ if (!Field->getType ().hasUniqueObjectRepresentations (Context))
2245
+ return false ;
2246
+ CharUnits FieldSize = Context.getTypeSizeInChars (Field->getType ());
2247
+ CharUnits FieldOffset =
2248
+ Context.toCharUnitsFromBits (Context.getFieldOffset (Field));
2249
+ // Has padding between fields.
2250
+ if (FieldOffset != CurOffset)
2251
+ return false ;
2252
+ CurOffset += FieldSize;
2253
+ }
2254
+ // Check for tail padding.
2255
+ return CurOffset == StructSize;
2256
+ }
2257
+
2258
+ bool QualType::hasUniqueObjectRepresentations (const ASTContext &Context) const {
2259
+ // C++17 [meta.unary.prop]:
2260
+ // The predicate condition for a template specialization
2261
+ // has_unique_object_representations<T> shall be
2262
+ // satisfied if and only if:
2263
+ // (9.1) — T is trivially copyable, and
2264
+ // (9.2) — any two objects of type T with the same value have the same
2265
+ // object representation, where two objects
2266
+ // of array or non-union class type are considered to have the same value
2267
+ // if their respective sequences of
2268
+ // direct subobjects have the same values, and two objects of union type
2269
+ // are considered to have the same
2270
+ // value if they have the same active member and the corresponding members
2271
+ // have the same value.
2272
+ // The set of scalar types for which this condition holds is
2273
+ // implementation-defined. [ Note: If a type has padding
2274
+ // bits, the condition does not hold; otherwise, the condition holds true
2275
+ // for unsigned integral types. — end
2276
+ // note ]
2277
+ if (isNull ())
2278
+ return false ;
2279
+
2280
+ // Arrays are unique only if their element type is unique.
2281
+ if ((*this )->isArrayType ())
2282
+ return Context.getBaseElementType (*this ).hasUniqueObjectRepresentations (
2283
+ Context);
2284
+
2285
+ // (9.1) — T is trivially copyable, and
2286
+ if (!isTriviallyCopyableType (Context))
2287
+ return false ;
2288
+
2289
+ // Functions are not unique.
2290
+ if ((*this )->isFunctionType ())
2291
+ return false ;
2292
+
2293
+ // All integrals and enums are unique!
2294
+ if ((*this )->isIntegralOrEnumerationType ())
2295
+ return true ;
2296
+
2297
+ // All pointers are unique, since they're just integrals.
2298
+ if ((*this )->isPointerType () || (*this )->isMemberPointerType ())
2299
+ return true ;
2300
+
2301
+ if ((*this )->isRecordType ()) {
2302
+ const RecordDecl *Record = getTypePtr ()->getAs <RecordType>()->getDecl ();
2303
+
2304
+ // Lambda types are not unique, so exclude them immediately.
2305
+ if (Record->isLambda ())
2306
+ return false ;
2307
+
2308
+ if (Record->isUnion ())
2309
+ return unionHasUniqueObjectRepresentations (Context);
2310
+ return structHasUniqueObjectRepresentations (Context);
2311
+ }
2312
+ return false ;
2313
+ }
2314
+
2169
2315
bool QualType::isNonWeakInMRRWithObjCWeak (const ASTContext &Context) const {
2170
2316
return !Context.getLangOpts ().ObjCAutoRefCount &&
2171
2317
Context.getLangOpts ().ObjCWeak &&
0 commit comments