Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ASTStructuralEquivalence.cpp ---------------------------------------===//
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
//  This file implement StructuralEquivalenceContext class and helper functions
10
//  for layout matching.
11
//
12
// The structural equivalence check could have been implemented as a parallel
13
// BFS on a pair of graphs.  That must have been the original approach at the
14
// beginning.
15
// Let's consider this simple BFS algorithm from the `s` source:
16
// ```
17
// void bfs(Graph G, int s)
18
// {
19
//   Queue<Integer> queue = new Queue<Integer>();
20
//   marked[s] = true; // Mark the source
21
//   queue.enqueue(s); // and put it on the queue.
22
//   while (!q.isEmpty()) {
23
//     int v = queue.dequeue(); // Remove next vertex from the queue.
24
//     for (int w : G.adj(v))
25
//       if (!marked[w]) // For every unmarked adjacent vertex,
26
//       {
27
//         marked[w] = true;
28
//         queue.enqueue(w);
29
//       }
30
//   }
31
// }
32
// ```
33
// Indeed, it has it's queue, which holds pairs of nodes, one from each graph,
34
// this is the `DeclsToCheck` member. `VisitedDecls` plays the role of the
35
// marking (`marked`) functionality above, we use it to check whether we've
36
// already seen a pair of nodes.
37
//
38
// We put in the elements into the queue only in the toplevel decl check
39
// function:
40
// ```
41
// static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
42
//                                      Decl *D1, Decl *D2);
43
// ```
44
// The `while` loop where we iterate over the children is implemented in
45
// `Finish()`.  And `Finish` is called only from the two **member** functions
46
// which check the equivalency of two Decls or two Types. ASTImporter (and
47
// other clients) call only these functions.
48
//
49
// The `static` implementation functions are called from `Finish`, these push
50
// the children nodes to the queue via `static bool
51
// IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1,
52
// Decl *D2)`.  So far so good, this is almost like the BFS.  However, if we
53
// let a static implementation function to call `Finish` via another **member**
54
// function that means we end up with two nested while loops each of them
55
// working on the same queue. This is wrong and nobody can reason about it's
56
// doing. Thus, static implementation functions must not call the **member**
57
// functions.
58
//
59
//===----------------------------------------------------------------------===//
60
61
#include "clang/AST/ASTStructuralEquivalence.h"
62
#include "clang/AST/ASTContext.h"
63
#include "clang/AST/ASTDiagnostic.h"
64
#include "clang/AST/Decl.h"
65
#include "clang/AST/DeclBase.h"
66
#include "clang/AST/DeclCXX.h"
67
#include "clang/AST/DeclFriend.h"
68
#include "clang/AST/DeclObjC.h"
69
#include "clang/AST/DeclOpenMP.h"
70
#include "clang/AST/DeclTemplate.h"
71
#include "clang/AST/ExprCXX.h"
72
#include "clang/AST/ExprConcepts.h"
73
#include "clang/AST/ExprObjC.h"
74
#include "clang/AST/ExprOpenMP.h"
75
#include "clang/AST/NestedNameSpecifier.h"
76
#include "clang/AST/StmtObjC.h"
77
#include "clang/AST/StmtOpenMP.h"
78
#include "clang/AST/TemplateBase.h"
79
#include "clang/AST/TemplateName.h"
80
#include "clang/AST/Type.h"
81
#include "clang/Basic/ExceptionSpecificationType.h"
82
#include "clang/Basic/IdentifierTable.h"
83
#include "clang/Basic/LLVM.h"
84
#include "clang/Basic/SourceLocation.h"
85
#include "llvm/ADT/APInt.h"
86
#include "llvm/ADT/APSInt.h"
87
#include "llvm/ADT/StringExtras.h"
88
#include "llvm/Support/Casting.h"
89
#include "llvm/Support/Compiler.h"
90
#include "llvm/Support/ErrorHandling.h"
91
#include <cassert>
92
#include <optional>
93
#include <utility>
94
95
using namespace clang;
96
97
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
98
                                     QualType T1, QualType T2);
99
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
100
                                     Decl *D1, Decl *D2);
101
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
102
                                     const TemplateArgument &Arg1,
103
                                     const TemplateArgument &Arg2);
104
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
105
                                     const TemplateArgumentLoc &Arg1,
106
                                     const TemplateArgumentLoc &Arg2);
107
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
108
                                     NestedNameSpecifier *NNS1,
109
                                     NestedNameSpecifier *NNS2);
110
static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
111
                                     const IdentifierInfo *Name2);
112
113
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
114
                                     const DeclarationName Name1,
115
0
                                     const DeclarationName Name2) {
116
0
  if (Name1.getNameKind() != Name2.getNameKind())
117
0
    return false;
118
119
0
  switch (Name1.getNameKind()) {
120
121
0
  case DeclarationName::Identifier:
122
0
    return IsStructurallyEquivalent(Name1.getAsIdentifierInfo(),
123
0
                                    Name2.getAsIdentifierInfo());
124
125
0
  case DeclarationName::CXXConstructorName:
126
0
  case DeclarationName::CXXDestructorName:
127
0
  case DeclarationName::CXXConversionFunctionName:
128
0
    return IsStructurallyEquivalent(Context, Name1.getCXXNameType(),
129
0
                                    Name2.getCXXNameType());
130
131
0
  case DeclarationName::CXXDeductionGuideName: {
132
0
    if (!IsStructurallyEquivalent(
133
0
            Context, Name1.getCXXDeductionGuideTemplate()->getDeclName(),
134
0
            Name2.getCXXDeductionGuideTemplate()->getDeclName()))
135
0
      return false;
136
0
    return IsStructurallyEquivalent(Context,
137
0
                                    Name1.getCXXDeductionGuideTemplate(),
138
0
                                    Name2.getCXXDeductionGuideTemplate());
139
0
  }
140
141
0
  case DeclarationName::CXXOperatorName:
142
0
    return Name1.getCXXOverloadedOperator() == Name2.getCXXOverloadedOperator();
143
144
0
  case DeclarationName::CXXLiteralOperatorName:
145
0
    return IsStructurallyEquivalent(Name1.getCXXLiteralIdentifier(),
146
0
                                    Name2.getCXXLiteralIdentifier());
147
148
0
  case DeclarationName::CXXUsingDirective:
149
0
    return true; // FIXME When do we consider two using directives equal?
150
151
0
  case DeclarationName::ObjCZeroArgSelector:
152
0
  case DeclarationName::ObjCOneArgSelector:
153
0
  case DeclarationName::ObjCMultiArgSelector:
154
0
    return true; // FIXME
155
0
  }
156
157
0
  llvm_unreachable("Unhandled kind of DeclarationName");
158
0
  return true;
159
0
}
160
161
namespace {
162
/// Encapsulates Stmt comparison logic.
163
class StmtComparer {
164
  StructuralEquivalenceContext &Context;
165
166
  // IsStmtEquivalent overloads. Each overload compares a specific statement
167
  // and only has to compare the data that is specific to the specific statement
168
  // class. Should only be called from TraverseStmt.
169
170
0
  bool IsStmtEquivalent(const AddrLabelExpr *E1, const AddrLabelExpr *E2) {
171
0
    return IsStructurallyEquivalent(Context, E1->getLabel(), E2->getLabel());
172
0
  }
173
174
0
  bool IsStmtEquivalent(const AtomicExpr *E1, const AtomicExpr *E2) {
175
0
    return E1->getOp() == E2->getOp();
176
0
  }
177
178
0
  bool IsStmtEquivalent(const BinaryOperator *E1, const BinaryOperator *E2) {
179
0
    return E1->getOpcode() == E2->getOpcode();
180
0
  }
181
182
0
  bool IsStmtEquivalent(const CallExpr *E1, const CallExpr *E2) {
183
    // FIXME: IsStructurallyEquivalent requires non-const Decls.
184
0
    Decl *Callee1 = const_cast<Decl *>(E1->getCalleeDecl());
185
0
    Decl *Callee2 = const_cast<Decl *>(E2->getCalleeDecl());
186
187
    // Compare whether both calls know their callee.
188
0
    if (static_cast<bool>(Callee1) != static_cast<bool>(Callee2))
189
0
      return false;
190
191
    // Both calls have no callee, so nothing to do.
192
0
    if (!static_cast<bool>(Callee1))
193
0
      return true;
194
195
0
    assert(Callee2);
196
0
    return IsStructurallyEquivalent(Context, Callee1, Callee2);
197
0
  }
198
199
  bool IsStmtEquivalent(const CharacterLiteral *E1,
200
0
                        const CharacterLiteral *E2) {
201
0
    return E1->getValue() == E2->getValue() && E1->getKind() == E2->getKind();
202
0
  }
203
204
0
  bool IsStmtEquivalent(const ChooseExpr *E1, const ChooseExpr *E2) {
205
0
    return true; // Semantics only depend on children.
206
0
  }
207
208
0
  bool IsStmtEquivalent(const CompoundStmt *E1, const CompoundStmt *E2) {
209
    // Number of children is actually checked by the generic children comparison
210
    // code, but a CompoundStmt is one of the few statements where the number of
211
    // children frequently differs and the number of statements is also always
212
    // precomputed. Directly comparing the number of children here is thus
213
    // just an optimization.
214
0
    return E1->size() == E2->size();
215
0
  }
216
217
0
  bool IsStmtEquivalent(const DeclRefExpr *DRE1, const DeclRefExpr *DRE2) {
218
0
    const ValueDecl *Decl1 = DRE1->getDecl();
219
0
    const ValueDecl *Decl2 = DRE2->getDecl();
220
0
    if (!Decl1 || !Decl2)
221
0
      return false;
222
0
    return IsStructurallyEquivalent(Context, const_cast<ValueDecl *>(Decl1),
223
0
                                    const_cast<ValueDecl *>(Decl2));
224
0
  }
225
226
  bool IsStmtEquivalent(const DependentScopeDeclRefExpr *DE1,
227
0
                        const DependentScopeDeclRefExpr *DE2) {
228
0
    if (!IsStructurallyEquivalent(Context, DE1->getDeclName(),
229
0
                                  DE2->getDeclName()))
230
0
      return false;
231
0
    return IsStructurallyEquivalent(Context, DE1->getQualifier(),
232
0
                                    DE2->getQualifier());
233
0
  }
234
235
0
  bool IsStmtEquivalent(const Expr *E1, const Expr *E2) {
236
0
    return IsStructurallyEquivalent(Context, E1->getType(), E2->getType());
237
0
  }
238
239
  bool IsStmtEquivalent(const ExpressionTraitExpr *E1,
240
0
                        const ExpressionTraitExpr *E2) {
241
0
    return E1->getTrait() == E2->getTrait() && E1->getValue() == E2->getValue();
242
0
  }
243
244
0
  bool IsStmtEquivalent(const FloatingLiteral *E1, const FloatingLiteral *E2) {
245
0
    return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue();
246
0
  }
247
248
  bool IsStmtEquivalent(const GenericSelectionExpr *E1,
249
0
                        const GenericSelectionExpr *E2) {
250
0
    for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
251
0
                                 E2->getAssocTypeSourceInfos())) {
252
0
      std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
253
0
      std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
254
      // Skip this case if there are a different number of associated types.
255
0
      if (!Child1 || !Child2)
256
0
        return false;
257
258
0
      if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
259
0
                                    (*Child2)->getType()))
260
0
        return false;
261
0
    }
262
263
0
    return true;
264
0
  }
265
266
  bool IsStmtEquivalent(const ImplicitCastExpr *CastE1,
267
0
                        const ImplicitCastExpr *CastE2) {
268
0
    return IsStructurallyEquivalent(Context, CastE1->getType(),
269
0
                                    CastE2->getType());
270
0
  }
271
272
0
  bool IsStmtEquivalent(const IntegerLiteral *E1, const IntegerLiteral *E2) {
273
0
    return E1->getValue() == E2->getValue();
274
0
  }
275
276
0
  bool IsStmtEquivalent(const MemberExpr *E1, const MemberExpr *E2) {
277
0
    return IsStructurallyEquivalent(Context, E1->getFoundDecl(),
278
0
                                    E2->getFoundDecl());
279
0
  }
280
281
  bool IsStmtEquivalent(const ObjCStringLiteral *E1,
282
0
                        const ObjCStringLiteral *E2) {
283
    // Just wraps a StringLiteral child.
284
0
    return true;
285
0
  }
286
287
0
  bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }
288
289
0
  bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) {
290
0
    LabelDecl *L1 = S1->getLabel();
291
0
    LabelDecl *L2 = S2->getLabel();
292
0
    if (!L1 || !L2)
293
0
      return L1 == L2;
294
295
0
    IdentifierInfo *Name1 = L1->getIdentifier();
296
0
    IdentifierInfo *Name2 = L2->getIdentifier();
297
0
    return ::IsStructurallyEquivalent(Name1, Name2);
298
0
  }
299
300
0
  bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) {
301
0
    return E1->getIdentKind() == E2->getIdentKind();
302
0
  }
303
304
0
  bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) {
305
0
    return E1->getTemplateDepth() == E2->getTemplateDepth();
306
0
  }
307
308
0
  bool IsStmtEquivalent(const StringLiteral *E1, const StringLiteral *E2) {
309
0
    return E1->getBytes() == E2->getBytes();
310
0
  }
311
312
  bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
313
0
                        const SubstNonTypeTemplateParmExpr *E2) {
314
0
    if (!IsStructurallyEquivalent(Context, E1->getAssociatedDecl(),
315
0
                                  E2->getAssociatedDecl()))
316
0
      return false;
317
0
    if (E1->getIndex() != E2->getIndex())
318
0
      return false;
319
0
    if (E1->getPackIndex() != E2->getPackIndex())
320
0
      return false;
321
0
    return true;
322
0
  }
323
324
  bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
