[Flang] remove whole-archive option for AIX linker (#76039)
[llvm-project.git] / clang / lib / Analysis / FlowSensitive / RecordOps.cpp
blobda4dd6dc0785159acc4e1a15a70c8a56cdf26238
1 //===-- RecordOps.cpp -------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Operations on records (structs, classes, and unions).
11 //===----------------------------------------------------------------------===//
13 #include "clang/Analysis/FlowSensitive/RecordOps.h"
15 #define DEBUG_TYPE "dataflow"
17 void clang::dataflow::copyRecord(RecordStorageLocation &Src,
18 RecordStorageLocation &Dst, Environment &Env) {
19 auto SrcType = Src.getType().getCanonicalType().getUnqualifiedType();
20 auto DstType = Dst.getType().getCanonicalType().getUnqualifiedType();
22 auto SrcDecl = SrcType->getAsCXXRecordDecl();
23 auto DstDecl = DstType->getAsCXXRecordDecl();
25 bool compatibleTypes =
26 SrcType == DstType ||
27 (SrcDecl && DstDecl && SrcDecl->isDerivedFrom(DstDecl));
28 (void)compatibleTypes;
30 LLVM_DEBUG({
31 if (!compatibleTypes) {
32 llvm::dbgs() << "Source type " << Src.getType() << "\n";
33 llvm::dbgs() << "Destination type " << Dst.getType() << "\n";
35 });
36 assert(compatibleTypes);
38 for (auto [Field, DstFieldLoc] : Dst.children()) {
39 StorageLocation *SrcFieldLoc = Src.getChild(*Field);
41 assert(Field->getType()->isReferenceType() ||
42 (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
44 if (Field->getType()->isRecordType()) {
45 copyRecord(cast<RecordStorageLocation>(*SrcFieldLoc),
46 cast<RecordStorageLocation>(*DstFieldLoc), Env);
47 } else if (Field->getType()->isReferenceType()) {
48 Dst.setChild(*Field, SrcFieldLoc);
49 } else {
50 if (Value *Val = Env.getValue(*SrcFieldLoc))
51 Env.setValue(*DstFieldLoc, *Val);
52 else
53 Env.clearValue(*DstFieldLoc);
57 for (const auto &[Name, SynthFieldLoc] : Src.synthetic_fields()) {
58 if (SynthFieldLoc->getType()->isRecordType()) {
59 copyRecord(*cast<RecordStorageLocation>(SynthFieldLoc),
60 cast<RecordStorageLocation>(Dst.getSyntheticField(Name)), Env);
61 } else {
62 if (Value *Val = Env.getValue(*SynthFieldLoc))
63 Env.setValue(Dst.getSyntheticField(Name), *Val);
64 else
65 Env.clearValue(Dst.getSyntheticField(Name));
69 RecordValue *DstVal = &Env.create<RecordValue>(Dst);
70 Env.setValue(Dst, *DstVal);
73 bool clang::dataflow::recordsEqual(const RecordStorageLocation &Loc1,
74 const Environment &Env1,
75 const RecordStorageLocation &Loc2,
76 const Environment &Env2) {
77 LLVM_DEBUG({
78 if (Loc2.getType().getCanonicalType().getUnqualifiedType() !=
79 Loc1.getType().getCanonicalType().getUnqualifiedType()) {
80 llvm::dbgs() << "Loc1 type " << Loc1.getType() << "\n";
81 llvm::dbgs() << "Loc2 type " << Loc2.getType() << "\n";
83 });
84 assert(Loc2.getType().getCanonicalType().getUnqualifiedType() ==
85 Loc1.getType().getCanonicalType().getUnqualifiedType());
87 for (auto [Field, FieldLoc1] : Loc1.children()) {
88 StorageLocation *FieldLoc2 = Loc2.getChild(*Field);
90 assert(Field->getType()->isReferenceType() ||
91 (FieldLoc1 != nullptr && FieldLoc2 != nullptr));
93 if (Field->getType()->isRecordType()) {
94 if (!recordsEqual(cast<RecordStorageLocation>(*FieldLoc1), Env1,
95 cast<RecordStorageLocation>(*FieldLoc2), Env2))
96 return false;
97 } else if (Field->getType()->isReferenceType()) {
98 if (FieldLoc1 != FieldLoc2)
99 return false;
100 } else if (Env1.getValue(*FieldLoc1) != Env2.getValue(*FieldLoc2)) {
101 return false;
105 for (const auto &[Name, SynthFieldLoc1] : Loc1.synthetic_fields()) {
106 if (SynthFieldLoc1->getType()->isRecordType()) {
107 if (!recordsEqual(
108 *cast<RecordStorageLocation>(SynthFieldLoc1), Env1,
109 cast<RecordStorageLocation>(Loc2.getSyntheticField(Name)), Env2))
110 return false;
111 } else if (Env1.getValue(*SynthFieldLoc1) !=
112 Env2.getValue(Loc2.getSyntheticField(Name))) {
113 return false;
117 return true;