Coverage Report

Created: 2020-09-22 08:39

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