325
0
                        const SubstNonTypeTemplateParmPackExpr *E2) {
326
0
    return IsStructurallyEquivalent(Context, E1->getArgumentPack(),
327
0
                                    E2->getArgumentPack());
328
0
  }
329
330
0
  bool IsStmtEquivalent(const TypeTraitExpr *E1, const TypeTraitExpr *E2) {
331
0
    if (E1->getTrait() != E2->getTrait())
332
0
      return false;
333
334
0
    for (auto Pair : zip_longest(E1->getArgs(), E2->getArgs())) {
335
0
      std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
336
0
      std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
337
      // Different number of args.
338
0
      if (!Child1 || !Child2)
339
0
        return false;
340
341
0
      if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
342
0
                                    (*Child2)->getType()))
343
0
        return false;
344
0
    }
345
0
    return true;
346
0
  }
347
348
  bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
349
0
                        const UnaryExprOrTypeTraitExpr *E2) {
350
0
    if (E1->getKind() != E2->getKind())
351
0
      return false;
352
0
    return IsStructurallyEquivalent(Context, E1->getTypeOfArgument(),
353
0
                                    E2->getTypeOfArgument());
354
0
  }
355
356
0
  bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) {
357
0
    return E1->getOpcode() == E2->getOpcode();
358
0
  }
359
360
0
  bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) {
361
    // Semantics only depend on children.
362
0
    return true;
363
0
  }
364
365
0
  bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
366
0
    if (!IsStructurallyEquivalent(Context, E1->getName(), E2->getName()))
367
0
      return false;
368
369
0
    if (static_cast<bool>(E1->getQualifier()) !=
370
0
        static_cast<bool>(E2->getQualifier()))
371
0
      return false;
372
0
    if (E1->getQualifier() &&
373
0
        !IsStructurallyEquivalent(Context, E1->getQualifier(),
374
0
                                  E2->getQualifier()))
375
0
      return false;
376
377
0
    if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs())
378
0
      return false;
379
0
    const TemplateArgumentLoc *Args1 = E1->getTemplateArgs();
380
0
    const TemplateArgumentLoc *Args2 = E2->getTemplateArgs();
381
0
    for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
382
0
         ++ArgI)
383
0
      if (!IsStructurallyEquivalent(Context, Args1[ArgI], Args2[ArgI]))
384
0
        return false;
385
386
0
    return true;
387
0
  }
388
389
0
  bool IsStmtEquivalent(const CXXBoolLiteralExpr *E1, const CXXBoolLiteralExpr *E2) {
390
0
    return E1->getValue() == E2->getValue();
391
0
  }
392
393
  /// End point of the traversal chain.
394
0
  bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
395
396
  // Create traversal methods that traverse the class hierarchy and return
397
  // the accumulated result of the comparison. Each TraverseStmt overload
398
  // calls the TraverseStmt overload of the parent class. For example,
399
  // the TraverseStmt overload for 'BinaryOperator' calls the TraverseStmt
400
  // overload of 'Expr' which then calls the overload for 'Stmt'.
401
#define STMT(CLASS, PARENT)                                                    \
402
0
  bool TraverseStmt(const CLASS *S1, const CLASS *S2) {                        \
403
0
    if (!TraverseStmt(static_cast<const PARENT *>(S1),                         \
404
0
                      static_cast<const PARENT *>(S2)))                        \
405
0
      return false;                                                            \
406
0
    return IsStmtEquivalent(S1, S2);                                           \
407
0
  }
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::WhileStmt const*, clang::WhileStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::LabelStmt const*, clang::LabelStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::VAArgExpr const*, clang::VAArgExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::UnaryOperator const*, clang::UnaryOperator const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::UnaryExprOrTypeTraitExpr const*, clang::UnaryExprOrTypeTraitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::TypoExpr const*, clang::TypoExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::TypeTraitExpr const*, clang::TypeTraitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SubstNonTypeTemplateParmPackExpr const*, clang::SubstNonTypeTemplateParmPackExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SubstNonTypeTemplateParmExpr const*, clang::SubstNonTypeTemplateParmExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::StringLiteral const*, clang::StringLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::StmtExpr const*, clang::StmtExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SourceLocExpr const*, clang::SourceLocExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SizeOfPackExpr const*, clang::SizeOfPackExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ShuffleVectorExpr const*, clang::ShuffleVectorExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SYCLUniqueStableNameExpr const*, clang::SYCLUniqueStableNameExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::RequiresExpr const*, clang::RequiresExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::RecoveryExpr const*, clang::RecoveryExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::PseudoObjectExpr const*, clang::PseudoObjectExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::PredefinedExpr const*, clang::PredefinedExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ParenListExpr const*, clang::ParenListExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ParenExpr const*, clang::ParenExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::PackExpansionExpr const*, clang::PackExpansionExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::UnresolvedMemberExpr const*, clang::UnresolvedMemberExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::UnresolvedLookupExpr const*, clang::UnresolvedLookupExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OpaqueValueExpr const*, clang::OpaqueValueExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OffsetOfExpr const*, clang::OffsetOfExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCSubscriptRefExpr const*, clang::ObjCSubscriptRefExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCStringLiteral const*, clang::ObjCStringLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCSelectorExpr const*, clang::ObjCSelectorExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCProtocolExpr const*, clang::ObjCProtocolExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCPropertyRefExpr const*, clang::ObjCPropertyRefExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCMessageExpr const*, clang::ObjCMessageExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCIvarRefExpr const*, clang::ObjCIvarRefExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCIsaExpr const*, clang::ObjCIsaExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCIndirectCopyRestoreExpr const*, clang::ObjCIndirectCopyRestoreExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCEncodeExpr const*, clang::ObjCEncodeExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCDictionaryLiteral const*, clang::ObjCDictionaryLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCBoxedExpr const*, clang::ObjCBoxedExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCBoolLiteralExpr const*, clang::ObjCBoolLiteralExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAvailabilityCheckExpr const*, clang::ObjCAvailabilityCheckExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCArrayLiteral const*, clang::ObjCArrayLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPIteratorExpr const*, clang::OMPIteratorExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPArrayShapingExpr const*, clang::OMPArrayShapingExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPArraySectionExpr const*, clang::OMPArraySectionExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::NoInitExpr const*, clang::NoInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MemberExpr const*, clang::MemberExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MatrixSubscriptExpr const*, clang::MatrixSubscriptExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MaterializeTemporaryExpr const*, clang::MaterializeTemporaryExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MSPropertySubscriptExpr const*, clang::MSPropertySubscriptExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MSPropertyRefExpr const*, clang::MSPropertyRefExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::LambdaExpr const*, clang::LambdaExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::IntegerLiteral const*, clang::IntegerLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::InitListExpr const*, clang::InitListExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ImplicitValueInitExpr const*, clang::ImplicitValueInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ImaginaryLiteral const*, clang::ImaginaryLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::GenericSelectionExpr const*, clang::GenericSelectionExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::GNUNullExpr const*, clang::GNUNullExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::FunctionParmPackExpr const*, clang::FunctionParmPackExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ExprWithCleanups const*, clang::ExprWithCleanups const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ConstantExpr const*, clang::ConstantExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::FloatingLiteral const*, clang::FloatingLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::FixedPointLiteral const*, clang::FixedPointLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ExtVectorElementExpr const*, clang::ExtVectorElementExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ExpressionTraitExpr const*, clang::ExpressionTraitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DesignatedInitUpdateExpr const*, clang::DesignatedInitUpdateExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DesignatedInitExpr const*, clang::DesignatedInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DependentScopeDeclRefExpr const*, clang::DependentScopeDeclRefExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DependentCoawaitExpr const*, clang::DependentCoawaitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DeclRefExpr const*, clang::DeclRefExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CoyieldExpr const*, clang::CoyieldExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CoawaitExpr const*, clang::CoawaitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ConvertVectorExpr const*, clang::ConvertVectorExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ConceptSpecializationExpr const*, clang::ConceptSpecializationExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CompoundLiteralExpr const*, clang::CompoundLiteralExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ChooseExpr const*, clang::ChooseExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CharacterLiteral const*, clang::CharacterLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ImplicitCastExpr const*, clang::ImplicitCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCBridgedCastExpr const*, clang::ObjCBridgedCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXStaticCastExpr const*, clang::CXXStaticCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXReinterpretCastExpr const*, clang::CXXReinterpretCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXDynamicCastExpr const*, clang::CXXDynamicCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXConstCastExpr const*, clang::CXXConstCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXAddrspaceCastExpr const*, clang::CXXAddrspaceCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXFunctionalCastExpr const*, clang::CXXFunctionalCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CStyleCastExpr const*, clang::CStyleCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::BuiltinBitCastExpr const*, clang::BuiltinBitCastExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CallExpr const*, clang::CallExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::UserDefinedLiteral const*, clang::UserDefinedLiteral const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXOperatorCallExpr const*, clang::CXXOperatorCallExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXMemberCallExpr const*, clang::CXXMemberCallExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CUDAKernelCallExpr const*, clang::CUDAKernelCallExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXUuidofExpr const*, clang::CXXUuidofExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXUnresolvedConstructExpr const*, clang::CXXUnresolvedConstructExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXTypeidExpr const*, clang::CXXTypeidExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXThrowExpr const*, clang::CXXThrowExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXThisExpr const*, clang::CXXThisExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXStdInitializerListExpr const*, clang::CXXStdInitializerListExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXScalarValueInitExpr const*, clang::CXXScalarValueInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXRewrittenBinaryOperator const*, clang::CXXRewrittenBinaryOperator const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXPseudoDestructorExpr const*, clang::CXXPseudoDestructorExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXParenListInitExpr const*, clang::CXXParenListInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXNullPtrLiteralExpr const*, clang::CXXNullPtrLiteralExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXNoexceptExpr const*, clang::CXXNoexceptExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXNewExpr const*, clang::CXXNewExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXInheritedCtorInitExpr const*, clang::CXXInheritedCtorInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXFoldExpr const*, clang::CXXFoldExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXDependentScopeMemberExpr const*, clang::CXXDependentScopeMemberExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXDeleteExpr const*, clang::CXXDeleteExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXDefaultInitExpr const*, clang::CXXDefaultInitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXDefaultArgExpr const*, clang::CXXDefaultArgExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXConstructExpr const*, clang::CXXConstructExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXTemporaryObjectExpr const*, clang::CXXTemporaryObjectExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXBoolLiteralExpr const*, clang::CXXBoolLiteralExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXBindTemporaryExpr const*, clang::CXXBindTemporaryExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::BlockExpr const*, clang::BlockExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::BinaryOperator const*, clang::BinaryOperator const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CompoundAssignOperator const*, clang::CompoundAssignOperator const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::AtomicExpr const*, clang::AtomicExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::AsTypeExpr const*, clang::AsTypeExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ArrayTypeTraitExpr const*, clang::ArrayTypeTraitExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ArraySubscriptExpr const*, clang::ArraySubscriptExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ArrayInitLoopExpr const*, clang::ArrayInitLoopExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ArrayInitIndexExpr const*, clang::ArrayInitIndexExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::AddrLabelExpr const*, clang::AddrLabelExpr const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ConditionalOperator const*, clang::ConditionalOperator const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::BinaryConditionalOperator const*, clang::BinaryConditionalOperator const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::AttributedStmt const*, clang::AttributedStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SwitchStmt const*, clang::SwitchStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DefaultStmt const*, clang::DefaultStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CaseStmt const*, clang::CaseStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SEHTryStmt const*, clang::SEHTryStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SEHLeaveStmt const*, clang::SEHLeaveStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SEHFinallyStmt const*, clang::SEHFinallyStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::SEHExceptStmt const*, clang::SEHExceptStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ReturnStmt const*, clang::ReturnStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCForCollectionStmt const*, clang::ObjCForCollectionStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAutoreleasePoolStmt const*, clang::ObjCAutoreleasePoolStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAtTryStmt const*, clang::ObjCAtTryStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAtThrowStmt const*, clang::ObjCAtThrowStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAtSynchronizedStmt const*, clang::ObjCAtSynchronizedStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAtFinallyStmt const*, clang::ObjCAtFinallyStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ObjCAtCatchStmt const*, clang::ObjCAtCatchStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTeamsDirective const*, clang::OMPTeamsDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTaskyieldDirective const*, clang::OMPTaskyieldDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTaskwaitDirective const*, clang::OMPTaskwaitDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTaskgroupDirective const*, clang::OMPTaskgroupDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTaskDirective const*, clang::OMPTaskDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetUpdateDirective const*, clang::OMPTargetUpdateDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetTeamsDirective const*, clang::OMPTargetTeamsDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetParallelForDirective const*, clang::OMPTargetParallelForDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetParallelDirective const*, clang::OMPTargetParallelDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetExitDataDirective const*, clang::OMPTargetExitDataDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetEnterDataDirective const*, clang::OMPTargetEnterDataDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetDirective const*, clang::OMPTargetDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetDataDirective const*, clang::OMPTargetDataDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPSingleDirective const*, clang::OMPSingleDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPSectionsDirective const*, clang::OMPSectionsDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPSectionDirective const*, clang::OMPSectionDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPScopeDirective const*, clang::OMPScopeDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPScanDirective const*, clang::OMPScanDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelSectionsDirective const*, clang::OMPParallelSectionsDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelMasterDirective const*, clang::OMPParallelMasterDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelMaskedDirective const*, clang::OMPParallelMaskedDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelDirective const*, clang::OMPParallelDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPOrderedDirective const*, clang::OMPOrderedDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMetaDirective const*, clang::OMPMetaDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMasterDirective const*, clang::OMPMasterDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMaskedDirective const*, clang::OMPMaskedDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPUnrollDirective const*, clang::OMPUnrollDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTileDirective const*, clang::OMPTileDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTeamsGenericLoopDirective const*, clang::OMPTeamsGenericLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTeamsDistributeSimdDirective const*, clang::OMPTeamsDistributeSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTeamsDistributeParallelForSimdDirective const*, clang::OMPTeamsDistributeParallelForSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTeamsDistributeParallelForDirective const*, clang::OMPTeamsDistributeParallelForDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTeamsDistributeDirective const*, clang::OMPTeamsDistributeDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTaskLoopSimdDirective const*, clang::OMPTaskLoopSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTaskLoopDirective const*, clang::OMPTaskLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetTeamsGenericLoopDirective const*, clang::OMPTargetTeamsGenericLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetTeamsDistributeSimdDirective const*, clang::OMPTargetTeamsDistributeSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetTeamsDistributeParallelForSimdDirective const*, clang::OMPTargetTeamsDistributeParallelForSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetTeamsDistributeParallelForDirective const*, clang::OMPTargetTeamsDistributeParallelForDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetTeamsDistributeDirective const*, clang::OMPTargetTeamsDistributeDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetSimdDirective const*, clang::OMPTargetSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetParallelGenericLoopDirective const*, clang::OMPTargetParallelGenericLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPTargetParallelForSimdDirective const*, clang::OMPTargetParallelForSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPSimdDirective const*, clang::OMPSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelMasterTaskLoopSimdDirective const*, clang::OMPParallelMasterTaskLoopSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelMasterTaskLoopDirective const*, clang::OMPParallelMasterTaskLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelMaskedTaskLoopSimdDirective const*, clang::OMPParallelMaskedTaskLoopSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelMaskedTaskLoopDirective const*, clang::OMPParallelMaskedTaskLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelGenericLoopDirective const*, clang::OMPParallelGenericLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelForSimdDirective const*, clang::OMPParallelForSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPParallelForDirective const*, clang::OMPParallelForDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMasterTaskLoopSimdDirective const*, clang::OMPMasterTaskLoopSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMasterTaskLoopDirective const*, clang::OMPMasterTaskLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMaskedTaskLoopSimdDirective const*, clang::OMPMaskedTaskLoopSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPMaskedTaskLoopDirective const*, clang::OMPMaskedTaskLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPGenericLoopDirective const*, clang::OMPGenericLoopDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPForSimdDirective const*, clang::OMPForSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPForDirective const*, clang::OMPForDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPDistributeSimdDirective const*, clang::OMPDistributeSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPDistributeParallelForSimdDirective const*, clang::OMPDistributeParallelForSimdDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPDistributeParallelForDirective const*, clang::OMPDistributeParallelForDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPDistributeDirective const*, clang::OMPDistributeDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPInteropDirective const*, clang::OMPInteropDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPFlushDirective const*, clang::OMPFlushDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPErrorDirective const*, clang::OMPErrorDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPDispatchDirective const*, clang::OMPDispatchDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPDepobjDirective const*, clang::OMPDepobjDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPCriticalDirective const*, clang::OMPCriticalDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPCancellationPointDirective const*, clang::OMPCancellationPointDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPCancelDirective const*, clang::OMPCancelDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPBarrierDirective const*, clang::OMPBarrierDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPAtomicDirective const*, clang::OMPAtomicDirective const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::OMPCanonicalLoop const*, clang::OMPCanonicalLoop const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::NullStmt const*, clang::NullStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MSDependentExistsStmt const*, clang::MSDependentExistsStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::IndirectGotoStmt const*, clang::IndirectGotoStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::IfStmt const*, clang::IfStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::GotoStmt const*, clang::GotoStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ForStmt const*, clang::ForStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DoStmt const*, clang::DoStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::DeclStmt const*, clang::DeclStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CoroutineBodyStmt const*, clang::CoroutineBodyStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CoreturnStmt const*, clang::CoreturnStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::ContinueStmt const*, clang::ContinueStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CompoundStmt const*, clang::CompoundStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CapturedStmt const*, clang::CapturedStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXTryStmt const*, clang::CXXTryStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXForRangeStmt const*, clang::CXXForRangeStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::CXXCatchStmt const*, clang::CXXCatchStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::BreakStmt const*, clang::BreakStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::MSAsmStmt const*, clang::MSAsmStmt const*)
Unexecuted instantiation: ASTStructuralEquivalence.cpp:(anonymous namespace)::StmtComparer::TraverseStmt(clang::GCCAsmStmt const*, clang::GCCAsmStmt const*)
408
#include "clang/AST/StmtNodes.inc"
409
410
public:
411
0
  StmtComparer(StructuralEquivalenceContext &C) : Context(C) {}
