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/Attr.h"
65#include "clang/AST/Decl.h"
66#include "clang/AST/DeclBase.h"
67#include "clang/AST/DeclCXX.h"
68#include "clang/AST/DeclFriend.h"
69#include "clang/AST/DeclObjC.h"
70#include "clang/AST/DeclOpenACC.h"
71#include "clang/AST/DeclOpenMP.h"
72#include "clang/AST/DeclTemplate.h"
73#include "clang/AST/ExprCXX.h"
74#include "clang/AST/ExprConcepts.h"
75#include "clang/AST/ExprObjC.h"
76#include "clang/AST/ExprOpenMP.h"
77#include "clang/AST/NestedNameSpecifier.h"
78#include "clang/AST/StmtObjC.h"
79#include "clang/AST/StmtOpenACC.h"
80#include "clang/AST/StmtOpenMP.h"
81#include "clang/AST/StmtSYCL.h"
82#include "clang/AST/TemplateBase.h"
83#include "clang/AST/TemplateName.h"
84#include "clang/AST/Type.h"
85#include "clang/Basic/ExceptionSpecificationType.h"
86#include "clang/Basic/IdentifierTable.h"
87#include "clang/Basic/LLVM.h"
88#include "clang/Basic/SourceLocation.h"
89#include "llvm/ADT/APInt.h"
90#include "llvm/ADT/APSInt.h"
91#include "llvm/ADT/STLExtras.h"
92#include "llvm/ADT/StringExtras.h"
93#include "llvm/Support/Compiler.h"
94#include "llvm/Support/ErrorHandling.h"
95#include <cassert>
96#include <optional>
97#include <utility>
98
99using namespace clang;
100
101static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
102 QualType T1, QualType T2);
103static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
104 Decl *D1, Decl *D2);
105static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
106 const Stmt *S1, const Stmt *S2);
107static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
108 const TemplateArgument &Arg1,
109 const TemplateArgument &Arg2);
110static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
111 const TemplateArgumentLoc &Arg1,
112 const TemplateArgumentLoc &Arg2);
113static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
114 NestedNameSpecifier NNS1,
115 NestedNameSpecifier NNS2);
116static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
117 const IdentifierInfo *Name2);
118
119static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
120 const DeclarationName Name1,
121 const DeclarationName Name2) {
122 if (Name1.getNameKind() != Name2.getNameKind())
123 return false;
124
125 switch (Name1.getNameKind()) {
126
127 case DeclarationName::Identifier:
128 return IsStructurallyEquivalent(Name1: Name1.getAsIdentifierInfo(),
129 Name2: Name2.getAsIdentifierInfo());
130
131 case DeclarationName::CXXConstructorName:
132 case DeclarationName::CXXDestructorName:
133 case DeclarationName::CXXConversionFunctionName:
134 return IsStructurallyEquivalent(Context, T1: Name1.getCXXNameType(),
135 T2: Name2.getCXXNameType());
136
137 case DeclarationName::CXXDeductionGuideName: {
138 if (!IsStructurallyEquivalent(
139 Context, Name1: Name1.getCXXDeductionGuideTemplate()->getDeclName(),
140 Name2: Name2.getCXXDeductionGuideTemplate()->getDeclName()))
141 return false;
142 return IsStructurallyEquivalent(Context,
143 D1: Name1.getCXXDeductionGuideTemplate(),
144 D2: Name2.getCXXDeductionGuideTemplate());
145 }
146
147 case DeclarationName::CXXOperatorName:
148 return Name1.getCXXOverloadedOperator() == Name2.getCXXOverloadedOperator();
149
150 case DeclarationName::CXXLiteralOperatorName:
151 return IsStructurallyEquivalent(Name1: Name1.getCXXLiteralIdentifier(),
152 Name2: Name2.getCXXLiteralIdentifier());
153
154 case DeclarationName::CXXUsingDirective:
155 return true; // FIXME When do we consider two using directives equal?
156
157 case DeclarationName::ObjCZeroArgSelector:
158 case DeclarationName::ObjCOneArgSelector:
159 case DeclarationName::ObjCMultiArgSelector:
160 return true; // FIXME
161 }
162
163 llvm_unreachable("Unhandled kind of DeclarationName");
164 return true;
165}
166
167namespace {
168/// Encapsulates Stmt comparison logic.
169class StmtComparer {
170 StructuralEquivalenceContext &Context;
171
172 // IsStmtEquivalent overloads. Each overload compares a specific statement
173 // and only has to compare the data that is specific to the specific statement
174 // class. Should only be called from TraverseStmt.
175
176 bool IsStmtEquivalent(const AddrLabelExpr *E1, const AddrLabelExpr *E2) {
177 return IsStructurallyEquivalent(Context, D1: E1->getLabel(), D2: E2->getLabel());
178 }
179
180 bool IsStmtEquivalent(const AtomicExpr *E1, const AtomicExpr *E2) {
181 return E1->getOp() == E2->getOp();
182 }
183
184 bool IsStmtEquivalent(const BinaryOperator *E1, const BinaryOperator *E2) {
185 return E1->getOpcode() == E2->getOpcode();
186 }
187
188 bool IsStmtEquivalent(const CallExpr *E1, const CallExpr *E2) {
189 // FIXME: IsStructurallyEquivalent requires non-const Decls.
190 Decl *Callee1 = const_cast<Decl *>(E1->getCalleeDecl());
191 Decl *Callee2 = const_cast<Decl *>(E2->getCalleeDecl());
192
193 // Compare whether both calls know their callee.
194 if (static_cast<bool>(Callee1) != static_cast<bool>(Callee2))
195 return false;
196
197 // Both calls have no callee, so nothing to do.
198 if (!static_cast<bool>(Callee1))
199 return true;
200
201 assert(Callee2);
202 return IsStructurallyEquivalent(Context, D1: Callee1, D2: Callee2);
203 }
204
205 bool IsStmtEquivalent(const CharacterLiteral *E1,
206 const CharacterLiteral *E2) {
207 return E1->getValue() == E2->getValue() && E1->getKind() == E2->getKind();
208 }
209
210 bool IsStmtEquivalent(const ChooseExpr *E1, const ChooseExpr *E2) {
211 return true; // Semantics only depend on children.
212 }
213
214 bool IsStmtEquivalent(const CompoundStmt *E1, const CompoundStmt *E2) {
215 // Number of children is actually checked by the generic children comparison
216 // code, but a CompoundStmt is one of the few statements where the number of
217 // children frequently differs and the number of statements is also always
218 // precomputed. Directly comparing the number of children here is thus
219 // just an optimization.
220 return E1->size() == E2->size();
221 }
222
223 bool IsStmtEquivalent(const DeclRefExpr *DRE1, const DeclRefExpr *DRE2) {
224 const ValueDecl *Decl1 = DRE1->getDecl();
225 const ValueDecl *Decl2 = DRE2->getDecl();
226 if (!Decl1 || !Decl2)
227 return false;
228 return IsStructurallyEquivalent(Context, D1: const_cast<ValueDecl *>(Decl1),
229 D2: const_cast<ValueDecl *>(Decl2));
230 }
231
232 bool IsStmtEquivalent(const DependentScopeDeclRefExpr *DE1,
233 const DependentScopeDeclRefExpr *DE2) {
234 if (!IsStructurallyEquivalent(Context, Name1: DE1->getDeclName(),
235 Name2: DE2->getDeclName()))
236 return false;
237 return IsStructurallyEquivalent(Context, NNS1: DE1->getQualifier(),
238 NNS2: DE2->getQualifier());
239 }
240
241 bool IsStmtEquivalent(const Expr *E1, const Expr *E2) {
242 return IsStructurallyEquivalent(Context, T1: E1->getType(), T2: E2->getType());
243 }
244
245 bool IsStmtEquivalent(const ExpressionTraitExpr *E1,
246 const ExpressionTraitExpr *E2) {
247 return E1->getTrait() == E2->getTrait() && E1->getValue() == E2->getValue();
248 }
249
250 bool IsStmtEquivalent(const FloatingLiteral *E1, const FloatingLiteral *E2) {
251 return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue();
252 }
253
254 bool IsStmtEquivalent(const GenericSelectionExpr *E1,
255 const GenericSelectionExpr *E2) {
256 for (auto Pair : zip_longest(t: E1->getAssocTypeSourceInfos(),
257 u: E2->getAssocTypeSourceInfos())) {
258 std::optional<TypeSourceInfo *> Child1 = std::get<0>(t&: Pair);
259 std::optional<TypeSourceInfo *> Child2 = std::get<1>(t&: Pair);
260 // Skip this case if there are a different number of associated types.
261 if (!Child1 || !Child2)
262 return false;
263
264 if (!IsStructurallyEquivalent(Context, T1: (*Child1)->getType(),
265 T2: (*Child2)->getType()))
266 return false;
267 }
268
269 return true;
270 }
271
272 bool IsStmtEquivalent(const ImplicitCastExpr *CastE1,
273 const ImplicitCastExpr *CastE2) {
274 return IsStructurallyEquivalent(Context, T1: CastE1->getType(),
275 T2: CastE2->getType());
276 }
277
278 bool IsStmtEquivalent(const IntegerLiteral *E1, const IntegerLiteral *E2) {
279 return E1->getValue() == E2->getValue();
280 }
281
282 bool IsStmtEquivalent(const MemberExpr *E1, const MemberExpr *E2) {
283 return IsStructurallyEquivalent(Context, D1: E1->getFoundDecl(),
284 D2: E2->getFoundDecl());
285 }
286
287 bool IsStmtEquivalent(const ObjCStringLiteral *E1,
288 const ObjCStringLiteral *E2) {
289 // Just wraps a StringLiteral child.
290 return true;
291 }
292
293 bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }
294
295 bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) {
296 LabelDecl *L1 = S1->getLabel();
297 LabelDecl *L2 = S2->getLabel();
298 if (!L1 || !L2)
299 return L1 == L2;
300
301 IdentifierInfo *Name1 = L1->getIdentifier();
302 IdentifierInfo *Name2 = L2->getIdentifier();
303 return ::IsStructurallyEquivalent(Name1, Name2);
304 }
305
306 bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) {
307 return E1->getIdentKind() == E2->getIdentKind();
308 }
309
310 bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) {
311 return E1->getTemplateDepth() == E2->getTemplateDepth();
312 }
313
314 bool IsStmtEquivalent(const StringLiteral *E1, const StringLiteral *E2) {
315 return E1->getBytes() == E2->getBytes();
316 }
317
318 bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
319 const SubstNonTypeTemplateParmExpr *E2) {
320 if (!IsStructurallyEquivalent(Context, D1: E1->getAssociatedDecl(),
321 D2: E2->getAssociatedDecl()))
322 return false;
323 if (E1->getIndex() != E2->getIndex())
324 return false;
325 if (E1->getPackIndex() != E2->getPackIndex())
326 return false;
327 return true;
328 }
329
330 bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
331 const SubstNonTypeTemplateParmPackExpr *E2) {
332 return IsStructurallyEquivalent(Context, Arg1: E1->getArgumentPack(),
333 Arg2: E2->getArgumentPack());
334 }
335
336 bool IsStmtEquivalent(const TypeTraitExpr *E1, const TypeTraitExpr *E2) {
337 if (E1->getTrait() != E2->getTrait())
338 return false;
339
340 for (auto Pair : zip_longest(t: E1->getArgs(), u: E2->getArgs())) {
341 std::optional<TypeSourceInfo *> Child1 = std::get<0>(t&: Pair);
342 std::optional<TypeSourceInfo *> Child2 = std::get<1>(t&: Pair);
343 // Different number of args.
344 if (!Child1 || !Child2)
345 return false;
346
347 if (!IsStructurallyEquivalent(Context, T1: (*Child1)->getType(),
348 T2: (*Child2)->getType()))
349 return false;
350 }
351 return true;
352 }
353
354 bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1,
355 const CXXDependentScopeMemberExpr *E2) {
356 if (!IsStructurallyEquivalent(Context, Name1: E1->getMember(), Name2: E2->getMember())) {
357 return false;
358 }
359 return IsStructurallyEquivalent(Context, T1: E1->getBaseType(),
360 T2: E2->getBaseType());
361 }
362
363 bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
364 const UnaryExprOrTypeTraitExpr *E2) {
365 if (E1->getKind() != E2->getKind())
366 return false;
367 return IsStructurallyEquivalent(Context, T1: E1->getTypeOfArgument(),
368 T2: E2->getTypeOfArgument());
369 }
370
371 bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) {
372 return E1->getOpcode() == E2->getOpcode();
373 }
374
375 bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) {
376 // Semantics only depend on children.
377 return true;
378 }
379
380 bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
381 if (!IsStructurallyEquivalent(Context, Name1: E1->getName(), Name2: E2->getName()))
382 return false;
383
384 if (static_cast<bool>(E1->getQualifier()) !=
385 static_cast<bool>(E2->getQualifier()))
386 return false;
387 if (E1->getQualifier() &&
388 !IsStructurallyEquivalent(Context, NNS1: E1->getQualifier(),
389 NNS2: E2->getQualifier()))
390 return false;
391
392 if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs())
393 return false;
394 const TemplateArgumentLoc *Args1 = E1->getTemplateArgs();
395 const TemplateArgumentLoc *Args2 = E2->getTemplateArgs();
396 for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
397 ++ArgI)
398 if (!IsStructurallyEquivalent(Context, Arg1: Args1[ArgI], Arg2: Args2[ArgI]))
399 return false;
400
401 return true;
402 }
403
404 bool IsStmtEquivalent(const CXXBoolLiteralExpr *E1, const CXXBoolLiteralExpr *E2) {
405 return E1->getValue() == E2->getValue();
406 }
407
408 /// End point of the traversal chain.
409 bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
410
411 // Create traversal methods that traverse the class hierarchy and return
412 // the accumulated result of the comparison. Each TraverseStmt overload
413 // calls the TraverseStmt overload of the parent class. For example,
414 // the TraverseStmt overload for 'BinaryOperator' calls the TraverseStmt
415 // overload of 'Expr' which then calls the overload for 'Stmt'.
416#define STMT(CLASS, PARENT) \
417 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
418 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
419 static_cast<const PARENT *>(S2))) \
420 return false; \
421 return IsStmtEquivalent(S1, S2); \
422 }
423#include "clang/AST/StmtNodes.inc"
424
425public:
426 StmtComparer(StructuralEquivalenceContext &C) : Context(C) {}
427
428 /// Determine whether two statements are equivalent. The statements have to
429 /// be of the same kind. The children of the statements and their properties
430 /// are not compared by this function.
431 bool IsEquivalent(const Stmt *S1, const Stmt *S2) {
432 if (S1->getStmtClass() != S2->getStmtClass())
433 return false;
434
435 // Each TraverseStmt walks the class hierarchy from the leaf class to
436 // the root class 'Stmt' (e.g. 'BinaryOperator' -> 'Expr' -> 'Stmt'). Cast
437 // the Stmt we have here to its specific subclass so that we call the
438 // overload that walks the whole class hierarchy from leaf to root (e.g.,
439 // cast to 'BinaryOperator' so that 'Expr' and 'Stmt' is traversed).
440 switch (S1->getStmtClass()) {
441 case Stmt::NoStmtClass:
442 llvm_unreachable("Can't traverse NoStmtClass");
443#define STMT(CLASS, PARENT) \
444 case Stmt::StmtClass::CLASS##Class: \
445 return TraverseStmt(static_cast<const CLASS *>(S1), \
446 static_cast<const CLASS *>(S2));
447#define ABSTRACT_STMT(S)
448#include "clang/AST/StmtNodes.inc"
449 }
450 llvm_unreachable("Invalid statement kind");
451 }
452};
453} // namespace
454
455namespace {
456/// Represents the result of comparing the attribute sets on two decls. If the
457/// sets are incompatible, A1/A2 point to the offending attributes.
458struct AttrComparisonResult {
459 bool Kind = false;
460 const Attr *A1 = nullptr, *A2 = nullptr;
461};
462} // namespace
463
464namespace {
465using AttrSet = llvm::SmallVector<const Attr *, 2>;
466}
467
468/// Determines whether D1 and D2 have compatible sets of attributes for the
469/// purposes of structural equivalence checking.
470static AttrComparisonResult
471areDeclAttrsEquivalent(const Decl *D1, const Decl *D2,
472 StructuralEquivalenceContext &Context) {
473 // If either declaration is implicit (i.e., compiler-generated, like
474 // __NSConstantString_tags), treat the declarations' attributes as equivalent.
475 if (D1->isImplicit() || D2->isImplicit())
476 return {.Kind: true};
477
478 AttrSet A1, A2;
479
480 // Ignore inherited attributes.
481 auto RemoveInherited = [](const Attr *A) { return !A->isInherited(); };
482
483 llvm::copy_if(Range: D1->attrs(), Out: std::back_inserter(x&: A1), P: RemoveInherited);
484 llvm::copy_if(Range: D2->attrs(), Out: std::back_inserter(x&: A2), P: RemoveInherited);
485
486 StructuralEquivalenceContext::AttrScopedAttrEquivalenceContext AttrCtx(
487 Context);
488 auto I1 = A1.begin(), E1 = A1.end(), I2 = A2.begin(), E2 = A2.end();
489 for (; I1 != E1 && I2 != E2; ++I1, ++I2) {
490 bool R = (*I1)->isEquivalent(Other: **I2, Context);
491 if (R)
492 R = !Context.checkDeclQueue();
493 if (!R)
494 return {.Kind: false, .A1: *I1, .A2: *I2};
495 }
496
497 if (I1 != E1)
498 return {.Kind: false, .A1: *I1};
499 if (I2 != E2)
500 return {.Kind: false, .A1: nullptr, .A2: *I2};
501
502 return {.Kind: true};
503}
504
505static bool
506CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
507 const Decl *D1, const Decl *D2,
508 const Decl *PrimaryDecl = nullptr) {
509 if (Context.Complain) {
510 AttrComparisonResult R = areDeclAttrsEquivalent(D1, D2, Context);
511 if (!R.Kind) {
512 const auto *DiagnoseDecl = cast<TypeDecl>(Val: PrimaryDecl ? PrimaryDecl : D2);
513 Context.Diag2(Loc: DiagnoseDecl->getLocation(),
514 DiagID: diag::warn_odr_tag_type_with_attributes)
515 << Context.ToCtx.getTypeDeclType(Decl: DiagnoseDecl)
516 << (PrimaryDecl != nullptr);
517 if (R.A1)
518 Context.Diag1(Loc: R.A1->getLoc(), DiagID: diag::note_odr_attr_here) << R.A1;
519 if (R.A2)
520 Context.Diag2(Loc: R.A2->getLoc(), DiagID: diag::note_odr_attr_here) << R.A2;
521 }
522 }
523
524 // The above diagnostic is a warning which defaults to an error. If treated
525 // as a warning, we'll go ahead and allow any attribute differences to be
526 // undefined behavior and the user gets what they get in terms of behavior.
527 return true;
528}
529
530static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
531 const UnaryOperator *E1,
532 const CXXOperatorCallExpr *E2) {
533 return UnaryOperator::getOverloadedOperator(Opc: E1->getOpcode()) ==
534 E2->getOperator() &&
535 IsStructurallyEquivalent(Context, S1: E1->getSubExpr(), S2: E2->getArg(Arg: 0));
536}
537
538static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
539 const CXXOperatorCallExpr *E1,
540 const UnaryOperator *E2) {
541 return E1->getOperator() ==
542 UnaryOperator::getOverloadedOperator(Opc: E2->getOpcode()) &&
543 IsStructurallyEquivalent(Context, S1: E1->getArg(Arg: 0), S2: E2->getSubExpr());
544}
545
546static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
547 const BinaryOperator *E1,
548 const CXXOperatorCallExpr *E2) {
549 return BinaryOperator::getOverloadedOperator(Opc: E1->getOpcode()) ==
550 E2->getOperator() &&
551 IsStructurallyEquivalent(Context, S1: E1->getLHS(), S2: E2->getArg(Arg: 0)) &&
552 IsStructurallyEquivalent(Context, S1: E1->getRHS(), S2: E2->getArg(Arg: 1));
553}
554
555static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
556 const CXXOperatorCallExpr *E1,
557 const BinaryOperator *E2) {
558 return E1->getOperator() ==
559 BinaryOperator::getOverloadedOperator(Opc: E2->getOpcode()) &&
560 IsStructurallyEquivalent(Context, S1: E1->getArg(Arg: 0), S2: E2->getLHS()) &&
561 IsStructurallyEquivalent(Context, S1: E1->getArg(Arg: 1), S2: E2->getRHS());
562}
563
564/// Determine structural equivalence of two statements.
565bool ASTStructuralEquivalence::isEquivalent(
566 StructuralEquivalenceContext &Context, const Stmt *S1, const Stmt *S2) {
567 if (!S1 || !S2)
568 return S1 == S2;
569
570 // Check for statements with similar syntax but different AST.
571 // A UnaryOperator node is more lightweight than a CXXOperatorCallExpr node.
572 // The more heavyweight node is only created if the definition-time name
573 // lookup had any results. The lookup results are stored CXXOperatorCallExpr
574 // only. The lookup results can be different in a "From" and "To" AST even if
575 // the compared structure is otherwise equivalent. For this reason we must
576 // treat a similar unary/binary operator node and CXXOperatorCall node as
577 // equivalent.
578 if (const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(Val: S2)) {
579 if (const auto *E1Unary = dyn_cast<UnaryOperator>(Val: S1))
580 return IsStructurallyEquivalent(Context, E1: E1Unary, E2: E2CXXOperatorCall);
581 if (const auto *E1Binary = dyn_cast<BinaryOperator>(Val: S1))
582 return IsStructurallyEquivalent(Context, E1: E1Binary, E2: E2CXXOperatorCall);
583 }
584 if (const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(Val: S1)) {
585 if (const auto *E2Unary = dyn_cast<UnaryOperator>(Val: S2))
586 return IsStructurallyEquivalent(Context, E1: E1CXXOperatorCall, E2: E2Unary);
587 if (const auto *E2Binary = dyn_cast<BinaryOperator>(Val: S2))
588 return IsStructurallyEquivalent(Context, E1: E1CXXOperatorCall, E2: E2Binary);
589 }
590
591 // Compare the statements itself.
592 StmtComparer Comparer(Context);
593 if (!Comparer.IsEquivalent(S1, S2))
594 return false;
595
596 // Iterate over the children of both statements and also compare them.
597 for (auto Pair : zip_longest(t: S1->children(), u: S2->children())) {
598 std::optional<const Stmt *> Child1 = std::get<0>(t&: Pair);
599 std::optional<const Stmt *> Child2 = std::get<1>(t&: Pair);
600 // One of the statements has a different amount of children than the other,
601 // so the statements can't be equivalent.
602 if (!Child1 || !Child2)
603 return false;
604 if (!IsStructurallyEquivalent(Context, S1: *Child1, S2: *Child2))
605 return false;
606 }
607 return true;
608}
609
610static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
611 const Stmt *S1, const Stmt *S2) {
612 return ASTStructuralEquivalence::isEquivalent(Context, S1, S2);
613}
614
615/// Determine whether two identifiers are equivalent.
616bool ASTStructuralEquivalence::isEquivalent(const IdentifierInfo *Name1,
617 const IdentifierInfo *Name2) {
618 if (!Name1 || !Name2)
619 return Name1 == Name2;
620
621 return Name1->getName() == Name2->getName();
622}
623
624static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
625 const IdentifierInfo *Name2) {
626 return ASTStructuralEquivalence::isEquivalent(Name1, Name2);
627}
628
629/// Determine whether two nested-name-specifiers are equivalent.
630static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
631 NestedNameSpecifier NNS1,
632 NestedNameSpecifier NNS2) {
633 auto Kind = NNS1.getKind();
634 if (Kind != NNS2.getKind())
635 return false;
636 switch (Kind) {
637 case NestedNameSpecifier::Kind::Null:
638 case NestedNameSpecifier::Kind::Global:
639 return true;
640 case NestedNameSpecifier::Kind::Namespace: {
641 auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix();
642 auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix();
643 if (!IsStructurallyEquivalent(Context,
644 D1: const_cast<NamespaceBaseDecl *>(Namespace1),
645 D2: const_cast<NamespaceBaseDecl *>(Namespace2)))
646 return false;
647 return IsStructurallyEquivalent(Context, NNS1: Prefix1, NNS2: Prefix2);
648 }
649 case NestedNameSpecifier::Kind::Type:
650 return IsStructurallyEquivalent(Context, T1: QualType(NNS1.getAsType(), 0),
651 T2: QualType(NNS2.getAsType(), 0));
652 case NestedNameSpecifier::Kind::MicrosoftSuper:
653 return IsStructurallyEquivalent(Context, D1: NNS1.getAsMicrosoftSuper(),
654 D2: NNS2.getAsMicrosoftSuper());
655 }
656 return false;
657}
658
659static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
660 const DependentTemplateStorage &S1,
661 const DependentTemplateStorage &S2) {
662 if (!IsStructurallyEquivalent(Context, NNS1: S1.getQualifier(), NNS2: S2.getQualifier()))
663 return false;
664
665 IdentifierOrOverloadedOperator IO1 = S1.getName(), IO2 = S2.getName();
666 const IdentifierInfo *II1 = IO1.getIdentifier(), *II2 = IO2.getIdentifier();
667 if (!II1 || !II2)
668 return IO1.getOperator() == IO2.getOperator();
669 return IsStructurallyEquivalent(Name1: II1, Name2: II2);
670}
671
672static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
673 const TemplateName &N1,
674 const TemplateName &N2) {
675 TemplateDecl *TemplateDeclN1 = N1.getAsTemplateDecl();
676 TemplateDecl *TemplateDeclN2 = N2.getAsTemplateDecl();
677 if (TemplateDeclN1 && TemplateDeclN2) {
678 if (!IsStructurallyEquivalent(Context, D1: TemplateDeclN1, D2: TemplateDeclN2))
679 return false;
680 // If the kind is different we compare only the template decl.
681 if (N1.getKind() != N2.getKind())
682 return true;
683 } else if (TemplateDeclN1 || TemplateDeclN2)
684 return false;
685 else if (N1.getKind() != N2.getKind())
686 return false;
687
688 // Check for special case incompatibilities.
689 switch (N1.getKind()) {
690
691 case TemplateName::OverloadedTemplate: {
692 OverloadedTemplateStorage *OS1 = N1.getAsOverloadedTemplate(),
693 *OS2 = N2.getAsOverloadedTemplate();
694 OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(),
695 E1 = OS1->end(), E2 = OS2->end();
696 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
697 if (!IsStructurallyEquivalent(Context, D1: *I1, D2: *I2))
698 return false;
699 return I1 == E1 && I2 == E2;
700 }
701
702 case TemplateName::AssumedTemplate: {
703 AssumedTemplateStorage *TN1 = N1.getAsAssumedTemplateName(),
704 *TN2 = N1.getAsAssumedTemplateName();
705 return TN1->getDeclName() == TN2->getDeclName();
706 }
707
708 case TemplateName::DependentTemplate:
709 return IsStructurallyEquivalent(Context, S1: *N1.getAsDependentTemplateName(),
710 S2: *N2.getAsDependentTemplateName());
711
712 case TemplateName::SubstTemplateTemplateParmPack: {
713 SubstTemplateTemplateParmPackStorage
714 *P1 = N1.getAsSubstTemplateTemplateParmPack(),
715 *P2 = N2.getAsSubstTemplateTemplateParmPack();
716 return IsStructurallyEquivalent(Context, Arg1: P1->getArgumentPack(),
717 Arg2: P2->getArgumentPack()) &&
718 IsStructurallyEquivalent(Context, D1: P1->getAssociatedDecl(),
719 D2: P2->getAssociatedDecl()) &&
720 P1->getIndex() == P2->getIndex();
721 }
722
723 case TemplateName::Template:
724 case TemplateName::QualifiedTemplate:
725 case TemplateName::SubstTemplateTemplateParm:
726 case TemplateName::UsingTemplate:
727 // It is sufficient to check value of getAsTemplateDecl.
728 break;
729
730 case TemplateName::DeducedTemplate:
731 // FIXME: We can't reach here.
732 llvm_unreachable("unimplemented");
733 }
734
735 return true;
736}
737
738static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
739 ArrayRef<TemplateArgument> Args1,
740 ArrayRef<TemplateArgument> Args2);
741
742/// Determine whether two template arguments are equivalent.
743static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
744 const TemplateArgument &Arg1,
745 const TemplateArgument &Arg2) {
746 if (Arg1.getKind() != Arg2.getKind())
747 return false;
748
749 switch (Arg1.getKind()) {
750 case TemplateArgument::Null:
751 return true;
752
753 case TemplateArgument::Type:
754 return IsStructurallyEquivalent(Context, T1: Arg1.getAsType(), T2: Arg2.getAsType());
755
756 case TemplateArgument::Integral:
757 if (!IsStructurallyEquivalent(Context, T1: Arg1.getIntegralType(),
758 T2: Arg2.getIntegralType()))
759 return false;
760
761 return llvm::APSInt::isSameValue(I1: Arg1.getAsIntegral(),
762 I2: Arg2.getAsIntegral());
763
764 case TemplateArgument::Declaration:
765 return IsStructurallyEquivalent(Context, D1: Arg1.getAsDecl(), D2: Arg2.getAsDecl());
766
767 case TemplateArgument::NullPtr:
768 return true; // FIXME: Is this correct?
769
770 case TemplateArgument::Template:
771 return IsStructurallyEquivalent(Context, N1: Arg1.getAsTemplate(),
772 N2: Arg2.getAsTemplate());
773
774 case TemplateArgument::TemplateExpansion:
775 return IsStructurallyEquivalent(Context,
776 N1: Arg1.getAsTemplateOrTemplatePattern(),
777 N2: Arg2.getAsTemplateOrTemplatePattern());
778
779 case TemplateArgument::Expression:
780 return IsStructurallyEquivalent(Context, S1: Arg1.getAsExpr(),
781 S2: Arg2.getAsExpr());
782
783 case TemplateArgument::StructuralValue:
784 return Arg1.structurallyEquals(Other: Arg2);
785
786 case TemplateArgument::Pack:
787 return IsStructurallyEquivalent(Context, Args1: Arg1.pack_elements(),
788 Args2: Arg2.pack_elements());
789 }
790
791 llvm_unreachable("Invalid template argument kind");
792}
793
794/// Determine structural equivalence of two template argument lists.
795static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
796 ArrayRef<TemplateArgument> Args1,
797 ArrayRef<TemplateArgument> Args2) {
798 if (Args1.size() != Args2.size())
799 return false;
800 for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
801 if (!IsStructurallyEquivalent(Context, Arg1: Args1[I], Arg2: Args2[I]))
802 return false;
803 }
804 return true;
805}
806
807/// Determine whether two template argument locations are equivalent.
808static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
809 const TemplateArgumentLoc &Arg1,
810 const TemplateArgumentLoc &Arg2) {
811 return IsStructurallyEquivalent(Context, Arg1: Arg1.getArgument(),
812 Arg2: Arg2.getArgument());
813}
814
815/// Determine structural equivalence for the common part of array
816/// types.
817static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context,
818 const ArrayType *Array1,
819 const ArrayType *Array2) {
820 if (!IsStructurallyEquivalent(Context, T1: Array1->getElementType(),
821 T2: Array2->getElementType()))
822 return false;
823 if (Array1->getSizeModifier() != Array2->getSizeModifier())
824 return false;
825 if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
826 return false;
827
828 return true;
829}
830
831/// Determine structural equivalence based on the ExtInfo of functions. This
832/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
833/// conventions bits but must not compare some other bits.
834static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
835 FunctionType::ExtInfo EI1,
836 FunctionType::ExtInfo EI2) {
837 // Compatible functions must have compatible calling conventions.
838 if (EI1.getCC() != EI2.getCC())
839 return false;
840
841 // Regparm is part of the calling convention.
842 if (EI1.getHasRegParm() != EI2.getHasRegParm())
843 return false;
844 if (EI1.getRegParm() != EI2.getRegParm())
845 return false;
846
847 if (EI1.getProducesResult() != EI2.getProducesResult())
848 return false;
849 if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs())
850 return false;
851 if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
852 return false;
853
854 return true;
855}
856
857/// Check the equivalence of exception specifications.
858static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext &Context,
859 const FunctionProtoType *Proto1,
860 const FunctionProtoType *Proto2) {
861
862 auto Spec1 = Proto1->getExceptionSpecType();
863 auto Spec2 = Proto2->getExceptionSpecType();
864
865 if (isUnresolvedExceptionSpec(ESpecType: Spec1) || isUnresolvedExceptionSpec(ESpecType: Spec2))
866 return true;
867
868 if (Spec1 != Spec2)
869 return false;
870 if (Spec1 == EST_Dynamic) {
871 if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
872 return false;
873 for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
874 if (!IsStructurallyEquivalent(Context, T1: Proto1->getExceptionType(i: I),
875 T2: Proto2->getExceptionType(i: I)))
876 return false;
877 }
878 } else if (isComputedNoexcept(ESpecType: Spec1)) {
879 if (!IsStructurallyEquivalent(Context, S1: Proto1->getNoexceptExpr(),
880 S2: Proto2->getNoexceptExpr()))
881 return false;
882 }
883
884 return true;
885}
886
887/// Determine structural equivalence of two types.
888bool ASTStructuralEquivalence::isEquivalent(
889 StructuralEquivalenceContext &Context, QualType T1, QualType T2) {
890 if (T1.isNull() || T2.isNull())
891 return T1.isNull() && T2.isNull();
892
893 QualType OrigT1 = T1;
894 QualType OrigT2 = T2;
895
896 if (!Context.StrictTypeSpelling) {
897 // We aren't being strict about token-to-token equivalence of types,
898 // so map down to the canonical type.
899 T1 = Context.FromCtx.getCanonicalType(T: T1);
900 T2 = Context.ToCtx.getCanonicalType(T: T2);
901 }
902
903 if (T1.getQualifiers() != T2.getQualifiers())
904 return false;
905
906 Type::TypeClass TC = T1->getTypeClass();
907
908 if (T1->getTypeClass() != T2->getTypeClass()) {
909 // Compare function types with prototypes vs. without prototypes as if
910 // both did not have prototypes.
911 if (T1->getTypeClass() == Type::FunctionProto &&
912 T2->getTypeClass() == Type::FunctionNoProto)
913 TC = Type::FunctionNoProto;
914 else if (T1->getTypeClass() == Type::FunctionNoProto &&
915 T2->getTypeClass() == Type::FunctionProto)
916 TC = Type::FunctionNoProto;
917 else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
918 (T1->getTypeClass() == Type::Enum ||
919 T2->getTypeClass() == Type::Enum)) {
920 // In C23, if not being strict about token equivalence, we need to handle
921 // the case where one type is an enumeration and the other type is an
922 // integral type.
923 //
924 // C23 6.7.3.3p16: The enumerated type is compatible with the underlying
925 // type of the enumeration.
926 //
927 // Treat the enumeration as its underlying type and use the builtin type
928 // class comparison.
929 if (T1->getTypeClass() == Type::Enum) {
930 T1 = cast<EnumType>(Val&: T1)->getDecl()->getIntegerType();
931 assert(T2->isBuiltinType() && !T1.isNull()); // Sanity check
932 } else if (T2->getTypeClass() == Type::Enum) {
933 T2 = cast<EnumType>(Val&: T2)->getDecl()->getIntegerType();
934 assert(T1->isBuiltinType() && !T2.isNull()); // Sanity check
935 }
936 TC = Type::Builtin;
937 } else
938 return false;
939 }
940
941 switch (TC) {
942 case Type::Builtin:
943 // FIXME: Deal with Char_S/Char_U.
944 if (cast<BuiltinType>(Val&: T1)->getKind() != cast<BuiltinType>(Val&: T2)->getKind())
945 return false;
946 break;
947
948 case Type::Complex:
949 if (!IsStructurallyEquivalent(Context,
950 T1: cast<ComplexType>(Val&: T1)->getElementType(),
951 T2: cast<ComplexType>(Val&: T2)->getElementType()))
952 return false;
953 break;
954
955 case Type::Adjusted:
956 case Type::Decayed:
957 case Type::ArrayParameter:
958 if (!IsStructurallyEquivalent(Context,
959 T1: cast<AdjustedType>(Val&: T1)->getOriginalType(),
960 T2: cast<AdjustedType>(Val&: T2)->getOriginalType()))
961 return false;
962 break;
963
964 case Type::Pointer:
965 if (!IsStructurallyEquivalent(Context,
966 T1: cast<PointerType>(Val&: T1)->getPointeeType(),
967 T2: cast<PointerType>(Val&: T2)->getPointeeType()))
968 return false;
969 break;
970
971 case Type::BlockPointer:
972 if (!IsStructurallyEquivalent(Context,
973 T1: cast<BlockPointerType>(Val&: T1)->getPointeeType(),
974 T2: cast<BlockPointerType>(Val&: T2)->getPointeeType()))
975 return false;
976 break;
977
978 case Type::LValueReference:
979 case Type::RValueReference: {
980 const auto *Ref1 = cast<ReferenceType>(Val&: T1);
981 const auto *Ref2 = cast<ReferenceType>(Val&: T2);
982 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
983 return false;
984 if (Ref1->isInnerRef() != Ref2->isInnerRef())
985 return false;
986 if (!IsStructurallyEquivalent(Context, T1: Ref1->getPointeeTypeAsWritten(),
987 T2: Ref2->getPointeeTypeAsWritten()))
988 return false;
989 break;
990 }
991
992 case Type::MemberPointer: {
993 const auto *MemPtr1 = cast<MemberPointerType>(Val&: T1);
994 const auto *MemPtr2 = cast<MemberPointerType>(Val&: T2);
995 if (!IsStructurallyEquivalent(Context, T1: MemPtr1->getPointeeType(),
996 T2: MemPtr2->getPointeeType()))
997 return false;
998 if (!IsStructurallyEquivalent(Context, NNS1: MemPtr1->getQualifier(),
999 NNS2: MemPtr2->getQualifier()))
1000 return false;
1001 CXXRecordDecl *D1 = MemPtr1->getMostRecentCXXRecordDecl(),
1002 *D2 = MemPtr2->getMostRecentCXXRecordDecl();
1003 if (D1 == D2)
1004 break;
1005 if (!D1 || !D2 || !IsStructurallyEquivalent(Context, D1, D2))
1006 return false;
1007 break;
1008 }
1009
1010 case Type::ConstantArray: {
1011 const auto *Array1 = cast<ConstantArrayType>(Val&: T1);
1012 const auto *Array2 = cast<ConstantArrayType>(Val&: T2);
1013 if (!llvm::APInt::isSameValue(I1: Array1->getSize(), I2: Array2->getSize()))
1014 return false;
1015
1016 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1017 return false;
1018 break;
1019 }
1020
1021 case Type::IncompleteArray:
1022 if (!IsArrayStructurallyEquivalent(Context, Array1: cast<ArrayType>(Val&: T1),
1023 Array2: cast<ArrayType>(Val&: T2)))
1024 return false;
1025 break;
1026
1027 case Type::VariableArray: {
1028 const auto *Array1 = cast<VariableArrayType>(Val&: T1);
1029 const auto *Array2 = cast<VariableArrayType>(Val&: T2);
1030 if (!IsStructurallyEquivalent(Context, S1: Array1->getSizeExpr(),
1031 S2: Array2->getSizeExpr()))
1032 return false;
1033
1034 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1035 return false;
1036
1037 break;
1038 }
1039
1040 case Type::DependentSizedArray: {
1041 const auto *Array1 = cast<DependentSizedArrayType>(Val&: T1);
1042 const auto *Array2 = cast<DependentSizedArrayType>(Val&: T2);
1043 if (!IsStructurallyEquivalent(Context, S1: Array1->getSizeExpr(),
1044 S2: Array2->getSizeExpr()))
1045 return false;
1046
1047 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1048 return false;
1049
1050 break;
1051 }
1052
1053 case Type::DependentAddressSpace: {
1054 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(Val&: T1);
1055 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(Val&: T2);
1056 if (!IsStructurallyEquivalent(Context, S1: DepAddressSpace1->getAddrSpaceExpr(),
1057 S2: DepAddressSpace2->getAddrSpaceExpr()))
1058 return false;
1059 if (!IsStructurallyEquivalent(Context, T1: DepAddressSpace1->getPointeeType(),
1060 T2: DepAddressSpace2->getPointeeType()))
1061 return false;
1062
1063 break;
1064 }
1065
1066 case Type::DependentSizedExtVector: {
1067 const auto *Vec1 = cast<DependentSizedExtVectorType>(Val&: T1);
1068 const auto *Vec2 = cast<DependentSizedExtVectorType>(Val&: T2);
1069 if (!IsStructurallyEquivalent(Context, S1: Vec1->getSizeExpr(),
1070 S2: Vec2->getSizeExpr()))
1071 return false;
1072 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1073 T2: Vec2->getElementType()))
1074 return false;
1075 break;
1076 }
1077
1078 case Type::DependentVector: {
1079 const auto *Vec1 = cast<DependentVectorType>(Val&: T1);
1080 const auto *Vec2 = cast<DependentVectorType>(Val&: T2);
1081 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1082 return false;
1083 if (!IsStructurallyEquivalent(Context, S1: Vec1->getSizeExpr(),
1084 S2: Vec2->getSizeExpr()))
1085 return false;
1086 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1087 T2: Vec2->getElementType()))
1088 return false;
1089 break;
1090 }
1091
1092 case Type::Vector:
1093 case Type::ExtVector: {
1094 const auto *Vec1 = cast<VectorType>(Val&: T1);
1095 const auto *Vec2 = cast<VectorType>(Val&: T2);
1096 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1097 T2: Vec2->getElementType()))
1098 return false;
1099 if (Vec1->getNumElements() != Vec2->getNumElements())
1100 return false;
1101 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1102 return false;
1103 break;
1104 }
1105
1106 case Type::DependentSizedMatrix: {
1107 const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(Val&: T1);
1108 const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(Val&: T2);
1109 // The element types, row and column expressions must be structurally
1110 // equivalent.
1111 if (!IsStructurallyEquivalent(Context, S1: Mat1->getRowExpr(),
1112 S2: Mat2->getRowExpr()) ||
1113 !IsStructurallyEquivalent(Context, S1: Mat1->getColumnExpr(),
1114 S2: Mat2->getColumnExpr()) ||
1115 !IsStructurallyEquivalent(Context, T1: Mat1->getElementType(),
1116 T2: Mat2->getElementType()))
1117 return false;
1118 break;
1119 }
1120
1121 case Type::ConstantMatrix: {
1122 const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(Val&: T1);
1123 const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(Val&: T2);
1124 // The element types must be structurally equivalent and the number of rows
1125 // and columns must match.
1126 if (!IsStructurallyEquivalent(Context, T1: Mat1->getElementType(),
1127 T2: Mat2->getElementType()) ||
1128 Mat1->getNumRows() != Mat2->getNumRows() ||
1129 Mat1->getNumColumns() != Mat2->getNumColumns())
1130 return false;
1131 break;
1132 }
1133
1134 case Type::FunctionProto: {
1135 const auto *Proto1 = cast<FunctionProtoType>(Val&: T1);
1136 const auto *Proto2 = cast<FunctionProtoType>(Val&: T2);
1137
1138 if (Proto1->getNumParams() != Proto2->getNumParams())
1139 return false;
1140 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1141 if (!IsStructurallyEquivalent(Context, T1: Proto1->getParamType(i: I),
1142 T2: Proto2->getParamType(i: I)))
1143 return false;
1144 }
1145 if (Proto1->isVariadic() != Proto2->isVariadic())
1146 return false;
1147
1148 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1149 return false;
1150
1151 // Check exceptions, this information is lost in canonical type.
1152 const auto *OrigProto1 =
1153 cast<FunctionProtoType>(Val: OrigT1.getDesugaredType(Context: Context.FromCtx));
1154 const auto *OrigProto2 =
1155 cast<FunctionProtoType>(Val: OrigT2.getDesugaredType(Context: Context.ToCtx));
1156 if (!IsEquivalentExceptionSpec(Context, Proto1: OrigProto1, Proto2: OrigProto2))
1157 return false;
1158
1159 // Fall through to check the bits common with FunctionNoProtoType.
1160 [[fallthrough]];
1161 }
1162
1163 case Type::FunctionNoProto: {
1164 const auto *Function1 = cast<FunctionType>(Val&: T1);
1165 const auto *Function2 = cast<FunctionType>(Val&: T2);
1166 if (!IsStructurallyEquivalent(Context, T1: Function1->getReturnType(),
1167 T2: Function2->getReturnType()))
1168 return false;
1169 if (!IsStructurallyEquivalent(Context, EI1: Function1->getExtInfo(),
1170 EI2: Function2->getExtInfo()))
1171 return false;
1172 break;
1173 }
1174
1175 case Type::UnresolvedUsing:
1176 if (!IsStructurallyEquivalent(Context,
1177 D1: cast<UnresolvedUsingType>(Val&: T1)->getDecl(),
1178 D2: cast<UnresolvedUsingType>(Val&: T2)->getDecl()))
1179 return false;
1180 break;
1181
1182 case Type::Attributed:
1183 if (!IsStructurallyEquivalent(Context,
1184 T1: cast<AttributedType>(Val&: T1)->getModifiedType(),
1185 T2: cast<AttributedType>(Val&: T2)->getModifiedType()))
1186 return false;
1187 if (!IsStructurallyEquivalent(
1188 Context, T1: cast<AttributedType>(Val&: T1)->getEquivalentType(),
1189 T2: cast<AttributedType>(Val&: T2)->getEquivalentType()))
1190 return false;
1191 break;
1192
1193 case Type::CountAttributed:
1194 if (!IsStructurallyEquivalent(Context,
1195 T1: cast<CountAttributedType>(Val&: T1)->desugar(),
1196 T2: cast<CountAttributedType>(Val&: T2)->desugar()))
1197 return false;
1198 break;
1199
1200 case Type::BTFTagAttributed:
1201 if (!IsStructurallyEquivalent(
1202 Context, T1: cast<BTFTagAttributedType>(Val&: T1)->getWrappedType(),
1203 T2: cast<BTFTagAttributedType>(Val&: T2)->getWrappedType()))
1204 return false;
1205 break;
1206
1207 case Type::OverflowBehavior:
1208 if (!IsStructurallyEquivalent(
1209 Context, T1: cast<OverflowBehaviorType>(Val&: T1)->getUnderlyingType(),
1210 T2: cast<OverflowBehaviorType>(Val&: T2)->getUnderlyingType()))
1211 return false;
1212 break;
1213
1214 case Type::HLSLAttributedResource:
1215 if (!IsStructurallyEquivalent(
1216 Context, T1: cast<HLSLAttributedResourceType>(Val&: T1)->getWrappedType(),
1217 T2: cast<HLSLAttributedResourceType>(Val&: T2)->getWrappedType()))
1218 return false;
1219 if (!IsStructurallyEquivalent(
1220 Context, T1: cast<HLSLAttributedResourceType>(Val&: T1)->getContainedType(),
1221 T2: cast<HLSLAttributedResourceType>(Val&: T2)->getContainedType()))
1222 return false;
1223 if (cast<HLSLAttributedResourceType>(Val&: T1)->getAttrs() !=
1224 cast<HLSLAttributedResourceType>(Val&: T2)->getAttrs())
1225 return false;
1226 break;
1227
1228 case Type::HLSLInlineSpirv:
1229 if (cast<HLSLInlineSpirvType>(Val&: T1)->getOpcode() !=
1230 cast<HLSLInlineSpirvType>(Val&: T2)->getOpcode() ||
1231 cast<HLSLInlineSpirvType>(Val&: T1)->getSize() !=
1232 cast<HLSLInlineSpirvType>(Val&: T2)->getSize() ||
1233 cast<HLSLInlineSpirvType>(Val&: T1)->getAlignment() !=
1234 cast<HLSLInlineSpirvType>(Val&: T2)->getAlignment())
1235 return false;
1236 for (size_t I = 0; I < cast<HLSLInlineSpirvType>(Val&: T1)->getOperands().size();
1237 I++) {
1238 if (cast<HLSLInlineSpirvType>(Val&: T1)->getOperands()[I] !=
1239 cast<HLSLInlineSpirvType>(Val&: T2)->getOperands()[I]) {
1240 return false;
1241 }
1242 }
1243 break;
1244
1245 case Type::Paren:
1246 if (!IsStructurallyEquivalent(Context, T1: cast<ParenType>(Val&: T1)->getInnerType(),
1247 T2: cast<ParenType>(Val&: T2)->getInnerType()))
1248 return false;
1249 break;
1250
1251 case Type::MacroQualified:
1252 if (!IsStructurallyEquivalent(
1253 Context, T1: cast<MacroQualifiedType>(Val&: T1)->getUnderlyingType(),
1254 T2: cast<MacroQualifiedType>(Val&: T2)->getUnderlyingType()))
1255 return false;
1256 break;
1257
1258 case Type::Using: {
1259 auto *U1 = cast<UsingType>(Val&: T1), *U2 = cast<UsingType>(Val&: T2);
1260 if (U1->getKeyword() != U2->getKeyword())
1261 return false;
1262 if (!IsStructurallyEquivalent(Context, NNS1: U1->getQualifier(),
1263 NNS2: U2->getQualifier()))
1264 return false;
1265 if (!IsStructurallyEquivalent(Context, D1: U1->getDecl(), D2: U2->getDecl()))
1266 return false;
1267 if (!IsStructurallyEquivalent(Context, T1: U1->desugar(), T2: U2->desugar()))
1268 return false;
1269 break;
1270 }
1271 case Type::Typedef: {
1272 auto *U1 = cast<TypedefType>(Val&: T1), *U2 = cast<TypedefType>(Val&: T2);
1273 if (U1->getKeyword() != U2->getKeyword())
1274 return false;
1275 if (!IsStructurallyEquivalent(Context, NNS1: U1->getQualifier(),
1276 NNS2: U2->getQualifier()))
1277 return false;
1278 if (!IsStructurallyEquivalent(Context, D1: U1->getDecl(), D2: U2->getDecl()))
1279 return false;
1280 if (U1->typeMatchesDecl() != U2->typeMatchesDecl())
1281 return false;
1282 if (!U1->typeMatchesDecl() &&
1283 !IsStructurallyEquivalent(Context, T1: U1->desugar(), T2: U2->desugar()))
1284 return false;
1285 break;
1286 }
1287
1288 case Type::TypeOfExpr:
1289 if (!IsStructurallyEquivalent(
1290 Context, S1: cast<TypeOfExprType>(Val&: T1)->getUnderlyingExpr(),
1291 S2: cast<TypeOfExprType>(Val&: T2)->getUnderlyingExpr()))
1292 return false;
1293 break;
1294
1295 case Type::TypeOf:
1296 if (!IsStructurallyEquivalent(Context,
1297 T1: cast<TypeOfType>(Val&: T1)->getUnmodifiedType(),
1298 T2: cast<TypeOfType>(Val&: T2)->getUnmodifiedType()))
1299 return false;
1300 break;
1301
1302 case Type::UnaryTransform:
1303 if (!IsStructurallyEquivalent(
1304 Context, T1: cast<UnaryTransformType>(Val&: T1)->getUnderlyingType(),
1305 T2: cast<UnaryTransformType>(Val&: T2)->getUnderlyingType()))
1306 return false;
1307 break;
1308
1309 case Type::Decltype:
1310 if (!IsStructurallyEquivalent(Context,
1311 S1: cast<DecltypeType>(Val&: T1)->getUnderlyingExpr(),
1312 S2: cast<DecltypeType>(Val&: T2)->getUnderlyingExpr()))
1313 return false;
1314 break;
1315
1316 case Type::Auto: {
1317 auto *Auto1 = cast<AutoType>(Val&: T1);
1318 auto *Auto2 = cast<AutoType>(Val&: T2);
1319 if (!IsStructurallyEquivalent(Context, T1: Auto1->getDeducedType(),
1320 T2: Auto2->getDeducedType()))
1321 return false;
1322 if (Auto1->isConstrained() != Auto2->isConstrained())
1323 return false;
1324 if (Auto1->isConstrained()) {
1325 if (Auto1->getTypeConstraintConcept() !=
1326 Auto2->getTypeConstraintConcept())
1327 return false;
1328 if (!IsStructurallyEquivalent(Context,
1329 Args1: Auto1->getTypeConstraintArguments(),
1330 Args2: Auto2->getTypeConstraintArguments()))
1331 return false;
1332 }
1333 break;
1334 }
1335
1336 case Type::DeducedTemplateSpecialization: {
1337 const auto *DT1 = cast<DeducedTemplateSpecializationType>(Val&: T1);
1338 const auto *DT2 = cast<DeducedTemplateSpecializationType>(Val&: T2);
1339 if (!IsStructurallyEquivalent(Context, N1: DT1->getTemplateName(),
1340 N2: DT2->getTemplateName()))
1341 return false;
1342 if (!IsStructurallyEquivalent(Context, T1: DT1->getDeducedType(),
1343 T2: DT2->getDeducedType()))
1344 return false;
1345 break;
1346 }
1347
1348 case Type::Record:
1349 case Type::Enum:
1350 case Type::InjectedClassName: {
1351 const auto *TT1 = cast<TagType>(Val&: T1), *TT2 = cast<TagType>(Val&: T2);
1352 if (TT1->getKeyword() != TT2->getKeyword())
1353 return false;
1354 if (TT1->isTagOwned() != TT2->isTagOwned())
1355 return false;
1356 if (!IsStructurallyEquivalent(Context, NNS1: TT1->getQualifier(),
1357 NNS2: TT2->getQualifier()))
1358 return false;
1359 if (!IsStructurallyEquivalent(Context, D1: TT1->getDecl(), D2: TT2->getDecl()))
1360 return false;
1361 break;
1362 }
1363
1364 case Type::TemplateTypeParm: {
1365 const auto *Parm1 = cast<TemplateTypeParmType>(Val&: T1);
1366 const auto *Parm2 = cast<TemplateTypeParmType>(Val&: T2);
1367 if (!Context.IgnoreTemplateParmDepth &&
1368 Parm1->getDepth() != Parm2->getDepth())
1369 return false;
1370 if (Parm1->getIndex() != Parm2->getIndex())
1371 return false;
1372 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1373 return false;
1374
1375 // Names of template type parameters are never significant.
1376 break;
1377 }
1378
1379 case Type::SubstTemplateTypeParm: {
1380 const auto *Subst1 = cast<SubstTemplateTypeParmType>(Val&: T1);
1381 const auto *Subst2 = cast<SubstTemplateTypeParmType>(Val&: T2);
1382 if (!IsStructurallyEquivalent(Context, T1: Subst1->getReplacementType(),
1383 T2: Subst2->getReplacementType()))
1384 return false;
1385 if (!IsStructurallyEquivalent(Context, D1: Subst1->getAssociatedDecl(),
1386 D2: Subst2->getAssociatedDecl()))
1387 return false;
1388 if (Subst1->getIndex() != Subst2->getIndex())
1389 return false;
1390 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1391 return false;
1392 break;
1393 }
1394
1395 case Type::SubstBuiltinTemplatePack: {
1396 const auto *Subst1 = cast<SubstBuiltinTemplatePackType>(Val&: T1);
1397 const auto *Subst2 = cast<SubstBuiltinTemplatePackType>(Val&: T2);
1398 if (!IsStructurallyEquivalent(Context, Arg1: Subst1->getArgumentPack(),
1399 Arg2: Subst2->getArgumentPack()))
1400 return false;
1401 break;
1402 }
1403 case Type::SubstTemplateTypeParmPack: {
1404 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(Val&: T1);
1405 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(Val&: T2);
1406 if (!IsStructurallyEquivalent(Context, D1: Subst1->getAssociatedDecl(),
1407 D2: Subst2->getAssociatedDecl()))
1408 return false;
1409 if (Subst1->getIndex() != Subst2->getIndex())
1410 return false;
1411 if (!IsStructurallyEquivalent(Context, Arg1: Subst1->getArgumentPack(),
1412 Arg2: Subst2->getArgumentPack()))
1413 return false;
1414 break;
1415 }
1416
1417 case Type::TemplateSpecialization: {
1418 const auto *Spec1 = cast<TemplateSpecializationType>(Val&: T1);
1419 const auto *Spec2 = cast<TemplateSpecializationType>(Val&: T2);
1420 if (!IsStructurallyEquivalent(Context, N1: Spec1->getTemplateName(),
1421 N2: Spec2->getTemplateName()))
1422 return false;
1423 if (!IsStructurallyEquivalent(Context, Args1: Spec1->template_arguments(),
1424 Args2: Spec2->template_arguments()))
1425 return false;
1426 break;
1427 }
1428
1429 case Type::DependentName: {
1430 const auto *Typename1 = cast<DependentNameType>(Val&: T1);
1431 const auto *Typename2 = cast<DependentNameType>(Val&: T2);
1432 if (!IsStructurallyEquivalent(Context, NNS1: Typename1->getQualifier(),
1433 NNS2: Typename2->getQualifier()))
1434 return false;
1435 if (!IsStructurallyEquivalent(Name1: Typename1->getIdentifier(),
1436 Name2: Typename2->getIdentifier()))
1437 return false;
1438
1439 break;
1440 }
1441
1442 case Type::PackExpansion:
1443 if (!IsStructurallyEquivalent(Context,
1444 T1: cast<PackExpansionType>(Val&: T1)->getPattern(),
1445 T2: cast<PackExpansionType>(Val&: T2)->getPattern()))
1446 return false;
1447 break;
1448
1449 case Type::PackIndexing:
1450 if (!IsStructurallyEquivalent(Context,
1451 T1: cast<PackIndexingType>(Val&: T1)->getPattern(),
1452 T2: cast<PackIndexingType>(Val&: T2)->getPattern()))
1453 if (!IsStructurallyEquivalent(Context,
1454 S1: cast<PackIndexingType>(Val&: T1)->getIndexExpr(),
1455 S2: cast<PackIndexingType>(Val&: T2)->getIndexExpr()))
1456 return false;
1457 break;
1458
1459 case Type::ObjCInterface: {
1460 const auto *Iface1 = cast<ObjCInterfaceType>(Val&: T1);
1461 const auto *Iface2 = cast<ObjCInterfaceType>(Val&: T2);
1462 if (!IsStructurallyEquivalent(Context, D1: Iface1->getDecl(),
1463 D2: Iface2->getDecl()))
1464 return false;
1465 break;
1466 }
1467
1468 case Type::ObjCTypeParam: {
1469 const auto *Obj1 = cast<ObjCTypeParamType>(Val&: T1);
1470 const auto *Obj2 = cast<ObjCTypeParamType>(Val&: T2);
1471 if (!IsStructurallyEquivalent(Context, D1: Obj1->getDecl(), D2: Obj2->getDecl()))
1472 return false;
1473
1474 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1475 return false;
1476 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1477 if (!IsStructurallyEquivalent(Context, D1: Obj1->getProtocol(I),
1478 D2: Obj2->getProtocol(I)))
1479 return false;
1480 }
1481 break;
1482 }
1483
1484 case Type::ObjCObject: {
1485 const auto *Obj1 = cast<ObjCObjectType>(Val&: T1);
1486 const auto *Obj2 = cast<ObjCObjectType>(Val&: T2);
1487 if (!IsStructurallyEquivalent(Context, T1: Obj1->getBaseType(),
1488 T2: Obj2->getBaseType()))
1489 return false;
1490 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1491 return false;
1492 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1493 if (!IsStructurallyEquivalent(Context, D1: Obj1->getProtocol(I),
1494 D2: Obj2->getProtocol(I)))
1495 return false;
1496 }
1497 break;
1498 }
1499
1500 case Type::ObjCObjectPointer: {
1501 const auto *Ptr1 = cast<ObjCObjectPointerType>(Val&: T1);
1502 const auto *Ptr2 = cast<ObjCObjectPointerType>(Val&: T2);
1503 if (!IsStructurallyEquivalent(Context, T1: Ptr1->getPointeeType(),
1504 T2: Ptr2->getPointeeType()))
1505 return false;
1506 break;
1507 }
1508
1509 case Type::Atomic:
1510 if (!IsStructurallyEquivalent(Context, T1: cast<AtomicType>(Val&: T1)->getValueType(),
1511 T2: cast<AtomicType>(Val&: T2)->getValueType()))
1512 return false;
1513 break;
1514
1515 case Type::Pipe:
1516 if (!IsStructurallyEquivalent(Context, T1: cast<PipeType>(Val&: T1)->getElementType(),
1517 T2: cast<PipeType>(Val&: T2)->getElementType()))
1518 return false;
1519 break;
1520 case Type::BitInt: {
1521 const auto *Int1 = cast<BitIntType>(Val&: T1);
1522 const auto *Int2 = cast<BitIntType>(Val&: T2);
1523
1524 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1525 Int1->getNumBits() != Int2->getNumBits())
1526 return false;
1527 break;
1528 }
1529 case Type::DependentBitInt: {
1530 const auto *Int1 = cast<DependentBitIntType>(Val&: T1);
1531 const auto *Int2 = cast<DependentBitIntType>(Val&: T2);
1532
1533 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1534 !IsStructurallyEquivalent(Context, S1: Int1->getNumBitsExpr(),
1535 S2: Int2->getNumBitsExpr()))
1536 return false;
1537 break;
1538 }
1539 case Type::PredefinedSugar: {
1540 const auto *TP1 = cast<PredefinedSugarType>(Val&: T1);
1541 const auto *TP2 = cast<PredefinedSugarType>(Val&: T2);
1542 if (TP1->getKind() != TP2->getKind())
1543 return false;
1544 break;
1545 }
1546 } // end switch
1547
1548 return true;
1549}
1550
1551static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1552 QualType T1, QualType T2) {
1553 return ASTStructuralEquivalence::isEquivalent(Context, T1, T2);
1554}
1555
1556static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1557 VarDecl *D1, VarDecl *D2) {
1558 IdentifierInfo *Name1 = D1->getIdentifier();
1559 IdentifierInfo *Name2 = D2->getIdentifier();
1560 if (!::IsStructurallyEquivalent(Name1, Name2))
1561 return false;
1562
1563 if (!IsStructurallyEquivalent(Context, T1: D1->getType(), T2: D2->getType()))
1564 return false;
1565
1566 // Compare storage class and initializer only if none or both are a
1567 // definition. Like a forward-declaration matches a class definition, variable
1568 // declarations that are not definitions should match with the definitions.
1569 if (D1->isThisDeclarationADefinition() != D2->isThisDeclarationADefinition())
1570 return true;
1571
1572 if (D1->getStorageClass() != D2->getStorageClass())
1573 return false;
1574
1575 return IsStructurallyEquivalent(Context, S1: D1->getInit(), S2: D2->getInit());
1576}
1577
1578static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1579 FieldDecl *Field1, FieldDecl *Field2,
1580 QualType Owner2Type) {
1581 const auto *Owner2 = cast<Decl>(Val: Field2->getDeclContext());
1582
1583 // In C23 mode, check for structural equivalence of attributes on the fields.
1584 // FIXME: Should this happen in C++ as well?
1585 if (Context.LangOpts.C23 &&
1586 !CheckStructurallyEquivalentAttributes(Context, D1: Field1, D2: Field2, PrimaryDecl: Owner2))
1587 return false;
1588
1589 // For anonymous structs/unions, match up the anonymous struct/union type
1590 // declarations directly, so that we don't go off searching for anonymous
1591 // types
1592 if (Field1->isAnonymousStructOrUnion() &&
1593 Field2->isAnonymousStructOrUnion()) {
1594 RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1595 RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1596 return IsStructurallyEquivalent(Context, D1, D2);
1597 }
1598
1599 // Check for equivalent field names.
1600 IdentifierInfo *Name1 = Field1->getIdentifier();
1601 IdentifierInfo *Name2 = Field2->getIdentifier();
1602 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1603 if (Context.Complain) {
1604 Context.Diag2(
1605 Loc: Owner2->getLocation(),
1606 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1607 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1608 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field_name)
1609 << Field2->getDeclName();
1610 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field_name)
1611 << Field1->getDeclName();
1612 }
1613 return false;
1614 }
1615
1616 if (!IsStructurallyEquivalent(Context, T1: Field1->getType(),
1617 T2: Field2->getType())) {
1618 if (Context.Complain) {
1619 Context.Diag2(
1620 Loc: Owner2->getLocation(),
1621 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1622 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1623 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field)
1624 << Field2->getDeclName() << Field2->getType();
1625 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field)
1626 << Field1->getDeclName() << Field1->getType();
1627 }
1628 return false;
1629 }
1630
1631 if ((Field1->isBitField() || Field2->isBitField()) &&
1632 !IsStructurallyEquivalent(Context, S1: Field1->getBitWidth(),
1633 S2: Field2->getBitWidth())) {
1634 // Two bit-fields can be structurally unequivalent but still be okay for
1635 // the purposes of C where they simply need to have the same values, not
1636 // the same token sequences.
1637 bool Diagnose = true;
1638 if (Context.LangOpts.C23 && Field1->isBitField() && Field2->isBitField())
1639 Diagnose = Field1->getBitWidthValue() != Field2->getBitWidthValue();
1640
1641 if (Diagnose && Context.Complain) {
1642 auto DiagNote = [&](const FieldDecl *FD,
1643 DiagnosticBuilder (
1644 StructuralEquivalenceContext::*Diag)(
1645 SourceLocation, unsigned)) {
1646 if (FD->isBitField()) {
1647 (Context.*Diag)(FD->getLocation(), diag::note_odr_field_bit_width)
1648 << FD->getDeclName() << FD->getBitWidthValue();
1649 } else {
1650 (Context.*Diag)(FD->getLocation(), diag::note_odr_field_not_bit_field)
1651 << FD->getDeclName();
1652 }
1653 };
1654
1655 Context.Diag2(
1656 Loc: Owner2->getLocation(),
1657 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1658 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1659 DiagNote(Field2, &StructuralEquivalenceContext::Diag2);
1660 DiagNote(Field1, &StructuralEquivalenceContext::Diag1);
1661 }
1662 return false;
1663 }
1664
1665 return true;
1666}
1667
1668/// Determine structural equivalence of two fields.
1669static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1670 FieldDecl *Field1, FieldDecl *Field2) {
1671 const auto *Owner2 = cast<RecordDecl>(Val: Field2->getDeclContext());
1672 return IsStructurallyEquivalent(Context, Field1, Field2,
1673 Owner2Type: Context.ToCtx.getCanonicalTagType(TD: Owner2));
1674}
1675
1676/// Determine structural equivalence of two IndirectFields.
1677static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1678 IndirectFieldDecl *ID1,
1679 IndirectFieldDecl *ID2) {
1680 return IsStructurallyEquivalent(Context, Field1: ID1->getAnonField(),
1681 Field2: ID2->getAnonField());
1682}
1683
1684/// Determine structural equivalence of two methods.
1685static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1686 CXXMethodDecl *Method1,
1687 CXXMethodDecl *Method2) {
1688 if (!Method1 && !Method2)
1689 return true;
1690 if (!Method1 || !Method2)
1691 return false;
1692
1693 bool PropertiesEqual =
1694 Method1->getDeclKind() == Method2->getDeclKind() &&
1695 Method1->getRefQualifier() == Method2->getRefQualifier() &&
1696 Method1->getAccess() == Method2->getAccess() &&
1697 Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1698 Method1->isStatic() == Method2->isStatic() &&
1699 Method1->isImplicitObjectMemberFunction() ==
1700 Method2->isImplicitObjectMemberFunction() &&
1701 Method1->isConst() == Method2->isConst() &&
1702 Method1->isVolatile() == Method2->isVolatile() &&
1703 Method1->isVirtual() == Method2->isVirtual() &&
1704 Method1->isPureVirtual() == Method2->isPureVirtual() &&
1705 Method1->isDefaulted() == Method2->isDefaulted() &&
1706 Method1->isDeleted() == Method2->isDeleted();
1707 if (!PropertiesEqual)
1708 return false;
1709 // FIXME: Check for 'final'.
1710
1711 if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Val: Method1)) {
1712 auto *Constructor2 = cast<CXXConstructorDecl>(Val: Method2);
1713 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1714 Other: Constructor2->getExplicitSpecifier()))
1715 return false;
1716 }
1717
1718 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Val: Method1)) {
1719 auto *Conversion2 = cast<CXXConversionDecl>(Val: Method2);
1720 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1721 Other: Conversion2->getExplicitSpecifier()))
1722 return false;
1723 if (!IsStructurallyEquivalent(Context, T1: Conversion1->getConversionType(),
1724 T2: Conversion2->getConversionType()))
1725 return false;
1726 }
1727
1728 const IdentifierInfo *Name1 = Method1->getIdentifier();
1729 const IdentifierInfo *Name2 = Method2->getIdentifier();
1730 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1731 return false;
1732 // TODO: Names do not match, add warning like at check for FieldDecl.
1733 }
1734
1735 // Check the prototypes.
1736 if (!::IsStructurallyEquivalent(Context,
1737 T1: Method1->getType(), T2: Method2->getType()))
1738 return false;
1739
1740 return true;
1741}
1742
1743/// Determine structural equivalence of two lambda classes.
1744static bool
1745IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context,
1746 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1747 assert(D1->isLambda() && D2->isLambda() &&
1748 "Must be called on lambda classes");
1749 if (!IsStructurallyEquivalent(Context, Method1: D1->getLambdaCallOperator(),
1750 Method2: D2->getLambdaCallOperator()))
1751 return false;
1752
1753 return true;
1754}
1755
1756/// Determine if context of a class is equivalent.
1757static bool
1758IsRecordContextStructurallyEquivalent(StructuralEquivalenceContext &Context,
1759 RecordDecl *D1, RecordDecl *D2) {
1760 // The context should be completely equal, including anonymous and inline
1761 // namespaces.
1762 // We compare objects as part of full translation units, not subtrees of
1763 // translation units.
1764 DeclContext *DC1 = D1->getDeclContext()->getNonTransparentContext();
1765 DeclContext *DC2 = D2->getDeclContext()->getNonTransparentContext();
1766 while (true) {
1767 // Special case: We allow a struct defined in a function to be equivalent
1768 // with a similar struct defined outside of a function.
1769 if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1770 (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1771 return true;
1772
1773 if (DC1->getDeclKind() != DC2->getDeclKind())
1774 return false;
1775 if (DC1->isTranslationUnit())
1776 break;
1777 if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1778 return false;
1779 if (const auto *ND1 = dyn_cast<NamedDecl>(Val: DC1)) {
1780 const auto *ND2 = cast<NamedDecl>(Val: DC2);
1781 if (!DC1->isInlineNamespace() &&
1782 !IsStructurallyEquivalent(Name1: ND1->getIdentifier(), Name2: ND2->getIdentifier()))
1783 return false;
1784 }
1785
1786 if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC1)) {
1787 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC2);
1788 if (!IsStructurallyEquivalent(Context, D1: D1Spec, D2: D2Spec))
1789 return false;
1790 }
1791
1792 DC1 = DC1->getParent()->getNonTransparentContext();
1793 DC2 = DC2->getParent()->getNonTransparentContext();
1794 }
1795
1796 return true;
1797}
1798
1799static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1800 auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1801 if (const IdentifierInfo *Name = D.getIdentifier())
1802 return Name;
1803 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1804 return TypedefName->getIdentifier();
1805 return nullptr;
1806 };
1807 return IsStructurallyEquivalent(Name1: GetName(D1), Name2: GetName(D2));
1808}
1809
1810/// Determine structural equivalence of two records.
1811static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1812 RecordDecl *D1, RecordDecl *D2) {
1813 // C23 6.2.7p1:
1814 // ... Moreover, two complete structure, union, or enumerated types declared
1815 // with the same tag are compatible if members satisfy the following
1816 // requirements:
1817 // - there shall be a one-to-one correspondence between their members such
1818 // that each pair of corresponding members are declared with compatible
1819 // types;
1820 // - if one member of the pair is declared with an alignment specifier, the
1821 // other is declared with an equivalent alignment specifier;
1822 // - and, if one member of the pair is declared with a name, the other is
1823 // declared with the same name.
1824 // For two structures, corresponding members shall be declared in the same
1825 // order. For two unions declared in the same translation unit, corresponding
1826 // members shall be declared in the same order. For two structures or unions,
1827 // corresponding bit-fields shall have the same widths. ... For determining
1828 // type compatibility, anonymous structures and unions are considered a
1829 // regular member of the containing structure or union type, and the type of
1830 // an anonymous structure or union is considered compatible to the type of
1831 // another anonymous structure or union, respectively, if their members
1832 // fulfill the preceding requirements. ... Otherwise, the structure, union,
1833 // or enumerated types are incompatible.
1834 if (!NameIsStructurallyEquivalent(D1: *D1, D2: *D2))
1835 return false;
1836
1837 if (D1->isUnion() != D2->isUnion()) {
1838 if (Context.Complain) {
1839 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
1840 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1841 << Context.ToCtx.getCanonicalTagType(TD: D2)
1842 << (&Context.FromCtx != &Context.ToCtx);
1843 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_tag_kind_here)
1844 << D1->getDeclName() << (unsigned)D1->getTagKind();
1845 }
1846 return false;
1847 }
1848
1849 if (!D1->getDeclName() && !D2->getDeclName()) {
1850 // If both anonymous structs/unions are in a record context, make sure
1851 // they occur in the same location in the context records.
1852 if (UnsignedOrNone Index1 =
1853 StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(Anon: D1)) {
1854 if (UnsignedOrNone Index2 =
1855 StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
1856 Anon: D2)) {
1857 if (*Index1 != *Index2)
1858 return false;
1859 }
1860 }
1861 }
1862
1863 // If the records occur in different context (namespace), these should be
1864 // different. This is specially important if the definition of one or both
1865 // records is missing. In C23, different contexts do not make for a different
1866 // structural type (a local struct definition can be a valid redefinition of
1867 // a file scope struct definition).
1868 if (!Context.LangOpts.C23 &&
1869 !IsRecordContextStructurallyEquivalent(Context, D1, D2))
1870 return false;
1871
1872 // If both declarations are class template specializations, we know
1873 // the ODR applies, so check the template and template arguments.
1874 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(Val: D1);
1875 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(Val: D2);
1876 if (Spec1 && Spec2) {
1877 // Check that the specialized templates are the same.
1878 if (!IsStructurallyEquivalent(Context, D1: Spec1->getSpecializedTemplate(),
1879 D2: Spec2->getSpecializedTemplate()))
1880 return false;
1881
1882 // Check that the template arguments are the same.
1883 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1884 return false;
1885
1886 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1887 if (!IsStructurallyEquivalent(Context, Arg1: Spec1->getTemplateArgs().get(Idx: I),
1888 Arg2: Spec2->getTemplateArgs().get(Idx: I)))
1889 return false;
1890 }
1891 // If one is a class template specialization and the other is not, these
1892 // structures are different.
1893 else if (Spec1 || Spec2)
1894 return false;
1895
1896 // Compare the definitions of these two records. If either or both are
1897 // incomplete (i.e. it is a forward decl), we assume that they are
1898 // equivalent. except in C23 mode.
1899 D1 = D1->getDefinition();
1900 D2 = D2->getDefinition();
1901 if (!D1 || !D2)
1902 return !Context.LangOpts.C23;
1903
1904 // In C23 mode, check for structural equivalence of attributes on the record
1905 // itself. FIXME: Should this happen in C++ as well?
1906 if (Context.LangOpts.C23 &&
1907 !CheckStructurallyEquivalentAttributes(Context, D1, D2))
1908 return false;
1909
1910 // If any of the records has external storage and we do a minimal check (or
1911 // AST import) we assume they are equivalent. (If we didn't have this
1912 // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1913 // another AST import which in turn would call the structural equivalency
1914 // check again and finally we'd have an improper result.)
1915 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1916 if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
1917 return true;
1918
1919 // If one definition is currently being defined, we do not compare for
1920 // equality and we assume that the decls are equal.
1921 if (D1->isBeingDefined() || D2->isBeingDefined())
1922 return true;
1923
1924 if (auto *D1CXX = dyn_cast<CXXRecordDecl>(Val: D1)) {
1925 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(Val: D2)) {
1926 if (D1CXX->hasExternalLexicalStorage() &&
1927 !D1CXX->isCompleteDefinition()) {
1928 D1CXX->getASTContext().getExternalSource()->CompleteType(Tag: D1CXX);
1929 }
1930
1931 if (D1CXX->isLambda() != D2CXX->isLambda())
1932 return false;
1933 if (D1CXX->isLambda()) {
1934 if (!IsStructurallyEquivalentLambdas(Context, D1: D1CXX, D2: D2CXX))
1935 return false;
1936 }
1937
1938 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1939 if (Context.Complain) {
1940 Context.Diag2(Loc: D2->getLocation(),
1941 DiagID: Context.getApplicableDiagnostic(
1942 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1943 << Context.ToCtx.getCanonicalTagType(TD: D2)
1944 << (&Context.FromCtx != &Context.ToCtx);
1945 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_number_of_bases)
1946 << D2CXX->getNumBases();
1947 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_number_of_bases)
1948 << D1CXX->getNumBases();
1949 }
1950 return false;
1951 }
1952
1953 // Check the base classes.
1954 for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1955 BaseEnd1 = D1CXX->bases_end(),
1956 Base2 = D2CXX->bases_begin();
1957 Base1 != BaseEnd1; ++Base1, ++Base2) {
1958 if (!IsStructurallyEquivalent(Context, T1: Base1->getType(),
1959 T2: Base2->getType())) {
1960 if (Context.Complain) {
1961 Context.Diag2(Loc: D2->getLocation(),
1962 DiagID: Context.getApplicableDiagnostic(
1963 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1964 << Context.ToCtx.getCanonicalTagType(TD: D2)
1965 << (&Context.FromCtx != &Context.ToCtx);
1966 Context.Diag2(Loc: Base2->getBeginLoc(), DiagID: diag::note_odr_base)
1967 << Base2->getType() << Base2->getSourceRange();
1968 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
1969 << Base1->getType() << Base1->getSourceRange();
1970 }
1971 return false;
1972 }
1973
1974 // Check virtual vs. non-virtual inheritance mismatch.
1975 if (Base1->isVirtual() != Base2->isVirtual()) {
1976 if (Context.Complain) {
1977 Context.Diag2(Loc: D2->getLocation(),
1978 DiagID: Context.getApplicableDiagnostic(
1979 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1980 << Context.ToCtx.getCanonicalTagType(TD: D2)
1981 << (&Context.FromCtx != &Context.ToCtx);
1982 Context.Diag2(Loc: Base2->getBeginLoc(), DiagID: diag::note_odr_virtual_base)
1983 << Base2->isVirtual() << Base2->getSourceRange();
1984 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
1985 << Base1->isVirtual() << Base1->getSourceRange();
1986 }
1987 return false;
1988 }
1989 }
1990
1991 // Check the friends for consistency.
1992 CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
1993 Friend2End = D2CXX->friend_end();
1994 for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
1995 Friend1End = D1CXX->friend_end();
1996 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1997 if (Friend2 == Friend2End) {
1998 if (Context.Complain) {
1999 Context.Diag2(Loc: D2->getLocation(),
2000 DiagID: Context.getApplicableDiagnostic(
2001 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2002 << Context.ToCtx.getCanonicalTagType(TD: D2CXX)
2003 << (&Context.FromCtx != &Context.ToCtx);
2004 Context.Diag1(Loc: (*Friend1)->getFriendLoc(), DiagID: diag::note_odr_friend);
2005 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_friend);
2006 }
2007 return false;
2008 }
2009
2010 if (!IsStructurallyEquivalent(Context, D1: *Friend1, D2: *Friend2)) {
2011 if (Context.Complain) {
2012 Context.Diag2(Loc: D2->getLocation(),
2013 DiagID: Context.getApplicableDiagnostic(
2014 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2015 << Context.ToCtx.getCanonicalTagType(TD: D2CXX)
2016 << (&Context.FromCtx != &Context.ToCtx);
2017 Context.Diag1(Loc: (*Friend1)->getFriendLoc(), DiagID: diag::note_odr_friend);
2018 Context.Diag2(Loc: (*Friend2)->getFriendLoc(), DiagID: diag::note_odr_friend);
2019 }
2020 return false;
2021 }
2022 }
2023
2024 if (Friend2 != Friend2End) {
2025 if (Context.Complain) {
2026 Context.Diag2(Loc: D2->getLocation(),
2027 DiagID: Context.getApplicableDiagnostic(
2028 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2029 << Context.ToCtx.getCanonicalTagType(TD: D2)
2030 << (&Context.FromCtx != &Context.ToCtx);
2031 Context.Diag2(Loc: (*Friend2)->getFriendLoc(), DiagID: diag::note_odr_friend);
2032 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_friend);
2033 }
2034 return false;
2035 }
2036 } else if (D1CXX->getNumBases() > 0) {
2037 if (Context.Complain) {
2038 Context.Diag2(Loc: D2->getLocation(),
2039 DiagID: Context.getApplicableDiagnostic(
2040 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2041 << Context.ToCtx.getCanonicalTagType(TD: D2)
2042 << (&Context.FromCtx != &Context.ToCtx);
2043 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
2044 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
2045 << Base1->getType() << Base1->getSourceRange();
2046 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_base);
2047 }
2048 return false;
2049 }
2050 }
2051
2052 // Check the fields for consistency.
2053 CanQualType D2Type = Context.ToCtx.getCanonicalTagType(TD: D2);
2054 RecordDecl::field_iterator Field2 = D2->field_begin(),
2055 Field2End = D2->field_end();
2056 for (RecordDecl::field_iterator Field1 = D1->field_begin(),
2057 Field1End = D1->field_end();
2058 Field1 != Field1End; ++Field1, ++Field2) {
2059 if (Field2 == Field2End) {
2060 if (Context.Complain) {
2061 Context.Diag2(Loc: D2->getLocation(),
2062 DiagID: Context.getApplicableDiagnostic(
2063 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2064 << Context.ToCtx.getCanonicalTagType(TD: D2)
2065 << (&Context.FromCtx != &Context.ToCtx);
2066 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field)
2067 << Field1->getDeclName() << Field1->getType();
2068 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_field);
2069 }
2070 return false;
2071 }
2072
2073 if (!IsStructurallyEquivalent(Context, Field1: *Field1, Field2: *Field2, Owner2Type: D2Type))
2074 return false;
2075 }
2076
2077 if (Field2 != Field2End) {
2078 if (Context.Complain) {
2079 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
2080 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2081 << Context.ToCtx.getCanonicalTagType(TD: D2)
2082 << (&Context.FromCtx != &Context.ToCtx);
2083 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field)
2084 << Field2->getDeclName() << Field2->getType();
2085 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_field);
2086 }
2087 return false;
2088 }
2089
2090 return true;
2091}
2092
2093static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2094 EnumConstantDecl *D1,
2095 EnumConstantDecl *D2) {
2096 const llvm::APSInt &FromVal = D1->getInitVal();
2097 const llvm::APSInt &ToVal = D2->getInitVal();
2098 if (FromVal.isSigned() != ToVal.isSigned())
2099 return false;
2100 if (FromVal.getBitWidth() != ToVal.getBitWidth())
2101 return false;
2102 if (FromVal != ToVal)
2103 return false;
2104
2105 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2106 return false;
2107
2108 // Init expressions are the most expensive check, so do them last.
2109 return IsStructurallyEquivalent(Context, S1: D1->getInitExpr(),
2110 S2: D2->getInitExpr());
2111}
2112
2113/// Determine structural equivalence of two enums.
2114static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2115 EnumDecl *D1, EnumDecl *D2) {
2116 if (!NameIsStructurallyEquivalent(D1: *D1, D2: *D2)) {
2117 return false;
2118 }
2119
2120 // Compare the definitions of these two enums. If either or both are
2121 // incomplete (i.e. forward declared), we assume that they are equivalent.
2122 // In C23, the order of the enumerations does not matter, only the names and
2123 // values do.
2124 D1 = D1->getDefinition();
2125 D2 = D2->getDefinition();
2126 if (!D1 || !D2)
2127 return true;
2128
2129 if (Context.LangOpts.C23 &&
2130 !CheckStructurallyEquivalentAttributes(Context, D1, D2))
2131 return false;
2132
2133 // In C23, if one enumeration has a fixed underlying type, the other shall
2134 // have a compatible fixed underlying type (6.2.7).
2135 if (Context.LangOpts.C23) {
2136 if (D1->isFixed() != D2->isFixed()) {
2137 if (Context.Complain) {
2138 Context.Diag2(Loc: D2->getLocation(),
2139 DiagID: Context.getApplicableDiagnostic(
2140 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2141 << Context.ToCtx.getCanonicalTagType(TD: D2)
2142 << (&Context.FromCtx != &Context.ToCtx);
2143 Context.Diag1(Loc: D1->getLocation(),
2144 DiagID: D1->isFixed()
2145 ? diag::note_odr_fixed_underlying_type
2146 : diag::note_odr_missing_fixed_underlying_type)
2147 << D1;
2148 Context.Diag2(Loc: D2->getLocation(),
2149 DiagID: D2->isFixed()
2150 ? diag::note_odr_fixed_underlying_type
2151 : diag::note_odr_missing_fixed_underlying_type)
2152 << D2;
2153 }
2154 return false;
2155 }
2156 if (D1->isFixed()) {
2157 assert(D2->isFixed() && "enums expected to have fixed underlying types");
2158 if (!IsStructurallyEquivalent(Context, T1: D1->getIntegerType(),
2159 T2: D2->getIntegerType())) {
2160 if (Context.Complain) {
2161 Context.Diag2(Loc: D2->getLocation(),
2162 DiagID: Context.getApplicableDiagnostic(
2163 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2164 << Context.ToCtx.getCanonicalTagType(TD: D2)
2165 << (&Context.FromCtx != &Context.ToCtx);
2166 Context.Diag2(Loc: D2->getLocation(),
2167 DiagID: diag::note_odr_incompatible_fixed_underlying_type)
2168 << D2 << D2->getIntegerType() << D1->getIntegerType();
2169 }
2170 return false;
2171 }
2172 }
2173 }
2174
2175 llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums;
2176 auto CopyEnumerators =
2177 [](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
2178 for (const EnumConstantDecl *ECD : Range)
2179 Cont.push_back(Elt: ECD);
2180 };
2181 CopyEnumerators(D1->enumerators(), D1Enums);
2182 CopyEnumerators(D2->enumerators(), D2Enums);
2183
2184 // In C23 mode, the order of the enumerations does not matter, so sort them
2185 // by name to get them both into a consistent ordering.
2186 if (Context.LangOpts.C23) {
2187 auto Sorter = [](const EnumConstantDecl *LHS, const EnumConstantDecl *RHS) {
2188 return LHS->getName() < RHS->getName();
2189 };
2190 llvm::sort(C&: D1Enums, Comp: Sorter);
2191 llvm::sort(C&: D2Enums, Comp: Sorter);
2192 }
2193
2194 auto EC2 = D2Enums.begin(), EC2End = D2Enums.end();
2195 for (auto EC1 = D1Enums.begin(), EC1End = D1Enums.end(); EC1 != EC1End;
2196 ++EC1, ++EC2) {
2197 if (EC2 == EC2End) {
2198 if (Context.Complain) {
2199 Context.Diag2(Loc: D2->getLocation(),
2200 DiagID: Context.getApplicableDiagnostic(
2201 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2202 << Context.ToCtx.getCanonicalTagType(TD: D2)
2203 << (&Context.FromCtx != &Context.ToCtx);
2204 Context.Diag1(Loc: (*EC1)->getLocation(), DiagID: diag::note_odr_enumerator)
2205 << (*EC1)->getDeclName() << toString(I: (*EC1)->getInitVal(), Radix: 10);
2206 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_enumerator);
2207 }
2208 return false;
2209 }
2210
2211 llvm::APSInt Val1 = (*EC1)->getInitVal();
2212 llvm::APSInt Val2 = (*EC2)->getInitVal();
2213 if (!llvm::APSInt::isSameValue(I1: Val1, I2: Val2) ||
2214 !IsStructurallyEquivalent(Name1: (*EC1)->getIdentifier(),
2215 Name2: (*EC2)->getIdentifier())) {
2216 if (Context.Complain) {
2217 Context.Diag2(Loc: D2->getLocation(),
2218 DiagID: Context.getApplicableDiagnostic(
2219 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2220 << Context.ToCtx.getCanonicalTagType(TD: D2)
2221 << (&Context.FromCtx != &Context.ToCtx);
2222 Context.Diag2(Loc: (*EC2)->getLocation(), DiagID: diag::note_odr_enumerator)
2223 << (*EC2)->getDeclName() << toString(I: (*EC2)->getInitVal(), Radix: 10);
2224 Context.Diag1(Loc: (*EC1)->getLocation(), DiagID: diag::note_odr_enumerator)
2225 << (*EC1)->getDeclName() << toString(I: (*EC1)->getInitVal(), Radix: 10);
2226 }
2227 return false;
2228 }
2229 if (Context.LangOpts.C23 &&
2230 !CheckStructurallyEquivalentAttributes(Context, D1: *EC1, D2: *EC2, PrimaryDecl: D2))
2231 return false;
2232 }
2233
2234 if (EC2 != EC2End) {
2235 if (Context.Complain) {
2236 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
2237 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2238 << Context.ToCtx.getCanonicalTagType(TD: D2)
2239 << (&Context.FromCtx != &Context.ToCtx);
2240 Context.Diag2(Loc: (*EC2)->getLocation(), DiagID: diag::note_odr_enumerator)
2241 << (*EC2)->getDeclName() << toString(I: (*EC2)->getInitVal(), Radix: 10);
2242 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_enumerator);
2243 }
2244 return false;
2245 }
2246
2247 return true;
2248}
2249
2250static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2251 TemplateParameterList *Params1,
2252 TemplateParameterList *Params2) {
2253 if (Params1->size() != Params2->size()) {
2254 if (Context.Complain) {
2255 Context.Diag2(Loc: Params2->getTemplateLoc(),
2256 DiagID: Context.getApplicableDiagnostic(
2257 ErrorDiagnostic: diag::err_odr_different_num_template_parameters))
2258 << Params1->size() << Params2->size();
2259 Context.Diag1(Loc: Params1->getTemplateLoc(),
2260 DiagID: diag::note_odr_template_parameter_list);
2261 }
2262 return false;
2263 }
2264
2265 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
2266 if (Params1->getParam(Idx: I)->getKind() != Params2->getParam(Idx: I)->getKind()) {
2267 if (Context.Complain) {
2268 Context.Diag2(Loc: Params2->getParam(Idx: I)->getLocation(),
2269 DiagID: Context.getApplicableDiagnostic(
2270 ErrorDiagnostic: diag::err_odr_different_template_parameter_kind));
2271 Context.Diag1(Loc: Params1->getParam(Idx: I)->getLocation(),
2272 DiagID: diag::note_odr_template_parameter_here);
2273 }
2274 return false;
2275 }
2276
2277 if (!IsStructurallyEquivalent(Context, D1: Params1->getParam(Idx: I),
2278 D2: Params2->getParam(Idx: I)))
2279 return false;
2280 }
2281
2282 return true;
2283}
2284
2285static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2286 TemplateTypeParmDecl *D1,
2287 TemplateTypeParmDecl *D2) {
2288 if (D1->isParameterPack() != D2->isParameterPack()) {
2289 if (Context.Complain) {
2290 Context.Diag2(Loc: D2->getLocation(),
2291 DiagID: Context.getApplicableDiagnostic(
2292 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2293 << D2->isParameterPack();
2294 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2295 << D1->isParameterPack();
2296 }
2297 return false;
2298 }
2299
2300 return true;
2301}
2302
2303static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2304 NonTypeTemplateParmDecl *D1,
2305 NonTypeTemplateParmDecl *D2) {
2306 if (D1->isParameterPack() != D2->isParameterPack()) {
2307 if (Context.Complain) {
2308 Context.Diag2(Loc: D2->getLocation(),
2309 DiagID: Context.getApplicableDiagnostic(
2310 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2311 << D2->isParameterPack();
2312 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2313 << D1->isParameterPack();
2314 }
2315 return false;
2316 }
2317 if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
2318 return false;
2319 if (D1->getIndex() != D2->getIndex())
2320 return false;
2321 // Check types.
2322 if (!IsStructurallyEquivalent(Context, T1: D1->getType(), T2: D2->getType())) {
2323 if (Context.Complain) {
2324 Context.Diag2(Loc: D2->getLocation(),
2325 DiagID: Context.getApplicableDiagnostic(
2326 ErrorDiagnostic: diag::err_odr_non_type_parameter_type_inconsistent))
2327 << D2->getType() << D1->getType();
2328 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_value_here)
2329 << D1->getType();
2330 }
2331 return false;
2332 }
2333
2334 return true;
2335}
2336
2337static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2338 TemplateTemplateParmDecl *D1,
2339 TemplateTemplateParmDecl *D2) {
2340 if (D1->isParameterPack() != D2->isParameterPack()) {
2341 if (Context.Complain) {
2342 Context.Diag2(Loc: D2->getLocation(),
2343 DiagID: Context.getApplicableDiagnostic(
2344 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2345 << D2->isParameterPack();
2346 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2347 << D1->isParameterPack();
2348 }
2349 return false;
2350 }
2351
2352 // Check template parameter lists.
2353 return D1->templateParameterKind() == D2->templateParameterKind() &&
2354 IsStructurallyEquivalent(Context, Params1: D1->getTemplateParameters(),
2355 Params2: D2->getTemplateParameters());
2356}
2357
2358static bool IsTemplateDeclCommonStructurallyEquivalent(
2359 StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2) {
2360 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2361 return false;
2362 if (!D1->getIdentifier()) // Special name
2363 if (D1->getNameAsString() != D2->getNameAsString())
2364 return false;
2365 return IsStructurallyEquivalent(Context&: Ctx, Params1: D1->getTemplateParameters(),
2366 Params2: D2->getTemplateParameters());
2367}
2368
2369static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2370 ClassTemplateDecl *D1,
2371 ClassTemplateDecl *D2) {
2372 // Check template parameters.
2373 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2374 return false;
2375
2376 // Check the templated declaration.
2377 return IsStructurallyEquivalent(Context, D1: D1->getTemplatedDecl(),
2378 D2: D2->getTemplatedDecl());
2379}
2380
2381static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2382 FunctionTemplateDecl *D1,
2383 FunctionTemplateDecl *D2) {
2384 // Check template parameters.
2385 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2386 return false;
2387
2388 // Check the templated declaration.
2389 return IsStructurallyEquivalent(Context, T1: D1->getTemplatedDecl()->getType(),
2390 T2: D2->getTemplatedDecl()->getType());
2391}
2392
2393static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2394 TypeAliasTemplateDecl *D1,
2395 TypeAliasTemplateDecl *D2) {
2396 // Check template parameters.
2397 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2398 return false;
2399
2400 // Check the templated declaration.
2401 return IsStructurallyEquivalent(Context, D1: D1->getTemplatedDecl(),
2402 D2: D2->getTemplatedDecl());
2403}
2404
2405static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2406 ConceptDecl *D1,
2407 ConceptDecl *D2) {
2408 // Check template parameters.
2409 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2410 return false;
2411
2412 // Check the constraint expression.
2413 return IsStructurallyEquivalent(Context, S1: D1->getConstraintExpr(),
2414 S2: D2->getConstraintExpr());
2415}
2416
2417static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2418 FriendDecl *D1, FriendDecl *D2) {
2419 if ((D1->getFriendType() && D2->getFriendDecl()) ||
2420 (D1->getFriendDecl() && D2->getFriendType())) {
2421 return false;
2422 }
2423 if (D1->getFriendType() && D2->getFriendType())
2424 return IsStructurallyEquivalent(Context,
2425 T1: D1->getFriendType()->getType(),
2426 T2: D2->getFriendType()->getType());
2427 if (D1->getFriendDecl() && D2->getFriendDecl())
2428 return IsStructurallyEquivalent(Context, D1: D1->getFriendDecl(),
2429 D2: D2->getFriendDecl());
2430 return false;
2431}
2432
2433static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2434 TypedefNameDecl *D1, TypedefNameDecl *D2) {
2435 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2436 return false;
2437
2438 return IsStructurallyEquivalent(Context, T1: D1->getUnderlyingType(),
2439 T2: D2->getUnderlyingType());
2440}
2441
2442static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2443 FunctionDecl *D1, FunctionDecl *D2) {
2444 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2445 return false;
2446
2447 if (D1->isOverloadedOperator()) {
2448 if (!D2->isOverloadedOperator())
2449 return false;
2450 if (D1->getOverloadedOperator() != D2->getOverloadedOperator())
2451 return false;
2452 }
2453
2454 // FIXME: Consider checking for function attributes as well.
2455 if (!IsStructurallyEquivalent(Context, T1: D1->getType(), T2: D2->getType()))
2456 return false;
2457
2458 return true;
2459}
2460
2461static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2462 ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2463 QualType Owner2Type) {
2464 if (D1->getAccessControl() != D2->getAccessControl())
2465 return false;
2466
2467 return IsStructurallyEquivalent(Context, Field1: cast<FieldDecl>(Val: D1),
2468 Field2: cast<FieldDecl>(Val: D2), Owner2Type);
2469}
2470
2471static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2472 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2473 QualType Owner2Type =
2474 Context.ToCtx.getObjCInterfaceType(Decl: D2->getContainingInterface());
2475 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2476}
2477
2478static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2479 ObjCMethodDecl *Method1,
2480 ObjCMethodDecl *Method2) {
2481 bool PropertiesEqual =
2482 Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2483 Method1->isVariadic() == Method2->isVariadic() &&
2484 Method1->isDirectMethod() == Method2->isDirectMethod();
2485 if (!PropertiesEqual)
2486 return false;
2487
2488 // Compare selector slot names.
2489 Selector Selector1 = Method1->getSelector(),
2490 Selector2 = Method2->getSelector();
2491 unsigned NumArgs = Selector1.getNumArgs();
2492 if (NumArgs != Selector2.getNumArgs())
2493 return false;
2494 // Compare all selector slots. For selectors with arguments it means all arg
2495 // slots. And if there are no arguments, compare the first-and-only slot.
2496 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2497 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2498 if (!IsStructurallyEquivalent(Name1: Selector1.getIdentifierInfoForSlot(argIndex: I),
2499 Name2: Selector2.getIdentifierInfoForSlot(argIndex: I)))
2500 return false;
2501 }
2502
2503 // Compare types.
2504 if (!IsStructurallyEquivalent(Context, T1: Method1->getReturnType(),
2505 T2: Method2->getReturnType()))
2506 return false;
2507 assert(
2508 Method1->param_size() == Method2->param_size() &&
2509 "Same number of arguments should be already enforced in Selector checks");
2510 for (ObjCMethodDecl::param_type_iterator
2511 ParamT1 = Method1->param_type_begin(),
2512 ParamT1End = Method1->param_type_end(),
2513 ParamT2 = Method2->param_type_begin(),
2514 ParamT2End = Method2->param_type_end();
2515 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2516 ++ParamT1, ++ParamT2) {
2517 if (!IsStructurallyEquivalent(Context, T1: *ParamT1, T2: *ParamT2))
2518 return false;
2519 }
2520
2521 return true;
2522}
2523
2524static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2525 ObjCCategoryDecl *D1,
2526 ObjCCategoryDecl *D2) {
2527 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2528 return false;
2529
2530 const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2531 *Intf2 = D2->getClassInterface();
2532 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2533 return false;
2534
2535 if (Intf1 &&
2536 !IsStructurallyEquivalent(Name1: Intf1->getIdentifier(), Name2: Intf2->getIdentifier()))
2537 return false;
2538
2539 // Compare protocols.
2540 ObjCCategoryDecl::protocol_iterator Protocol2 = D2->protocol_begin(),
2541 Protocol2End = D2->protocol_end();
2542 for (ObjCCategoryDecl::protocol_iterator Protocol1 = D1->protocol_begin(),
2543 Protocol1End = D1->protocol_end();
2544 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2545 if (Protocol2 == Protocol2End)
2546 return false;
2547 if (!IsStructurallyEquivalent(Name1: (*Protocol1)->getIdentifier(),
2548 Name2: (*Protocol2)->getIdentifier()))
2549 return false;
2550 }
2551 if (Protocol2 != Protocol2End)
2552 return false;
2553
2554 // Compare ivars.
2555 QualType D2Type =
2556 Intf2 ? Context.ToCtx.getObjCInterfaceType(Decl: Intf2) : QualType();
2557 ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(),
2558 Ivar2End = D2->ivar_end();
2559 for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(),
2560 Ivar1End = D1->ivar_end();
2561 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2562 if (Ivar2 == Ivar2End)
2563 return false;
2564 if (!IsStructurallyEquivalent(Context, D1: *Ivar1, D2: *Ivar2, Owner2Type: D2Type))
2565 return false;
2566 }
2567 if (Ivar2 != Ivar2End)
2568 return false;
2569
2570 // Compare methods.
2571 ObjCCategoryDecl::method_iterator Method2 = D2->meth_begin(),
2572 Method2End = D2->meth_end();
2573 for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2574 Method1End = D1->meth_end();
2575 Method1 != Method1End; ++Method1, ++Method2) {
2576 if (Method2 == Method2End)
2577 return false;
2578 if (!IsStructurallyEquivalent(Context, Method1: *Method1, Method2: *Method2))
2579 return false;
2580 }
2581 if (Method2 != Method2End)
2582 return false;
2583
2584 return true;
2585}
2586
2587/// Determine structural equivalence of two declarations.
2588static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2589 Decl *D1, Decl *D2) {
2590 // FIXME: Check for known structural equivalences via a callback of some sort.
2591
2592 D1 = D1->getCanonicalDecl();
2593 D2 = D2->getCanonicalDecl();
2594
2595 if (D1 == D2)
2596 return true;
2597
2598 std::pair<Decl *, Decl *> P{D1, D2};
2599
2600 // Check whether we already know that these two declarations are not
2601 // structurally equivalent.
2602 if (Context.NonEquivalentDecls.count(
2603 V: std::make_tuple(args&: D1, args&: D2, args&: Context.IgnoreTemplateParmDepth)))
2604 return false;
2605
2606 // Check if a check for these declarations is already pending.
2607 // If yes D1 and D2 will be checked later (from DeclsToCheck),
2608 // or these are already checked (and equivalent).
2609 bool Inserted = Context.VisitedDecls.insert(V: P).second;
2610 if (!Inserted)
2611 return true;
2612
2613 Context.DeclsToCheck.push(x: P);
2614
2615 return true;
2616}
2617
2618DiagnosticBuilder StructuralEquivalenceContext::Diag1(SourceLocation Loc,
2619 unsigned DiagID) {
2620 assert(Complain && "Not allowed to complain");
2621 if (LastDiagFromC2)
2622 FromCtx.getDiagnostics().notePriorDiagnosticFrom(Other: ToCtx.getDiagnostics());
2623 LastDiagFromC2 = false;
2624 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2625}
2626
2627DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc,
2628 unsigned DiagID) {
2629 assert(Complain && "Not allowed to complain");
2630 if (!LastDiagFromC2)
2631 ToCtx.getDiagnostics().notePriorDiagnosticFrom(Other: FromCtx.getDiagnostics());
2632 LastDiagFromC2 = true;
2633 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2634}
2635
2636UnsignedOrNone
2637StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
2638 ASTContext &Context = Anon->getASTContext();
2639 CanQualType AnonTy = Context.getCanonicalTagType(TD: Anon);
2640
2641 const auto *Owner = dyn_cast<RecordDecl>(Val: Anon->getDeclContext());
2642 if (!Owner)
2643 return std::nullopt;
2644
2645 unsigned Index = 0;
2646 for (const auto *D : Owner->noload_decls()) {
2647 const auto *F = dyn_cast<FieldDecl>(Val: D);
2648 if (!F)
2649 continue;
2650
2651 if (F->isAnonymousStructOrUnion()) {
2652 if (Context.hasSameType(T1: F->getType(), T2: AnonTy))
2653 break;
2654 ++Index;
2655 continue;
2656 }
2657
2658 // If the field looks like this:
2659 // struct { ... } A;
2660 QualType FieldType = F->getType();
2661 if (const auto *RecType = dyn_cast<RecordType>(Val&: FieldType)) {
2662 const RecordDecl *RecDecl = RecType->getDecl();
2663 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2664 if (Context.hasSameType(T1: FieldType, T2: AnonTy))
2665 break;
2666 ++Index;
2667 continue;
2668 }
2669 }
2670 }
2671
2672 return Index;
2673}
2674
2675unsigned StructuralEquivalenceContext::getApplicableDiagnostic(
2676 unsigned ErrorDiagnostic) {
2677 if (ErrorOnTagTypeMismatch)
2678 return ErrorDiagnostic;
2679
2680 switch (ErrorDiagnostic) {
2681 case diag::err_odr_variable_type_inconsistent:
2682 return diag::warn_odr_variable_type_inconsistent;
2683 case diag::err_odr_variable_multiple_def:
2684 return diag::warn_odr_variable_multiple_def;
2685 case diag::err_odr_function_type_inconsistent:
2686 return diag::warn_odr_function_type_inconsistent;
2687 case diag::err_odr_tag_type_inconsistent:
2688 return diag::warn_odr_tag_type_inconsistent;
2689 case diag::err_odr_field_type_inconsistent:
2690 return diag::warn_odr_field_type_inconsistent;
2691 case diag::err_odr_ivar_type_inconsistent:
2692 return diag::warn_odr_ivar_type_inconsistent;
2693 case diag::err_odr_objc_superclass_inconsistent:
2694 return diag::warn_odr_objc_superclass_inconsistent;
2695 case diag::err_odr_objc_method_result_type_inconsistent:
2696 return diag::warn_odr_objc_method_result_type_inconsistent;
2697 case diag::err_odr_objc_method_num_params_inconsistent:
2698 return diag::warn_odr_objc_method_num_params_inconsistent;
2699 case diag::err_odr_objc_method_param_type_inconsistent:
2700 return diag::warn_odr_objc_method_param_type_inconsistent;
2701 case diag::err_odr_objc_method_variadic_inconsistent:
2702 return diag::warn_odr_objc_method_variadic_inconsistent;
2703 case diag::err_odr_objc_property_type_inconsistent:
2704 return diag::warn_odr_objc_property_type_inconsistent;
2705 case diag::err_odr_objc_property_impl_kind_inconsistent:
2706 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2707 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2708 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2709 case diag::err_odr_different_num_template_parameters:
2710 return diag::warn_odr_different_num_template_parameters;
2711 case diag::err_odr_different_template_parameter_kind:
2712 return diag::warn_odr_different_template_parameter_kind;
2713 case diag::err_odr_parameter_pack_non_pack:
2714 return diag::warn_odr_parameter_pack_non_pack;
2715 case diag::err_odr_non_type_parameter_type_inconsistent:
2716 return diag::warn_odr_non_type_parameter_type_inconsistent;
2717 }
2718 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2719}
2720
2721bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) {
2722
2723 // Ensure that the implementation functions (all static functions in this TU)
2724 // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2725 // because that will wreak havoc the internal state (DeclsToCheck and
2726 // VisitedDecls members) and can cause faulty behaviour.
2727 // In other words: Do not start a graph search from a new node with the
2728 // internal data of another search in progress.
2729 // FIXME: Better encapsulation and separation of internal and public
2730 // functionality.
2731 assert(DeclsToCheck.empty());
2732 assert(VisitedDecls.empty());
2733
2734 if (!::IsStructurallyEquivalent(Context&: *this, D1, D2))
2735 return false;
2736
2737 return !Finish();
2738}
2739
2740bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
2741 assert(DeclsToCheck.empty());
2742 assert(VisitedDecls.empty());
2743 if (!::IsStructurallyEquivalent(Context&: *this, T1, T2))
2744 return false;
2745
2746 return !Finish();
2747}
2748
2749bool StructuralEquivalenceContext::IsEquivalent(Stmt *S1, Stmt *S2) {
2750 assert(DeclsToCheck.empty());
2751 assert(VisitedDecls.empty());
2752 if (!::IsStructurallyEquivalent(Context&: *this, S1, S2))
2753 return false;
2754
2755 return !Finish();
2756}
2757
2758bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2759 // Check for equivalent described template.
2760 TemplateDecl *Template1 = D1->getDescribedTemplate();
2761 TemplateDecl *Template2 = D2->getDescribedTemplate();
2762 if ((Template1 != nullptr) != (Template2 != nullptr))
2763 return false;
2764 if (Template1 && !IsStructurallyEquivalent(Context&: *this, D1: Template1, D2: Template2))
2765 return false;
2766
2767 // FIXME: Move check for identifier names into this function.
2768
2769 return true;
2770}
2771
2772bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2773 Decl *D1, Decl *D2) {
2774
2775 // Kind mismatch.
2776 if (D1->getKind() != D2->getKind())
2777 return false;
2778
2779 // Cast the Decls to their actual subclass so that the right overload of
2780 // IsStructurallyEquivalent is called.
2781 switch (D1->getKind()) {
2782#define ABSTRACT_DECL(DECL)
2783#define DECL(DERIVED, BASE) \
2784 case Decl::Kind::DERIVED: \
2785 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2786 static_cast<DERIVED##Decl *>(D2));
2787#include "clang/AST/DeclNodes.inc"
2788 }
2789 return true;
2790}
2791
2792bool StructuralEquivalenceContext::checkDeclQueue() {
2793 while (!DeclsToCheck.empty()) {
2794 // Check the next declaration.
2795 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2796 DeclsToCheck.pop();
2797
2798 Decl *D1 = P.first;
2799 Decl *D2 = P.second;
2800
2801 bool Equivalent =
2802 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2803
2804 if (!Equivalent) {
2805 // Note that these two declarations are not equivalent (and we already
2806 // know about it).
2807 NonEquivalentDecls.insert(
2808 V: std::make_tuple(args&: D1, args&: D2, args&: IgnoreTemplateParmDepth));
2809
2810 return true;
2811 }
2812 }
2813
2814 return false;
2815}
2816
2817bool StructuralEquivalenceContext::Finish() { return checkDeclQueue(); }
2818