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