412
413
  /// Determine whether two statements are equivalent. The statements have to
414
  /// be of the same kind. The children of the statements and their properties
415
  /// are not compared by this function.
416
0
  bool IsEquivalent(const Stmt *S1, const Stmt *S2) {
417
0
    if (S1->getStmtClass() != S2->getStmtClass())
418
0
      return false;
419
420
    // Each TraverseStmt walks the class hierarchy from the leaf class to
421
    // the root class 'Stmt' (e.g. 'BinaryOperator' -> 'Expr' -> 'Stmt'). Cast
422
    // the Stmt we have here to its specific subclass so that we call the
423
    // overload that walks the whole class hierarchy from leaf to root (e.g.,
424
    // cast to 'BinaryOperator' so that 'Expr' and 'Stmt' is traversed).
425
0
    switch (S1->getStmtClass()) {
426
0
    case Stmt::NoStmtClass:
427
0
      llvm_unreachable("Can't traverse NoStmtClass");
428
0
#define STMT(CLASS, PARENT)                                                    \
429
0
  case Stmt::StmtClass::CLASS##Class:                                          \
430
0
    return TraverseStmt(static_cast<const CLASS *>(S1),                        \
431
0
                        static_cast<const CLASS *>(S2));
432
0
#define ABSTRACT_STMT(S)
433
0
#include "clang/AST/StmtNodes.inc"
434
0
    }
435
0
    llvm_unreachable("Invalid statement kind");
436
0
  }
437
};
438
} // namespace
439
440
/// Determine structural equivalence of two statements.
441
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
442
0
                                     const Stmt *S1, const Stmt *S2) {
443
0
  if (!S1 || !S2)
444
0
    return S1 == S2;
445
446
  // Compare the statements itself.
447
0
  StmtComparer Comparer(Context);
448
0
  if (!Comparer.IsEquivalent(S1, S2))
449
0
    return false;
450
451
  // Iterate over the children of both statements and also compare them.
452
0
  for (auto Pair : zip_longest(S1->children(), S2->children())) {
453
0
    std::optional<const Stmt *> Child1 = std::get<0>(Pair);
454
0
    std::optional<const Stmt *> Child2 = std::get<1>(Pair);
455
    // One of the statements has a different amount of children than the other,
456
    // so the statements can't be equivalent.
457
0
    if (!Child1 || !Child2)
458
0
      return false;
459
0
    if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
460
0
      return false;
461
0
  }
462
0
  return true;
463
0
}
464
465
/// Determine whether two identifiers are equivalent.
466
static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
467
0
                                     const IdentifierInfo *Name2) {
468
0
  if (!Name1 || !Name2)
469
0
    return Name1 == Name2;
470
471
0
  return Name1->getName() == Name2->getName();
472
0
}
473
474
/// Determine whether two nested-name-specifiers are equivalent.
475
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
476
                                     NestedNameSpecifier *NNS1,
477
0
                                     NestedNameSpecifier *NNS2) {
478
0
  if (NNS1->getKind() != NNS2->getKind())
479
0
    return false;
480
481
0
  NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
482
0
                      *Prefix2 = NNS2->getPrefix();
483
0
  if ((bool)Prefix1 != (bool)Prefix2)
484
0
    return false;
485
486
0
  if (Prefix1)
487
0
    if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
488
0
      return false;
489
490
0
  switch (NNS1->getKind()) {
491
0
  case NestedNameSpecifier::Identifier:
492
0
    return IsStructurallyEquivalent(NNS1->getAsIdentifier(),
493
0
                                    NNS2->getAsIdentifier());
494
0
  case NestedNameSpecifier::Namespace:
495
0
    return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
496
0
                                    NNS2->getAsNamespace());
497
0
  case NestedNameSpecifier::NamespaceAlias:
498
0
    return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(),
499
0
                                    NNS2->getAsNamespaceAlias());
500
0
  case NestedNameSpecifier::TypeSpec:
501
0
  case NestedNameSpecifier::TypeSpecWithTemplate:
502
0
    return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
503
0
                                    QualType(NNS2->getAsType(), 0));
504
0
  case NestedNameSpecifier::Global:
505
0
    return true;
506
0
  case NestedNameSpecifier::Super:
507
0
    return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
508
0
                                    NNS2->getAsRecordDecl());
509
0
  }
510
0
  return false;
511
0
}
512
513
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
514
                                     const TemplateName &N1,
515
0
                                     const TemplateName &N2) {
516
0
  TemplateDecl *TemplateDeclN1 = N1.getAsTemplateDecl();
517
0
  TemplateDecl *TemplateDeclN2 = N2.getAsTemplateDecl();
518
0
  if (TemplateDeclN1 && TemplateDeclN2) {
519
0
    if (!IsStructurallyEquivalent(Context, TemplateDeclN1, TemplateDeclN2))
520
0
      return false;
521
    // If the kind is different we compare only the template decl.
522
0
    if (N1.getKind() != N2.getKind())
523
0
      return true;
524
0
  } else if (TemplateDeclN1 || TemplateDeclN2)
525
0
    return false;
526
0
  else if (N1.getKind() != N2.getKind())
527
0
    return false;
528
529
  // Check for special case incompatibilities.
530
0
  switch (N1.getKind()) {
531
532
0
  case TemplateName::OverloadedTemplate: {
533
0
    OverloadedTemplateStorage *OS1 = N1.getAsOverloadedTemplate(),
534
0
                              *OS2 = N2.getAsOverloadedTemplate();
535
0
    OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(),
536
0
                                        E1 = OS1->end(), E2 = OS2->end();
537
0
    for (; I1 != E1 && I2 != E2; ++I1, ++I2)
538
0
      if (!IsStructurallyEquivalent(Context, *I1, *I2))
539
0
        return false;
540
0
    return I1 == E1 && I2 == E2;
541
0
  }
542
543
0
  case TemplateName::AssumedTemplate: {
544
0
    AssumedTemplateStorage *TN1 = N1.getAsAssumedTemplateName(),
545
0
                           *TN2 = N1.getAsAssumedTemplateName();
546
0
    return TN1->getDeclName() == TN2->getDeclName();
547
0
  }
548
549
0
  case TemplateName::DependentTemplate: {
550
0
    DependentTemplateName *DN1 = N1.getAsDependentTemplateName(),
551
0
                          *DN2 = N2.getAsDependentTemplateName();
552
0
    if (!IsStructurallyEquivalent(Context, DN1->getQualifier(),
553
0
                                  DN2->getQualifier()))
554
0
      return false;
555
0
    if (DN1->isIdentifier() && DN2->isIdentifier())
556
0
      return IsStructurallyEquivalent(DN1->getIdentifier(),
557
0
                                      DN2->getIdentifier());
558
0
    else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator())
559
0
      return DN1->getOperator() == DN2->getOperator();
560
0
    return false;
561
0
  }
562
563
0
  case TemplateName::SubstTemplateTemplateParmPack: {
564
0
    SubstTemplateTemplateParmPackStorage
565
0
        *P1 = N1.getAsSubstTemplateTemplateParmPack(),
566
0
        *P2 = N2.getAsSubstTemplateTemplateParmPack();
567
0
    return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
568
0
                                    P2->getArgumentPack()) &&
569
0
           IsStructurallyEquivalent(Context, P1->getAssociatedDecl(),
570
0
                                    P2->getAssociatedDecl()) &&
571
0
           P1->getIndex() == P2->getIndex();
572
0
  }
573
574
0
   case TemplateName::Template:
575
0
   case TemplateName::QualifiedTemplate:
576
0
   case TemplateName::SubstTemplateTemplateParm:
577
0
   case TemplateName::UsingTemplate:
578
     // It is sufficient to check value of getAsTemplateDecl.
579
0
     break;
580
581
0
  }
582
583
0
  return true;
584
0
}
585
586
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
587
                                     ArrayRef<TemplateArgument> Args1,
588
                                     ArrayRef<TemplateArgument> Args2);
589
590
/// Determine whether two template arguments are equivalent.
591
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
592
                                     const TemplateArgument &Arg1,
593
0
                                     const TemplateArgument &Arg2) {
594
0
  if (Arg1.getKind() != Arg2.getKind())
595
0
    return false;
596
597
0
  switch (Arg1.getKind()) {
598
0
  case TemplateArgument::Null:
599
0
    return true;
600
601
0
  case TemplateArgument::Type:
602
0
    return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
603
604
0
  case TemplateArgument::Integral:
605
0
    if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
606
0
                                          Arg2.getIntegralType()))
607
0
      return false;
608
609
0
    return llvm::APSInt::isSameValue(Arg1.getAsIntegral(),
610
0
                                     Arg2.getAsIntegral());
611
612
0
  case TemplateArgument::Declaration:
613
0
    return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
614
615
0
  case TemplateArgument::NullPtr:
616
0
    return true; // FIXME: Is this correct?
617
618
0
  case TemplateArgument::Template:
619
0
    return IsStructurallyEquivalent(Context, Arg1.getAsTemplate(),
620
0
                                    Arg2.getAsTemplate());
