Coverage Report

Created: 2022-01-18 06:27

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