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
98using namespace clang;
99
100static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
101 QualType T1, QualType T2);
102static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
103 Decl *D1, Decl *D2);
104static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
105 const Stmt *S1, const Stmt *S2);
106static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
107 const TemplateArgument &Arg1,
108 const TemplateArgument &Arg2);
109static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
110 const TemplateArgumentLoc &Arg1,
111 const TemplateArgumentLoc &Arg2);
112static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
113 NestedNameSpecifier *NNS1,
114 NestedNameSpecifier *NNS2);
115static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
116 const IdentifierInfo *Name2);
117
118static 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: Name1.getAsIdentifierInfo(),
128 Name2: Name2.getAsIdentifierInfo());
129
130 case DeclarationName::CXXConstructorName:
131 case DeclarationName::CXXDestructorName:
132 case DeclarationName::CXXConversionFunctionName:
133 return IsStructurallyEquivalent(Context, T1: Name1.getCXXNameType(),
134 T2: Name2.getCXXNameType());
135
136 case DeclarationName::CXXDeductionGuideName: {
137 if (!IsStructurallyEquivalent(
138 Context, Name1: Name1.getCXXDeductionGuideTemplate()->getDeclName(),
139 Name2: Name2.getCXXDeductionGuideTemplate()->getDeclName()))
140 return false;
141 return IsStructurallyEquivalent(Context,
142 D1: Name1.getCXXDeductionGuideTemplate(),
143 D2: Name2.getCXXDeductionGuideTemplate());
144 }
145
146 case DeclarationName::CXXOperatorName:
147 return Name1.getCXXOverloadedOperator() == Name2.getCXXOverloadedOperator();
148
149 case DeclarationName::CXXLiteralOperatorName:
150 return IsStructurallyEquivalent(Name1: Name1.getCXXLiteralIdentifier(),
151 Name2: 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
166namespace {
167/// Encapsulates Stmt comparison logic.
168class 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
175 bool IsStmtEquivalent(const AddrLabelExpr *E1, const AddrLabelExpr *E2) {
176 return IsStructurallyEquivalent(Context, D1: E1->getLabel(), D2: E2->getLabel());
177 }
178
179 bool IsStmtEquivalent(const AtomicExpr *E1, const AtomicExpr *E2) {
180 return E1->getOp() == E2->getOp();
181 }
182
183 bool IsStmtEquivalent(const BinaryOperator *E1, const BinaryOperator *E2) {
184 return E1->getOpcode() == E2->getOpcode();
185 }
186
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, D1: Callee1, D2: Callee2);
202 }
203
204 bool IsStmtEquivalent(const CharacterLiteral *E1,
205 const CharacterLiteral *E2) {
206 return E1->getValue() == E2->getValue() && E1->getKind() == E2->getKind();
207 }
208
209 bool IsStmtEquivalent(const ChooseExpr *E1, const ChooseExpr *E2) {
210 return true; // Semantics only depend on children.
211 }
212
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
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, D1: const_cast<ValueDecl *>(Decl1),
228 D2: const_cast<ValueDecl *>(Decl2));
229 }
230
231 bool IsStmtEquivalent(const DependentScopeDeclRefExpr *DE1,
232 const DependentScopeDeclRefExpr *DE2) {
233 if (!IsStructurallyEquivalent(Context, Name1: DE1->getDeclName(),
234 Name2: DE2->getDeclName()))
235 return false;
236 return IsStructurallyEquivalent(Context, NNS1: DE1->getQualifier(),
237 NNS2: DE2->getQualifier());
238 }
239
240 bool IsStmtEquivalent(const Expr *E1, const Expr *E2) {
241 return IsStructurallyEquivalent(Context, T1: E1->getType(), T2: E2->getType());
242 }
243
244 bool IsStmtEquivalent(const ExpressionTraitExpr *E1,
245 const ExpressionTraitExpr *E2) {
246 return E1->getTrait() == E2->getTrait() && E1->getValue() == E2->getValue();
247 }
248
249 bool IsStmtEquivalent(const FloatingLiteral *E1, const FloatingLiteral *E2) {
250 return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue();
251 }
252
253 bool IsStmtEquivalent(const GenericSelectionExpr *E1,
254 const GenericSelectionExpr *E2) {
255 for (auto Pair : zip_longest(t: E1->getAssocTypeSourceInfos(),
256 u: E2->getAssocTypeSourceInfos())) {
257 std::optional<TypeSourceInfo *> Child1 = std::get<0>(t&: Pair);
258 std::optional<TypeSourceInfo *> Child2 = std::get<1>(t&: 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, T1: (*Child1)->getType(),
264 T2: (*Child2)->getType()))
265 return false;
266 }
267
268 return true;
269 }
270
271 bool IsStmtEquivalent(const ImplicitCastExpr *CastE1,
272 const ImplicitCastExpr *CastE2) {
273 return IsStructurallyEquivalent(Context, T1: CastE1->getType(),
274 T2: CastE2->getType());
275 }
276
277 bool IsStmtEquivalent(const IntegerLiteral *E1, const IntegerLiteral *E2) {
278 return E1->getValue() == E2->getValue();
279 }
280
281 bool IsStmtEquivalent(const MemberExpr *E1, const MemberExpr *E2) {
282 return IsStructurallyEquivalent(Context, D1: E1->getFoundDecl(),
283 D2: E2->getFoundDecl());
284 }
285
286 bool IsStmtEquivalent(const ObjCStringLiteral *E1,
287 const ObjCStringLiteral *E2) {
288 // Just wraps a StringLiteral child.
289 return true;
290 }
291
292 bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }
293
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
305 bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) {
306 return E1->getIdentKind() == E2->getIdentKind();
307 }
308
309 bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) {
310 return E1->getTemplateDepth() == E2->getTemplateDepth();
311 }
312
313 bool IsStmtEquivalent(const StringLiteral *E1, const StringLiteral *E2) {
314 return E1->getBytes() == E2->getBytes();
315 }
316
317 bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
318 const SubstNonTypeTemplateParmExpr *E2) {
319 if (!IsStructurallyEquivalent(Context, D1: E1->getAssociatedDecl(),
320 D2: 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
329 bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
330 const SubstNonTypeTemplateParmPackExpr *E2) {
331 return IsStructurallyEquivalent(Context, Arg1: E1->getArgumentPack(),
332 Arg2: E2->getArgumentPack());
333 }
334
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(t: E1->getArgs(), u: E2->getArgs())) {
340 std::optional<TypeSourceInfo *> Child1 = std::get<0>(t&: Pair);
341 std::optional<TypeSourceInfo *> Child2 = std::get<1>(t&: Pair);
342 // Different number of args.
343 if (!Child1 || !Child2)
344 return false;
345
346 if (!IsStructurallyEquivalent(Context, T1: (*Child1)->getType(),
347 T2: (*Child2)->getType()))
348 return false;
349 }
350 return true;
351 }
352
353 bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1,
354 const CXXDependentScopeMemberExpr *E2) {
355 if (!IsStructurallyEquivalent(Context, Name1: E1->getMember(), Name2: E2->getMember())) {
356 return false;
357 }
358 return IsStructurallyEquivalent(Context, T1: E1->getBaseType(),
359 T2: E2->getBaseType());
360 }
361
362 bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
363 const UnaryExprOrTypeTraitExpr *E2) {
364 if (E1->getKind() != E2->getKind())
365 return false;
366 return IsStructurallyEquivalent(Context, T1: E1->getTypeOfArgument(),
367 T2: E2->getTypeOfArgument());
368 }
369
370 bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) {
371 return E1->getOpcode() == E2->getOpcode();
372 }
373
374 bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) {
375 // Semantics only depend on children.
376 return true;
377 }
378
379 bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
380 if (!IsStructurallyEquivalent(Context, Name1: E1->getName(), Name2: 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, NNS1: E1->getQualifier(),
388 NNS2: 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, Arg1: Args1[ArgI], Arg2: Args2[ArgI]))
398 return false;
399
400 return true;
401 }
402
403 bool IsStmtEquivalent(const CXXBoolLiteralExpr *E1, const CXXBoolLiteralExpr *E2) {
404 return E1->getValue() == E2->getValue();
405 }
406
407 /// End point of the traversal chain.
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
424public:
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.
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
454static bool
455CheckStructurallyEquivalentAttributes(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>(Val: PrimaryDecl ? PrimaryDecl : D2);
475 Context.Diag2(Loc: DiagnoseDecl->getLocation(),
476 DiagID: diag::warn_odr_tag_type_with_attributes)
477 << Context.ToCtx.getTypeDeclType(Decl: DiagnoseDecl)
478 << (PrimaryDecl != nullptr);
479 if (D1Attr)
480 Context.Diag1(Loc: D1Attr->getLoc(), DiagID: diag::note_odr_attr_here) << D1Attr;
481 if (D2Attr)
482 Context.Diag1(Loc: D2Attr->getLoc(), DiagID: 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
491static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
492 const UnaryOperator *E1,
493 const CXXOperatorCallExpr *E2) {
494 return UnaryOperator::getOverloadedOperator(Opc: E1->getOpcode()) ==
495 E2->getOperator() &&
496 IsStructurallyEquivalent(Context, S1: E1->getSubExpr(), S2: E2->getArg(Arg: 0));
497}
498
499static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
500 const CXXOperatorCallExpr *E1,
501 const UnaryOperator *E2) {
502 return E1->getOperator() ==
503 UnaryOperator::getOverloadedOperator(Opc: E2->getOpcode()) &&
504 IsStructurallyEquivalent(Context, S1: E1->getArg(Arg: 0), S2: E2->getSubExpr());
505}
506
507static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
508 const BinaryOperator *E1,
509 const CXXOperatorCallExpr *E2) {
510 return BinaryOperator::getOverloadedOperator(Opc: E1->getOpcode()) ==
511 E2->getOperator() &&
512 IsStructurallyEquivalent(Context, S1: E1->getLHS(), S2: E2->getArg(Arg: 0)) &&
513 IsStructurallyEquivalent(Context, S1: E1->getRHS(), S2: E2->getArg(Arg: 1));
514}
515
516static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
517 const CXXOperatorCallExpr *E1,
518 const BinaryOperator *E2) {
519 return E1->getOperator() ==
520 BinaryOperator::getOverloadedOperator(Opc: E2->getOpcode()) &&
521 IsStructurallyEquivalent(Context, S1: E1->getArg(Arg: 0), S2: E2->getLHS()) &&
522 IsStructurallyEquivalent(Context, S1: E1->getArg(Arg: 1), S2: E2->getRHS());
523}
524
525/// Determine structural equivalence of two statements.
526static 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>(Val: S2)) {
540 if (const auto *E1Unary = dyn_cast<UnaryOperator>(Val: S1))
541 return IsStructurallyEquivalent(Context, E1: E1Unary, E2: E2CXXOperatorCall);
542 if (const auto *E1Binary = dyn_cast<BinaryOperator>(Val: S1))
543 return IsStructurallyEquivalent(Context, E1: E1Binary, E2: E2CXXOperatorCall);
544 }
545 if (const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(Val: S1)) {
546 if (const auto *E2Unary = dyn_cast<UnaryOperator>(Val: S2))
547 return IsStructurallyEquivalent(Context, E1: E1CXXOperatorCall, E2: E2Unary);
548 if (const auto *E2Binary = dyn_cast<BinaryOperator>(Val: S2))
549 return IsStructurallyEquivalent(Context, E1: E1CXXOperatorCall, E2: 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(t: S1->children(), u: S2->children())) {
559 std::optional<const Stmt *> Child1 = std::get<0>(t&: Pair);
560 std::optional<const Stmt *> Child2 = std::get<1>(t&: 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, S1: *Child1, S2: *Child2))
566 return false;
567 }
568 return true;
569}
570
571/// Determine whether two identifiers are equivalent.
572static 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.
581static 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, NNS1: Prefix1, NNS2: Prefix2))
594 return false;
595
596 switch (NNS1->getKind()) {
597 case NestedNameSpecifier::Identifier:
598 return IsStructurallyEquivalent(Name1: NNS1->getAsIdentifier(),
599 Name2: NNS2->getAsIdentifier());
600 case NestedNameSpecifier::Namespace:
601 return IsStructurallyEquivalent(Context, D1: NNS1->getAsNamespace(),
602 D2: NNS2->getAsNamespace());
603 case NestedNameSpecifier::NamespaceAlias:
604 return IsStructurallyEquivalent(Context, D1: NNS1->getAsNamespaceAlias(),
605 D2: NNS2->getAsNamespaceAlias());
606 case NestedNameSpecifier::TypeSpec:
607 return IsStructurallyEquivalent(Context, T1: QualType(NNS1->getAsType(), 0),
608 T2: QualType(NNS2->getAsType(), 0));
609 case NestedNameSpecifier::Global:
610 return true;
611 case NestedNameSpecifier::Super:
612 return IsStructurallyEquivalent(Context, D1: NNS1->getAsRecordDecl(),
613 D2: NNS2->getAsRecordDecl());
614 }
615 return false;
616}
617
618static 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(Name1: II1, Name2: II2);
631}
632
633static 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, D1: TemplateDeclN1, D2: 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, D1: *I1, D2: *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, S1: *N1.getAsDependentTemplateName(),
671 S2: *N2.getAsDependentTemplateName());
672
673 case TemplateName::SubstTemplateTemplateParmPack: {
674 SubstTemplateTemplateParmPackStorage
675 *P1 = N1.getAsSubstTemplateTemplateParmPack(),
676 *P2 = N2.getAsSubstTemplateTemplateParmPack();
677 return IsStructurallyEquivalent(Context, Arg1: P1->getArgumentPack(),
678 Arg2: P2->getArgumentPack()) &&
679 IsStructurallyEquivalent(Context, D1: P1->getAssociatedDecl(),
680 D2: 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
699static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
700 ArrayRef<TemplateArgument> Args1,
701 ArrayRef<TemplateArgument> Args2);
702
703/// Determine whether two template arguments are equivalent.
704static 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, T1: Arg1.getAsType(), T2: Arg2.getAsType());
716
717 case TemplateArgument::Integral:
718 if (!IsStructurallyEquivalent(Context, T1: Arg1.getIntegralType(),
719 T2: Arg2.getIntegralType()))
720 return false;
721
722 return llvm::APSInt::isSameValue(I1: Arg1.getAsIntegral(),
723 I2: Arg2.getAsIntegral());
724
725 case TemplateArgument::Declaration:
726 return IsStructurallyEquivalent(Context, D1: Arg1.getAsDecl(), D2: Arg2.getAsDecl());
727
728 case TemplateArgument::NullPtr:
729 return true; // FIXME: Is this correct?
730
731 case TemplateArgument::Template:
732 return IsStructurallyEquivalent(Context, N1: Arg1.getAsTemplate(),
733 N2: Arg2.getAsTemplate());
734
735 case TemplateArgument::TemplateExpansion:
736 return IsStructurallyEquivalent(Context,
737 N1: Arg1.getAsTemplateOrTemplatePattern(),
738 N2: Arg2.getAsTemplateOrTemplatePattern());
739
740 case TemplateArgument::Expression:
741 return IsStructurallyEquivalent(Context, S1: Arg1.getAsExpr(),
742 S2: Arg2.getAsExpr());
743
744 case TemplateArgument::StructuralValue:
745 return Arg1.structurallyEquals(Other: Arg2);
746
747 case TemplateArgument::Pack:
748 return IsStructurallyEquivalent(Context, Args1: Arg1.pack_elements(),
749 Args2: Arg2.pack_elements());
750 }
751
752 llvm_unreachable("Invalid template argument kind");
753}
754
755/// Determine structural equivalence of two template argument lists.
756static 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, Arg1: Args1[I], Arg2: Args2[I]))
763 return false;
764 }
765 return true;
766}
767
768/// Determine whether two template argument locations are equivalent.
769static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
770 const TemplateArgumentLoc &Arg1,
771 const TemplateArgumentLoc &Arg2) {
772 return IsStructurallyEquivalent(Context, Arg1: Arg1.getArgument(),
773 Arg2: Arg2.getArgument());
774}
775
776/// Determine structural equivalence for the common part of array
777/// types.
778static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context,
779 const ArrayType *Array1,
780 const ArrayType *Array2) {
781 if (!IsStructurallyEquivalent(Context, T1: Array1->getElementType(),
782 T2: 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.
795static 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.
819static 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(ESpecType: Spec1) || isUnresolvedExceptionSpec(ESpecType: 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, T1: Proto1->getExceptionType(i: I),
836 T2: Proto2->getExceptionType(i: I)))
837 return false;
838 }
839 } else if (isComputedNoexcept(ESpecType: Spec1)) {
840 if (!IsStructurallyEquivalent(Context, S1: Proto1->getNoexceptExpr(),
841 S2: Proto2->getNoexceptExpr()))
842 return false;
843 }
844
845 return true;
846}
847
848/// Determine structural equivalence of two types.
849static 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(T: T1);
861 T2 = Context.ToCtx.getCanonicalType(T: 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>(Val&: T1)->getKind() != cast<BuiltinType>(Val&: T2)->getKind())
908 return false;
909 break;
910
911 case Type::Complex:
912 if (!IsStructurallyEquivalent(Context,
913 T1: cast<ComplexType>(Val&: T1)->getElementType(),
914 T2: cast<ComplexType>(Val&: 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 T1: cast<AdjustedType>(Val&: T1)->getOriginalType(),
923 T2: cast<AdjustedType>(Val&: T2)->getOriginalType()))
924 return false;
925 break;
926
927 case Type::Pointer:
928 if (!IsStructurallyEquivalent(Context,
929 T1: cast<PointerType>(Val&: T1)->getPointeeType(),
930 T2: cast<PointerType>(Val&: T2)->getPointeeType()))
931 return false;
932 break;
933
934 case Type::BlockPointer:
935 if (!IsStructurallyEquivalent(Context,
936 T1: cast<BlockPointerType>(Val&: T1)->getPointeeType(),
937 T2: cast<BlockPointerType>(Val&: T2)->getPointeeType()))
938 return false;
939 break;
940
941 case Type::LValueReference:
942 case Type::RValueReference: {
943 const auto *Ref1 = cast<ReferenceType>(Val&: T1);
944 const auto *Ref2 = cast<ReferenceType>(Val&: T2);
945 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
946 return false;
947 if (Ref1->isInnerRef() != Ref2->isInnerRef())
948 return false;
949 if (!IsStructurallyEquivalent(Context, T1: Ref1->getPointeeTypeAsWritten(),
950 T2: Ref2->getPointeeTypeAsWritten()))
951 return false;
952 break;
953 }
954
955 case Type::MemberPointer: {
956 const auto *MemPtr1 = cast<MemberPointerType>(Val&: T1);
957 const auto *MemPtr2 = cast<MemberPointerType>(Val&: T2);
958 if (!IsStructurallyEquivalent(Context, T1: MemPtr1->getPointeeType(),
959 T2: MemPtr2->getPointeeType()))
960 return false;
961 if (!IsStructurallyEquivalent(Context, NNS1: MemPtr1->getQualifier(),
962 NNS2: 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>(Val&: T1);
975 const auto *Array2 = cast<ConstantArrayType>(Val&: T2);
976 if (!llvm::APInt::isSameValue(I1: Array1->getSize(), I2: 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, Array1: cast<ArrayType>(Val&: T1),
986 Array2: cast<ArrayType>(Val&: T2)))
987 return false;
988 break;
989
990 case Type::VariableArray: {
991 const auto *Array1 = cast<VariableArrayType>(Val&: T1);
992 const auto *Array2 = cast<VariableArrayType>(Val&: T2);
993 if (!IsStructurallyEquivalent(Context, S1: Array1->getSizeExpr(),
994 S2: 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>(Val&: T1);
1005 const auto *Array2 = cast<DependentSizedArrayType>(Val&: T2);
1006 if (!IsStructurallyEquivalent(Context, S1: Array1->getSizeExpr(),
1007 S2: 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>(Val&: T1);
1018 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(Val&: T2);
1019 if (!IsStructurallyEquivalent(Context, S1: DepAddressSpace1->getAddrSpaceExpr(),
1020 S2: DepAddressSpace2->getAddrSpaceExpr()))
1021 return false;
1022 if (!IsStructurallyEquivalent(Context, T1: DepAddressSpace1->getPointeeType(),
1023 T2: DepAddressSpace2->getPointeeType()))
1024 return false;
1025
1026 break;
1027 }
1028
1029 case Type::DependentSizedExtVector: {
1030 const auto *Vec1 = cast<DependentSizedExtVectorType>(Val&: T1);
1031 const auto *Vec2 = cast<DependentSizedExtVectorType>(Val&: T2);
1032 if (!IsStructurallyEquivalent(Context, S1: Vec1->getSizeExpr(),
1033 S2: Vec2->getSizeExpr()))
1034 return false;
1035 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1036 T2: Vec2->getElementType()))
1037 return false;
1038 break;
1039 }
1040
1041 case Type::DependentVector: {
1042 const auto *Vec1 = cast<DependentVectorType>(Val&: T1);
1043 const auto *Vec2 = cast<DependentVectorType>(Val&: T2);
1044 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1045 return false;
1046 if (!IsStructurallyEquivalent(Context, S1: Vec1->getSizeExpr(),
1047 S2: Vec2->getSizeExpr()))
1048 return false;
1049 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1050 T2: Vec2->getElementType()))
1051 return false;
1052 break;
1053 }
1054
1055 case Type::Vector:
1056 case Type::ExtVector: {
1057 const auto *Vec1 = cast<VectorType>(Val&: T1);
1058 const auto *Vec2 = cast<VectorType>(Val&: T2);
1059 if (!IsStructurallyEquivalent(Context, T1: Vec1->getElementType(),
1060 T2: 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>(Val&: T1);
1071 const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(Val&: T2);
1072 // The element types, row and column expressions must be structurally
1073 // equivalent.
1074 if (!IsStructurallyEquivalent(Context, S1: Mat1->getRowExpr(),
1075 S2: Mat2->getRowExpr()) ||
1076 !IsStructurallyEquivalent(Context, S1: Mat1->getColumnExpr(),
1077 S2: Mat2->getColumnExpr()) ||
1078 !IsStructurallyEquivalent(Context, T1: Mat1->getElementType(),
1079 T2: Mat2->getElementType()))
1080 return false;
1081 break;
1082 }
1083
1084 case Type::ConstantMatrix: {
1085 const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(Val&: T1);
1086 const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(Val&: T2);
1087 // The element types must be structurally equivalent and the number of rows
1088 // and columns must match.
1089 if (!IsStructurallyEquivalent(Context, T1: Mat1->getElementType(),
1090 T2: 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>(Val&: T1);
1099 const auto *Proto2 = cast<FunctionProtoType>(Val&: 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, T1: Proto1->getParamType(i: I),
1105 T2: Proto2->getParamType(i: 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>(Val: OrigT1.getDesugaredType(Context: Context.FromCtx));
1117 const auto *OrigProto2 =
1118 cast<FunctionProtoType>(Val: OrigT2.getDesugaredType(Context: Context.ToCtx));
1119 if (!IsEquivalentExceptionSpec(Context, Proto1: OrigProto1, Proto2: 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>(Val&: T1);
1128 const auto *Function2 = cast<FunctionType>(Val&: T2);
1129 if (!IsStructurallyEquivalent(Context, T1: Function1->getReturnType(),
1130 T2: Function2->getReturnType()))
1131 return false;
1132 if (!IsStructurallyEquivalent(Context, EI1: Function1->getExtInfo(),
1133 EI2: Function2->getExtInfo()))
1134 return false;
1135 break;
1136 }
1137
1138 case Type::UnresolvedUsing:
1139 if (!IsStructurallyEquivalent(Context,
1140 D1: cast<UnresolvedUsingType>(Val&: T1)->getDecl(),
1141 D2: cast<UnresolvedUsingType>(Val&: T2)->getDecl()))
1142 return false;
1143 break;
1144
1145 case Type::Attributed:
1146 if (!IsStructurallyEquivalent(Context,
1147 T1: cast<AttributedType>(Val&: T1)->getModifiedType(),
1148 T2: cast<AttributedType>(Val&: T2)->getModifiedType()))
1149 return false;
1150 if (!IsStructurallyEquivalent(
1151 Context, T1: cast<AttributedType>(Val&: T1)->getEquivalentType(),
1152 T2: cast<AttributedType>(Val&: T2)->getEquivalentType()))
1153 return false;
1154 break;
1155
1156 case Type::CountAttributed:
1157 if (!IsStructurallyEquivalent(Context,
1158 T1: cast<CountAttributedType>(Val&: T1)->desugar(),
1159 T2: cast<CountAttributedType>(Val&: T2)->desugar()))
1160 return false;
1161 break;
1162
1163 case Type::BTFTagAttributed:
1164 if (!IsStructurallyEquivalent(
1165 Context, T1: cast<BTFTagAttributedType>(Val&: T1)->getWrappedType(),
1166 T2: cast<BTFTagAttributedType>(Val&: T2)->getWrappedType()))
1167 return false;
1168 break;
1169
1170 case Type::HLSLAttributedResource:
1171 if (!IsStructurallyEquivalent(
1172 Context, T1: cast<HLSLAttributedResourceType>(Val&: T1)->getWrappedType(),
1173 T2: cast<HLSLAttributedResourceType>(Val&: T2)->getWrappedType()))
1174 return false;
1175 if (!IsStructurallyEquivalent(
1176 Context, T1: cast<HLSLAttributedResourceType>(Val&: T1)->getContainedType(),
1177 T2: cast<HLSLAttributedResourceType>(Val&: T2)->getContainedType()))
1178 return false;
1179 if (cast<HLSLAttributedResourceType>(Val&: T1)->getAttrs() !=
1180 cast<HLSLAttributedResourceType>(Val&: T2)->getAttrs())
1181 return false;
1182 break;
1183
1184 case Type::HLSLInlineSpirv:
1185 if (cast<HLSLInlineSpirvType>(Val&: T1)->getOpcode() !=
1186 cast<HLSLInlineSpirvType>(Val&: T2)->getOpcode() ||
1187 cast<HLSLInlineSpirvType>(Val&: T1)->getSize() !=
1188 cast<HLSLInlineSpirvType>(Val&: T2)->getSize() ||
1189 cast<HLSLInlineSpirvType>(Val&: T1)->getAlignment() !=
1190 cast<HLSLInlineSpirvType>(Val&: T2)->getAlignment())
1191 return false;
1192 for (size_t I = 0; I < cast<HLSLInlineSpirvType>(Val&: T1)->getOperands().size();
1193 I++) {
1194 if (cast<HLSLInlineSpirvType>(Val&: T1)->getOperands()[I] !=
1195 cast<HLSLInlineSpirvType>(Val&: T2)->getOperands()[I]) {
1196 return false;
1197 }
1198 }
1199 break;
1200
1201 case Type::Paren:
1202 if (!IsStructurallyEquivalent(Context, T1: cast<ParenType>(Val&: T1)->getInnerType(),
1203 T2: cast<ParenType>(Val&: T2)->getInnerType()))
1204 return false;
1205 break;
1206
1207 case Type::MacroQualified:
1208 if (!IsStructurallyEquivalent(
1209 Context, T1: cast<MacroQualifiedType>(Val&: T1)->getUnderlyingType(),
1210 T2: cast<MacroQualifiedType>(Val&: T2)->getUnderlyingType()))
1211 return false;
1212 break;
1213
1214 case Type::Using:
1215 if (!IsStructurallyEquivalent(Context, D1: cast<UsingType>(Val&: T1)->getFoundDecl(),
1216 D2: cast<UsingType>(Val&: T2)->getFoundDecl()))
1217 return false;
1218 if (!IsStructurallyEquivalent(Context,
1219 T1: cast<UsingType>(Val&: T1)->getUnderlyingType(),
1220 T2: cast<UsingType>(Val&: T2)->getUnderlyingType()))
1221 return false;
1222 break;
1223
1224 case Type::Typedef:
1225 if (!IsStructurallyEquivalent(Context, D1: cast<TypedefType>(Val&: T1)->getDecl(),
1226 D2: cast<TypedefType>(Val&: T2)->getDecl()) ||
1227 !IsStructurallyEquivalent(Context, T1: cast<TypedefType>(Val&: T1)->desugar(),
1228 T2: cast<TypedefType>(Val&: T2)->desugar()))
1229 return false;
1230 break;
1231
1232 case Type::TypeOfExpr:
1233 if (!IsStructurallyEquivalent(
1234 Context, S1: cast<TypeOfExprType>(Val&: T1)->getUnderlyingExpr(),
1235 S2: cast<TypeOfExprType>(Val&: T2)->getUnderlyingExpr()))
1236 return false;
1237 break;
1238
1239 case Type::TypeOf:
1240 if (!IsStructurallyEquivalent(Context,
1241 T1: cast<TypeOfType>(Val&: T1)->getUnmodifiedType(),
1242 T2: cast<TypeOfType>(Val&: T2)->getUnmodifiedType()))
1243 return false;
1244 break;
1245
1246 case Type::UnaryTransform:
1247 if (!IsStructurallyEquivalent(
1248 Context, T1: cast<UnaryTransformType>(Val&: T1)->getUnderlyingType(),
1249 T2: cast<UnaryTransformType>(Val&: T2)->getUnderlyingType()))
1250 return false;
1251 break;
1252
1253 case Type::Decltype:
1254 if (!IsStructurallyEquivalent(Context,
1255 S1: cast<DecltypeType>(Val&: T1)->getUnderlyingExpr(),
1256 S2: cast<DecltypeType>(Val&: T2)->getUnderlyingExpr()))
1257 return false;
1258 break;
1259
1260 case Type::Auto: {
1261 auto *Auto1 = cast<AutoType>(Val&: T1);
1262 auto *Auto2 = cast<AutoType>(Val&: T2);
1263 if (!IsStructurallyEquivalent(Context, T1: Auto1->getDeducedType(),
1264 T2: 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 Args1: Auto1->getTypeConstraintArguments(),
1274 Args2: Auto2->getTypeConstraintArguments()))
1275 return false;
1276 }
1277 break;
1278 }
1279
1280 case Type::DeducedTemplateSpecialization: {
1281 const auto *DT1 = cast<DeducedTemplateSpecializationType>(Val&: T1);
1282 const auto *DT2 = cast<DeducedTemplateSpecializationType>(Val&: T2);
1283 if (!IsStructurallyEquivalent(Context, N1: DT1->getTemplateName(),
1284 N2: DT2->getTemplateName()))
1285 return false;
1286 if (!IsStructurallyEquivalent(Context, T1: DT1->getDeducedType(),
1287 T2: DT2->getDeducedType()))
1288 return false;
1289 break;
1290 }
1291
1292 case Type::Record:
1293 case Type::Enum:
1294 if (!IsStructurallyEquivalent(Context, D1: cast<TagType>(Val&: T1)->getDecl(),
1295 D2: cast<TagType>(Val&: T2)->getDecl()))
1296 return false;
1297 break;
1298
1299 case Type::TemplateTypeParm: {
1300 const auto *Parm1 = cast<TemplateTypeParmType>(Val&: T1);
1301 const auto *Parm2 = cast<TemplateTypeParmType>(Val&: 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>(Val&: T1);
1316 const auto *Subst2 = cast<SubstTemplateTypeParmType>(Val&: T2);
1317 if (!IsStructurallyEquivalent(Context, T1: Subst1->getReplacementType(),
1318 T2: Subst2->getReplacementType()))
1319 return false;
1320 if (!IsStructurallyEquivalent(Context, D1: Subst1->getAssociatedDecl(),
1321 D2: 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>(Val&: T1);
1332 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(Val&: T2);
1333 if (!IsStructurallyEquivalent(Context, D1: Subst1->getAssociatedDecl(),
1334 D2: Subst2->getAssociatedDecl()))
1335 return false;
1336 if (Subst1->getIndex() != Subst2->getIndex())
1337 return false;
1338 if (!IsStructurallyEquivalent(Context, Arg1: Subst1->getArgumentPack(),
1339 Arg2: Subst2->getArgumentPack()))
1340 return false;
1341 break;
1342 }
1343
1344 case Type::TemplateSpecialization: {
1345 const auto *Spec1 = cast<TemplateSpecializationType>(Val&: T1);
1346 const auto *Spec2 = cast<TemplateSpecializationType>(Val&: T2);
1347 if (!IsStructurallyEquivalent(Context, N1: Spec1->getTemplateName(),
1348 N2: Spec2->getTemplateName()))
1349 return false;
1350 if (!IsStructurallyEquivalent(Context, Args1: Spec1->template_arguments(),
1351 Args2: Spec2->template_arguments()))
1352 return false;
1353 break;
1354 }
1355
1356 case Type::Elaborated: {
1357 const auto *Elab1 = cast<ElaboratedType>(Val&: T1);
1358 const auto *Elab2 = cast<ElaboratedType>(Val&: 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, NNS1: Elab1->getQualifier(),
1365 NNS2: Elab2->getQualifier()))
1366 return false;
1367 if (!IsStructurallyEquivalent(Context, T1: Elab1->getNamedType(),
1368 T2: Elab2->getNamedType()))
1369 return false;
1370 break;
1371 }
1372
1373 case Type::InjectedClassName: {
1374 const auto *Inj1 = cast<InjectedClassNameType>(Val&: T1);
1375 const auto *Inj2 = cast<InjectedClassNameType>(Val&: T2);
1376 if (!IsStructurallyEquivalent(Context,
1377 T1: Inj1->getInjectedSpecializationType(),
1378 T2: Inj2->getInjectedSpecializationType()))
1379 return false;
1380 break;
1381 }
1382
1383 case Type::DependentName: {
1384 const auto *Typename1 = cast<DependentNameType>(Val&: T1);
1385 const auto *Typename2 = cast<DependentNameType>(Val&: T2);
1386 if (!IsStructurallyEquivalent(Context, NNS1: Typename1->getQualifier(),
1387 NNS2: Typename2->getQualifier()))
1388 return false;
1389 if (!IsStructurallyEquivalent(Name1: Typename1->getIdentifier(),
1390 Name2: Typename2->getIdentifier()))
1391 return false;
1392
1393 break;
1394 }
1395
1396 case Type::DependentTemplateSpecialization: {
1397 const auto *Spec1 = cast<DependentTemplateSpecializationType>(Val&: T1);
1398 const auto *Spec2 = cast<DependentTemplateSpecializationType>(Val&: T2);
1399 if (Spec1->getKeyword() != Spec2->getKeyword())
1400 return false;
1401 if (!IsStructurallyEquivalent(Context, S1: Spec1->getDependentTemplateName(),
1402 S2: Spec2->getDependentTemplateName()))
1403 return false;
1404 if (!IsStructurallyEquivalent(Context, Args1: Spec1->template_arguments(),
1405 Args2: Spec2->template_arguments()))
1406 return false;
1407 break;
1408 }
1409
1410 case Type::PackExpansion:
1411 if (!IsStructurallyEquivalent(Context,
1412 T1: cast<PackExpansionType>(Val&: T1)->getPattern(),
1413 T2: cast<PackExpansionType>(Val&: T2)->getPattern()))
1414 return false;
1415 break;
1416
1417 case Type::PackIndexing:
1418 if (!IsStructurallyEquivalent(Context,
1419 T1: cast<PackIndexingType>(Val&: T1)->getPattern(),
1420 T2: cast<PackIndexingType>(Val&: T2)->getPattern()))
1421 if (!IsStructurallyEquivalent(Context,
1422 S1: cast<PackIndexingType>(Val&: T1)->getIndexExpr(),
1423 S2: cast<PackIndexingType>(Val&: T2)->getIndexExpr()))
1424 return false;
1425 break;
1426
1427 case Type::ObjCInterface: {
1428 const auto *Iface1 = cast<ObjCInterfaceType>(Val&: T1);
1429 const auto *Iface2 = cast<ObjCInterfaceType>(Val&: T2);
1430 if (!IsStructurallyEquivalent(Context, D1: Iface1->getDecl(),
1431 D2: Iface2->getDecl()))
1432 return false;
1433 break;
1434 }
1435
1436 case Type::ObjCTypeParam: {
1437 const auto *Obj1 = cast<ObjCTypeParamType>(Val&: T1);
1438 const auto *Obj2 = cast<ObjCTypeParamType>(Val&: T2);
1439 if (!IsStructurallyEquivalent(Context, D1: Obj1->getDecl(), D2: 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, D1: Obj1->getProtocol(I),
1446 D2: Obj2->getProtocol(I)))
1447 return false;
1448 }
1449 break;
1450 }
1451
1452 case Type::ObjCObject: {
1453 const auto *Obj1 = cast<ObjCObjectType>(Val&: T1);
1454 const auto *Obj2 = cast<ObjCObjectType>(Val&: T2);
1455 if (!IsStructurallyEquivalent(Context, T1: Obj1->getBaseType(),
1456 T2: 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, D1: Obj1->getProtocol(I),
1462 D2: Obj2->getProtocol(I)))
1463 return false;
1464 }
1465 break;
1466 }
1467
1468 case Type::ObjCObjectPointer: {
1469 const auto *Ptr1 = cast<ObjCObjectPointerType>(Val&: T1);
1470 const auto *Ptr2 = cast<ObjCObjectPointerType>(Val&: T2);
1471 if (!IsStructurallyEquivalent(Context, T1: Ptr1->getPointeeType(),
1472 T2: Ptr2->getPointeeType()))
1473 return false;
1474 break;
1475 }
1476
1477 case Type::Atomic:
1478 if (!IsStructurallyEquivalent(Context, T1: cast<AtomicType>(Val&: T1)->getValueType(),
1479 T2: cast<AtomicType>(Val&: T2)->getValueType()))
1480 return false;
1481 break;
1482
1483 case Type::Pipe:
1484 if (!IsStructurallyEquivalent(Context, T1: cast<PipeType>(Val&: T1)->getElementType(),
1485 T2: cast<PipeType>(Val&: T2)->getElementType()))
1486 return false;
1487 break;
1488 case Type::BitInt: {
1489 const auto *Int1 = cast<BitIntType>(Val&: T1);
1490 const auto *Int2 = cast<BitIntType>(Val&: 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>(Val&: T1);
1499 const auto *Int2 = cast<DependentBitIntType>(Val&: T2);
1500
1501 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1502 !IsStructurallyEquivalent(Context, S1: Int1->getNumBitsExpr(),
1503 S2: Int2->getNumBitsExpr()))
1504 return false;
1505 break;
1506 }
1507 } // end switch
1508
1509 return true;
1510}
1511
1512static 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, T1: D1->getType(), T2: 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, S1: D1->getInit(), S2: D2->getInit());
1532}
1533
1534static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1535 FieldDecl *Field1, FieldDecl *Field2,
1536 QualType Owner2Type) {
1537 const auto *Owner2 = cast<Decl>(Val: 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, D1: Field1, D2: Field2, PrimaryDecl: 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 Loc: Owner2->getLocation(),
1562 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1563 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1564 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field_name)
1565 << Field2->getDeclName();
1566 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field_name)
1567 << Field1->getDeclName();
1568 }
1569 return false;
1570 }
1571
1572 if (!IsStructurallyEquivalent(Context, T1: Field1->getType(),
1573 T2: Field2->getType())) {
1574 if (Context.Complain) {
1575 Context.Diag2(
1576 Loc: Owner2->getLocation(),
1577 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1578 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1579 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field)
1580 << Field2->getDeclName() << Field2->getType();
1581 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field)
1582 << Field1->getDeclName() << Field1->getType();
1583 }
1584 return false;
1585 }
1586
1587 if ((Field1->isBitField() || Field2->isBitField()) &&
1588 !IsStructurallyEquivalent(Context, S1: Field1->getBitWidth(),
1589 S2: 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 Loc: Owner2->getLocation(),
1613 DiagID: Context.getApplicableDiagnostic(ErrorDiagnostic: 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.
1625static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
1626 FieldDecl *Field1, FieldDecl *Field2) {
1627 const auto *Owner2 = cast<RecordDecl>(Val: Field2->getDeclContext());
1628 return IsStructurallyEquivalent(Context, Field1, Field2,
1629 Owner2Type: Context.ToCtx.getTypeDeclType(Decl: Owner2));
1630}
1631
1632/// Determine structural equivalence of two methods.
1633static 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>(Val: Method1)) {
1660 auto *Constructor2 = cast<CXXConstructorDecl>(Val: Method2);
1661 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1662 Other: Constructor2->getExplicitSpecifier()))
1663 return false;
1664 }
1665
1666 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Val: Method1)) {
1667 auto *Conversion2 = cast<CXXConversionDecl>(Val: Method2);
1668 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1669 Other: Conversion2->getExplicitSpecifier()))
1670 return false;
1671 if (!IsStructurallyEquivalent(Context, T1: Conversion1->getConversionType(),
1672 T2: 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 T1: Method1->getType(), T2: Method2->getType()))
1686 return false;
1687
1688 return true;
1689}
1690
1691/// Determine structural equivalence of two lambda classes.
1692static bool
1693IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context,
1694 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1695 assert(D1->isLambda() && D2->isLambda() &&
1696 "Must be called on lambda classes");
1697 if (!IsStructurallyEquivalent(Context, Method1: D1->getLambdaCallOperator(),
1698 Method2: D2->getLambdaCallOperator()))
1699 return false;
1700
1701 return true;
1702}
1703
1704/// Determine if context of a class is equivalent.
1705static bool
1706IsRecordContextStructurallyEquivalent(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>(Val: DC1)) {
1728 const auto *ND2 = cast<NamedDecl>(Val: DC2);
1729 if (!DC1->isInlineNamespace() &&
1730 !IsStructurallyEquivalent(Name1: ND1->getIdentifier(), Name2: ND2->getIdentifier()))
1731 return false;
1732 }
1733
1734 if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC1)) {
1735 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC2);
1736 if (!IsStructurallyEquivalent(Context, D1: D1Spec, D2: D2Spec))
1737 return false;
1738 }
1739
1740 DC1 = DC1->getParent()->getNonTransparentContext();
1741 DC2 = DC2->getParent()->getNonTransparentContext();
1742 }
1743
1744 return true;
1745}
1746
1747static 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(Name1: GetName(D1), Name2: GetName(D2));
1756}
1757
1758/// Determine structural equivalence of two records.
1759static 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: *D1, D2: *D2))
1796 return false;
1797
1798 if (D1->isUnion() != D2->isUnion()) {
1799 if (Context.Complain) {
1800 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
1801 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1802 << Context.ToCtx.getTypeDeclType(Decl: D2)
1803 << (&Context.FromCtx != &Context.ToCtx);
1804 Context.Diag1(Loc: D1->getLocation(), DiagID: 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(Anon: D1)) {
1815 if (UnsignedOrNone Index2 =
1816 StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
1817 Anon: 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>(Val: D1);
1842 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(Val: D2);
1843 if (Spec1 && Spec2) {
1844 // Check that the specialized templates are the same.
1845 if (!IsStructurallyEquivalent(Context, D1: Spec1->getSpecializedTemplate(),
1846 D2: 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, Arg1: Spec1->getTemplateArgs().get(Idx: I),
1855 Arg2: Spec2->getTemplateArgs().get(Idx: 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>(Val: D1)) {
1886 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(Val: D2)) {
1887 if (D1CXX->hasExternalLexicalStorage() &&
1888 !D1CXX->isCompleteDefinition()) {
1889 D1CXX->getASTContext().getExternalSource()->CompleteType(Tag: D1CXX);
1890 }
1891
1892 if (D1CXX->isLambda() != D2CXX->isLambda())
1893 return false;
1894 if (D1CXX->isLambda()) {
1895 if (!IsStructurallyEquivalentLambdas(Context, D1: D1CXX, D2: D2CXX))
1896 return false;
1897 }
1898
1899 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1900 if (Context.Complain) {
1901 Context.Diag2(Loc: D2->getLocation(),
1902 DiagID: Context.getApplicableDiagnostic(
1903 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1904 << Context.ToCtx.getTypeDeclType(Decl: D2)
1905 << (&Context.FromCtx != &Context.ToCtx);
1906 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_number_of_bases)
1907 << D2CXX->getNumBases();
1908 Context.Diag1(Loc: D1->getLocation(), DiagID: 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, T1: Base1->getType(),
1920 T2: Base2->getType())) {
1921 if (Context.Complain) {
1922 Context.Diag2(Loc: D2->getLocation(),
1923 DiagID: Context.getApplicableDiagnostic(
1924 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1925 << Context.ToCtx.getTypeDeclType(Decl: D2)
1926 << (&Context.FromCtx != &Context.ToCtx);
1927 Context.Diag2(Loc: Base2->getBeginLoc(), DiagID: diag::note_odr_base)
1928 << Base2->getType() << Base2->getSourceRange();
1929 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: 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(Loc: D2->getLocation(),
1939 DiagID: Context.getApplicableDiagnostic(
1940 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1941 << Context.ToCtx.getTypeDeclType(Decl: D2)
1942 << (&Context.FromCtx != &Context.ToCtx);
1943 Context.Diag2(Loc: Base2->getBeginLoc(), DiagID: diag::note_odr_virtual_base)
1944 << Base2->isVirtual() << Base2->getSourceRange();
1945 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: 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(Loc: D2->getLocation(),
1961 DiagID: Context.getApplicableDiagnostic(
1962 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1963 << Context.ToCtx.getTypeDeclType(Decl: D2CXX)
1964 << (&Context.FromCtx != &Context.ToCtx);
1965 Context.Diag1(Loc: (*Friend1)->getFriendLoc(), DiagID: diag::note_odr_friend);
1966 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_friend);
1967 }
1968 return false;
1969 }
1970
1971 if (!IsStructurallyEquivalent(Context, D1: *Friend1, D2: *Friend2)) {
1972 if (Context.Complain) {
1973 Context.Diag2(Loc: D2->getLocation(),
1974 DiagID: Context.getApplicableDiagnostic(
1975 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1976 << Context.ToCtx.getTypeDeclType(Decl: D2CXX)
1977 << (&Context.FromCtx != &Context.ToCtx);
1978 Context.Diag1(Loc: (*Friend1)->getFriendLoc(), DiagID: diag::note_odr_friend);
1979 Context.Diag2(Loc: (*Friend2)->getFriendLoc(), DiagID: diag::note_odr_friend);
1980 }
1981 return false;
1982 }
1983 }
1984
1985 if (Friend2 != Friend2End) {
1986 if (Context.Complain) {
1987 Context.Diag2(Loc: D2->getLocation(),
1988 DiagID: Context.getApplicableDiagnostic(
1989 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
1990 << Context.ToCtx.getTypeDeclType(Decl: D2)
1991 << (&Context.FromCtx != &Context.ToCtx);
1992 Context.Diag2(Loc: (*Friend2)->getFriendLoc(), DiagID: diag::note_odr_friend);
1993 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_friend);
1994 }
1995 return false;
1996 }
1997 } else if (D1CXX->getNumBases() > 0) {
1998 if (Context.Complain) {
1999 Context.Diag2(Loc: D2->getLocation(),
2000 DiagID: Context.getApplicableDiagnostic(
2001 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2002 << Context.ToCtx.getTypeDeclType(Decl: D2)
2003 << (&Context.FromCtx != &Context.ToCtx);
2004 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
2005 Context.Diag1(Loc: Base1->getBeginLoc(), DiagID: diag::note_odr_base)
2006 << Base1->getType() << Base1->getSourceRange();
2007 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_base);
2008 }
2009 return false;
2010 }
2011 }
2012
2013 // Check the fields for consistency.
2014 QualType D2Type = Context.ToCtx.getTypeDeclType(Decl: 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(Loc: D2->getLocation(),
2023 DiagID: Context.getApplicableDiagnostic(
2024 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2025 << Context.ToCtx.getTypeDeclType(Decl: D2)
2026 << (&Context.FromCtx != &Context.ToCtx);
2027 Context.Diag1(Loc: Field1->getLocation(), DiagID: diag::note_odr_field)
2028 << Field1->getDeclName() << Field1->getType();
2029 Context.Diag2(Loc: D2->getLocation(), DiagID: diag::note_odr_missing_field);
2030 }
2031 return false;
2032 }
2033
2034 if (!IsStructurallyEquivalent(Context, Field1: *Field1, Field2: *Field2, Owner2Type: D2Type))
2035 return false;
2036 }
2037
2038 if (Field2 != Field2End) {
2039 if (Context.Complain) {
2040 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
2041 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2042 << Context.ToCtx.getTypeDeclType(Decl: D2)
2043 << (&Context.FromCtx != &Context.ToCtx);
2044 Context.Diag2(Loc: Field2->getLocation(), DiagID: diag::note_odr_field)
2045 << Field2->getDeclName() << Field2->getType();
2046 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_field);
2047 }
2048 return false;
2049 }
2050
2051 return true;
2052}
2053
2054static 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(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2067 return false;
2068
2069 // Init expressions are the most expensive check, so do them last.
2070 return IsStructurallyEquivalent(Context, S1: D1->getInitExpr(),
2071 S2: D2->getInitExpr());
2072}
2073
2074/// Determine structural equivalence of two enums.
2075static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2076 EnumDecl *D1, EnumDecl *D2) {
2077 if (!NameIsStructurallyEquivalent(D1: *D1, D2: *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(Loc: D2->getLocation(),
2100 DiagID: Context.getApplicableDiagnostic(
2101 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2102 << Context.ToCtx.getTypeDeclType(Decl: D2)
2103 << (&Context.FromCtx != &Context.ToCtx);
2104 Context.Diag1(Loc: D1->getLocation(),
2105 DiagID: D1->isFixed()
2106 ? diag::note_odr_fixed_underlying_type
2107 : diag::note_odr_missing_fixed_underlying_type)
2108 << D1;
2109 Context.Diag2(Loc: D2->getLocation(),
2110 DiagID: 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, T1: D1->getIntegerType(),
2120 T2: D2->getIntegerType())) {
2121 if (Context.Complain) {
2122 Context.Diag2(Loc: D2->getLocation(),
2123 DiagID: Context.getApplicableDiagnostic(
2124 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2125 << Context.ToCtx.getTypeDeclType(Decl: D2)
2126 << (&Context.FromCtx != &Context.ToCtx);
2127 Context.Diag2(Loc: D2->getLocation(),
2128 DiagID: 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(Elt: 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(C&: D1Enums, Comp: Sorter);
2152 llvm::sort(C&: D2Enums, Comp: 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(Loc: D2->getLocation(),
2161 DiagID: Context.getApplicableDiagnostic(
2162 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2163 << Context.ToCtx.getTypeDeclType(Decl: D2)
2164 << (&Context.FromCtx != &Context.ToCtx);
2165 Context.Diag1(Loc: (*EC1)->getLocation(), DiagID: diag::note_odr_enumerator)
2166 << (*EC1)->getDeclName() << toString(I: (*EC1)->getInitVal(), Radix: 10);
2167 Context.Diag2(Loc: D2->getLocation(), DiagID: 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(I1: Val1, I2: Val2) ||
2175 !IsStructurallyEquivalent(Name1: (*EC1)->getIdentifier(),
2176 Name2: (*EC2)->getIdentifier())) {
2177 if (Context.Complain) {
2178 Context.Diag2(Loc: D2->getLocation(),
2179 DiagID: Context.getApplicableDiagnostic(
2180 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2181 << Context.ToCtx.getTypeDeclType(Decl: D2)
2182 << (&Context.FromCtx != &Context.ToCtx);
2183 Context.Diag2(Loc: (*EC2)->getLocation(), DiagID: diag::note_odr_enumerator)
2184 << (*EC2)->getDeclName() << toString(I: (*EC2)->getInitVal(), Radix: 10);
2185 Context.Diag1(Loc: (*EC1)->getLocation(), DiagID: diag::note_odr_enumerator)
2186 << (*EC1)->getDeclName() << toString(I: (*EC1)->getInitVal(), Radix: 10);
2187 }
2188 return false;
2189 }
2190 if (Context.LangOpts.C23 &&
2191 !CheckStructurallyEquivalentAttributes(Context, D1: *EC1, D2: *EC2, PrimaryDecl: D2))
2192 return false;
2193 }
2194
2195 if (EC2 != EC2End) {
2196 if (Context.Complain) {
2197 Context.Diag2(Loc: D2->getLocation(), DiagID: Context.getApplicableDiagnostic(
2198 ErrorDiagnostic: diag::err_odr_tag_type_inconsistent))
2199 << Context.ToCtx.getTypeDeclType(Decl: D2)
2200 << (&Context.FromCtx != &Context.ToCtx);
2201 Context.Diag2(Loc: (*EC2)->getLocation(), DiagID: diag::note_odr_enumerator)
2202 << (*EC2)->getDeclName() << toString(I: (*EC2)->getInitVal(), Radix: 10);
2203 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_missing_enumerator);
2204 }
2205 return false;
2206 }
2207
2208 return true;
2209}
2210
2211static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2212 TemplateParameterList *Params1,
2213 TemplateParameterList *Params2) {
2214 if (Params1->size() != Params2->size()) {
2215 if (Context.Complain) {
2216 Context.Diag2(Loc: Params2->getTemplateLoc(),
2217 DiagID: Context.getApplicableDiagnostic(
2218 ErrorDiagnostic: diag::err_odr_different_num_template_parameters))
2219 << Params1->size() << Params2->size();
2220 Context.Diag1(Loc: Params1->getTemplateLoc(),
2221 DiagID: 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(Idx: I)->getKind() != Params2->getParam(Idx: I)->getKind()) {
2228 if (Context.Complain) {
2229 Context.Diag2(Loc: Params2->getParam(Idx: I)->getLocation(),
2230 DiagID: Context.getApplicableDiagnostic(
2231 ErrorDiagnostic: diag::err_odr_different_template_parameter_kind));
2232 Context.Diag1(Loc: Params1->getParam(Idx: I)->getLocation(),
2233 DiagID: diag::note_odr_template_parameter_here);
2234 }
2235 return false;
2236 }
2237
2238 if (!IsStructurallyEquivalent(Context, D1: Params1->getParam(Idx: I),
2239 D2: Params2->getParam(Idx: I)))
2240 return false;
2241 }
2242
2243 return true;
2244}
2245
2246static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2247 TemplateTypeParmDecl *D1,
2248 TemplateTypeParmDecl *D2) {
2249 if (D1->isParameterPack() != D2->isParameterPack()) {
2250 if (Context.Complain) {
2251 Context.Diag2(Loc: D2->getLocation(),
2252 DiagID: Context.getApplicableDiagnostic(
2253 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2254 << D2->isParameterPack();
2255 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_parameter_pack_non_pack)
2256 << D1->isParameterPack();
2257 }
2258 return false;
2259 }
2260
2261 return true;
2262}
2263
2264static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2265 NonTypeTemplateParmDecl *D1,
2266 NonTypeTemplateParmDecl *D2) {
2267 if (D1->isParameterPack() != D2->isParameterPack()) {
2268 if (Context.Complain) {
2269 Context.Diag2(Loc: D2->getLocation(),
2270 DiagID: Context.getApplicableDiagnostic(
2271 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2272 << D2->isParameterPack();
2273 Context.Diag1(Loc: D1->getLocation(), DiagID: 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, T1: D1->getType(), T2: D2->getType())) {
2284 if (Context.Complain) {
2285 Context.Diag2(Loc: D2->getLocation(),
2286 DiagID: Context.getApplicableDiagnostic(
2287 ErrorDiagnostic: diag::err_odr_non_type_parameter_type_inconsistent))
2288 << D2->getType() << D1->getType();
2289 Context.Diag1(Loc: D1->getLocation(), DiagID: diag::note_odr_value_here)
2290 << D1->getType();
2291 }
2292 return false;
2293 }
2294
2295 return true;
2296}
2297
2298static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2299 TemplateTemplateParmDecl *D1,
2300 TemplateTemplateParmDecl *D2) {
2301 if (D1->isParameterPack() != D2->isParameterPack()) {
2302 if (Context.Complain) {
2303 Context.Diag2(Loc: D2->getLocation(),
2304 DiagID: Context.getApplicableDiagnostic(
2305 ErrorDiagnostic: diag::err_odr_parameter_pack_non_pack))
2306 << D2->isParameterPack();
2307 Context.Diag1(Loc: D1->getLocation(), DiagID: 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, Params1: D1->getTemplateParameters(),
2315 Params2: D2->getTemplateParameters());
2316}
2317
2318static bool IsTemplateDeclCommonStructurallyEquivalent(
2319 StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2) {
2320 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2321 return false;
2322 if (!D1->getIdentifier()) // Special name
2323 if (D1->getNameAsString() != D2->getNameAsString())
2324 return false;
2325 return IsStructurallyEquivalent(Context&: Ctx, Params1: D1->getTemplateParameters(),
2326 Params2: D2->getTemplateParameters());
2327}
2328
2329static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2330 ClassTemplateDecl *D1,
2331 ClassTemplateDecl *D2) {
2332 // Check template parameters.
2333 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2334 return false;
2335
2336 // Check the templated declaration.
2337 return IsStructurallyEquivalent(Context, D1: D1->getTemplatedDecl(),
2338 D2: D2->getTemplatedDecl());
2339}
2340
2341static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2342 FunctionTemplateDecl *D1,
2343 FunctionTemplateDecl *D2) {
2344 // Check template parameters.
2345 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2346 return false;
2347
2348 // Check the templated declaration.
2349 return IsStructurallyEquivalent(Context, T1: D1->getTemplatedDecl()->getType(),
2350 T2: D2->getTemplatedDecl()->getType());
2351}
2352
2353static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2354 TypeAliasTemplateDecl *D1,
2355 TypeAliasTemplateDecl *D2) {
2356 // Check template parameters.
2357 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2358 return false;
2359
2360 // Check the templated declaration.
2361 return IsStructurallyEquivalent(Context, D1: D1->getTemplatedDecl(),
2362 D2: D2->getTemplatedDecl());
2363}
2364
2365static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2366 ConceptDecl *D1,
2367 ConceptDecl *D2) {
2368 // Check template parameters.
2369 if (!IsTemplateDeclCommonStructurallyEquivalent(Ctx&: Context, D1, D2))
2370 return false;
2371
2372 // Check the constraint expression.
2373 return IsStructurallyEquivalent(Context, S1: D1->getConstraintExpr(),
2374 S2: D2->getConstraintExpr());
2375}
2376
2377static 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 T1: D1->getFriendType()->getType(),
2386 T2: D2->getFriendType()->getType());
2387 if (D1->getFriendDecl() && D2->getFriendDecl())
2388 return IsStructurallyEquivalent(Context, D1: D1->getFriendDecl(),
2389 D2: D2->getFriendDecl());
2390 return false;
2391}
2392
2393static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2394 TypedefNameDecl *D1, TypedefNameDecl *D2) {
2395 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: D2->getIdentifier()))
2396 return false;
2397
2398 return IsStructurallyEquivalent(Context, T1: D1->getUnderlyingType(),
2399 T2: D2->getUnderlyingType());
2400}
2401
2402static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2403 FunctionDecl *D1, FunctionDecl *D2) {
2404 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: 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, T1: D1->getType(), T2: D2->getType()))
2416 return false;
2417
2418 return true;
2419}
2420
2421static 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, Field1: cast<FieldDecl>(Val: D1),
2428 Field2: cast<FieldDecl>(Val: D2), Owner2Type);
2429}
2430
2431static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2432 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2433 QualType Owner2Type =
2434 Context.ToCtx.getObjCInterfaceType(Decl: D2->getContainingInterface());
2435 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2436}
2437
2438static 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(Name1: Selector1.getIdentifierInfoForSlot(argIndex: I),
2459 Name2: Selector2.getIdentifierInfoForSlot(argIndex: I)))
2460 return false;
2461 }
2462
2463 // Compare types.
2464 if (!IsStructurallyEquivalent(Context, T1: Method1->getReturnType(),
2465 T2: 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, T1: *ParamT1, T2: *ParamT2))
2478 return false;
2479 }
2480
2481 return true;
2482}
2483
2484static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
2485 ObjCCategoryDecl *D1,
2486 ObjCCategoryDecl *D2) {
2487 if (!IsStructurallyEquivalent(Name1: D1->getIdentifier(), Name2: 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(Name1: Intf1->getIdentifier(), Name2: 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(Name1: (*Protocol1)->getIdentifier(),
2508 Name2: (*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(Decl: 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, D1: *Ivar1, D2: *Ivar2, Owner2Type: 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: *Method1, Method2: *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.
2548static 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 V: std::make_tuple(args&: D1, args&: D2, args&: 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(V: P).second;
2566 if (!Inserted)
2567 return true;
2568
2569 Context.DeclsToCheck.push(x: P);
2570
2571 return true;
2572}
2573
2574DiagnosticBuilder StructuralEquivalenceContext::Diag1(SourceLocation Loc,
2575 unsigned DiagID) {
2576 assert(Complain && "Not allowed to complain");
2577 if (LastDiagFromC2)
2578 FromCtx.getDiagnostics().notePriorDiagnosticFrom(Other: ToCtx.getDiagnostics());
2579 LastDiagFromC2 = false;
2580 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2581}
2582
2583DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc,
2584 unsigned DiagID) {
2585 assert(Complain && "Not allowed to complain");
2586 if (!LastDiagFromC2)
2587 ToCtx.getDiagnostics().notePriorDiagnosticFrom(Other: FromCtx.getDiagnostics());
2588 LastDiagFromC2 = true;
2589 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2590}
2591
2592UnsignedOrNone
2593StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
2594 ASTContext &Context = Anon->getASTContext();
2595 QualType AnonTy = Context.getRecordType(Decl: Anon);
2596
2597 const auto *Owner = dyn_cast<RecordDecl>(Val: 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>(Val: D);
2604 if (!F)
2605 continue;
2606
2607 if (F->isAnonymousStructOrUnion()) {
2608 if (Context.hasSameType(T1: F->getType(), T2: 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>(Val&: FieldType))
2619 FieldType = ElabType->getNamedType();
2620
2621 if (const auto *RecType = dyn_cast<RecordType>(Val&: FieldType)) {
2622 const RecordDecl *RecDecl = RecType->getDecl();
2623 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2624 if (Context.hasSameType(T1: FieldType, T2: AnonTy))
2625 break;
2626 ++Index;
2627 continue;
2628 }
2629 }
2630 }
2631
2632 return Index;
2633}
2634
2635unsigned 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
2681bool 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(Context&: *this, D1, D2))
2695 return false;
2696
2697 return !Finish();
2698}
2699
2700bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
2701 assert(DeclsToCheck.empty());
2702 assert(VisitedDecls.empty());
2703 if (!::IsStructurallyEquivalent(Context&: *this, T1, T2))
2704 return false;
2705
2706 return !Finish();
2707}
2708
2709bool StructuralEquivalenceContext::IsEquivalent(Stmt *S1, Stmt *S2) {
2710 assert(DeclsToCheck.empty());
2711 assert(VisitedDecls.empty());
2712 if (!::IsStructurallyEquivalent(Context&: *this, S1, S2))
2713 return false;
2714
2715 return !Finish();
2716}
2717
2718bool 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(Context&: *this, D1: Template1, D2: Template2))
2725 return false;
2726
2727 // FIXME: Move check for identifier names into this function.
2728
2729 return true;
2730}
2731
2732bool 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
2752bool 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 V: std::make_tuple(args&: D1, args&: D2, args&: IgnoreTemplateParmDepth));
2769
2770 return true;
2771 }
2772 }
2773
2774 return false;
2775}
2776

source code of clang/lib/AST/ASTStructuralEquivalence.cpp