621
622
0
  case TemplateArgument::TemplateExpansion:
623
0
    return IsStructurallyEquivalent(Context,
624
0
                                    Arg1.getAsTemplateOrTemplatePattern(),
625
0
                                    Arg2.getAsTemplateOrTemplatePattern());
626
627
0
  case TemplateArgument::Expression:
628
0
    return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
629
0
                                    Arg2.getAsExpr());
630
631
0
  case TemplateArgument::Pack:
632
0
    return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
633
0
                                    Arg2.pack_elements());
634
0
  }
635
636
0
  llvm_unreachable("Invalid template argument kind");
637
0
}
638
639
/// Determine structural equivalence of two template argument lists.
640
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
641
                                     ArrayRef<TemplateArgument> Args1,
642
0
                                     ArrayRef<TemplateArgument> Args2) {
643
0
  if (Args1.size() != Args2.size())
644
0
    return false;
645
0
  for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
646
0
    if (!IsStructurallyEquivalent(Context, Args1[I], Args2[I]))
647
0
      return false;
648
0
  }
649
0
  return true;
650
0
}
651
652
/// Determine whether two template argument locations are equivalent.
653
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
654
                                     const TemplateArgumentLoc &Arg1,
655
0
                                     const TemplateArgumentLoc &Arg2) {
656
0
  return IsStructurallyEquivalent(Context, Arg1.getArgument(),
657
0
                                  Arg2.getArgument());
658
0
}
659
660
/// Determine structural equivalence for the common part of array
661
/// types.
662
static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context,
663
                                          const ArrayType *Array1,
664
0
                                          const ArrayType *Array2) {
665
0
  if (!IsStructurallyEquivalent(Context, Array1->getElementType(),
666
0
                                Array2->getElementType()))
667
0
    return false;
668
0
  if (Array1->getSizeModifier() != Array2->getSizeModifier())
669
0
    return false;
670
0
  if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
671
0
    return false;
672
673
0
  return true;
674
0
}
675
676
/// Determine structural equivalence based on the ExtInfo of functions. This
677
/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
678
/// conventions bits but must not compare some other bits.
679
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
680
                                     FunctionType::ExtInfo EI1,
681
0
                                     FunctionType::ExtInfo EI2) {
682
  // Compatible functions must have compatible calling conventions.
683
0
  if (EI1.getCC() != EI2.getCC())
684
0
    return false;
685
686
  // Regparm is part of the calling convention.
687
0
  if (EI1.getHasRegParm() != EI2.getHasRegParm())
688
0
    return false;
689
0
  if (EI1.getRegParm() != EI2.getRegParm())
690
0
    return false;
691
692
0
  if (EI1.getProducesResult() != EI2.getProducesResult())
693
0
    return false;
694
0
  if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs())
695
0
    return false;
696
0
  if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
697
0
    return false;
698
699
0
  return true;
700
0
}
701
702
/// Check the equivalence of exception specifications.
703
static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext &Context,
704
                                      const FunctionProtoType *Proto1,
705
0
                                      const FunctionProtoType *Proto2) {
706
707
0
  auto Spec1 = Proto1->getExceptionSpecType();
708
0
  auto Spec2 = Proto2->getExceptionSpecType();
709
710
0
  if (isUnresolvedExceptionSpec(Spec1) || isUnresolvedExceptionSpec(Spec2))
711
0
    return true;
712
713
0
  if (Spec1 != Spec2)
714
0
    return false;
715
0
  if (Spec1 == EST_Dynamic) {
716
0
    if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
717
0
      return false;
718
0
    for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
719
0
      if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
720
0
                                    Proto2->getExceptionType(I)))
721
0
        return false;
722
0
    }
723
0
  } else if (isComputedNoexcept(Spec1)) {
724
0
    if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
725
0
                                  Proto2->getNoexceptExpr()))
726
0
      return false;
727
0
  }
728
729
0
  return true;
730
0
}
731
732
/// Determine structural equivalence of two types.
733
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
734
0
                                     QualType T1, QualType T2) {
735
0
  if (T1.isNull() || T2.isNull())
736
0
    return T1.isNull() && T2.isNull();
737
738
0
  QualType OrigT1 = T1;
739
0
  QualType OrigT2 = T2;
740
741
0
  if (!Context.StrictTypeSpelling) {
742
    // We aren't being strict about token-to-token equivalence of types,
743
    // so map down to the canonical type.
744
0
    T1 = Context.FromCtx.getCanonicalType(T1);
745
0
    T2 = Context.ToCtx.getCanonicalType(T2);
746
0
  }
747
748
0
  if (T1.getQualifiers() != T2.getQualifiers())
749
0
    return false;
750
751
0
  Type::TypeClass TC = T1->getTypeClass();
752
753
0
  if (T1->getTypeClass() != T2->getTypeClass()) {
754
    // Compare function types with prototypes vs. without prototypes as if
755
    // both did not have prototypes.
756
0
    if (T1->getTypeClass() == Type::FunctionProto &&
757
0
        T2->getTypeClass() == Type::FunctionNoProto)
758
0
      TC = Type::FunctionNoProto;
759
0
    else if (T1->getTypeClass() == Type::FunctionNoProto &&
760
0
             T2->getTypeClass() == Type::FunctionProto)
761
0
      TC = Type::FunctionNoProto;
762
0
    else
763
0
      return false;
764
0
  }
765
766
0
  switch (TC) {
767
0
  case Type::Builtin:
768
    // FIXME: Deal with Char_S/Char_U.
769
0
    if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind())
770
0
      return false;
771
0
    break;
772
773
0
  case Type::Complex:
774
0
    if (!IsStructurallyEquivalent(Context,
775
0
                                  cast<ComplexType>(T1)->getElementType(),
776
0
                                  cast<ComplexType>(T2)->getElementType()))
777
0
      return false;
778
0
    break;
779
780
0
  case Type::Adjusted:
781
0
  case Type::Decayed:
782
0
    if (!IsStructurallyEquivalent(Context,
783
0
                                  cast<AdjustedType>(T1)->getOriginalType(),
784
0
                                  cast<AdjustedType>(T2)->getOriginalType()))
785
0
      return false;
786
0
    break;
787
788
0
  case Type::Pointer:
789
0
    if (!IsStructurallyEquivalent(Context,
790
0
                                  cast<PointerType>(T1)->getPointeeType(),
791
0
                                  cast<PointerType>(T2)->getPointeeType()))
792
0
      return false;
793
0
    break;
794
795
0
  case Type::BlockPointer:
796
0
    if (!IsStructurallyEquivalent(Context,
797
0
                                  cast<BlockPointerType>(T1)->getPointeeType(),
798
0
                                  cast<BlockPointerType>(T2)->getPointeeType()))
799
0
      return false;
800
0
    break;
801
802
0
  case Type::LValueReference:
803
0
  case Type::RValueReference: {
804
0
    const auto *Ref1 = cast<ReferenceType>(T1);
805
0
    const auto *Ref2 = cast<ReferenceType>(T2);
806
0
    if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
807
0
      return false;
808
0
    if (Ref1->isInnerRef() != Ref2->isInnerRef())
809
0
      return false;
810
0
    if (!IsStructurallyEquivalent(Context, Ref1->getPointeeTypeAsWritten(),
811
0
                                  Ref2->getPointeeTypeAsWritten()))
812
0
      return false;
813
0
    break;
814
0
  }
815
816
0
  case Type::MemberPointer: {
817
0
    const auto *MemPtr1 = cast<MemberPointerType>(T1);
818
0
    const auto *MemPtr2 = cast<MemberPointerType>(T2);
819
0
    if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
820
0
                                  MemPtr2->getPointeeType()))
821
0
      return false;
822
0
    if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0),
823
0
                                  QualType(MemPtr2->getClass(), 0)))
824
0
      return false;
825
0
    break;
826
0
  }
827
828
0
  case Type::ConstantArray: {
829
0
    const auto *Array1 = cast<ConstantArrayType>(T1);
830
0
    const auto *Array2 = cast<ConstantArrayType>(T2);
831
0
    if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
832
0
      return false;
833
834
0
    if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
835
0
      return false;
836
0
    break;
837
0
  }
838
839
0
  case Type::IncompleteArray:
840
0
    if (!IsArrayStructurallyEquivalent(Context, cast<ArrayType>(T1),
841
0
                                       cast<ArrayType>(T2)))
842
0
      return false;
843
0
    break;
844
845
0
  case Type::VariableArray: {
846
0
    const auto *Array1 = cast<VariableArrayType>(T1);
847
0
    const auto *Array2 = cast<VariableArrayType>(T2);
848
0
    if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
849
0
                                  Array2->getSizeExpr()))
850
0
      return false;
851
852
0
    if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
853
0
      return false;
854
855
0
    break;
856
0
  }
857
858
0
  case Type::DependentSizedArray: {
859
0
    const auto *Array1 = cast<DependentSizedArrayType>(T1);
860
0
    const auto *Array2 = cast<DependentSizedArrayType>(T2);
861
0
    if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
862
0
                                  Array2->getSizeExpr()))
863
0
      return false;
864
865
0
    if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
866
0
      return false;
867
868
0
    break;
869
0
  }
870
871
0
  case Type::DependentAddressSpace: {
872
0
    const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
873
0
    const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
874
0
    if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
875
0
                                  DepAddressSpace2->getAddrSpaceExpr()))
876
0
      return false;
877
0
    if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(),
878
0
                                  DepAddressSpace2->getPointeeType()))
879
0
      return false;
880
881
0
    break;
882
0
  }
883
884
0
  case Type::DependentSizedExtVector: {
885
0
    const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
886
0
    const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
887
0
    if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
888
0
                                  Vec2->getSizeExpr()))
889
0
      return false;
890
0
    if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
891
0
                                  Vec2->getElementType()))
892
0
      return false;
893
0
    break;
894
0
  }
895
896
0
  case Type::DependentVector: {
897
0
    const auto *Vec1 = cast<DependentVectorType>(T1);
898
0
    const auto *Vec2 = cast<DependentVectorType>(T2);
899
0
    if (Vec1->getVectorKind() != Vec2->getVectorKind())
900
0
      return false;
901
0
    if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
902
0
                                  Vec2->getSizeExpr()))
903
0
      return false;
904
0
    if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
905
0
                                  Vec2->getElementType()))
906
0
      return false;
907
0
    break;
908
0
  }
909
910
0
  case Type::Vector:
911
0
  case Type::ExtVector: {
912
0
    const auto *Vec1 = cast<VectorType>(T1);
913
0
    const auto *Vec2 = cast<VectorType>(T2);
914
0
    if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
915
0
                                  Vec2->getElementType()))
916
0
      return false;
917
0
    if (Vec1->getNumElements() != Vec2->getNumElements())
918
0
      return false;
919
0
    if (Vec1->getVectorKind() != Vec2->getVectorKind())
920
0
      return false;
921
0
    break;
922
0
  }
923
924
0
  case Type::DependentSizedMatrix: {
925
0
    const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(T1);
926
0
    const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(T2);
927
    // The element types, row and column expressions must be structurally
928
    // equivalent.
929
0
    if (!IsStructurallyEquivalent(Context, Mat1->getRowExpr(),
930
0
                                  Mat2->getRowExpr()) ||
931
0
        !IsStructurallyEquivalent(Context, Mat1->getColumnExpr(),
932
0
                                  Mat2->getColumnExpr()) ||
933
0
        !IsStructurallyEquivalent(Context, Mat1->getElementType(),
934
0
                                  Mat2->getElementType()))
935
0
      return false;
936
0
    break;
937
0
  }
938
939
0
  case Type::ConstantMatrix: {
940
0
    const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(T1);
941
0
    const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(T2);
942
    // The element types must be structurally equivalent and the number of rows
943
    // and columns must match.
944
0
    if (!IsStructurallyEquivalent(Context, Mat1->getElementType(),
945
0
                                  Mat2->getElementType()) ||
946
0
        Mat1->getNumRows() != Mat2->getNumRows() ||
947
0
        Mat1->getNumColumns() != Mat2->getNumColumns())
948
0
      return false;
949
0
    break;
950
0
  }
951
952
0
  case Type::FunctionProto: {
953
0
    const auto *Proto1 = cast<FunctionProtoType>(T1);
954
0
    const auto *Proto2 = cast<FunctionProtoType>(T2);
955
956
0
    if (Proto1->getNumParams() != Proto2->getNumParams())
957
0
      return false;
958
0
    for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
959
0
      if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I),
960
0
                                    Proto2->getParamType(I)))
961
0
        return false;
962
0
    }
963
0
    if (Proto1->isVariadic() != Proto2->isVariadic())
964
0
      return false;
965
966
0
    if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
967
0
      return false;
968
969
    // Check exceptions, this information is lost in canonical type.
970
0
    const auto *OrigProto1 =
971
0
        cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
972
0
    const auto *OrigProto2 =
973
0
        cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
974
0
    if (!IsEquivalentExceptionSpec(Context, OrigProto1, OrigProto2))
975
0
      return false;
976
977
    // Fall through to check the bits common with FunctionNoProtoType.
978
0
    [[fallthrough]];
979
0
  }
980
981
0
  case Type::FunctionNoProto: {
982
0
    const auto *Function1 = cast<FunctionType>(T1);
983
0
    const auto *Function2 = cast<FunctionType>(T2);
984
0
    if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
985
0
                                  Function2->getReturnType()))
986
0
      return false;
987
0
    if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
988
0
                                  Function2->getExtInfo()))
989
0
      return false;
990
0
    break;
991
0
  }
992
993
0
  case Type::UnresolvedUsing:
994
0
    if (!IsStructurallyEquivalent(Context,
995
0
                                  cast<UnresolvedUsingType>(T1)->getDecl(),
996
0
                                  cast<UnresolvedUsingType>(T2)->getDecl()))
