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. If the enumeration is invalid, e.g., it could be a
929 // forward declaration of an enumeration without a fixed underlying type,
930 // we'll default to 'int' for error recovery. If one type is an
931 // enumeration, the other must be an enumeration or integral, otherwise
932 // they're not structurally equivalent. e.g., it could be an enum in one
933 // struct and a union in another.
934 if (T1->getTypeClass() == Type::Enum) {
935 if (!T2->isBuiltinType() && !T2->isEnumeralType())
936 return false;
937 T1 = cast<EnumType>(Val&: T1)->getDecl()->getIntegerType();
938 if (T1.isNull())
939 T1 = Context.FromCtx.IntTy;
940 } else if (T2->getTypeClass() == Type::Enum) {
941 if (!T1->isBuiltinType() && !T1->isEnumeralType())
942 return false;
943 T2 = cast<EnumType>(Val&: T2)->getDecl()->getIntegerType();
944 if (T2.isNull())
945 T2 = Context.ToCtx.IntTy;
946 }
947 TC = Type::Builtin;
948 } else
949 return false;
950 }
951
952 switch (TC) {
953 case Type::Builtin:
954 // FIXME: Deal with Char_S/Char_U.
955 if (cast<BuiltinType>(Val&: T1)->getKind() != cast<BuiltinType>(Val&: T2)->getKind())
956 return false;
957 break;
958
959 case Type::Complex:
960 if (!IsStructurallyEquivalent(Context,
961 T1: cast<ComplexType>(Val&: T1)->getElementType(),
962 T2: cast<ComplexType>(Val&: T2)->getElementType()))
963 return false;
964 break;
965
966 case Type::Adjusted:
967 case Type::Decayed:
968 case Type::ArrayParameter:
969 if (!IsStructurallyEquivalent(Context,
970 T1: cast<AdjustedType>(Val&: T1)->getOriginalType(),
971 T2: cast<AdjustedType>(Val&: T2)->getOriginalType()))
972 return false;
973 break;
974
975 case Type::Pointer:
976 if (!IsStructurallyEquivalent(Context,
977 T1: cast<PointerType>(Val&: T1)->getPointeeType(),
978 T2: cast<PointerType>(Val&: T2)->getPointeeType()))
979 return false;
980 break;
981
982 case Type::BlockPointer:
983 if (!IsStructurallyEquivalent(Context,
984 T1: cast<BlockPointerType>(Val&: T1)->getPointeeType(),
985 T2: cast<BlockPointerType>(Val&: T2)->getPointeeType()))
986 return false;
987 break;
988
989 case Type::LValueReference:
990 case Type::RValueReference: {
991 const auto *Ref1 = cast<ReferenceType>(Val&: T1);
992 const auto *Ref2 = cast<ReferenceType>(Val&: T2);
993 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
994 return false;
995 if (Ref1->isInnerRef() != Ref2->isInnerRef())
996 return false;
997 if (!IsStructurallyEquivalent(Context, T1: Ref1->getPointeeTypeAsWritten(),
998 T2: Ref2->getPointeeTypeAsWritten()))
999 return false;
1000 break;
1001 }
1002
1003 case Type::MemberPointer: {
1004 const auto *MemPtr1 = cast<MemberPointerType>(Val&: T1);
1005 const auto *MemPtr2 = cast<MemberPointerType>(Val&: T2);
1006 if (!IsStructurallyEquivalent(Context, T1: MemPtr1->getPointeeType(),
1007 T2: MemPtr2->getPointeeType()))
1008 return false;
1009 if (!IsStructurallyEquivalent(Context, NNS1: MemPtr1->getQualifier(),
1010 NNS2: MemPtr2->getQualifier()))
1011 return false;
1012 CXXRecordDecl *D1 = MemPtr1->getMostRecentCXXRecordDecl(),
1013 *D2 = MemPtr2->getMostRecentCXXRecordDecl();
1014 if (D1 == D2)
1015 break;
1016 if (!D1 || !D2 || !IsStructurallyEquivalent(Context, D1, D2))
1017 return false;
1018 break;
1019 }
1020
1021 case Type::ConstantArray: {
1022 const auto *Array1 = cast<ConstantArrayType>(Val&: T1);
1023 const auto *Array2 = cast<ConstantArrayType>(Val&: T2);
1024 if (!llvm::APInt::isSameValue(I1: Array1->getSize(), I2: Array2->getSize()))
1025 return false;
1026
1027 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1028 return false;
1029 break;
1030 }
1031
1032 case Type::IncompleteArray:
1033 if (!IsArrayStructurallyEquivalent(Context, Array1: cast<ArrayType>(Val&: T1),
1034 Array2: cast<ArrayType>(Val&: T2)))
1035 return false;
1036 break;
1037
1038 case Type::VariableArray: {
1039 const auto *Array1 = cast<VariableArrayType>(Val&: T1);
1040 const auto *Array2 = cast<VariableArrayType>(Val&: T2);
1041 if (!IsStructurallyEquivalent(Context, S1: Array1->getSizeExpr(),
1042 S2: Array2->getSizeExpr()))
1043 return false;
1044
1045 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1046 return false;
1047
1048 break;
1049 }
1050
1051 case Type::DependentSizedArray: {
1052 const auto *Array1 = cast<DependentSizedArrayType>(Val&: T1);
1053 const auto *Array2 = cast<DependentSizedArrayType>(Val&: T2);
1054 if (!IsStructurallyEquivalent(Context, S1: Array1->getSizeExpr(),
1055 S2: Array2->getSizeExpr()))
1056 return false;
1057
1058 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1059 return false;
1060
1061 break;
1062 }
1063
1064 case Type::DependentAddressSpace: {
1065 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(Val&: T1);
1066 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(Val&: T2);
1067 if (!IsStructurallyEquivalent(Context, S1: DepAddressSpace1->getAddrSpaceExpr(),
1068 S2: DepAddressSpace2->getAddrSpaceExpr()))
1069 return false;
1070 if (!IsStructurallyEquivalent(Context, T1: DepAddressSpace1->getPointeeType(),
1071 T2: DepAddressSpace2->getPointeeType()))
1072 return false;
1073
1074 break;
1075 }
1076
1077 case Type::DependentSizedExtVector: {
1078 const auto *Vec1 = cast<DependentSizedExtVectorType>(Val&: T1);
1079 const auto *Vec2 = cast<DependentSizedExtVectorType>(Val&: T2);
1080 if (!IsStructurallyEquivalent(Context, S1: Vec1->getSizeExpr(),
1081 S2: Vec2->getSizeExpr()))
1082 return false;
1083 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1084 T2: Vec2->getElementType()))
1085 return false;
1086 break;
1087 }
1088
1089 case Type::DependentVector: {
1090 const auto *Vec1 = cast<DependentVectorType>(Val&: T1);
1091 const auto *Vec2 = cast<DependentVectorType>(Val&: T2);
1092 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1093 return false;
1094 if (!IsStructurallyEquivalent(Context, S1: Vec1->getSizeExpr(),
1095 S2: Vec2->getSizeExpr()))
1096 return false;
1097 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1098 T2: Vec2->getElementType()))
1099 return false;
1100 break;
1101 }
1102
1103 case Type::Vector:
1104 case Type::ExtVector: {
1105 const auto *Vec1 = cast<VectorType>(Val&: T1);
1106 const auto *Vec2 = cast<VectorType>(Val&: T2);
1107 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1108 T2: Vec2->getElementType()))
1109 return false;
1110 if (Vec1->getNumElements() != Vec2->getNumElements())
1111 return false;
1112 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1113 return false;
1114 break;
1115 }
1116
1117 case Type::DependentSizedMatrix: {
1118 const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(Val&: T1);
1119 const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(Val&: T2);
1120 // The element types, row and column expressions must be structurally
1121 // equivalent.
1122 if (!IsStructurallyEquivalent(Context, S1: Mat1->getRowExpr(),
1123 S2: Mat2->getRowExpr()) ||
1124 !IsStructurallyEquivalent(Context, S1: Mat1->getColumnExpr(),
1125 S2: Mat2->getColumnExpr()) ||
1126 !IsStructurallyEquivalent(Context, T1: Mat1->getElementType(),
1127 T2: Mat2->getElementType()))
1128 return false;
1129 break;
1130 }
1131
1132 case Type::ConstantMatrix: {
1133 const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(Val&: T1);
1134 const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(Val&: T2);
1135 // The element types must be structurally equivalent and the number of rows
1136 // and columns must match.
1137 if (!IsStructurallyEquivalent(Context, T1: Mat1->getElementType(),
1138 T2: Mat2->getElementType()) ||
1139 Mat1->getNumRows() != Mat2->getNumRows() ||
1140 Mat1->getNumColumns() != Mat2->getNumColumns())
1141 return false;
1142 break;
1143 }
1144
1145 case Type::FunctionProto: {
1146 const auto *Proto1 = cast<FunctionProtoType>(Val&: T1);
1147 const auto *Proto2 = cast<FunctionProtoType>(Val&: T2);
1148
1149 if (Proto1->getNumParams() != Proto2->getNumParams())
1150 return false;
1151 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1152 if (!IsStructurallyEquivalent(Context, T1: Proto1->getParamType(i: I),
1153 T2: Proto2->getParamType(i: I)))
1154 return false;
1155 }
1156 if (Proto1->isVariadic() != Proto2->isVariadic())
1157 return false;
1158
1159 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1160 return false;
1161
1162 // Check exceptions, this information is lost in canonical type.
1163 const auto *OrigProto1 =
1164 cast<FunctionProtoType>(Val: OrigT1.getDesugaredType(Context: Context.FromCtx));
1165 const auto *OrigProto2 =
1166 cast<FunctionProtoType>(Val: OrigT2.getDesugaredType(Context: Context.ToCtx));
1167 if (!IsEquivalentExceptionSpec(Context, Proto1: OrigProto1, Proto2: OrigProto2))
1168 return false;
1169
1170 // Fall through to check the bits common with FunctionNoProtoType.
1171 [[fallthrough]];
1172 }
1173
1174 case Type::FunctionNoProto: {
1175 const auto *Function1 = cast<FunctionType>(Val&: T1);
1176 const auto *Function2 = cast<FunctionType>(Val&: T2);
1177 if (!IsStructurallyEquivalent(Context, T1: Function1->getReturnType(),
1178 T2: Function2->getReturnType()))
1179 return false;
1180 if (!IsStructurallyEquivalent(Context, EI1: Function1->getExtInfo(),
1181 EI2: Function2->getExtInfo()))
1182 return false;
1183 break;
1184 }
1185
1186 case Type::UnresolvedUsing:
1187 if (!IsStructurallyEquivalent(Context,
1188 D1: cast<UnresolvedUsingType>(Val&: T1)->getDecl(),
1189 D2: cast<UnresolvedUsingType>(Val&: T2)->getDecl()))
1190 return false;
1191 break;
1192
1193 case Type::Attributed:
1194 if (!IsStructurallyEquivalent(Context,
1195 T1: cast<AttributedType>(Val&: T1)->getModifiedType(),
1196 T2: cast<AttributedType>(Val&: T2)->getModifiedType()))
1197 return false;
1198 if (!IsStructurallyEquivalent(
1199 Context, T1: cast<AttributedType>(Val&: T1)->getEquivalentType(),
1200 T2: cast<AttributedType>(Val&: T2)->getEquivalentType()))
1201 return false;
1202 break;
1203
1204 case Type::CountAttributed:
1205 if (!IsStructurallyEquivalent(Context,
1206 T1: cast<CountAttributedType>(Val&: T1)->desugar(),
1207 T2: cast<CountAttributedType>(Val&: T2)->desugar()))
1208 return false;
1209 break;
1210
1211 case Type::BTFTagAttributed:
1212 if (!IsStructurallyEquivalent(
1213 Context, T1: cast<BTFTagAttributedType>(Val&: T1)->getWrappedType(),
1214 T2: cast<BTFTagAttributedType>(Val&: T2)->getWrappedType()))
1215 return false;
1216 break;
1217
1218 case Type::OverflowBehavior:
1219 if (!IsStructurallyEquivalent(
1220 Context, T1: cast<OverflowBehaviorType>(Val&: T1)->getUnderlyingType(),
1221 T2: cast<OverflowBehaviorType>(Val&: T2)->getUnderlyingType()))
1222 return false;
1223 break;
1224
1225 case Type::HLSLAttributedResource:
1226 if (!IsStructurallyEquivalent(
1227 Context, T1: cast<HLSLAttributedResourceType>(Val&: T1)->getWrappedType(),
1228 T2: cast<HLSLAttributedResourceType>(Val&: T2)->getWrappedType()))
1229 return false;
1230 if (!IsStructurallyEquivalent(
1231 Context, T1: cast<HLSLAttributedResourceType>(Val&: T1)->getContainedType(),
1232 T2: cast<HLSLAttributedResourceType>(Val&: T2)->getContainedType()))
1233 return false;
1234 if (cast<HLSLAttributedResourceType>(Val&: T1)->getAttrs() !=
1235 cast<HLSLAttributedResourceType>(Val&: T2)->getAttrs())
1236 return false;
1237 break;
1238
1239 case Type::HLSLInlineSpirv:
1240 if (cast<HLSLInlineSpirvType>(Val&: T1)->getOpcode() !=
1241 cast<HLSLInlineSpirvType>(Val&: T2)->getOpcode() ||
1242 cast<HLSLInlineSpirvType>(Val&: T1)->getSize() !=
1243 cast<HLSLInlineSpirvType>(Val&: T2)->getSize() ||
1244 cast<HLSLInlineSpirvType>(Val&: T1)->getAlignment() !=
1245 cast<HLSLInlineSpirvType>(Val&: T2)->getAlignment())
1246 return false;
1247 for (size_t I = 0; I < cast<HLSLInlineSpirvType>(Val&: T1)->getOperands().size();
1248 I++) {
1249 if (cast<HLSLInlineSpirvType>(Val&: T1)->getOperands()[I] !=
1250 cast<HLSLInlineSpirvType>(Val&: T2)->getOperands()[I]) {
1251 return false;
1252 }
1253 }
1254 break;
1255
1256 case Type::Paren:
1257 if (!IsStructurallyEquivalent(Context, T1: cast<ParenType>(Val&: T1)->getInnerType(),
1258 T2: cast<ParenType>(Val&: T2)->getInnerType()))
1259 return false;
1260 break;
1261
1262 case Type::MacroQualified:
1263 if (!IsStructurallyEquivalent(
1264 Context, T1: cast<MacroQualifiedType>(Val&: T1)->getUnderlyingType(),
1265 T2: cast<MacroQualifiedType>(Val&: T2)->getUnderlyingType()))
1266 return false;
1267 break;
1268
1269 case Type::Using: {
1270 auto *U1 = cast<UsingType>(Val&: T1), *U2 = cast<UsingType>(Val&: T2);
1271 if (U1->getKeyword() != U2->getKeyword())
1272 return false;
1273 if (!IsStructurallyEquivalent(Context, NNS1: U1->getQualifier(),
1274 NNS2: U2->getQualifier()))
1275 return false;
1276 if (!IsStructurallyEquivalent(Context, D1: U1->getDecl(), D2: U2->getDecl()))
1277 return false;
1278 if (!IsStructurallyEquivalent(Context, T1: U1->desugar(), T2: U2->desugar()))
1279 return false;
1280 break;
1281 }
1282 case Type::Typedef: {
1283 auto *U1 = cast<TypedefType>(Val&: T1), *U2 = cast<TypedefType>(Val&: T2);
1284 if (U1->getKeyword() != U2->getKeyword())
1285 return false;
1286 if (!IsStructurallyEquivalent(Context, NNS1: U1->getQualifier(),
1287 NNS2: U2->getQualifier()))
1288 return false;
1289 if (!IsStructurallyEquivalent(Context, D1: U1->getDecl(), D2: U2->getDecl()))
1290 return false;
1291 if (U1->typeMatchesDecl() != U2->typeMatchesDecl())
1292 return false;
1293 if (!U1->typeMatchesDecl() &&
1294 !IsStructurallyEquivalent(Context, T1: U1->desugar(), T2: U2->desugar()))
1295 return false;
1296 break;
1297 }
1298
1299 case Type::TypeOfExpr:
1300 if (!IsStructurallyEquivalent(
1301 Context, S1: cast<TypeOfExprType>(Val&: T1)->getUnderlyingExpr(),
1302 S2: cast<TypeOfExprType>(Val&: T2)->getUnderlyingExpr()))
1303 return false;
1304 break;
1305
1306 case Type::TypeOf:
1307 if (!IsStructurallyEquivalent(Context,
1308 T1: cast<TypeOfType>(Val&: T1)->getUnmodifiedType(),
1309 T2: cast<TypeOfType>(Val&: T2)->getUnmodifiedType()))
1310 return false;
1311 break;
1312
1313 case Type::UnaryTransform:
1314 if (!IsStructurallyEquivalent(
1315 Context, T1: cast<UnaryTransformType>(Val&: T1)->getUnderlyingType(),
1316 T2: cast<UnaryTransformType>(Val&: T2)->getUnderlyingType()))
1317 return false;
1318 break;
1319
1320 case Type::Decltype:
1321 if (!IsStructurallyEquivalent(Context,
1322 S1: cast<DecltypeType>(Val&: T1)->getUnderlyingExpr(),
1323 S2: cast<DecltypeType>(Val&: T2)->getUnderlyingExpr()))
1324 return false;
1325 break;
1326
1327 case Type::Auto: {
1328 auto *Auto1 = cast<AutoType>(Val&: T1);
1329 auto *Auto2 = cast<AutoType>(Val&: T2);
1330 if (!IsStructurallyEquivalent(Context, T1: Auto1->getDeducedType(),
1331 T2: Auto2->getDeducedType()))
1332 return false;
1333 if (Auto1->isConstrained() != Auto2->isConstrained())
1334 return false;
1335 if (Auto1->isConstrained()) {
1336 if (Auto1->getTypeConstraintConcept() !=
1337 Auto2->getTypeConstraintConcept())
1338 return false;
1339 if (!IsStructurallyEquivalent(Context,
1340 Args1: Auto1->getTypeConstraintArguments(),
1341 Args2: Auto2->getTypeConstraintArguments()))
1342 return false;
1343 }
1344 break;
1345 }
1346
1347 case Type::DeducedTemplateSpecialization: {
1348 const auto *DT1 = cast<DeducedTemplateSpecializationType>(Val&: T1);
1349 const auto *DT2 = cast<DeducedTemplateSpecializationType>(Val&: T2);
1350 if (!IsStructurallyEquivalent(Context, N1: DT1->getTemplateName(),
1351 N2: DT2->getTemplateName()))
1352 return false;
1353 if (!IsStructurallyEquivalent(Context, T1: DT1->getDeducedType(),
1354 T2: DT2->getDeducedType()))
1355 return false;
1356 break;
1357 }
1358
1359 case Type::Record:
1360 case Type::Enum:
1361 case Type::InjectedClassName: {
1362 const auto *TT1 = cast<TagType>(Val&: T1), *TT2 = cast<TagType>(Val&: T2);
1363 if (TT1->getKeyword() != TT2->getKeyword())
1364 return false;
1365 if (TT1->isTagOwned() != TT2->isTagOwned())
1366 return false;
1367 if (!IsStructurallyEquivalent(Context, NNS1: TT1->getQualifier(),
1368 NNS2: TT2->getQualifier()))
1369 return false;
1370 if (!IsStructurallyEquivalent(Context, D1: TT1->getDecl(), D2: TT2->getDecl()))
1371 return false;
1372 break;
1373 }
1374
1375 case Type::TemplateTypeParm: {
1376 const auto *Parm1 = cast<TemplateTypeParmType>(Val&: T1);
1377 const auto *Parm2 = cast<TemplateTypeParmType>(Val&: T2);
1378 if (!Context.IgnoreTemplateParmDepth &&
1379 Parm1->getDepth() != Parm2->getDepth())
1380 return false;
1381 if (Parm1->getIndex() != Parm2->getIndex())
1382 return false;
1383 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1384 return false;
1385
1386 // Names of template type parameters are never significant.
1387 break;
1388 }
1389
1390 case Type::SubstTemplateTypeParm: {
1391 const auto *Subst1 = cast<SubstTemplateTypeParmType>(Val&: T1);
1392 const auto *Subst2 = cast<SubstTemplateTypeParmType>(Val&: T2);
1393 if (!IsStructurallyEquivalent(Context, T1: Subst1->getReplacementType(),
1394 T2: Subst2->getReplacementType()))
1395 return false;
1396 if (!IsStructurallyEquivalent(Context, D1: Subst1->getAssociatedDecl(),
1397 D2: Subst2->getAssociatedDecl()))
1398 return false;
1399 if (Subst1->getIndex() != Subst2->getIndex())
1400 return false;
1401 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1402 return false;
1403 break;
1404 }
1405
1406 case Type::SubstBuiltinTemplatePack: {
1407 const auto *Subst1 = cast<SubstBuiltinTemplatePackType>(Val&: T1);
1408 const auto *Subst2 = cast<SubstBuiltinTemplatePackType>(Val&: T2);
1409 if (!IsStructurallyEquivalent(Context, Arg1: Subst1->getArgumentPack(),
1410 Arg2: Subst2->getArgumentPack()))
1411 return false;
1412 break;
1413 }
1414 case Type::SubstTemplateTypeParmPack: {
1415 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(Val&: T1);
1416 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(Val&: T2);
1417 if (!IsStructurallyEquivalent(Context, D1: Subst1->getAssociatedDecl(),
1418 D2: Subst2->getAssociatedDecl()))
1419 return false;
1420 if (Subst1->getIndex() != Subst2->getIndex())
1421 return false;
1422 if (!IsStructurallyEquivalent(Context, Arg1: Subst1->getArgumentPack(),
1423 Arg2: Subst2->getArgumentPack()))
1424 return false;
1425 break;
1426 }
1427
1428 case Type::TemplateSpecialization: {
1429 const auto *Spec1 = cast<TemplateSpecializationType>(Val&: T1);
1430 const auto *Spec2 = cast<TemplateSpecializationType>(Val&: T2);
1431 if (!IsStructurallyEquivalent(Context, N1: Spec1->getTemplateName(),
1432 N2: Spec2->getTemplateName()))
1433 return false;
1434 if (!IsStructurallyEquivalent(Context, Args1: Spec1->template_arguments(),
1435 Args2: Spec2->template_arguments()))
1436 return false;
1437 break;
1438 }
1439
1440 case Type::DependentName: {
1441 const auto *Typename1 = cast<DependentNameType>(Val&: T1);
1442 const auto *Typename2 = cast<DependentNameType>(Val&: T2);
1443 if (!IsStructurallyEquivalent(Context, NNS1: Typename1->getQualifier(),
1444 NNS2: Typename2->getQualifier()))
1445 return false;
1446 if (!IsStructurallyEquivalent(Name1: Typename1->getIdentifier(),
1447 Name2: Typename2->getIdentifier()))
1448 return false;
1449
1450 break;
1451 }
1452
1453 case Type::PackExpansion:
1454 if (!IsStructurallyEquivalent(Context,
1455 T1: cast<PackExpansionType>(Val&: T1)->getPattern(),
1456 T2: cast<PackExpansionType>(Val&: T2)->getPattern()))
1457 return false;
1458 break;
1459
1460 case Type::PackIndexing:
1461 if (!IsStructurallyEquivalent(Context,
1462 T1: cast<PackIndexingType>(Val&: T1)->getPattern(),
1463 T2: cast<PackIndexingType>(Val&: T2)->getPattern()))
1464 if (!IsStructurallyEquivalent(Context,
1465 S1: cast<PackIndexingType>(Val&: T1)->getIndexExpr(),
1466 S2: cast<PackIndexingType>(Val&: T2)->getIndexExpr()))
1467 return false;
1468 break;
1469
1470 case Type::ObjCInterface: {
1471 const auto *Iface1 = cast<ObjCInterfaceType>(Val&: T1);
1472 const auto *Iface2 = cast<ObjCInterfaceType>(Val&: T2);
1473 if (!IsStructurallyEquivalent(Context, D1: Iface1->getDecl(),
1474 D2: Iface2->getDecl()))
1475 return false;
1476 break;
1477 }
1478
1479 case Type::ObjCTypeParam: {
1480 const auto *Obj1 = cast<ObjCTypeParamType>(Val&: T1);
1481 const auto *Obj2 = cast<ObjCTypeParamType>(Val&: T2);
1482 if (!IsStructurallyEquivalent(Context, D1: Obj1->getDecl(), D2: Obj2->getDecl()))
1483 return false;
1484
1485 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1486 return false;
1487 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1488 if (!IsStructurallyEquivalent(Context, D1: Obj1->getProtocol(I),
1489 D2: Obj2->getProtocol(I)))
1490 return false;
1491 }
1492 break;
1493 }
1494
1495 case Type::ObjCObject: {
1496 const auto *Obj1 = cast<ObjCObjectType>(Val&: T1);
1497 const auto *Obj2 = cast<ObjCObjectType>(Val&: T2);
1498 if (!IsStructurallyEquivalent(Context, T1: Obj1->getBaseType(),
1499 T2: Obj2->getBaseType()))
1500 return false;
1501 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1502 return false;
1503 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1504 if (!IsStructurallyEquivalent(Context, D1: Obj1->getProtocol(I),
1505 D2: Obj2->getProtocol(I)))
1506 return false;
1507 }
1508 break;
1509 }
1510
1511 case Type::ObjCObjectPointer: {
1512 const auto *Ptr1 = cast<ObjCObjectPointerType>(Val&: T1);
1513 const auto *Ptr2 = cast<ObjCObjectPointerType>(Val&: T2);
1514 if (!IsStructurallyEquivalent(Context, T1: Ptr1->getPointeeType(),
1515 T2: Ptr2->getPointeeType()))
1516 return false;
1517 break;
1518 }
1519
1520 case Type::Atomic:
1521 if (!IsStructurallyEquivalent(Context, T1: cast<AtomicType>(Val&: T1)->getValueType(),
1522 T2: cast<AtomicType>(Val&: T2)->getValueType()))
1523 return false;
1524 break;
1525
1526 case Type::Pipe:
1527 if (!IsStructurallyEquivalent(Context, T1: cast<PipeType>(Val&: T1)->getElementType(),
1528 T2: cast<PipeType>(Val&: T2)->getElementType()))
1529 return false;
1530 break;
1531 case Type::BitInt: {
1532 const auto *Int1 = cast<BitIntType>(Val&: T1);
1533 const auto *Int2 = cast<BitIntType>(Val&: T2);
1534
1535 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1536 Int1->getNumBits() != Int2->getNumBits())
1537 return false;
1538 break;
1539 }
1540 case Type::DependentBitInt: {
1541 const auto *Int1 = cast<DependentBitIntType>(Val&: T1);
1542 const auto *Int2 = cast<DependentBitIntType>(Val&: T2);
1543
1544 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1545 !IsStructurallyEquivalent(Context, S1: Int1->getNumBitsExpr(),
1546 S2: Int2->getNumBitsExpr()))
1547 return false;
1548 break;
1549 }
1550 case Type::PredefinedSugar: {
1551 const auto *TP1 = cast<PredefinedSugarType>(Val&: T1);
1552 const auto *TP2 = cast<PredefinedSugarType>(Val&: T2);
1553 if (TP1->getKind() != TP2->getKind())
1554 return false;
1555 break;
1556 }
1557 } // end switch
1558
1559 return true;
1560}
1561
1562static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1563 QualType T1, QualType T2) {
1564 return ASTStructuralEquivalence::isEquivalent(Context, T1, T2);
1565}
1566
1567static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1568 VarDecl *D1, VarDecl *D2) {
1569 IdentifierInfo *Name1 = D1->getIdentifier();
1570 IdentifierInfo *Name2 = D2->getIdentifier();
1571 if (!::IsStructurallyEquivalent(Name1, Name2))
1572 return false;
1573
1574 if (!IsStructurallyEquivalent(Context, T1: D1->getType(), T2: D2->getType()))
1575 return false;
1576
1577 // Compare storage class and initializer only if none or both are a
1578 // definition. Like a forward-declaration matches a class definition, variable
1579 // declarations that are not definitions should match with the definitions.
1580 if (D1->isThisDeclarationADefinition() != D2->isThisDeclarationADefinition())
1581 return true;
1582
1583 if (D1->getStorageClass() != D2->getStorageClass())
1584 return false;
1585
1586 return IsStructurallyEquivalent(Context, S1: D1->getInit(), S2: D2->getInit());
1587}
1588
1589static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1590 FieldDecl *Field1, FieldDecl *Field2,
1591 QualType Owner2Type) {
1592 const auto *Owner2 = cast<Decl>(Val: Field2->getDeclContext());
1593
1594 // In C23 mode, check for structural equivalence of attributes on the fields.
1595 // FIXME: Should this happen in C++ as well?
1596 if (Context.LangOpts.C23 &&
1597 !CheckStructurallyEquivalentAttributes(Context, D1: Field1, D2: Field2, PrimaryDecl: Owner2))
1598 return false;
1599
1600 // For anonymous structs/unions, match up the anonymous struct/union type
1601 // declarations directly, so that we don't go off searching for anonymous
1602 // types
1603 if (Field1->isAnonymousStructOrUnion() &&
1604 Field2->isAnonymousStructOrUnion()) {
1605 RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1606 RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1607 return IsStructurallyEquivalent(Context, D1, D2);
1608 }
1609
1610 // Check for equivalent field names.
1611 IdentifierInfo *Name1 = Field1->getIdentifier();
1612 IdentifierInfo *Name2 = Field2->getIdentifier();
1613 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1614 if (Context.Complain) {
1615 Context.Diag2(
1616 Loc: Owner2->getLocation(),
1617 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1618 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1619 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field_name)
1620 << Field2->getDeclName();
1621 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field_name)
1622 << Field1->getDeclName();
1623 }
1624 return false;
1625 }
1626
1627 if (!IsStructurallyEquivalent(Context, T1: Field1->getType(),
1628 T2: Field2->getType())) {
1629 if (Context.Complain) {
1630 Context.Diag2(
1631 Loc: Owner2->getLocation(),
1632 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1633 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1634 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field)
1635 << Field2->getDeclName() << Field2->getType();
1636 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field)
1637 << Field1->getDeclName() << Field1->getType();
1638 }
1639 return false;
1640 }
1641
1642 if ((Field1->isBitField() || Field2->isBitField()) &&
1643 !IsStructurallyEquivalent(Context, S1: Field1->getBitWidth(),
1644 S2: Field2->getBitWidth())) {
1645 // Two bit-fields can be structurally unequivalent but still be okay for
1646 // the purposes of C where they simply need to have the same values, not
1647 // the same token sequences.
1648 bool Diagnose = true;
1649 if (Context.LangOpts.C23 && Field1->isBitField() && Field2->isBitField())
1650 Diagnose = Field1->getBitWidthValue() != Field2->getBitWidthValue();
1651
1652 if (Diagnose && Context.Complain) {
1653 auto DiagNote = [&](const FieldDecl *FD,
1654 DiagnosticBuilder (
1655 StructuralEquivalenceContext::*Diag)(
1656 SourceLocation, unsigned)) {
1657 if (FD->isBitField()) {
1658 (Context.*Diag)(FD->getLocation(), diag::note_odr_field_bit_width)
1659 << FD->getDeclName() << FD->getBitWidthValue();
1660 } else {
1661 (Context.*Diag)(FD->getLocation(), diag::note_odr_field_not_bit_field)
1662 << FD->getDeclName();
1663 }
1664 };
1665
1666 Context.Diag2(
1667 Loc: Owner2->getLocation(),
1668 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1669 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1670 DiagNote(Field2, &StructuralEquivalenceContext::Diag2);
1671 DiagNote(Field1, &StructuralEquivalenceContext::Diag1);
1672 }
1673 return false;
1674 }
1675
1676 return true;
1677}
1678
1679/// Determine structural equivalence of two fields.
1680static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1681 FieldDecl *Field1, FieldDecl *Field2) {
1682 const auto *Owner2 = cast<RecordDecl>(Val: Field2->getDeclContext());
1683 return IsStructurallyEquivalent(Context, Field1, Field2,
1684 Owner2Type: Context.ToCtx.getCanonicalTagType(TD: Owner2));
1685}
1686
1687/// Determine structural equivalence of two IndirectFields.
1688static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1689 IndirectFieldDecl *ID1,
1690 IndirectFieldDecl *ID2) {
1691 return IsStructurallyEquivalent(Context, Field1: ID1->getAnonField(),
1692 Field2: ID2->getAnonField());
1693}
1694
1695/// Determine structural equivalence of two methods.
1696static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1697 CXXMethodDecl *Method1,
1698 CXXMethodDecl *Method2) {
1699 if (!Method1 && !Method2)
1700 return true;
1701 if (!Method1 || !Method2)
1702 return false;
1703
1704 bool PropertiesEqual =
1705 Method1->getDeclKind() == Method2->getDeclKind() &&
1706 Method1->getRefQualifier() == Method2->getRefQualifier() &&
1707 Method1->getAccess() == Method2->getAccess() &&
1708 Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1709 Method1->isStatic() == Method2->isStatic() &&
1710 Method1->isImplicitObjectMemberFunction() ==
1711 Method2->isImplicitObjectMemberFunction() &&
1712 Method1->isConst() == Method2->isConst() &&
1713 Method1->isVolatile() == Method2->isVolatile() &&
1714 Method1->isVirtual() == Method2->isVirtual() &&
1715 Method1->isPureVirtual() == Method2->isPureVirtual() &&
1716 Method1->isDefaulted() == Method2->isDefaulted() &&
1717 Method1->isDeleted() == Method2->isDeleted();
1718 if (!PropertiesEqual)
1719 return false;
1720 // FIXME: Check for 'final'.
1721
1722 if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Val: Method1)) {
1723 auto *Constructor2 = cast<CXXConstructorDecl>(Val: Method2);
1724 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1725 Other: Constructor2->getExplicitSpecifier()))
1726 return false;
1727 }
1728
1729 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Val: Method1)) {
1730 auto *Conversion2 = cast<CXXConversionDecl>(Val: Method2);
1731 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1732 Other: Conversion2->getExplicitSpecifier()))
1733 return false;
1734 if (!IsStructurallyEquivalent(Context, T1: Conversion1->getConversionType(),
1735 T2: Conversion2->getConversionType()))
1736 return false;
1737 }
1738
1739 const IdentifierInfo *Name1 = Method1->getIdentifier();
1740 const IdentifierInfo *Name2 = Method2->getIdentifier();
1741 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1742 return false;
1743 // TODO: Names do not match, add warning like at check for FieldDecl.
1744 }
1745
1746 // Check the prototypes.
1747 if (!::IsStructurallyEquivalent(Context,
1748 T1: Method1->getType(), T2: Method2->getType()))
1749 return false;
1750
1751 return true;
1752}
1753
1754/// Determine structural equivalence of two lambda classes.
1755static bool
1756IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context,
1757 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1758 assert(D1->isLambda() && D2->isLambda() &&
1759 "Must be called on lambda classes");
1760 if (!IsStructurallyEquivalent(Context, Method1: D1->getLambdaCallOperator(),
1761 Method2: D2->getLambdaCallOperator()))
1762 return false;
1763
1764 return true;
1765}
1766
1767/// Determine if context of a class is equivalent.
1768static bool
1769IsRecordContextStructurallyEquivalent(StructuralEquivalenceContext &Context,
1770 RecordDecl *D1, RecordDecl *D2) {
1771 // The context should be completely equal, including anonymous and inline
1772 // namespaces.
1773 // We compare objects as part of full translation units, not subtrees of
1774 // translation units.
1775 DeclContext *DC1 = D1->getDeclContext()->getNonTransparentContext();
1776 DeclContext *DC2 = D2->getDeclContext()->getNonTransparentContext();
1777 while (true) {
1778 // Special case: We allow a struct defined in a function to be equivalent
1779 // with a similar struct defined outside of a function.
1780 if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1781 (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1782 return true;
1783
1784 if (DC1->getDeclKind() != DC2->getDeclKind())
1785 return false;
1786 if (DC1->isTranslationUnit())
1787 break;
1788 if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1789 return false;
1790 if (const auto *ND1 = dyn_cast<NamedDecl>(Val: DC1)) {
1791 const auto *ND2 = cast<NamedDecl>(Val: DC2);
1792 if (!DC1->isInlineNamespace() &&
1793 !IsStructurallyEquivalent(Name1: ND1->getIdentifier(), Name2: ND2->getIdentifier()))
1794 return false;
1795 }
1796
1797 if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC1)) {
1798 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC2);
1799 if (!IsStructurallyEquivalent(Context, D1: D1Spec, D2: D2Spec))
1800 return false;
1801 }
1802
1803 DC1 = DC1->getParent()->getNonTransparentContext();
1804 DC2 = DC2->getParent()->getNonTransparentContext();
1805 }
1806
1807 return true;
1808}
1809
1810static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1811 auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1812 if (const IdentifierInfo *Name = D.getIdentifier())
1813 return Name;
1814 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1815 return TypedefName->getIdentifier();
1816 return nullptr;
1817 };
1818 return IsStructurallyEquivalent(Name1: GetName(D1), Name2: GetName(D2));
1819}
1820
1821/// Determine structural equivalence of two records.
1822static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1823 RecordDecl *D1, RecordDecl *D2) {
1824 // C23 6.2.7p1:
1825 // ... Moreover, two complete structure, union, or enumerated types declared
1826 // with the same tag are compatible if members satisfy the following
1827 // requirements:
1828 // - there shall be a one-to-one correspondence between their members such
1829 // that each pair of corresponding members are declared with compatible
1830 // types;
1831 // - if one member of the pair is declared with an alignment specifier, the
1832 // other is declared with an equivalent alignment specifier;
1833 // - and, if one member of the pair is declared with a name, the other is
1834 // declared with the same name.
1835 // For two structures, corresponding members shall be declared in the same
1836 // order. For two unions declared in the same translation unit, corresponding
1837 // members shall be declared in the same order. For two structures or unions,
1838 // corresponding bit-fields shall have the same widths. ... For determining
1839 // type compatibility, anonymous structures and unions are considered a
1840 // regular member of the containing structure or union type, and the type of
1841 // an anonymous structure or union is considered compatible to the type of
1842 // another anonymous structure or union, respectively, if their members
1843 // fulfill the preceding requirements. ... Otherwise, the structure, union,
1844 // or enumerated types are incompatible.
1845 if (!NameIsStructurallyEquivalent(D1: *D1, D2: *D2))
1846 return false;
1847
1848 if (D1->isUnion() != D2->isUnion()) {
1849 if (Context.Complain) {
1850 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
1851 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1852 << Context.ToCtx.getCanonicalTagType(TD: D2)
1853 << (&Context.FromCtx != &Context.ToCtx);
1854 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_tag_kind_here)
1855 << D1->getDeclName() << (unsigned)D1->getTagKind();
1856 }
1857 return false;
1858 }
1859
1860 if (!D1->getDeclName() && !D2->getDeclName()) {
1861 // If both anonymous structs/unions are in a record context, make sure
1862 // they occur in the same location in the context records.
1863 if (UnsignedOrNone Index1 =
1864 StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(Anon: D1)) {
1865 if (UnsignedOrNone Index2 =
1866 StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
1867 Anon: D2)) {
1868 if (*Index1 != *Index2)
1869 return false;
1870 }
1871 }
1872 }
1873
1874 // If the records occur in different context (namespace), these should be
1875 // different. This is specially important if the definition of one or both
1876 // records is missing. In C23, different contexts do not make for a different
1877 // structural type (a local struct definition can be a valid redefinition of
1878 // a file scope struct definition).
1879 if (!Context.LangOpts.C23 &&
1880 !IsRecordContextStructurallyEquivalent(Context, D1, D2))
1881 return false;
1882
1883 // If both declarations are class template specializations, we know
1884 // the ODR applies, so check the template and template arguments.
1885 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(Val: D1);
1886 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(Val: D2);
1887 if (Spec1 && Spec2) {
1888 // Check that the specialized templates are the same.
1889 if (!IsStructurallyEquivalent(Context, D1: Spec1->getSpecializedTemplate(),
1890 D2: Spec2->getSpecializedTemplate()))
1891 return false;
1892
1893 // Check that the template arguments are the same.
1894 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1895 return false;
1896
1897 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1898 if (!IsStructurallyEquivalent(Context, Arg1: Spec1->getTemplateArgs().get(Idx: I),
1899 Arg2: Spec2->getTemplateArgs().get(Idx: I)))
1900 return false;
1901 }
1902 // If one is a class template specialization and the other is not, these
1903 // structures are different.
1904 else if (Spec1 || Spec2)
1905 return false;
1906
1907 // Compare the definitions of these two records. If either or both are
1908 // incomplete (i.e. it is a forward decl), we assume that they are
1909 // equivalent. except in C23 mode.
1910 D1 = D1->getDefinition();
1911 D2 = D2->getDefinition();
1912 if (!D1 || !D2)
1913 return !Context.LangOpts.C23;
1914
1915 // In C23 mode, check for structural equivalence of attributes on the record
1916 // itself. FIXME: Should this happen in C++ as well?
1917 if (Context.LangOpts.C23 &&
1918 !CheckStructurallyEquivalentAttributes(Context, D1, D2))
1919 return false;
1920
1921 // If any of the records has external storage and we do a minimal check (or
1922 // AST import) we assume they are equivalent. (If we didn't have this
1923 // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1924 // another AST import which in turn would call the structural equivalency
1925 // check again and finally we'd have an improper result.)
1926 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1927 if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
1928 return true;
1929
1930 // If one definition is currently being defined, we do not compare for
1931 // equality and we assume that the decls are equal.
1932 if (D1->isBeingDefined() || D2->isBeingDefined())
1933 return true;
1934
1935 if (auto *D1CXX = dyn_cast<CXXRecordDecl>(Val: D1)) {
1936 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(Val: D2)) {
1937 if (D1CXX->hasExternalLexicalStorage() &&
1938 !D1CXX->isCompleteDefinition()) {
1939 D1CXX->getASTContext().getExternalSource()->CompleteType(Tag: D1CXX);
1940 }
1941
1942 if (D1CXX->isLambda() != D2CXX->isLambda())
1943 return false;
1944 if (D1CXX->isLambda()) {
1945 if (!IsStructurallyEquivalentLambdas(Context, D1: D1CXX, D2: D2CXX))
1946 return false;
1947 }
1948
1949 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1950 if (Context.Complain) {
1951 Context.Diag2(Loc: D2->getLocation(),
1952 DiagID: Context.getApplicableDiagnostic(
1953 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1954 << Context.ToCtx.getCanonicalTagType(TD: D2)
1955 << (&Context.FromCtx != &Context.ToCtx);
1956 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_number_of_bases)
1957 << D2CXX->getNumBases();
1958 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_number_of_bases)
1959 << D1CXX->getNumBases();
1960 }
1961 return false;
1962 }
1963
1964 // Check the base classes.
1965 for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1966 BaseEnd1 = D1CXX->bases_end(),
1967 Base2 = D2CXX->bases_begin();
1968 Base1 != BaseEnd1; ++Base1, ++Base2) {
1969 if (!IsStructurallyEquivalent(Context, T1: Base1->getType(),
1970 T2: Base2->getType())) {
1971 if (Context.Complain) {
1972 Context.Diag2(Loc: D2->getLocation(),
1973 DiagID: Context.getApplicableDiagnostic(
1974 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1975 << Context.ToCtx.getCanonicalTagType(TD: D2)
1976 << (&Context.FromCtx != &Context.ToCtx);
1977 Context.Diag2(Loc: Base2->getBeginLoc(), DiagID: diag::note_odr_base)
1978 << Base2->getType() << Base2->getSourceRange();
1979 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
1980 << Base1->getType() << Base1->getSourceRange();
1981 }
1982 return false;
1983 }
1984
1985 // Check virtual vs. non-virtual inheritance mismatch.
1986 if (Base1->isVirtual() != Base2->isVirtual()) {
1987 if (Context.Complain) {
1988 Context.Diag2(Loc: D2->getLocation(),
1989 DiagID: Context.getApplicableDiagnostic(
1990 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1991 << Context.ToCtx.getCanonicalTagType(TD: D2)
1992 << (&Context.FromCtx != &Context.ToCtx);
1993 Context.Diag2(Loc: Base2->getBeginLoc(), DiagID: diag::note_odr_virtual_base)
1994 << Base2->isVirtual() << Base2->getSourceRange();
1995 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
1996 << Base1->isVirtual() << Base1->getSourceRange();
1997 }
1998 return false;
1999 }
2000 }
2001
2002 // Check the friends for consistency.
2003 CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
2004 Friend2End = D2CXX->friend_end();
2005 for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
2006 Friend1End = D1CXX->friend_end();
2007 Friend1 != Friend1End; ++Friend1, ++Friend2) {
2008 if (Friend2 == Friend2End) {
2009 if (Context.Complain) {
2010 Context.Diag2(Loc: D2->getLocation(),
2011 DiagID: Context.getApplicableDiagnostic(
2012 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2013 << Context.ToCtx.getCanonicalTagType(TD: D2CXX)
2014 << (&Context.FromCtx != &Context.ToCtx);
2015 Context.Diag1(Loc: (*Friend1)->getFriendLoc(), DiagID: diag::note_odr_friend);
2016 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_friend);
2017 }
2018 return false;
2019 }
2020
2021 if (!IsStructurallyEquivalent(Context, D1: *Friend1, D2: *Friend2)) {
2022 if (Context.Complain) {
2023 Context.Diag2(Loc: D2->getLocation(),
2024 DiagID: Context.getApplicableDiagnostic(
2025 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2026 << Context.ToCtx.getCanonicalTagType(TD: D2CXX)
2027 << (&Context.FromCtx != &Context.ToCtx);
2028 Context.Diag1(Loc: (*Friend1)->getFriendLoc(), DiagID: diag::note_odr_friend);
2029 Context.Diag2(Loc: (*Friend2)->getFriendLoc(), DiagID: diag::note_odr_friend);
2030 }
2031 return false;
2032 }
2033 }
2034
2035 if (Friend2 != Friend2End) {
2036 if (Context.Complain) {
2037 Context.Diag2(Loc: D2->getLocation(),
2038 DiagID: Context.getApplicableDiagnostic(
2039 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2040 << Context.ToCtx.getCanonicalTagType(TD: D2)
2041 << (&Context.FromCtx != &Context.ToCtx);
2042 Context.Diag2(Loc: (*Friend2)->getFriendLoc(), DiagID: diag::note_odr_friend);
2043 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_friend);
2044 }
2045 return false;
2046 }
2047 } else if (D1CXX->getNumBases() > 0) {
2048 if (Context.Complain) {
2049 Context.Diag2(Loc: D2->getLocation(),
2050 DiagID: Context.getApplicableDiagnostic(
2051 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2052 << Context.ToCtx.getCanonicalTagType(TD: D2)
2053 << (&Context.FromCtx != &Context.ToCtx);
2054 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
2055 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
2056 << Base1->getType() << Base1->getSourceRange();
2057 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_base);
2058 }
2059 return false;
2060 }
2061 }
2062
2063 // Check the fields for consistency.
2064 CanQualType D2Type = Context.ToCtx.getCanonicalTagType(TD: D2);
2065 RecordDecl::field_iterator Field2 = D2->field_begin(),
2066 Field2End = D2->field_end();
2067 for (RecordDecl::field_iterator Field1 = D1->field_begin(),
2068 Field1End = D1->field_end();
2069 Field1 != Field1End; ++Field1, ++Field2) {
2070 if (Field2 == Field2End) {
2071 if (Context.Complain) {
2072 Context.Diag2(Loc: D2->getLocation(),
2073 DiagID: Context.getApplicableDiagnostic(
2074 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2075 << Context.ToCtx.getCanonicalTagType(TD: D2)
2076 << (&Context.FromCtx != &Context.ToCtx);
2077 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field)
2078 << Field1->getDeclName() << Field1->getType();
2079 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_field);
2080 }
2081 return false;
2082 }
2083
2084 if (!IsStructurallyEquivalent(Context, Field1: *Field1, Field2: *Field2, Owner2Type: D2Type))
2085 return false;
2086 }
2087
2088 if (Field2 != Field2End) {
2089 if (Context.Complain) {
2090 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
2091 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2092 << Context.ToCtx.getCanonicalTagType(TD: D2)
2093 << (&Context.FromCtx != &Context.ToCtx);
2094 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field)
2095 << Field2->getDeclName() << Field2->getType();
2096 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_field);
2097 }
2098 return false;
2099 }
2100
2101 return true;
2102}
2103
2104static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2105 EnumConstantDecl *D1,
2106 EnumConstantDecl *D2) {
2107 const llvm::APSInt &FromVal = D1->getInitVal();
2108 const llvm::APSInt &ToVal = D2->getInitVal();
2109 if (FromVal.isSigned() != ToVal.isSigned())
2110 return false;
2111 if (FromVal.getBitWidth() != ToVal.getBitWidth())
2112 return false;
2113 if (FromVal != ToVal)
2114 return false;
2115
2116 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2117 return false;
2118
2119 // Init expressions are the most expensive check, so do them last.
2120 return IsStructurallyEquivalent(Context, S1: D1->getInitExpr(),
2121 S2: D2->getInitExpr());
2122}
2123
2124/// Determine structural equivalence of two enums.
2125static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2126 EnumDecl *D1, EnumDecl *D2) {
2127 if (!NameIsStructurallyEquivalent(D1: *D1, D2: *D2)) {
2128 return false;
2129 }
2130
2131 // Compare the definitions of these two enums. If either or both are
2132 // incomplete (i.e. forward declared), we assume that they are equivalent.
2133 // In C23, the order of the enumerations does not matter, only the names and
2134 // values do.
2135 D1 = D1->getDefinition();
2136 D2 = D2->getDefinition();
2137 if (!D1 || !D2)
2138 return true;
2139
2140 if (Context.LangOpts.C23 &&
2141 !CheckStructurallyEquivalentAttributes(Context, D1, D2))
2142 return false;
2143
2144 // In C23, if one enumeration has a fixed underlying type, the other shall
2145 // have a compatible fixed underlying type (6.2.7).
2146 if (Context.LangOpts.C23) {
2147 if (D1->isFixed() != D2->isFixed()) {
2148 if (Context.Complain) {
2149 Context.Diag2(Loc: D2->getLocation(),
2150 DiagID: Context.getApplicableDiagnostic(
2151 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2152 << Context.ToCtx.getCanonicalTagType(TD: D2)
2153 << (&Context.FromCtx != &Context.ToCtx);
2154 Context.Diag1(Loc: D1->getLocation(),
2155 DiagID: D1->isFixed()
2156 ? diag::note_odr_fixed_underlying_type
2157 : diag::note_odr_missing_fixed_underlying_type)
2158 << D1;
2159 Context.Diag2(Loc: D2->getLocation(),
2160 DiagID: D2->isFixed()
2161 ? diag::note_odr_fixed_underlying_type
2162 : diag::note_odr_missing_fixed_underlying_type)
2163 << D2;
2164 }
2165 return false;
2166 }
2167 if (D1->isFixed()) {
2168 assert(D2->isFixed() && "enums expected to have fixed underlying types");
2169 if (!IsStructurallyEquivalent(Context, T1: D1->getIntegerType(),
2170 T2: D2->getIntegerType())) {
2171 if (Context.Complain) {
2172 Context.Diag2(Loc: D2->getLocation(),
2173 DiagID: Context.getApplicableDiagnostic(
2174 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2175 << Context.ToCtx.getCanonicalTagType(TD: D2)
2176 << (&Context.FromCtx != &Context.ToCtx);
2177 Context.Diag2(Loc: D2->getLocation(),
2178 DiagID: diag::note_odr_incompatible_fixed_underlying_type)
2179 << D2 << D2->getIntegerType() << D1->getIntegerType();
2180 }
2181 return false;
2182 }
2183 }
2184 }
2185
2186 llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums;
2187 auto CopyEnumerators =
2188 [](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
2189 for (const EnumConstantDecl *ECD : Range)
2190 Cont.push_back(Elt: ECD);
2191 };
2192 CopyEnumerators(D1->enumerators(), D1Enums);
2193 CopyEnumerators(D2->enumerators(), D2Enums);
2194
2195 // In C23 mode, the order of the enumerations does not matter, so sort them
2196 // by name to get them both into a consistent ordering.
2197 if (Context.LangOpts.C23) {
2198 auto Sorter = [](const EnumConstantDecl *LHS, const EnumConstantDecl *RHS) {
2199 return LHS->getName() < RHS->getName();
2200 };
2201 llvm::sort(C&: D1Enums, Comp: Sorter);
2202 llvm::sort(C&: D2Enums, Comp: Sorter);
2203 }
2204
2205 auto EC2 = D2Enums.begin(), EC2End = D2Enums.end();
2206 for (auto EC1 = D1Enums.begin(), EC1End = D1Enums.end(); EC1 != EC1End;
2207 ++EC1, ++EC2) {
2208 if (EC2 == EC2End) {
2209 if (Context.Complain) {
2210 Context.Diag2(Loc: D2->getLocation(),
2211 DiagID: Context.getApplicableDiagnostic(
2212 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2213 << Context.ToCtx.getCanonicalTagType(TD: D2)
2214 << (&Context.FromCtx != &Context.ToCtx);
2215 Context.Diag1(Loc: (*EC1)->getLocation(), DiagID: diag::note_odr_enumerator)
2216 << (*EC1)->getDeclName() << toString(I: (*EC1)->getInitVal(), Radix: 10);
2217 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_enumerator);
2218 }
2219 return false;
2220 }
2221
2222 llvm::APSInt Val1 = (*EC1)->getInitVal();
2223 llvm::APSInt Val2 = (*EC2)->getInitVal();
2224 if (!llvm::APSInt::isSameValue(I1: Val1, I2: Val2) ||
2225 !IsStructurallyEquivalent(Name1: (*EC1)->getIdentifier(),
2226 Name2: (*EC2)->getIdentifier())) {
2227 if (Context.Complain) {
2228 Context.Diag2(Loc: D2->getLocation(),
2229 DiagID: Context.getApplicableDiagnostic(
2230 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2231 << Context.ToCtx.getCanonicalTagType(TD: D2)
2232 << (&Context.FromCtx != &Context.ToCtx);
2233 Context.Diag2(Loc: (*EC2)->getLocation(), DiagID: diag::note_odr_enumerator)
2234 << (*EC2)->getDeclName() << toString(I: (*EC2)->getInitVal(), Radix: 10);
2235 Context.Diag1(Loc: (*EC1)->getLocation(), DiagID: diag::note_odr_enumerator)
2236 << (*EC1)->getDeclName() << toString(I: (*EC1)->getInitVal(), Radix: 10);
2237 }
2238 return false;
2239 }
2240 if (Context.LangOpts.C23 &&
2241 !CheckStructurallyEquivalentAttributes(Context, D1: *EC1, D2: *EC2, PrimaryDecl: D2))
2242 return false;
2243 }
2244
2245 if (EC2 != EC2End) {
2246 if (Context.Complain) {
2247 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
2248 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2249 << Context.ToCtx.getCanonicalTagType(TD: D2)
2250 << (&Context.FromCtx != &Context.ToCtx);
2251 Context.Diag2(Loc: (*EC2)->getLocation(), DiagID: diag::note_odr_enumerator)
2252 << (*EC2)->getDeclName() << toString(I: (*EC2)->getInitVal(), Radix: 10);
2253 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_enumerator);
2254 }
2255 return false;
2256 }
2257
2258 return true;
2259}
2260
2261static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2262 TemplateParameterList *Params1,
2263 TemplateParameterList *Params2) {
2264 if (Params1->size() != Params2->size()) {
2265 if (Context.Complain) {
2266 Context.Diag2(Loc: Params2->getTemplateLoc(),
2267 DiagID: Context.getApplicableDiagnostic(
2268 ErrorDiagnostic: diag::err_odr_different_num_template_parameters))
2269 << Params1->size() << Params2->size();
2270 Context.Diag1(Loc: Params1->getTemplateLoc(),
2271 DiagID: diag::note_odr_template_parameter_list);
2272 }
2273 return false;
2274 }
2275
2276 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
2277 if (Params1->getParam(Idx: I)->getKind() != Params2->getParam(Idx: I)->getKind()) {
2278 if (Context.Complain) {
2279 Context.Diag2(Loc: Params2->getParam(Idx: I)->getLocation(),
2280 DiagID: Context.getApplicableDiagnostic(
2281 ErrorDiagnostic: diag::err_odr_different_template_parameter_kind));
2282 Context.Diag1(Loc: Params1->getParam(Idx: I)->getLocation(),
2283 DiagID: diag::note_odr_template_parameter_here);
2284 }
2285 return false;
2286 }
2287
2288 if (!IsStructurallyEquivalent(Context, D1: Params1->getParam(Idx: I),
2289 D2: Params2->getParam(Idx: I)))
2290 return false;
2291 }
2292
2293 return true;
2294}
2295
2296static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2297 TemplateTypeParmDecl *D1,
2298 TemplateTypeParmDecl *D2) {
2299 if (D1->isParameterPack() != D2->isParameterPack()) {
2300 if (Context.Complain) {
2301 Context.Diag2(Loc: D2->getLocation(),
2302 DiagID: Context.getApplicableDiagnostic(
2303 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2304 << D2->isParameterPack();
2305 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2306 << D1->isParameterPack();
2307 }
2308 return false;
2309 }
2310
2311 return true;
2312}
2313
2314static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2315 NonTypeTemplateParmDecl *D1,
2316 NonTypeTemplateParmDecl *D2) {
2317 if (D1->isParameterPack() != D2->isParameterPack()) {
2318 if (Context.Complain) {
2319 Context.Diag2(Loc: D2->getLocation(),
2320 DiagID: Context.getApplicableDiagnostic(
2321 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2322 << D2->isParameterPack();
2323 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2324 << D1->isParameterPack();
2325 }
2326 return false;
2327 }
2328 if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
2329 return false;
2330 if (D1->getIndex() != D2->getIndex())
2331 return false;
2332 // Check types.
2333 if (!IsStructurallyEquivalent(Context, T1: D1->getType(), T2: D2->getType())) {
2334 if (Context.Complain) {
2335 Context.Diag2(Loc: D2->getLocation(),
2336 DiagID: Context.getApplicableDiagnostic(
2337 ErrorDiagnostic: diag::err_odr_non_type_parameter_type_inconsistent))
2338 << D2->getType() << D1->getType();
2339 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_value_here)
2340 << D1->getType();
2341 }
2342 return false;
2343 }
2344
2345 return true;
2346}
2347
2348static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2349 TemplateTemplateParmDecl *D1,
2350 TemplateTemplateParmDecl *D2) {
2351 if (D1->isParameterPack() != D2->isParameterPack()) {
2352 if (Context.Complain) {
2353 Context.Diag2(Loc: D2->getLocation(),
2354 DiagID: Context.getApplicableDiagnostic(
2355 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2356 << D2->isParameterPack();
2357 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2358 << D1->isParameterPack();
2359 }
2360 return false;
2361 }
2362
2363 // Check template parameter lists.
2364 return D1->templateParameterKind() == D2->templateParameterKind() &&
2365 IsStructurallyEquivalent(Context, Params1: D1->getTemplateParameters(),
2366 Params2: D2->getTemplateParameters());
2367}
2368
2369static bool IsTemplateDeclCommonStructurallyEquivalent(
2370 StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2) {
2371 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2372 return false;
2373 if (!D1->getIdentifier()) // Special name
2374 if (D1->getNameAsString() != D2->getNameAsString())
2375 return false;
2376 return IsStructurallyEquivalent(Context&: Ctx, Params1: D1->getTemplateParameters(),
2377 Params2: D2->getTemplateParameters());
2378}
2379
2380static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2381 ClassTemplateDecl *D1,
2382 ClassTemplateDecl *D2) {
2383 // Check template parameters.
2384 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2385 return false;
2386
2387 // Check the templated declaration.
2388 return IsStructurallyEquivalent(Context, D1: D1->getTemplatedDecl(),
2389 D2: D2->getTemplatedDecl());
2390}
2391
2392static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2393 FunctionTemplateDecl *D1,
2394 FunctionTemplateDecl *D2) {
2395 // Check template parameters.
2396 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2397 return false;
2398
2399 // Check the templated declaration.
2400 return IsStructurallyEquivalent(Context, T1: D1->getTemplatedDecl()->getType(),
2401 T2: D2->getTemplatedDecl()->getType());
2402}
2403
2404static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2405 TypeAliasTemplateDecl *D1,
2406 TypeAliasTemplateDecl *D2) {
2407 // Check template parameters.
2408 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2409 return false;
2410
2411 // Check the templated declaration.
2412 return IsStructurallyEquivalent(Context, D1: D1->getTemplatedDecl(),
2413 D2: D2->getTemplatedDecl());
2414}
2415
2416static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2417 ConceptDecl *D1,
2418 ConceptDecl *D2) {
2419 // Check template parameters.
2420 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2421 return false;
2422
2423 // Check the constraint expression.
2424 return IsStructurallyEquivalent(Context, S1: D1->getConstraintExpr(),
2425 S2: D2->getConstraintExpr());
2426}
2427
2428static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2429 FriendDecl *D1, FriendDecl *D2) {
2430 if ((D1->getFriendType() && D2->getFriendDecl()) ||
2431 (D1->getFriendDecl() && D2->getFriendType())) {
2432 return false;
2433 }
2434 if (D1->getFriendType() && D2->getFriendType())
2435 return IsStructurallyEquivalent(Context,
2436 T1: D1->getFriendType()->getType(),
2437 T2: D2->getFriendType()->getType());
2438 if (D1->getFriendDecl() && D2->getFriendDecl())
2439 return IsStructurallyEquivalent(Context, D1: D1->getFriendDecl(),
2440 D2: D2->getFriendDecl());
2441 return false;
2442}
2443
2444static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2445 TypedefNameDecl *D1, TypedefNameDecl *D2) {
2446 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2447 return false;
2448
2449 return IsStructurallyEquivalent(Context, T1: D1->getUnderlyingType(),
2450 T2: D2->getUnderlyingType());
2451}
2452
2453static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2454 FunctionDecl *D1, FunctionDecl *D2) {
2455 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2456 return false;
2457
2458 if (D1->isOverloadedOperator()) {
2459 if (!D2->isOverloadedOperator())
2460 return false;
2461 if (D1->getOverloadedOperator() != D2->getOverloadedOperator())
2462 return false;
2463 }
2464
2465 // FIXME: Consider checking for function attributes as well.
2466 if (!IsStructurallyEquivalent(Context, T1: D1->getType(), T2: D2->getType()))
2467 return false;
2468
2469 return true;
2470}
2471
2472static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2473 ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2474 QualType Owner2Type) {
2475 if (D1->getAccessControl() != D2->getAccessControl())
2476 return false;
2477
2478 return IsStructurallyEquivalent(Context, Field1: cast<FieldDecl>(Val: D1),
2479 Field2: cast<FieldDecl>(Val: D2), Owner2Type);
2480}
2481
2482static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2483 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2484 QualType Owner2Type =
2485 Context.ToCtx.getObjCInterfaceType(Decl: D2->getContainingInterface());
2486 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2487}
2488
2489static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2490 ObjCMethodDecl *Method1,
2491 ObjCMethodDecl *Method2) {
2492 bool PropertiesEqual =
2493 Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2494 Method1->isVariadic() == Method2->isVariadic() &&
2495 Method1->isDirectMethod() == Method2->isDirectMethod();
2496 if (!PropertiesEqual)
2497 return false;
2498
2499 // Compare selector slot names.
2500 Selector Selector1 = Method1->getSelector(),
2501 Selector2 = Method2->getSelector();
2502 unsigned NumArgs = Selector1.getNumArgs();
2503 if (NumArgs != Selector2.getNumArgs())
2504 return false;
2505 // Compare all selector slots. For selectors with arguments it means all arg
2506 // slots. And if there are no arguments, compare the first-and-only slot.
2507 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2508 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2509 if (!IsStructurallyEquivalent(Name1: Selector1.getIdentifierInfoForSlot(argIndex: I),
2510 Name2: Selector2.getIdentifierInfoForSlot(argIndex: I)))
2511 return false;
2512 }
2513
2514 // Compare types.
2515 if (!IsStructurallyEquivalent(Context, T1: Method1->getReturnType(),
2516 T2: Method2->getReturnType()))
2517 return false;
2518 assert(
2519 Method1->param_size() == Method2->param_size() &&
2520 "Same number of arguments should be already enforced in Selector checks");
2521 for (ObjCMethodDecl::param_type_iterator
2522 ParamT1 = Method1->param_type_begin(),
2523 ParamT1End = Method1->param_type_end(),
2524 ParamT2 = Method2->param_type_begin(),
2525 ParamT2End = Method2->param_type_end();
2526 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2527 ++ParamT1, ++ParamT2) {
2528 if (!IsStructurallyEquivalent(Context, T1: *ParamT1, T2: *ParamT2))
2529 return false;
2530 }
2531
2532 return true;
2533}
2534
2535static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2536 ObjCCategoryDecl *D1,
2537 ObjCCategoryDecl *D2) {
2538 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2539 return false;
2540
2541 const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2542 *Intf2 = D2->getClassInterface();
2543 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2544 return false;
2545
2546 if (Intf1 &&
2547 !IsStructurallyEquivalent(Name1: Intf1->getIdentifier(), Name2: Intf2->getIdentifier()))
2548 return false;
2549
2550 // Compare protocols.
2551 ObjCCategoryDecl::protocol_iterator Protocol2 = D2->protocol_begin(),
2552 Protocol2End = D2->protocol_end();
2553 for (ObjCCategoryDecl::protocol_iterator Protocol1 = D1->protocol_begin(),
2554 Protocol1End = D1->protocol_end();
2555 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2556 if (Protocol2 == Protocol2End)
2557 return false;
2558 if (!IsStructurallyEquivalent(Name1: (*Protocol1)->getIdentifier(),
2559 Name2: (*Protocol2)->getIdentifier()))
2560 return false;
2561 }
2562 if (Protocol2 != Protocol2End)
2563 return false;
2564
2565 // Compare ivars.
2566 QualType D2Type =
2567 Intf2 ? Context.ToCtx.getObjCInterfaceType(Decl: Intf2) : QualType();
2568 ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(),
2569 Ivar2End = D2->ivar_end();
2570 for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(),
2571 Ivar1End = D1->ivar_end();
2572 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2573 if (Ivar2 == Ivar2End)
2574 return false;
2575 if (!IsStructurallyEquivalent(Context, D1: *Ivar1, D2: *Ivar2, Owner2Type: D2Type))
2576 return false;
2577 }
2578 if (Ivar2 != Ivar2End)
2579 return false;
2580
2581 // Compare methods.
2582 ObjCCategoryDecl::method_iterator Method2 = D2->meth_begin(),
2583 Method2End = D2->meth_end();
2584 for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2585 Method1End = D1->meth_end();
2586 Method1 != Method1End; ++Method1, ++Method2) {
2587 if (Method2 == Method2End)
2588 return false;
2589 if (!IsStructurallyEquivalent(Context, Method1: *Method1, Method2: *Method2))
2590 return false;
2591 }
2592 if (Method2 != Method2End)
2593 return false;
2594
2595 return true;
2596}
2597
2598/// Determine structural equivalence of two declarations.
2599static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2600 Decl *D1, Decl *D2) {
2601 // FIXME: Check for known structural equivalences via a callback of some sort.
2602
2603 D1 = D1->getCanonicalDecl();
2604 D2 = D2->getCanonicalDecl();
2605
2606 if (D1 == D2)
2607 return true;
2608
2609 std::pair<Decl *, Decl *> P{D1, D2};
2610
2611 // Check whether we already know that these two declarations are not
2612 // structurally equivalent.
2613 if (Context.NonEquivalentDecls.count(
2614 V: std::make_tuple(args&: D1, args&: D2, args&: Context.IgnoreTemplateParmDepth)))
2615 return false;
2616
2617 // Check if a check for these declarations is already pending.
2618 // If yes D1 and D2 will be checked later (from DeclsToCheck),
2619 // or these are already checked (and equivalent).
2620 bool Inserted = Context.VisitedDecls.insert(V: P).second;
2621 if (!Inserted)
2622 return true;
2623
2624 Context.DeclsToCheck.push(x: P);
2625
2626 return true;
2627}
2628
2629DiagnosticBuilder StructuralEquivalenceContext::Diag1(SourceLocation Loc,
2630 unsigned DiagID) {
2631 assert(Complain && "Not allowed to complain");
2632 if (LastDiagFromC2)
2633 FromCtx.getDiagnostics().notePriorDiagnosticFrom(Other: ToCtx.getDiagnostics());
2634 LastDiagFromC2 = false;
2635 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2636}
2637
2638DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc,
2639 unsigned DiagID) {
2640 assert(Complain && "Not allowed to complain");
2641 if (!LastDiagFromC2)
2642 ToCtx.getDiagnostics().notePriorDiagnosticFrom(Other: FromCtx.getDiagnostics());
2643 LastDiagFromC2 = true;
2644 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2645}
2646
2647UnsignedOrNone
2648StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
2649 ASTContext &Context = Anon->getASTContext();
2650 CanQualType AnonTy = Context.getCanonicalTagType(TD: Anon);
2651
2652 const auto *Owner = dyn_cast<RecordDecl>(Val: Anon->getDeclContext());
2653 if (!Owner)
2654 return std::nullopt;
2655
2656 unsigned Index = 0;
2657 for (const auto *D : Owner->noload_decls()) {
2658 const auto *F = dyn_cast<FieldDecl>(Val: D);
2659 if (!F)
2660 continue;
2661
2662 if (F->isAnonymousStructOrUnion()) {
2663 if (Context.hasSameType(T1: F->getType(), T2: AnonTy))
2664 break;
2665 ++Index;
2666 continue;
2667 }
2668
2669 // If the field looks like this:
2670 // struct { ... } A;
2671 QualType FieldType = F->getType();
2672 if (const auto *RecType = dyn_cast<RecordType>(Val&: FieldType)) {
2673 const RecordDecl *RecDecl = RecType->getDecl();
2674 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2675 if (Context.hasSameType(T1: FieldType, T2: AnonTy))
2676 break;
2677 ++Index;
2678 continue;
2679 }
2680 }
2681 }
2682
2683 return Index;
2684}
2685
2686unsigned StructuralEquivalenceContext::getApplicableDiagnostic(
2687 unsigned ErrorDiagnostic) {
2688 if (ErrorOnTagTypeMismatch)
2689 return ErrorDiagnostic;
2690
2691 switch (ErrorDiagnostic) {
2692 case diag::err_odr_variable_type_inconsistent:
2693 return diag::warn_odr_variable_type_inconsistent;
2694 case diag::err_odr_variable_multiple_def:
2695 return diag::warn_odr_variable_multiple_def;
2696 case diag::err_odr_function_type_inconsistent:
2697 return diag::warn_odr_function_type_inconsistent;
2698 case diag::err_odr_tag_type_inconsistent:
2699 return diag::warn_odr_tag_type_inconsistent;
2700 case diag::err_odr_field_type_inconsistent:
2701 return diag::warn_odr_field_type_inconsistent;
2702 case diag::err_odr_ivar_type_inconsistent:
2703 return diag::warn_odr_ivar_type_inconsistent;
2704 case diag::err_odr_objc_superclass_inconsistent:
2705 return diag::warn_odr_objc_superclass_inconsistent;
2706 case diag::err_odr_objc_method_result_type_inconsistent:
2707 return diag::warn_odr_objc_method_result_type_inconsistent;
2708 case diag::err_odr_objc_method_num_params_inconsistent:
2709 return diag::warn_odr_objc_method_num_params_inconsistent;
2710 case diag::err_odr_objc_method_param_type_inconsistent:
2711 return diag::warn_odr_objc_method_param_type_inconsistent;
2712 case diag::err_odr_objc_method_variadic_inconsistent:
2713 return diag::warn_odr_objc_method_variadic_inconsistent;
2714 case diag::err_odr_objc_property_type_inconsistent:
2715 return diag::warn_odr_objc_property_type_inconsistent;
2716 case diag::err_odr_objc_property_impl_kind_inconsistent:
2717 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2718 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2719 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2720 case diag::err_odr_different_num_template_parameters:
2721 return diag::warn_odr_different_num_template_parameters;
2722 case diag::err_odr_different_template_parameter_kind:
2723 return diag::warn_odr_different_template_parameter_kind;
2724 case diag::err_odr_parameter_pack_non_pack:
2725 return diag::warn_odr_parameter_pack_non_pack;
2726 case diag::err_odr_non_type_parameter_type_inconsistent:
2727 return diag::warn_odr_non_type_parameter_type_inconsistent;
2728 }
2729 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2730}
2731
2732bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) {
2733
2734 // Ensure that the implementation functions (all static functions in this TU)
2735 // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2736 // because that will wreak havoc the internal state (DeclsToCheck and
2737 // VisitedDecls members) and can cause faulty behaviour.
2738 // In other words: Do not start a graph search from a new node with the
2739 // internal data of another search in progress.
2740 // FIXME: Better encapsulation and separation of internal and public
2741 // functionality.
2742 assert(DeclsToCheck.empty());
2743 assert(VisitedDecls.empty());
2744
2745 if (!::IsStructurallyEquivalent(Context&: *this, D1, D2))
2746 return false;
2747
2748 return !Finish();
2749}
2750
2751bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
2752 assert(DeclsToCheck.empty());
2753 assert(VisitedDecls.empty());
2754 if (!::IsStructurallyEquivalent(Context&: *this, T1, T2))
2755 return false;
2756
2757 return !Finish();
2758}
2759
2760bool StructuralEquivalenceContext::IsEquivalent(Stmt *S1, Stmt *S2) {
2761 assert(DeclsToCheck.empty());
2762 assert(VisitedDecls.empty());
2763 if (!::IsStructurallyEquivalent(Context&: *this, S1, S2))
2764 return false;
2765
2766 return !Finish();
2767}
2768
2769bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2770 // Check for equivalent described template.
2771 TemplateDecl *Template1 = D1->getDescribedTemplate();
2772 TemplateDecl *Template2 = D2->getDescribedTemplate();
2773 if ((Template1 != nullptr) != (Template2 != nullptr))
2774 return false;
2775 if (Template1 && !IsStructurallyEquivalent(Context&: *this, D1: Template1, D2: Template2))
2776 return false;
2777
2778 // FIXME: Move check for identifier names into this function.
2779
2780 return true;
2781}
2782
2783bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2784 Decl *D1, Decl *D2) {
2785
2786 // Kind mismatch.
2787 if (D1->getKind() != D2->getKind())
2788 return false;
2789
2790 // Cast the Decls to their actual subclass so that the right overload of
2791 // IsStructurallyEquivalent is called.
2792 switch (D1->getKind()) {
2793#define ABSTRACT_DECL(DECL)
2794#define DECL(DERIVED, BASE) \
2795 case Decl::Kind::DERIVED: \
2796 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2797 static_cast<DERIVED##Decl *>(D2));
2798#include "clang/AST/DeclNodes.inc"
2799 }
2800 return true;
2801}
2802
2803bool StructuralEquivalenceContext::checkDeclQueue() {
2804 while (!DeclsToCheck.empty()) {
2805 // Check the next declaration.
2806 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2807 DeclsToCheck.pop();
2808
2809 Decl *D1 = P.first;
2810 Decl *D2 = P.second;
2811
2812 bool Equivalent =
2813 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2814
2815 if (!Equivalent) {
2816 // Note that these two declarations are not equivalent (and we already
2817 // know about it).
2818 NonEquivalentDecls.insert(
2819 V: std::make_tuple(args&: D1, args&: D2, args&: IgnoreTemplateParmDepth));
2820
2821 return true;
2822 }
2823 }
2824
2825 return false;
2826}
2827
2828bool StructuralEquivalenceContext::Finish() { return checkDeclQueue(); }
2829