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