997
0
      return false;
998
0
    break;
999
1000
0
  case Type::Attributed:
1001
0
    if (!IsStructurallyEquivalent(Context,
1002
0
                                  cast<AttributedType>(T1)->getModifiedType(),
1003
0
                                  cast<AttributedType>(T2)->getModifiedType()))
1004
0
      return false;
1005
0
    if (!IsStructurallyEquivalent(
1006
0
            Context, cast<AttributedType>(T1)->getEquivalentType(),
1007
0
            cast<AttributedType>(T2)->getEquivalentType()))
1008
0
      return false;
1009
0
    break;
1010
1011
0
  case Type::BTFTagAttributed:
1012
0
    if (!IsStructurallyEquivalent(
1013
0
            Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1014
0
            cast<BTFTagAttributedType>(T2)->getWrappedType()))
1015
0
      return false;
1016
0
    break;
1017
1018
0
  case Type::Paren:
1019
0
    if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(),
1020
0
                                  cast<ParenType>(T2)->getInnerType()))
1021
0
      return false;
1022
0
    break;
1023
1024
0
  case Type::MacroQualified:
1025
0
    if (!IsStructurallyEquivalent(
1026
0
            Context, cast<MacroQualifiedType>(T1)->getUnderlyingType(),
1027
0
            cast<MacroQualifiedType>(T2)->getUnderlyingType()))
1028
0
      return false;
1029
0
    break;
1030
1031
0
  case Type::Using:
1032
0
    if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
1033
0
                                  cast<UsingType>(T2)->getFoundDecl()))
1034
0
      return false;
1035
0
    if (!IsStructurallyEquivalent(Context,
1036
0
                                  cast<UsingType>(T1)->getUnderlyingType(),
1037
0
                                  cast<UsingType>(T2)->getUnderlyingType()))
1038
0
      return false;
1039
0
    break;
1040
1041
0
  case Type::Typedef:
1042
0
    if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
1043
0
                                  cast<TypedefType>(T2)->getDecl()) ||
1044
0
        !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
1045
0
                                  cast<TypedefType>(T2)->desugar()))
1046
0
      return false;
1047
0
    break;
1048
1049
0
  case Type::TypeOfExpr:
1050
0
    if (!IsStructurallyEquivalent(
1051
0
            Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1052
0
            cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1053
0
      return false;
1054
0
    break;
1055
1056
0
  case Type::TypeOf:
1057
0
    if (!IsStructurallyEquivalent(Context,
1058
0
                                  cast<TypeOfType>(T1)->getUnmodifiedType(),
1059
0
                                  cast<TypeOfType>(T2)->getUnmodifiedType()))
1060
0
      return false;
1061
0
    break;
1062
1063
0
  case Type::UnaryTransform:
1064
0
    if (!IsStructurallyEquivalent(
1065
0
            Context, cast<UnaryTransformType>(T1)->getUnderlyingType(),
1066
0
            cast<UnaryTransformType>(T2)->getUnderlyingType()))
1067
0
      return false;
1068
0
    break;
1069
1070
0
  case Type::Decltype:
1071
0
    if (!IsStructurallyEquivalent(Context,
1072
0
                                  cast<DecltypeType>(T1)->getUnderlyingExpr(),
1073
0
                                  cast<DecltypeType>(T2)->getUnderlyingExpr()))
1074
0
      return false;
1075
0
    break;
1076
1077
0
  case Type::Auto: {
1078
0
    auto *Auto1 = cast<AutoType>(T1);
1079
0
    auto *Auto2 = cast<AutoType>(T2);
1080
0
    if (!IsStructurallyEquivalent(Context, Auto1->getDeducedType(),
1081
0
                                  Auto2->getDeducedType()))
1082
0
      return false;
1083
0
    if (Auto1->isConstrained() != Auto2->isConstrained())
1084
0
      return false;
1085
0
    if (Auto1->isConstrained()) {
1086
0
      if (Auto1->getTypeConstraintConcept() !=
1087
0
          Auto2->getTypeConstraintConcept())
1088
0
        return false;
1089
0
      if (!IsStructurallyEquivalent(Context,
1090
0
                                    Auto1->getTypeConstraintArguments(),
1091
0
                                    Auto2->getTypeConstraintArguments()))
1092
0
        return false;
1093
0
    }
1094
0
    break;
1095
0
  }
1096
1097
0
  case Type::DeducedTemplateSpecialization: {
1098
0
    const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1099
0
    const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1100
0
    if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(),
1101
0
                                  DT2->getTemplateName()))
1102
0
      return false;
1103
0
    if (!IsStructurallyEquivalent(Context, DT1->getDeducedType(),
1104
0
                                  DT2->getDeducedType()))
1105
0
      return false;
1106
0
    break;
1107
0
  }
1108
1109
0
  case Type::Record:
1110
0
  case Type::Enum:
1111
0
    if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(),
1112
0
                                  cast<TagType>(T2)->getDecl()))
1113
0
      return false;
1114
0
    break;
1115
1116
0
  case Type::TemplateTypeParm: {
1117
0
    const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1118
0
    const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1119
0
    if (!Context.IgnoreTemplateParmDepth &&
1120
0
        Parm1->getDepth() != Parm2->getDepth())
1121
0
      return false;
1122
0
    if (Parm1->getIndex() != Parm2->getIndex())
1123
0
      return false;
1124
0
    if (Parm1->isParameterPack() != Parm2->isParameterPack())
1125
0
      return false;
1126
1127
    // Names of template type parameters are never significant.
1128
0
    break;
1129
0
  }
1130
1131
0
  case Type::SubstTemplateTypeParm: {
1132
0
    const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1133
0
    const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1134
0
    if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
1135
0
                                  Subst2->getReplacementType()))
1136
0
      return false;
1137
0
    if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1138
0
                                  Subst2->getAssociatedDecl()))
1139
0
      return false;
1140
0
    if (Subst1->getIndex() != Subst2->getIndex())
1141
0
      return false;
1142
0
    if (Subst1->getPackIndex() != Subst2->getPackIndex())
1143
0
      return false;
1144
0
    break;
1145
0
  }
1146
1147
0
  case Type::SubstTemplateTypeParmPack: {
1148
0
    const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1149
0
    const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1150
0
    if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1151
0
                                  Subst2->getAssociatedDecl()))
1152
0
      return false;
1153
0
    if (Subst1->getIndex() != Subst2->getIndex())
1154
0
      return false;
1155
0
    if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
1156
0
                                  Subst2->getArgumentPack()))
1157
0
      return false;
1158
0
    break;
1159
0
  }
1160
1161
0
  case Type::TemplateSpecialization: {
1162
0
    const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1163
0
    const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1164
0
    if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
1165
0
                                  Spec2->getTemplateName()))
1166
0
      return false;
1167
0
    if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1168
0
                                  Spec2->template_arguments()))
1169
0
      return false;
1170
0
    break;
1171
0
  }
1172
1173
0
  case Type::Elaborated: {
1174
0
    const auto *Elab1 = cast<ElaboratedType>(T1);
1175
0
    const auto *Elab2 = cast<ElaboratedType>(T2);
1176
    // CHECKME: what if a keyword is ElaboratedTypeKeyword::None or
1177
    // ElaboratedTypeKeyword::Typename
1178
    // ?
1179
0
    if (Elab1->getKeyword() != Elab2->getKeyword())
1180
0
      return false;
1181
0
    if (!IsStructurallyEquivalent(Context, Elab1->getQualifier(),
1182
0
                                  Elab2->getQualifier()))
1183
0
      return false;
1184
0
    if (!IsStructurallyEquivalent(Context, Elab1->getNamedType(),
1185
0
                                  Elab2->getNamedType()))
1186
0
      return false;
1187
0
    break;
1188
0
  }
1189
1190
0
  case Type::InjectedClassName: {
1191
0
    const auto *Inj1 = cast<InjectedClassNameType>(T1);
1192
0
    const auto *Inj2 = cast<InjectedClassNameType>(T2);
1193
0
    if (!IsStructurallyEquivalent(Context,
1194
0
                                  Inj1->getInjectedSpecializationType(),
1195
0
                                  Inj2->getInjectedSpecializationType()))
1196
0
      return false;
1197
0
    break;
1198
0
  }
1199
1200
0
  case Type::DependentName: {
1201
0
    const auto *Typename1 = cast<DependentNameType>(T1);
1202
0
    const auto *Typename2 = cast<DependentNameType>(T2);
1203
0
    if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(),
1204
0
                                  Typename2->getQualifier()))
1205
0
      return false;
1206
0
    if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
1207
0
                                  Typename2->getIdentifier()))
1208
0
      return false;
1209
1210
0
    break;
1211
0
  }
1212
1213
0
  case Type::DependentTemplateSpecialization: {
1214
0
    const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1215
0
    const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1216
0
    if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(),
1217
0
                                  Spec2->getQualifier()))
1218
0
      return false;
1219
0
    if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
1220
0
                                  Spec2->getIdentifier()))
1221
0
      return false;
1222
0
    if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1223
0
                                  Spec2->template_arguments()))
1224
0
      return false;
1225
0
    break;
1226
0
  }
1227
1228
0
  case Type::PackExpansion:
1229
0
    if (!IsStructurallyEquivalent(Context,
1230
0
                                  cast<PackExpansionType>(T1)->getPattern(),
1231
0
                                  cast<PackExpansionType>(T2)->getPattern()))
1232
0
      return false;
1233
0
    break;
1234
1235
0
  case Type::ObjCInterface: {
1236
0
    const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1237
0
    const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1238
0
    if (!IsStructurallyEquivalent(Context, Iface1->getDecl(),
1239
0
                                  Iface2->getDecl()))
1240
0
      return false;
1241
0
    break;
1242
0
  }
1243
1244
0
  case Type::ObjCTypeParam: {
1245
0
    const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1246
0
    const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1247
0
    if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), Obj2->getDecl()))
1248
0
      return false;
1249
1250
0
    if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1251
0
      return false;
1252
0
    for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1253
0
      if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1254
0
                                    Obj2->getProtocol(I)))
1255
0
        return false;
1256
0
    }
1257
0
    break;
1258
0
  }
1259
1260
0
  case Type::ObjCObject: {
1261
0
    const auto *Obj1 = cast<ObjCObjectType>(T1);
1262
0
    const auto *Obj2 = cast<ObjCObjectType>(T2);
1263
0
    if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(),
1264
0
                                  Obj2->getBaseType()))
1265
0
      return false;
1266
0
    if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1267
0
      return false;
1268
0
    for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1269
0
      if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1270
0
                                    Obj2->getProtocol(I)))
1271
0
        return false;
1272
0
    }
1273
0
    break;
1274
0
  }
1275
1276
0
  case Type::ObjCObjectPointer: {
1277
0
    const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1278
0
    const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1279
0
    if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(),
1280
0
                                  Ptr2->getPointeeType()))
1281
0
      return false;
1282
0
    break;
1283
0
  }
1284
1285
0
  case Type::Atomic:
1286
0
    if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(),
1287
0
                                  cast<AtomicType>(T2)->getValueType()))
1288
0
      return false;
1289
0
    break;
1290
1291
0
  case Type::Pipe:
1292
0
    if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(),
1293
0
                                  cast<PipeType>(T2)->getElementType()))
1294
0
      return false;
1295
0
    break;
1296
0
  case Type::BitInt: {
1297
0
    const auto *Int1 = cast<BitIntType>(T1);
1298
0
    const auto *Int2 = cast<BitIntType>(T2);
1299
1300
0
    if (Int1->isUnsigned() != Int2->isUnsigned() ||
1301
0
        Int1->getNumBits() != Int2->getNumBits())
1302
0
      return false;
1303
0
    break;
1304
0
  }
1305
0
  case Type::DependentBitInt: {
1306
0
    const auto *Int1 = cast<DependentBitIntType>(T1);
1307
0
    const auto *Int2 = cast<DependentBitIntType>(T2);
1308
1309
0
    if (Int1->isUnsigned() != Int2->isUnsigned() ||
1310
0
        !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
1311
0
                                  Int2->getNumBitsExpr()))
1312
0
      return false;
1313
0
    break;
1314
0
  }
1315
0
  } // end switch
1316
1317
0
  return true;
1318
0
}
1319
1320
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1321
0
                                     VarDecl *D1, VarDecl *D2) {
1322
0
  if (D1->getStorageClass() != D2->getStorageClass())
1323
0
    return false;
1324
1325
0
  IdentifierInfo *Name1 = D1->getIdentifier();
1326
0
  IdentifierInfo *Name2 = D2->getIdentifier();
1327
0
  if (!::IsStructurallyEquivalent(Name1, Name2))
1328
0
    return false;
1329
1330
0
  if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
1331
0
    return false;
1332
1333
0
  return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit());
1334
0
}
1335
1336
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1337
                                     FieldDecl *Field1, FieldDecl *Field2,
