Coverage Report

Created: 2021-01-23 06:44

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