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