1338
0
                                     QualType Owner2Type) {
1339
0
  const auto *Owner2 = cast<Decl>(Field2->getDeclContext());
1340
1341
  // For anonymous structs/unions, match up the anonymous struct/union type
1342
  // declarations directly, so that we don't go off searching for anonymous
1343
  // types
1344
0
  if (Field1->isAnonymousStructOrUnion() &&
1345
0
      Field2->isAnonymousStructOrUnion()) {
1346
0
    RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1347
0
    RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1348
0
    return IsStructurallyEquivalent(Context, D1, D2);
1349
0
  }
1350
1351
  // Check for equivalent field names.
1352
0
  IdentifierInfo *Name1 = Field1->getIdentifier();
1353
0
  IdentifierInfo *Name2 = Field2->getIdentifier();
1354
0
  if (!::IsStructurallyEquivalent(Name1, Name2)) {
1355
0
    if (Context.Complain) {
1356
0
      Context.Diag2(
1357
0
          Owner2->getLocation(),
1358
0
          Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1359
0
          << Owner2Type;
1360
0
      Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
1361
0
          << Field2->getDeclName();
1362
0
      Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
1363
0
          << Field1->getDeclName();
1364
0
    }
1365
0
    return false;
1366
0
  }
1367
1368
0
  if (!IsStructurallyEquivalent(Context, Field1->getType(),
1369
0
                                Field2->getType())) {
1370
0
    if (Context.Complain) {
1371
0
      Context.Diag2(
1372
0
          Owner2->getLocation(),
1373
0
          Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1374
0
          << Owner2Type;
1375
0
      Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1376
0
          << Field2->getDeclName() << Field2->getType();
1377
0
      Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1378
0
          << Field1->getDeclName() << Field1->getType();
1379
0
    }
1380
0
    return false;
1381
0
  }
1382
1383
0
  if (Field1->isBitField())
1384
0
    return IsStructurallyEquivalent(Context, Field1->getBitWidth(),
1385
0
                                    Field2->getBitWidth());
1386
1387
0
  return true;
1388
0
}
1389
1390
/// Determine structural equivalence of two fields.
1391
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1392
0
                                     FieldDecl *Field1, FieldDecl *Field2) {
1393
0
  const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
1394
0
  return IsStructurallyEquivalent(Context, Field1, Field2,
1395
0
                                  Context.ToCtx.getTypeDeclType(Owner2));
1396
0
}
1397
1398
/// Determine structural equivalence of two methods.
1399
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1400
                                     CXXMethodDecl *Method1,
1401
0
                                     CXXMethodDecl *Method2) {
1402
0
  bool PropertiesEqual =
1403
0
      Method1->getDeclKind() == Method2->getDeclKind() &&
1404
0
      Method1->getRefQualifier() == Method2->getRefQualifier() &&
1405
0
      Method1->getAccess() == Method2->getAccess() &&
1406
0
      Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1407
0
      Method1->isStatic() == Method2->isStatic() &&
1408
0
      Method1->isImplicitObjectMemberFunction() ==
1409
0
          Method2->isImplicitObjectMemberFunction() &&
1410
0
      Method1->isConst() == Method2->isConst() &&
1411
0
      Method1->isVolatile() == Method2->isVolatile() &&
1412
0
      Method1->isVirtual() == Method2->isVirtual() &&
1413
0
      Method1->isPure() == Method2->isPure() &&
1414
0
      Method1->isDefaulted() == Method2->isDefaulted() &&
1415
0
      Method1->isDeleted() == Method2->isDeleted();
1416
0
  if (!PropertiesEqual)
1417
0
    return false;
1418
  // FIXME: Check for 'final'.
1419
1420
0
  if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1421
0
    auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1422
0
    if (!Constructor1->getExplicitSpecifier().isEquivalent(
1423
0
            Constructor2->getExplicitSpecifier()))
1424
0
      return false;
1425
0
  }
1426
1427
0
  if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1428
0
    auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1429
0
    if (!Conversion1->getExplicitSpecifier().isEquivalent(
1430
0
            Conversion2->getExplicitSpecifier()))
1431
0
      return false;
1432
0
    if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
1433
0
                                  Conversion2->getConversionType()))
1434
0
      return false;
1435
0
  }
1436
1437
0
  const IdentifierInfo *Name1 = Method1->getIdentifier();
1438
0
  const IdentifierInfo *Name2 = Method2->getIdentifier();
1439
0
  if (!::IsStructurallyEquivalent(Name1, Name2)) {
1440
0
    return false;
1441
    // TODO: Names do not match, add warning like at check for FieldDecl.
1442
0
  }
1443
1444
  // Check the prototypes.
1445
0
  if (!::IsStructurallyEquivalent(Context,
1446
0
                                  Method1->getType(), Method2->getType()))
1447
0
    return false;
1448
1449
0
  return true;
1450
0
}
1451
1452
/// Determine structural equivalence of two lambda classes.
1453
static bool
1454
IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context,
1455
0
                                CXXRecordDecl *D1, CXXRecordDecl *D2) {
1456
0
  assert(D1->isLambda() && D2->isLambda() &&
1457
0
         "Must be called on lambda classes");
1458
0
  if (!IsStructurallyEquivalent(Context, D1->getLambdaCallOperator(),
1459
0
                                D2->getLambdaCallOperator()))
1460
0
    return false;
1461
1462
0
  return true;
1463
0
}
1464
1465
/// Determine if context of a class is equivalent.
1466
static bool
1467
IsRecordContextStructurallyEquivalent(StructuralEquivalenceContext &Context,
1468
0
                                      RecordDecl *D1, RecordDecl *D2) {
1469
  // The context should be completely equal, including anonymous and inline
1470
  // namespaces.
1471
  // We compare objects as part of full translation units, not subtrees of
1472
  // translation units.
1473
0
  DeclContext *DC1 = D1->getDeclContext()->getNonTransparentContext();
1474
0
  DeclContext *DC2 = D2->getDeclContext()->getNonTransparentContext();
1475
0
  while (true) {
1476
    // Special case: We allow a struct defined in a function to be equivalent
1477
    // with a similar struct defined outside of a function.
1478
0
    if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1479
0
        (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1480
0
      return true;
1481
1482
0
    if (DC1->getDeclKind() != DC2->getDeclKind())
1483
0
      return false;
1484
0
    if (DC1->isTranslationUnit())
1485
0
      break;
1486
0
    if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1487
0
      return false;
1488
0
    if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1489
0
      const auto *ND2 = cast<NamedDecl>(DC2);
1490
0
      if (!DC1->isInlineNamespace() &&
1491
0
          !IsStructurallyEquivalent(ND1->getIdentifier(), ND2->getIdentifier()))
1492
0
        return false;
1493
0
    }
1494
1495
0
    if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1496
0
      auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1497
0
      if (!IsStructurallyEquivalent(Context, D1Spec, D2Spec))
1498
0
        return false;
1499
0
    }
1500
1501
0
    DC1 = DC1->getParent()->getNonTransparentContext();
1502
0
    DC2 = DC2->getParent()->getNonTransparentContext();
1503
0
  }
1504
1505
0
  return true;
1506
0
}
1507
1508
0
static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1509
0
  auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1510
0
    if (const IdentifierInfo *Name = D.getIdentifier())
1511
0
      return Name;
1512
0
    if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1513
0
      return TypedefName->getIdentifier();
1514
0
    return nullptr;
1515
0
  };
1516
0
  return IsStructurallyEquivalent(GetName(D1), GetName(D2));
1517
0
}
1518
1519
/// Determine structural equivalence of two records.
1520
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1521
0
                                     RecordDecl *D1, RecordDecl *D2) {
1522
0
  if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1523
0
    return false;
1524
0
  }
1525
1526
0
  if (D1->isUnion() != D2->isUnion()) {
1527
0
    if (Context.Complain) {
1528
0
      Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1529
0
                                           diag::err_odr_tag_type_inconsistent))
1530
0
          << Context.ToCtx.getTypeDeclType(D2);
1531
0
      Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
1532
0
          << D1->getDeclName() << (unsigned)D1->getTagKind();
1533
0
    }
1534
0
    return false;
1535
0
  }
1536
1537
0
  if (!D1->getDeclName() && !D2->getDeclName()) {
1538
    // If both anonymous structs/unions are in a record context, make sure
1539
    // they occur in the same location in the context records.
1540
0
    if (std::optional<unsigned> Index1 =
1541
0
            StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(D1)) {
1542
0
      if (std::optional<unsigned> Index2 =
1543
0
              StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
1544
0
                  D2)) {
1545
0
        if (*Index1 != *Index2)
1546
0
          return false;
1547
0
      }
1548
0
    }
1549
0
  }
1550
1551
  // If the records occur in different context (namespace), these should be
1552
  // different. This is specially important if the definition of one or both
1553
  // records is missing.
1554
0
  if (!IsRecordContextStructurallyEquivalent(Context, D1, D2))
1555
0
    return false;
1556
1557
  // If both declarations are class template specializations, we know
1558
  // the ODR applies, so check the template and template arguments.
1559
0
  const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1560
0
  const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1561
0
  if (Spec1 && Spec2) {
1562
    // Check that the specialized templates are the same.
1563
0
    if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
1564
0
                                  Spec2->getSpecializedTemplate()))
1565
0
      return false;
1566
1567
    // Check that the template arguments are the same.
1568
0
    if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1569
0
      return false;
1570
1571
0
    for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1572
0
      if (!IsStructurallyEquivalent(Context, Spec1->getTemplateArgs().get(I),
1573
0
                                    Spec2->getTemplateArgs().get(I)))
1574
0
        return false;
1575
0
  }
1576
  // If one is a class template specialization and the other is not, these
1577
  // structures are different.
1578
0
  else if (Spec1 || Spec2)
1579
0
    return false;
1580
1581
  // Compare the definitions of these two records. If either or both are
1582
  // incomplete (i.e. it is a forward decl), we assume that they are
1583
  // equivalent.
1584
0
  D1 = D1->getDefinition();
1585
0
  D2 = D2->getDefinition();
1586
0
  if (!D1 || !D2)
1587
0
    return true;
1588
1589
  // If any of the records has external storage and we do a minimal check (or
1590
  // AST import) we assume they are equivalent. (If we didn't have this
1591
  // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1592
  // another AST import which in turn would call the structural equivalency
1593
  // check again and finally we'd have an improper result.)
1594
0
  if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1595
0
    if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
1596
0
      return true;
1597
1598
  // If one definition is currently being defined, we do not compare for
1599
  // equality and we assume that the decls are equal.
1600
0
  if (D1->isBeingDefined() || D2->isBeingDefined())
1601
0
    return true;
1602
1603
0
  if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1604
0
    if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1605
0
      if (D1CXX->hasExternalLexicalStorage() &&
1606
0
          !D1CXX->isCompleteDefinition()) {
1607
0
        D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1608
0
      }
1609
1610
0
      if (D1CXX->isLambda() != D2CXX->isLambda())
1611
0
        return false;
1612
0
      if (D1CXX->isLambda()) {
1613
0
        if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX))
1614
0
          return false;
1615
0
      }
1616
1617
0
      if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1618
0
        if (Context.Complain) {
1619
0
          Context.Diag2(D2->getLocation(),
1620
0
                        Context.getApplicableDiagnostic(
1621
0
                            diag::err_odr_tag_type_inconsistent))
1622
0
              << Context.ToCtx.getTypeDeclType(D2);
1623
0
          Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
1624
0
              << D2CXX->getNumBases();
1625
0
          Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
1626
0
              << D1CXX->getNumBases();
1627
0
        }
1628
0
        return false;
1629
0
      }
1630
1631
      // Check the base classes.
1632
0
      for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1633
0
                                              BaseEnd1 = D1CXX->bases_end(),
1634
0
                                              Base2 = D2CXX->bases_begin();
1635
0
           Base1 != BaseEnd1; ++Base1, ++Base2) {
1636
0
        if (!IsStructurallyEquivalent(Context, Base1->getType(),
1637
0
                                      Base2->getType())) {
1638
0
          if (Context.Complain) {
1639
0
            Context.Diag2(D2->getLocation(),
1640
0
                          Context.getApplicableDiagnostic(
1641
0
                              diag::err_odr_tag_type_inconsistent))
1642
0
                << Context.ToCtx.getTypeDeclType(D2);
1643
0
            Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1644
0
                << Base2->getType() << Base2->getSourceRange();
1645
0
            Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1646
0
                << Base1->getType() << Base1->getSourceRange();
1647
0
          }
1648
0
          return false;
1649
0
        }
1650
1651
        // Check virtual vs. non-virtual inheritance mismatch.
1652
0
        if (Base1->isVirtual() != Base2->isVirtual()) {
1653
0
          if (Context.Complain) {
1654
0
            Context.Diag2(D2->getLocation(),
1655
0
                          Context.getApplicableDiagnostic(
1656
0
                              diag::err_odr_tag_type_inconsistent))
1657
0
                << Context.ToCtx.getTypeDeclType(D2);
1658
0
            Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1659
0
                << Base2->isVirtual() << Base2->getSourceRange();
1660
0
            Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1661
0
                << Base1->isVirtual() << Base1->getSourceRange();
1662
0
          }
1663
0
          return false;
1664
0
        }
1665
0
      }
1666
1667
      // Check the friends for consistency.
1668
0
      CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
1669
0
                                     Friend2End = D2CXX->friend_end();
1670
0
      for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
1671
0
                                          Friend1End = D1CXX->friend_end();
1672
0
           Friend1 != Friend1End; ++Friend1, ++Friend2) {
1673
0
        if (Friend2 == Friend2End) {
1674
0
          if (Context.Complain) {
1675
0
            Context.Diag2(D2->getLocation(),
1676
0
                          Context.getApplicableDiagnostic(
1677
0
                              diag::err_odr_tag_type_inconsistent))
1678
0
                << Context.ToCtx.getTypeDeclType(D2CXX);
1679
0
            Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1680
0
            Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
1681
0
          }
1682
0
          return false;
1683
0
        }
1684
1685
0
        if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) {
1686
0
          if (Context.Complain) {
1687
0
            Context.Diag2(D2->getLocation(),
1688
0
                          Context.getApplicableDiagnostic(
1689
0
                              diag::err_odr_tag_type_inconsistent))
1690
0
                << Context.ToCtx.getTypeDeclType(D2CXX);
1691
0
            Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1692
0
            Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1693
0
          }
1694
0
          return false;
1695
0
        }
1696
0
      }
1697
1698
0
      if (Friend2 != Friend2End) {
1699
0
        if (Context.Complain) {
1700
0
          Context.Diag2(D2->getLocation(),
1701
0
                        Context.getApplicableDiagnostic(
1702
0
                            diag::err_odr_tag_type_inconsistent))
1703
0
              << Context.ToCtx.getTypeDeclType(D2);
1704
0
          Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1705
0
          Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
1706
0
        }
1707
0
        return false;
1708
0
      }
