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