1709
0
    } else if (D1CXX->getNumBases() > 0) {
1710
0
      if (Context.Complain) {
1711
0
        Context.Diag2(D2->getLocation(),
1712
0
                      Context.getApplicableDiagnostic(
1713
0
                          diag::err_odr_tag_type_inconsistent))
1714
0
            << Context.ToCtx.getTypeDeclType(D2);
1715
0
        const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
1716
0
        Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1717
0
            << Base1->getType() << Base1->getSourceRange();
1718
0
        Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
1719
0
      }
1720
0
      return false;
1721
0
    }
1722
0
  }
1723
1724
  // Check the fields for consistency.
1725
0
  QualType D2Type = Context.ToCtx.getTypeDeclType(D2);
1726
0
  RecordDecl::field_iterator Field2 = D2->field_begin(),
1727
0
                             Field2End = D2->field_end();
1728
0
  for (RecordDecl::field_iterator Field1 = D1->field_begin(),
1729
0
                                  Field1End = D1->field_end();
1730
0
       Field1 != Field1End; ++Field1, ++Field2) {
1731
0
    if (Field2 == Field2End) {
1732
0
      if (Context.Complain) {
1733
0
        Context.Diag2(D2->getLocation(),
1734
0
                      Context.getApplicableDiagnostic(
1735
0
                          diag::err_odr_tag_type_inconsistent))
1736
0
            << Context.ToCtx.getTypeDeclType(D2);
1737
0
        Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1738
0
            << Field1->getDeclName() << Field1->getType();
1739
0
        Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
1740
0
      }
1741
0
      return false;
1742
0
    }
1743
1744
0
    if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type))
1745
0
      return false;
1746
0
  }
1747
1748
0
  if (Field2 != Field2End) {
1749
0
    if (Context.Complain) {
1750
0
      Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1751
0
                                           diag::err_odr_tag_type_inconsistent))
1752
0
          << Context.ToCtx.getTypeDeclType(D2);
1753
0
      Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1754
0
          << Field2->getDeclName() << Field2->getType();
1755
0
      Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
1756
0
    }
1757
0
    return false;
1758
0
  }
1759
1760
0
  return true;
1761
0
}
1762
1763
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1764
                                     EnumConstantDecl *D1,
1765
0
                                     EnumConstantDecl *D2) {
1766
0
  const llvm::APSInt &FromVal = D1->getInitVal();
1767
0
  const llvm::APSInt &ToVal = D2->getInitVal();
1768
0
  if (FromVal.isSigned() != ToVal.isSigned())
1769
0
    return false;
1770
0
  if (FromVal.getBitWidth() != ToVal.getBitWidth())
1771
0
    return false;
1772
0
  if (FromVal != ToVal)
1773
0
    return false;
1774
1775
0
  if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
1776
0
    return false;
1777
1778
  // Init expressions are the most expensive check, so do them last.
1779
0
  return IsStructurallyEquivalent(Context, D1->getInitExpr(),
1780
0
                                  D2->getInitExpr());
1781
0
}
1782
1783
/// Determine structural equivalence of two enums.
1784
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1785
0
                                     EnumDecl *D1, EnumDecl *D2) {
1786
0
  if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1787
0
    return false;
1788
0
  }
1789
1790
  // Compare the definitions of these two enums. If either or both are
1791
  // incomplete (i.e. forward declared), we assume that they are equivalent.
1792
0
  D1 = D1->getDefinition();
1793
0
  D2 = D2->getDefinition();
1794
0
  if (!D1 || !D2)
1795
0
    return true;
1796
1797
0
  EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(),
1798
0
                                EC2End = D2->enumerator_end();
1799
0
  for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(),
1800
0
                                     EC1End = D1->enumerator_end();
1801
0
       EC1 != EC1End; ++EC1, ++EC2) {
1802
0
    if (EC2 == EC2End) {
1803
0
      if (Context.Complain) {
1804
0
        Context.Diag2(D2->getLocation(),
1805
0
                      Context.getApplicableDiagnostic(
1806
0
                          diag::err_odr_tag_type_inconsistent))
1807
0
            << Context.ToCtx.getTypeDeclType(D2);
1808
0
        Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1809
0
            << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1810
0
        Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
1811
0
      }
1812
0
      return false;
1813
0
    }
1814
1815
0
    llvm::APSInt Val1 = EC1->getInitVal();
1816
0
    llvm::APSInt Val2 = EC2->getInitVal();
1817
0
    if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1818
0
        !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
1819
0
      if (Context.Complain) {
1820
0
        Context.Diag2(D2->getLocation(),
1821
0
                      Context.getApplicableDiagnostic(
1822
0
                          diag::err_odr_tag_type_inconsistent))
1823
0
            << Context.ToCtx.getTypeDeclType(D2);
1824
0
        Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1825
0
            << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1826
0
        Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1827
0
            << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1828
0
      }
1829
0
      return false;
1830
0
    }
1831
0
  }
1832
1833
0
  if (EC2 != EC2End) {
1834
0
    if (Context.Complain) {
1835
0
      Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1836
0
                                           diag::err_odr_tag_type_inconsistent))
1837
0
          << Context.ToCtx.getTypeDeclType(D2);
1838
0
      Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1839
0
          << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1840
0
      Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
1841
0
    }
1842
0
    return false;
1843
0
  }
1844
1845
0
  return true;
1846
0
}
1847
1848
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1849
                                     TemplateParameterList *Params1,
1850
0
                                     TemplateParameterList *Params2) {
1851
0
  if (Params1->size() != Params2->size()) {
1852
0
    if (Context.Complain) {
1853
0
      Context.Diag2(Params2->getTemplateLoc(),
1854
0
                    Context.getApplicableDiagnostic(
1855
0
                        diag::err_odr_different_num_template_parameters))
1856
0
          << Params1->size() << Params2->size();
1857
0
      Context.Diag1(Params1->getTemplateLoc(),
1858
0
                    diag::note_odr_template_parameter_list);
1859
0
    }
1860
0
    return false;
1861
0
  }
1862
1863
0
  for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
1864
0
    if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
1865
0
      if (Context.Complain) {
1866
0
        Context.Diag2(Params2->getParam(I)->getLocation(),
1867
0
                      Context.getApplicableDiagnostic(
1868
0
                          diag::err_odr_different_template_parameter_kind));
1869
0
        Context.Diag1(Params1->getParam(I)->getLocation(),
1870
0
                      diag::note_odr_template_parameter_here);
1871
0
      }
1872
0
      return false;
1873
0
    }
1874
1875
0
    if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
1876
0
                                  Params2->getParam(I)))
1877
0
      return false;
1878
0
  }
1879
1880
0
  return true;
1881
0
}
1882
1883
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1884
                                     TemplateTypeParmDecl *D1,
1885
0
                                     TemplateTypeParmDecl *D2) {
1886
0
  if (D1->isParameterPack() != D2->isParameterPack()) {
1887
0
    if (Context.Complain) {
1888
0
      Context.Diag2(D2->getLocation(),
1889
0
                    Context.getApplicableDiagnostic(
1890
0
                        diag::err_odr_parameter_pack_non_pack))
1891
0
          << D2->isParameterPack();
1892
0
      Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1893
0
          << D1->isParameterPack();
1894
0
    }
1895
0
    return false;
1896
0
  }
1897
1898
0
  return true;
1899
0
}
1900
1901
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1902
                                     NonTypeTemplateParmDecl *D1,
1903
0
                                     NonTypeTemplateParmDecl *D2) {
1904
0
  if (D1->isParameterPack() != D2->isParameterPack()) {
1905
0
    if (Context.Complain) {
1906
0
      Context.Diag2(D2->getLocation(),
1907
0
                    Context.getApplicableDiagnostic(
1908
0
                        diag::err_odr_parameter_pack_non_pack))
1909
0
          << D2->isParameterPack();
1910
0
      Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1911
0
          << D1->isParameterPack();
1912
0
    }
1913
0
    return false;
1914
0
  }
1915
1916
  // Check types.
1917
0
  if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
1918
0
    if (Context.Complain) {
1919
0
      Context.Diag2(D2->getLocation(),
1920
0
                    Context.getApplicableDiagnostic(
1921
0
                        diag::err_odr_non_type_parameter_type_inconsistent))
1922
0
          << D2->getType() << D1->getType();
1923
0
      Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
1924
0
          << D1->getType();
1925
0
    }
1926
0
    return false;
1927
0
  }
1928
1929
0
  return true;
1930
0
}
1931
1932
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1933
                                     TemplateTemplateParmDecl *D1,
1934
0
                                     TemplateTemplateParmDecl *D2) {
1935
0
  if (D1->isParameterPack() != D2->isParameterPack()) {
1936
0
    if (Context.Complain) {
1937
0
      Context.Diag2(D2->getLocation(),
1938
0
                    Context.getApplicableDiagnostic(
1939
0
                        diag::err_odr_parameter_pack_non_pack))
1940
0
          << D2->isParameterPack();
1941
0
      Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1942
0
          << D1->isParameterPack();
1943
0
    }
1944
0
    return false;
1945
0
  }
1946
1947
  // Check template parameter lists.
1948
0
  return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
1949
0
                                  D2->getTemplateParameters());
1950
0
}
1951
1952
static bool IsTemplateDeclCommonStructurallyEquivalent(
1953
0
    StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2) {
1954
0
  if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
1955
0
    return false;
1956
0
  if (!D1->getIdentifier()) // Special name
1957
0
    if (D1->getNameAsString() != D2->getNameAsString())
1958
0
      return false;
1959
0
  return IsStructurallyEquivalent(Ctx, D1->getTemplateParameters(),
1960
0
                                  D2->getTemplateParameters());
1961
0
}
1962
1963
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1964
                                     ClassTemplateDecl *D1,
1965
0
                                     ClassTemplateDecl *D2) {
1966
  // Check template parameters.
1967
0
  if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
1968
0
    return false;
1969
1970
  // Check the templated declaration.
1971
0
  return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
1972
0
                                  D2->getTemplatedDecl());
1973
0
}
1974
1975
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1976
                                     FunctionTemplateDecl *D1,
1977
0
                                     FunctionTemplateDecl *D2) {
1978
  // Check template parameters.
1979
0
  if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
1980
0
    return false;
1981
1982
  // Check the templated declaration.
1983
0
  return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
1984
0
                                  D2->getTemplatedDecl()->getType());
1985
0
}
1986
1987
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1988
                                     TypeAliasTemplateDecl *D1,
1989
0
                                     TypeAliasTemplateDecl *D2) {
1990
  // Check template parameters.
1991
0
  if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
1992
0
    return false;
1993
1994
  // Check the templated declaration.
1995
0
  return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
1996
0
                                  D2->getTemplatedDecl());
1997
0
}
1998
1999
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2000
                                     ConceptDecl *D1,
2001
0
                                     ConceptDecl *D2) {
2002
  // Check template parameters.
2003
0
  if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2004
0
    return false;
2005
2006
  // Check the constraint expression.
2007
0
  return IsStructurallyEquivalent(Context, D1->getConstraintExpr(),
2008
0
                                  D2->getConstraintExpr());
2009
0
}
2010
2011
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2012
0
                                     FriendDecl *D1, FriendDecl *D2) {
2013
0
  if ((D1->getFriendType() && D2->getFriendDecl()) ||
2014
0
      (D1->getFriendDecl() && D2->getFriendType())) {
2015
0
      return false;
2016
0
  }
2017
0
  if (D1->getFriendType() && D2->getFriendType())
2018
0
    return IsStructurallyEquivalent(Context,
2019
0
                                    D1->getFriendType()->getType(),
2020
0
                                    D2->getFriendType()->getType());
2021
0
  if (D1->getFriendDecl() && D2->getFriendDecl())
2022
0
    return IsStructurallyEquivalent(Context, D1->getFriendDecl(),
2023
0
                                    D2->getFriendDecl());
2024
0
  return false;
2025
0
}
2026
2027
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2028
0
                                     TypedefNameDecl *D1, TypedefNameDecl *D2) {
2029
0
  if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
2030
0
    return false;
2031
2032
0
  return IsStructurallyEquivalent(Context, D1->getUnderlyingType(),
2033
0
                                  D2->getUnderlyingType());
2034
0
}
2035
2036
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2037
0
                                     FunctionDecl *D1, FunctionDecl *D2) {
2038
0
  if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
2039
0
    return false;
2040
2041
0
  if (D1->isOverloadedOperator()) {
2042
0
    if (!D2->isOverloadedOperator())
2043
0
      return false;
2044
0
    if (D1->getOverloadedOperator() != D2->getOverloadedOperator())
2045
0
      return false;
2046
0
  }
2047
2048
  // FIXME: Consider checking for function attributes as well.
2049
0
  if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
2050
0
    return false;
2051
2052
0
  return true;
2053
0
}
2054
2055
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2056
                                     ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2057
0
                                     QualType Owner2Type) {
2058
0
  if (D1->getAccessControl() != D2->getAccessControl())
2059
0
    return false;
2060
2061
0
  return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1),
2062
0
                                  cast<FieldDecl>(D2), Owner2Type);
2063
0
}
2064
2065
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2066
0
                                     ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2067
0
  QualType Owner2Type =
2068
0
      Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface());
2069
0
  return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2070
0
}
2071
2072
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2073
                                     ObjCMethodDecl *Method1,
2074
0
                                     ObjCMethodDecl *Method2) {
2075
0
  bool PropertiesEqual =
2076
0
      Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2077
0
      Method1->isVariadic() == Method2->isVariadic() &&
2078
0
      Method1->isDirectMethod() == Method2->isDirectMethod();
2079
0
  if (!PropertiesEqual)
2080
0
    return false;
2081
2082
  // Compare selector slot names.
2083
0
  Selector Selector1 = Method1->getSelector(),
2084
0
           Selector2 = Method2->getSelector();
2085
0
  unsigned NumArgs = Selector1.getNumArgs();
2086
0
  if (NumArgs != Selector2.getNumArgs())
2087
0
    return false;
2088
  // Compare all selector slots. For selectors with arguments it means all arg
2089
  // slots. And if there are no arguments, compare the first-and-only slot.
2090
0
  unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2091
0
  for (unsigned I = 0; I < SlotsToCheck; ++I) {
2092
0
    if (!IsStructurallyEquivalent(Selector1.getIdentifierInfoForSlot(I),
2093
0
                                  Selector2.getIdentifierInfoForSlot(I)))
2094
0
      return false;
2095
0
  }
2096
2097
  // Compare types.
2098
0
  if (!IsStructurallyEquivalent(Context, Method1->getReturnType(),
2099
0
                                Method2->getReturnType()))
2100
0
    return false;
2101
0
  assert(
2102
0
      Method1->param_size() == Method2->param_size() &&
2103
0
      "Same number of arguments should be already enforced in Selector checks");
2104
0
  for (ObjCMethodDecl::param_type_iterator
2105
0
           ParamT1 = Method1->param_type_begin(),
2106
0
           ParamT1End = Method1->param_type_end(),
2107
0
           ParamT2 = Method2->param_type_begin(),
2108
0
           ParamT2End = Method2->param_type_end();
2109
0
       (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2110
0
       ++ParamT1, ++ParamT2) {
2111
0
    if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2))
2112
0
      return false;
2113
0
  }
2114
2115
0
  return true;
2116
0
}
2117
2118
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2119
                                     ObjCCategoryDecl *D1,
2120
0
                                     ObjCCategoryDecl *D2) {
2121
0
  if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
2122
0
    return false;
2123
2124
0
  const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2125
0
                          *Intf2 = D2->getClassInterface();
2126
0
  if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2127
0
    return false;
2128
2129
0
  if (Intf1 &&
2130
0
      !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier()))
2131
0
    return false;
2132
2133
  // Compare protocols.
2134
0
  ObjCCategoryDecl::protocol_iterator Protocol2 = D2->protocol_begin(),
2135
0
                                      Protocol2End = D2->protocol_end();
2136
0
  for (ObjCCategoryDecl::protocol_iterator Protocol1 = D1->protocol_begin(),
2137
0
                                           Protocol1End = D1->protocol_end();
2138
0
       Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2139
0
    if (Protocol2 == Protocol2End)
2140
0
      return false;
2141
0
    if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(),
2142
0
                                  (*Protocol2)->getIdentifier()))
2143
0
      return false;
2144
0
  }
2145
0
  if (Protocol2 != Protocol2End)
2146
0
    return false;
2147
2148
  // Compare ivars.
2149
0
  QualType D2Type =
2150
0
      Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType();
2151
0
  ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(),
2152
0
                                  Ivar2End = D2->ivar_end();
2153
0
  for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(),
2154
0
                                       Ivar1End = D1->ivar_end();
2155
0
       Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2156
0
    if (Ivar2 == Ivar2End)
2157
0
      return false;
2158
0
    if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type))
2159
0
      return false;
2160
0
  }
2161
0
  if (Ivar2 != Ivar2End)
2162
0
    return false;
2163
2164
  // Compare methods.
2165
0
  ObjCCategoryDecl::method_iterator Method2 = D2->meth_begin(),
2166
0
                                    Method2End = D2->meth_end();
2167
0
  for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2168
0
                                         Method1End = D1->meth_end();
2169
0
       Method1 != Method1End; ++Method1, ++Method2) {
2170
0
    if (Method2 == Method2End)
2171
0
      return false;
2172
0
    if (!IsStructurallyEquivalent(Context, *Method1, *Method2))
2173
0
      return false;
2174
0
  }
2175
0
  if (Method2 != Method2End)
2176
0
    return false;
2177
2178
0
  return true;
2179
0
}
2180
2181
/// Determine structural equivalence of two declarations.
2182
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2183
0
                                     Decl *D1, Decl *D2) {
2184
  // FIXME: Check for known structural equivalences via a callback of some sort.
2185
2186
0
  D1 = D1->getCanonicalDecl();
2187
0
  D2 = D2->getCanonicalDecl();
2188
0
  std::pair<Decl *, Decl *> P{D1, D2};
2189
2190
  // Check whether we already know that these two declarations are not
2191
  // structurally equivalent.
2192
0
  if (Context.NonEquivalentDecls.count(P))
2193
0
    return false;
2194
2195
  // Check if a check for these declarations is already pending.
2196
  // If yes D1 and D2 will be checked later (from DeclsToCheck),
2197
  // or these are already checked (and equivalent).
2198
0
  bool Inserted = Context.VisitedDecls.insert(P).second;
2199
0
  if (!Inserted)
2200
0
    return true;
2201
2202
0
  Context.DeclsToCheck.push(P);
2203
2204
0
  return true;
2205
0
}
2206
2207
DiagnosticBuilder StructuralEquivalenceContext::Diag1(SourceLocation Loc,
2208
0
                                                      unsigned DiagID) {
2209
0
  assert(Complain && "Not allowed to complain");
2210
0
  if (LastDiagFromC2)
2211
0
    FromCtx.getDiagnostics().notePriorDiagnosticFrom(ToCtx.getDiagnostics());
2212
0
  LastDiagFromC2 = false;
2213
0
  return FromCtx.getDiagnostics().Report(Loc, DiagID);
2214
0
}
2215
2216
DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc,
2217
0
                                                      unsigned DiagID) {
2218
0
  assert(Complain && "Not allowed to complain");
2219
0
  if (!LastDiagFromC2)
2220
0
    ToCtx.getDiagnostics().notePriorDiagnosticFrom(FromCtx.getDiagnostics());
2221
0
  LastDiagFromC2 = true;
2222
0
  return ToCtx.getDiagnostics().Report(Loc, DiagID);
2223
0
}
2224
2225
std::optional<unsigned>
2226
0
StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
2227
0
  ASTContext &Context = Anon->getASTContext();
2228
0
  QualType AnonTy = Context.getRecordType(Anon);
2229
2230
0
  const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
2231
0
  if (!Owner)
2232
0
    return std::nullopt;
2233
2234
0
  unsigned Index = 0;
2235
0
  for (const auto *D : Owner->noload_decls()) {
2236
0
    const auto *F = dyn_cast<FieldDecl>(D);
2237
0
    if (!F)
2238
0
      continue;
2239
2240
0
    if (F->isAnonymousStructOrUnion()) {
2241
0
      if (Context.hasSameType(F->getType(), AnonTy))
2242
0
        break;
2243
0
      ++Index;
2244
0
      continue;
2245
0
    }
2246
2247
    // If the field looks like this:
2248
    // struct { ... } A;
2249
0
    QualType FieldType = F->getType();
2250
    // In case of nested structs.
2251
0
    while (const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2252
0
      FieldType = ElabType->getNamedType();
2253
2254
0
    if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2255
0
      const RecordDecl *RecDecl = RecType->getDecl();
2256
0
      if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2257
0
        if (Context.hasSameType(FieldType, AnonTy))
2258
0
          break;
2259
0
        ++Index;
2260
0
        continue;
2261
0
      }
2262
0
    }
2263
0
  }
2264
2265
0
  return Index;
2266
0
}
2267
2268
unsigned StructuralEquivalenceContext::getApplicableDiagnostic(
2269
0
    unsigned ErrorDiagnostic) {
2270
0
  if (ErrorOnTagTypeMismatch)
2271
0
    return ErrorDiagnostic;
2272
2273
0
  switch (ErrorDiagnostic) {
2274
0
  case diag::err_odr_variable_type_inconsistent:
2275
0
    return diag::warn_odr_variable_type_inconsistent;
2276
0
  case diag::err_odr_variable_multiple_def:
2277
0
    return diag::warn_odr_variable_multiple_def;
2278
0
  case diag::err_odr_function_type_inconsistent:
2279
0
    return diag::warn_odr_function_type_inconsistent;
2280
0
  case diag::err_odr_tag_type_inconsistent:
2281
0
    return diag::warn_odr_tag_type_inconsistent;
2282
0
  case diag::err_odr_field_type_inconsistent:
2283
0
    return diag::warn_odr_field_type_inconsistent;
2284
0
  case diag::err_odr_ivar_type_inconsistent:
2285
0
    return diag::warn_odr_ivar_type_inconsistent;
2286
0
  case diag::err_odr_objc_superclass_inconsistent:
2287
0
    return diag::warn_odr_objc_superclass_inconsistent;
2288
0
  case diag::err_odr_objc_method_result_type_inconsistent:
2289
0
    return diag::warn_odr_objc_method_result_type_inconsistent;
2290
0
  case diag::err_odr_objc_method_num_params_inconsistent:
2291
0
    return diag::warn_odr_objc_method_num_params_inconsistent;
2292
0
  case diag::err_odr_objc_method_param_type_inconsistent:
2293
0
    return diag::warn_odr_objc_method_param_type_inconsistent;
2294
0
  case diag::err_odr_objc_method_variadic_inconsistent:
2295
0
    return diag::warn_odr_objc_method_variadic_inconsistent;
2296
0
  case diag::err_odr_objc_property_type_inconsistent:
2297
0
    return diag::warn_odr_objc_property_type_inconsistent;
2298
0
  case diag::err_odr_objc_property_impl_kind_inconsistent:
2299
0
    return diag::warn_odr_objc_property_impl_kind_inconsistent;
2300
0
  case diag::err_odr_objc_synthesize_ivar_inconsistent:
2301
0
    return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2302
0
  case diag::err_odr_different_num_template_parameters:
2303
0
    return diag::warn_odr_different_num_template_parameters;
2304
0
  case diag::err_odr_different_template_parameter_kind:
2305
0
    return diag::warn_odr_different_template_parameter_kind;
2306
0
  case diag::err_odr_parameter_pack_non_pack:
2307
0
    return diag::warn_odr_parameter_pack_non_pack;
2308
0
  case diag::err_odr_non_type_parameter_type_inconsistent:
2309
0
    return diag::warn_odr_non_type_parameter_type_inconsistent;
2310
0
  }
2311
0
  llvm_unreachable("Diagnostic kind not handled in preceding switch");
2312
0
}
2313
2314
0
bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) {
2315
2316
  // Ensure that the implementation functions (all static functions in this TU)
2317
  // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2318
  // because that will wreak havoc the internal state (DeclsToCheck and
2319
  // VisitedDecls members) and can cause faulty behaviour.
2320
  // In other words: Do not start a graph search from a new node with the
2321
  // internal data of another search in progress.
2322
  // FIXME: Better encapsulation and separation of internal and public
2323
  // functionality.
2324
0
  assert(DeclsToCheck.empty());
2325
0
  assert(VisitedDecls.empty());
2326
2327
0
  if (!::IsStructurallyEquivalent(*this, D1, D2))
2328
0
    return false;
2329
2330
0
  return !Finish();
2331
0
}
2332
2333
0
bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
2334
0
  assert(DeclsToCheck.empty());
2335
0
  assert(VisitedDecls.empty());
2336
0
  if (!::IsStructurallyEquivalent(*this, T1, T2))
2337
0
    return false;
2338
2339
0
  return !Finish();
2340
0
}
2341
2342
0
bool StructuralEquivalenceContext::IsEquivalent(Stmt *S1, Stmt *S2) {
2343
0
  assert(DeclsToCheck.empty());
2344
0
  assert(VisitedDecls.empty());
2345
0
  if (!::IsStructurallyEquivalent(*this, S1, S2))
2346
0
    return false;
2347
2348
0
  return !Finish();
2349
0
}
2350
2351
0
bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2352
  // Check for equivalent described template.
2353
0
  TemplateDecl *Template1 = D1->getDescribedTemplate();
2354
0
  TemplateDecl *Template2 = D2->getDescribedTemplate();
2355
0
  if ((Template1 != nullptr) != (Template2 != nullptr))
2356
0
    return false;
2357
0
  if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2))
2358
0
    return false;
2359
2360
  // FIXME: Move check for identifier names into this function.
2361
2362
0
  return true;
2363
0
}
2364
2365
bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2366
0
    Decl *D1, Decl *D2) {
2367
2368
  // Kind mismatch.
2369
0
  if (D1->getKind() != D2->getKind())
2370
0
    return false;
2371
2372
  // Cast the Decls to their actual subclass so that the right overload of
2373
  // IsStructurallyEquivalent is called.
2374
0
  switch (D1->getKind()) {
2375
0
#define ABSTRACT_DECL(DECL)
2376
0
#define DECL(DERIVED, BASE)                                                    \
2377
0
  case Decl::Kind::DERIVED:                                                    \
2378
0
    return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2379
0
                                      static_cast<DERIVED##Decl *>(D2));
2380
0
#include "clang/AST/DeclNodes.inc"
2381
0
  }
2382
0
  return true;
2383
0
}
2384
2385
0
bool StructuralEquivalenceContext::Finish() {
2386
0
  while (!DeclsToCheck.empty()) {
2387
    // Check the next declaration.
2388
0
    std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2389
0
    DeclsToCheck.pop();
2390
2391
0
    Decl *D1 = P.first;
2392
0
    Decl *D2 = P.second;
2393
2394
0
    bool Equivalent =
2395
0
        CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2396
2397
0
    if (!Equivalent) {
2398
      // Note that these two declarations are not equivalent (and we already
2399
      // know about it).
2400
0
      NonEquivalentDecls.insert(P);
2401
2402
0
      return true;
2403
0
    }
2404
0
  }
2405
2406
0
  return false;
2407
0
}