clang 18.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/Decl.h"
65#include "clang/AST/DeclBase.h"
66#include "clang/AST/DeclCXX.h"
68#include "clang/AST/DeclObjC.h"
71#include "clang/AST/ExprCXX.h"
73#include "clang/AST/ExprObjC.h"
76#include "clang/AST/StmtObjC.h"
80#include "clang/AST/Type.h"
83#include "clang/Basic/LLVM.h"
85#include "llvm/ADT/APInt.h"
86#include "llvm/ADT/APSInt.h"
87#include "llvm/ADT/StringExtras.h"
88#include "llvm/Support/Casting.h"
89#include "llvm/Support/Compiler.h"
90#include "llvm/Support/ErrorHandling.h"
91#include <cassert>
92#include <optional>
93#include <utility>
94
95using namespace clang;
96
98 QualType T1, QualType T2);
100 Decl *D1, Decl *D2);
102 const TemplateArgument &Arg1,
103 const TemplateArgument &Arg2);
105 const TemplateArgumentLoc &Arg1,
106 const TemplateArgumentLoc &Arg2);
109 NestedNameSpecifier *NNS2);
110static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
111 const IdentifierInfo *Name2);
112
114 const DeclarationName Name1,
115 const DeclarationName Name2) {
116 if (Name1.getNameKind() != Name2.getNameKind())
117 return false;
118
119 switch (Name1.getNameKind()) {
120
123 Name2.getAsIdentifierInfo());
124
128 return IsStructurallyEquivalent(Context, Name1.getCXXNameType(),
129 Name2.getCXXNameType());
130
133 Context, Name1.getCXXDeductionGuideTemplate()->getDeclName(),
135 return false;
136 return IsStructurallyEquivalent(Context,
139 }
140
142 return Name1.getCXXOverloadedOperator() == Name2.getCXXOverloadedOperator();
143
147
149 return true; // FIXME When do we consider two using directives equal?
150
154 return true; // FIXME
155 }
156
157 llvm_unreachable("Unhandled kind of DeclarationName");
158 return true;
159}
160
161namespace {
162/// Encapsulates Stmt comparison logic.
163class StmtComparer {
165
166 // IsStmtEquivalent overloads. Each overload compares a specific statement
167 // and only has to compare the data that is specific to the specific statement
168 // class. Should only be called from TraverseStmt.
169
170 bool IsStmtEquivalent(const AddrLabelExpr *E1, const AddrLabelExpr *E2) {
171 return IsStructurallyEquivalent(Context, E1->getLabel(), E2->getLabel());
172 }
173
174 bool IsStmtEquivalent(const AtomicExpr *E1, const AtomicExpr *E2) {
175 return E1->getOp() == E2->getOp();
176 }
177
178 bool IsStmtEquivalent(const BinaryOperator *E1, const BinaryOperator *E2) {
179 return E1->getOpcode() == E2->getOpcode();
180 }
181
182 bool IsStmtEquivalent(const CallExpr *E1, const CallExpr *E2) {
183 // FIXME: IsStructurallyEquivalent requires non-const Decls.
184 Decl *Callee1 = const_cast<Decl *>(E1->getCalleeDecl());
185 Decl *Callee2 = const_cast<Decl *>(E2->getCalleeDecl());
186
187 // Compare whether both calls know their callee.
188 if (static_cast<bool>(Callee1) != static_cast<bool>(Callee2))
189 return false;
190
191 // Both calls have no callee, so nothing to do.
192 if (!static_cast<bool>(Callee1))
193 return true;
194
195 assert(Callee2);
196 return IsStructurallyEquivalent(Context, Callee1, Callee2);
197 }
198
199 bool IsStmtEquivalent(const CharacterLiteral *E1,
200 const CharacterLiteral *E2) {
201 return E1->getValue() == E2->getValue() && E1->getKind() == E2->getKind();
202 }
203
204 bool IsStmtEquivalent(const ChooseExpr *E1, const ChooseExpr *E2) {
205 return true; // Semantics only depend on children.
206 }
207
208 bool IsStmtEquivalent(const CompoundStmt *E1, const CompoundStmt *E2) {
209 // Number of children is actually checked by the generic children comparison
210 // code, but a CompoundStmt is one of the few statements where the number of
211 // children frequently differs and the number of statements is also always
212 // precomputed. Directly comparing the number of children here is thus
213 // just an optimization.
214 return E1->size() == E2->size();
215 }
216
217 bool IsStmtEquivalent(const DeclRefExpr *DRE1, const DeclRefExpr *DRE2) {
218 const ValueDecl *Decl1 = DRE1->getDecl();
219 const ValueDecl *Decl2 = DRE2->getDecl();
220 if (!Decl1 || !Decl2)
221 return false;
222 return IsStructurallyEquivalent(Context, const_cast<ValueDecl *>(Decl1),
223 const_cast<ValueDecl *>(Decl2));
224 }
225
226 bool IsStmtEquivalent(const DependentScopeDeclRefExpr *DE1,
227 const DependentScopeDeclRefExpr *DE2) {
228 if (!IsStructurallyEquivalent(Context, DE1->getDeclName(),
229 DE2->getDeclName()))
230 return false;
231 return IsStructurallyEquivalent(Context, DE1->getQualifier(),
232 DE2->getQualifier());
233 }
234
235 bool IsStmtEquivalent(const Expr *E1, const Expr *E2) {
236 return IsStructurallyEquivalent(Context, E1->getType(), E2->getType());
237 }
238
239 bool IsStmtEquivalent(const ExpressionTraitExpr *E1,
240 const ExpressionTraitExpr *E2) {
241 return E1->getTrait() == E2->getTrait() && E1->getValue() == E2->getValue();
242 }
243
244 bool IsStmtEquivalent(const FloatingLiteral *E1, const FloatingLiteral *E2) {
245 return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue();
246 }
247
248 bool IsStmtEquivalent(const GenericSelectionExpr *E1,
249 const GenericSelectionExpr *E2) {
250 for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
252 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
253 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
254 // Skip this case if there are a different number of associated types.
255 if (!Child1 || !Child2)
256 return false;
257
258 if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
259 (*Child2)->getType()))
260 return false;
261 }
262
263 return true;
264 }
265
266 bool IsStmtEquivalent(const ImplicitCastExpr *CastE1,
267 const ImplicitCastExpr *CastE2) {
268 return IsStructurallyEquivalent(Context, CastE1->getType(),
269 CastE2->getType());
270 }
271
272 bool IsStmtEquivalent(const IntegerLiteral *E1, const IntegerLiteral *E2) {
273 return E1->getValue() == E2->getValue();
274 }
275
276 bool IsStmtEquivalent(const MemberExpr *E1, const MemberExpr *E2) {
277 return IsStructurallyEquivalent(Context, E1->getFoundDecl(),
278 E2->getFoundDecl());
279 }
280
281 bool IsStmtEquivalent(const ObjCStringLiteral *E1,
282 const ObjCStringLiteral *E2) {
283 // Just wraps a StringLiteral child.
284 return true;
285 }
286
287 bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }
288
289 bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) {
290 LabelDecl *L1 = S1->getLabel();
291 LabelDecl *L2 = S2->getLabel();
292 if (!L1 || !L2)
293 return L1 == L2;
294
295 IdentifierInfo *Name1 = L1->getIdentifier();
296 IdentifierInfo *Name2 = L2->getIdentifier();
297 return ::IsStructurallyEquivalent(Name1, Name2);
298 }
299
300 bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) {
301 return E1->getIdentKind() == E2->getIdentKind();
302 }
303
304 bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) {
305 return E1->getTemplateDepth() == E2->getTemplateDepth();
306 }
307
308 bool IsStmtEquivalent(const StringLiteral *E1, const StringLiteral *E2) {
309 return E1->getBytes() == E2->getBytes();
310 }
311
312 bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
315 E2->getAssociatedDecl()))
316 return false;
317 if (E1->getIndex() != E2->getIndex())
318 return false;
319 if (E1->getPackIndex() != E2->getPackIndex())
320 return false;
321 return true;
322 }
323
324 bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
326 return IsStructurallyEquivalent(Context, E1->getArgumentPack(),
327 E2->getArgumentPack());
328 }
329
330 bool IsStmtEquivalent(const TypeTraitExpr *E1, const TypeTraitExpr *E2) {
331 if (E1->getTrait() != E2->getTrait())
332 return false;
333
334 for (auto Pair : zip_longest(E1->getArgs(), E2->getArgs())) {
335 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
336 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
337 // Different number of args.
338 if (!Child1 || !Child2)
339 return false;
340
341 if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
342 (*Child2)->getType()))
343 return false;
344 }
345 return true;
346 }
347
348 bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
349 const UnaryExprOrTypeTraitExpr *E2) {
350 if (E1->getKind() != E2->getKind())
351 return false;
352 return IsStructurallyEquivalent(Context, E1->getTypeOfArgument(),
353 E2->getTypeOfArgument());
354 }
355
356 bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) {
357 return E1->getOpcode() == E2->getOpcode();
358 }
359
360 bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) {
361 // Semantics only depend on children.
362 return true;
363 }
364
365 bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
366 if (!IsStructurallyEquivalent(Context, E1->getName(), E2->getName()))
367 return false;
368
369 if (static_cast<bool>(E1->getQualifier()) !=
370 static_cast<bool>(E2->getQualifier()))
371 return false;
372 if (E1->getQualifier() &&
374 E2->getQualifier()))
375 return false;
376
377 if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs())
378 return false;
379 const TemplateArgumentLoc *Args1 = E1->getTemplateArgs();
380 const TemplateArgumentLoc *Args2 = E2->getTemplateArgs();
381 for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
382 ++ArgI)
383 if (!IsStructurallyEquivalent(Context, Args1[ArgI], Args2[ArgI]))
384 return false;
385
386 return true;
387 }
388
389 bool IsStmtEquivalent(const CXXBoolLiteralExpr *E1, const CXXBoolLiteralExpr *E2) {
390 return E1->getValue() == E2->getValue();
391 }
392
393 /// End point of the traversal chain.
394 bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
395
396 // Create traversal methods that traverse the class hierarchy and return
397 // the accumulated result of the comparison. Each TraverseStmt overload
398 // calls the TraverseStmt overload of the parent class. For example,
399 // the TraverseStmt overload for 'BinaryOperator' calls the TraverseStmt
400 // overload of 'Expr' which then calls the overload for 'Stmt'.
401#define STMT(CLASS, PARENT) \
402 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
403 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
404 static_cast<const PARENT *>(S2))) \
405 return false; \
406 return IsStmtEquivalent(S1, S2); \
407 }
408#include "clang/AST/StmtNodes.inc"
409
410public:
411 StmtComparer(StructuralEquivalenceContext &C) : Context(C) {}
412
413 /// Determine whether two statements are equivalent. The statements have to
414 /// be of the same kind. The children of the statements and their properties
415 /// are not compared by this function.
416 bool IsEquivalent(const Stmt *S1, const Stmt *S2) {
417 if (S1->getStmtClass() != S2->getStmtClass())
418 return false;
419
420 // Each TraverseStmt walks the class hierarchy from the leaf class to
421 // the root class 'Stmt' (e.g. 'BinaryOperator' -> 'Expr' -> 'Stmt'). Cast
422 // the Stmt we have here to its specific subclass so that we call the
423 // overload that walks the whole class hierarchy from leaf to root (e.g.,
424 // cast to 'BinaryOperator' so that 'Expr' and 'Stmt' is traversed).
425 switch (S1->getStmtClass()) {
427 llvm_unreachable("Can't traverse NoStmtClass");
428#define STMT(CLASS, PARENT) \
429 case Stmt::StmtClass::CLASS##Class: \
430 return TraverseStmt(static_cast<const CLASS *>(S1), \
431 static_cast<const CLASS *>(S2));
432#define ABSTRACT_STMT(S)
433#include "clang/AST/StmtNodes.inc"
434 }
435 llvm_unreachable("Invalid statement kind");
436 }
437};
438} // namespace
439
440/// Determine structural equivalence of two statements.
442 const Stmt *S1, const Stmt *S2) {
443 if (!S1 || !S2)
444 return S1 == S2;
445
446 // Compare the statements itself.
447 StmtComparer Comparer(Context);
448 if (!Comparer.IsEquivalent(S1, S2))
449 return false;
450
451 // Iterate over the children of both statements and also compare them.
452 for (auto Pair : zip_longest(S1->children(), S2->children())) {
453 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
454 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
455 // One of the statements has a different amount of children than the other,
456 // so the statements can't be equivalent.
457 if (!Child1 || !Child2)
458 return false;
459 if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
460 return false;
461 }
462 return true;
463}
464
465/// Determine whether two identifiers are equivalent.
467 const IdentifierInfo *Name2) {
468 if (!Name1 || !Name2)
469 return Name1 == Name2;
470
471 return Name1->getName() == Name2->getName();
472}
473
474/// Determine whether two nested-name-specifiers are equivalent.
477 NestedNameSpecifier *NNS2) {
478 if (NNS1->getKind() != NNS2->getKind())
479 return false;
480
481 NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
482 *Prefix2 = NNS2->getPrefix();
483 if ((bool)Prefix1 != (bool)Prefix2)
484 return false;
485
486 if (Prefix1)
487 if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
488 return false;
489
490 switch (NNS1->getKind()) {
493 NNS2->getAsIdentifier());
495 return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
496 NNS2->getAsNamespace());
498 return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(),
499 NNS2->getAsNamespaceAlias());
502 return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
503 QualType(NNS2->getAsType(), 0));
505 return true;
507 return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
508 NNS2->getAsRecordDecl());
509 }
510 return false;
511}
512
514 const TemplateName &N1,
515 const TemplateName &N2) {
516 TemplateDecl *TemplateDeclN1 = N1.getAsTemplateDecl();
517 TemplateDecl *TemplateDeclN2 = N2.getAsTemplateDecl();
518 if (TemplateDeclN1 && TemplateDeclN2) {
519 if (!IsStructurallyEquivalent(Context, TemplateDeclN1, TemplateDeclN2))
520 return false;
521 // If the kind is different we compare only the template decl.
522 if (N1.getKind() != N2.getKind())
523 return true;
524 } else if (TemplateDeclN1 || TemplateDeclN2)
525 return false;
526 else if (N1.getKind() != N2.getKind())
527 return false;
528
529 // Check for special case incompatibilities.
530 switch (N1.getKind()) {
531
534 *OS2 = N2.getAsOverloadedTemplate();
535 OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(),
536 E1 = OS1->end(), E2 = OS2->end();
537 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
538 if (!IsStructurallyEquivalent(Context, *I1, *I2))
539 return false;
540 return I1 == E1 && I2 == E2;
541 }
542
545 *TN2 = N1.getAsAssumedTemplateName();
546 return TN1->getDeclName() == TN2->getDeclName();
547 }
548
551 *DN2 = N2.getAsDependentTemplateName();
552 if (!IsStructurallyEquivalent(Context, DN1->getQualifier(),
553 DN2->getQualifier()))
554 return false;
555 if (DN1->isIdentifier() && DN2->isIdentifier())
557 DN2->getIdentifier());
558 else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator())
559 return DN1->getOperator() == DN2->getOperator();
560 return false;
561 }
562
567 return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
568 P2->getArgumentPack()) &&
570 P2->getAssociatedDecl()) &&
571 P1->getIndex() == P2->getIndex();
572 }
573
578 // It is sufficient to check value of getAsTemplateDecl.
579 break;
580
581 }
582
583 return true;
584}
585
589
590/// Determine whether two template arguments are equivalent.
592 const TemplateArgument &Arg1,
593 const TemplateArgument &Arg2) {
594 if (Arg1.getKind() != Arg2.getKind())
595 return false;
596
597 switch (Arg1.getKind()) {
599 return true;
600
602 return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
603
605 if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
606 Arg2.getIntegralType()))
607 return false;
608
609 return llvm::APSInt::isSameValue(Arg1.getAsIntegral(),
610 Arg2.getAsIntegral());
611
613 return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
614
616 return true; // FIXME: Is this correct?
617
619 return IsStructurallyEquivalent(Context, Arg1.getAsTemplate(),
620 Arg2.getAsTemplate());
621
623 return IsStructurallyEquivalent(Context,
626
628 return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
629 Arg2.getAsExpr());
630
632 return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
633 Arg2.pack_elements());
634 }
635
636 llvm_unreachable("Invalid template argument kind");
637}
638
639/// Determine structural equivalence of two template argument lists.
643 if (Args1.size() != Args2.size())
644 return false;
645 for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
646 if (!IsStructurallyEquivalent(Context, Args1[I], Args2[I]))
647 return false;
648 }
649 return true;
650}
651
652/// Determine whether two template argument locations are equivalent.
654 const TemplateArgumentLoc &Arg1,
655 const TemplateArgumentLoc &Arg2) {
656 return IsStructurallyEquivalent(Context, Arg1.getArgument(),
657 Arg2.getArgument());
658}
659
660/// Determine structural equivalence for the common part of array
661/// types.
663 const ArrayType *Array1,
664 const ArrayType *Array2) {
665 if (!IsStructurallyEquivalent(Context, Array1->getElementType(),
666 Array2->getElementType()))
667 return false;
668 if (Array1->getSizeModifier() != Array2->getSizeModifier())
669 return false;
670 if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
671 return false;
672
673 return true;
674}
675
676/// Determine structural equivalence based on the ExtInfo of functions. This
677/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
678/// conventions bits but must not compare some other bits.
682 // Compatible functions must have compatible calling conventions.
683 if (EI1.getCC() != EI2.getCC())
684 return false;
685
686 // Regparm is part of the calling convention.
687 if (EI1.getHasRegParm() != EI2.getHasRegParm())
688 return false;
689 if (EI1.getRegParm() != EI2.getRegParm())
690 return false;
691
692 if (EI1.getProducesResult() != EI2.getProducesResult())
693 return false;
695 return false;
696 if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
697 return false;
698
699 return true;
700}
701
702/// Check the equivalence of exception specifications.
704 const FunctionProtoType *Proto1,
705 const FunctionProtoType *Proto2) {
706
707 auto Spec1 = Proto1->getExceptionSpecType();
708 auto Spec2 = Proto2->getExceptionSpecType();
709
711 return true;
712
713 if (Spec1 != Spec2)
714 return false;
715 if (Spec1 == EST_Dynamic) {
716 if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
717 return false;
718 for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
719 if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
720 Proto2->getExceptionType(I)))
721 return false;
722 }
723 } else if (isComputedNoexcept(Spec1)) {
724 if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
725 Proto2->getNoexceptExpr()))
726 return false;
727 }
728
729 return true;
730}
731
732/// Determine structural equivalence of two types.
734 QualType T1, QualType T2) {
735 if (T1.isNull() || T2.isNull())
736 return T1.isNull() && T2.isNull();
737
738 QualType OrigT1 = T1;
739 QualType OrigT2 = T2;
740
741 if (!Context.StrictTypeSpelling) {
742 // We aren't being strict about token-to-token equivalence of types,
743 // so map down to the canonical type.
744 T1 = Context.FromCtx.getCanonicalType(T1);
745 T2 = Context.ToCtx.getCanonicalType(T2);
746 }
747
748 if (T1.getQualifiers() != T2.getQualifiers())
749 return false;
750
751 Type::TypeClass TC = T1->getTypeClass();
752
753 if (T1->getTypeClass() != T2->getTypeClass()) {
754 // Compare function types with prototypes vs. without prototypes as if
755 // both did not have prototypes.
756 if (T1->getTypeClass() == Type::FunctionProto &&
757 T2->getTypeClass() == Type::FunctionNoProto)
758 TC = Type::FunctionNoProto;
759 else if (T1->getTypeClass() == Type::FunctionNoProto &&
760 T2->getTypeClass() == Type::FunctionProto)
761 TC = Type::FunctionNoProto;
762 else
763 return false;
764 }
765
766 switch (TC) {
767 case Type::Builtin:
768 // FIXME: Deal with Char_S/Char_U.
769 if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind())
770 return false;
771 break;
772
773 case Type::Complex:
774 if (!IsStructurallyEquivalent(Context,
775 cast<ComplexType>(T1)->getElementType(),
776 cast<ComplexType>(T2)->getElementType()))
777 return false;
778 break;
779
780 case Type::Adjusted:
781 case Type::Decayed:
782 if (!IsStructurallyEquivalent(Context,
783 cast<AdjustedType>(T1)->getOriginalType(),
784 cast<AdjustedType>(T2)->getOriginalType()))
785 return false;
786 break;
787
788 case Type::Pointer:
789 if (!IsStructurallyEquivalent(Context,
790 cast<PointerType>(T1)->getPointeeType(),
791 cast<PointerType>(T2)->getPointeeType()))
792 return false;
793 break;
794
795 case Type::BlockPointer:
796 if (!IsStructurallyEquivalent(Context,
797 cast<BlockPointerType>(T1)->getPointeeType(),
798 cast<BlockPointerType>(T2)->getPointeeType()))
799 return false;
800 break;
801
802 case Type::LValueReference:
803 case Type::RValueReference: {
804 const auto *Ref1 = cast<ReferenceType>(T1);
805 const auto *Ref2 = cast<ReferenceType>(T2);
806 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
807 return false;
808 if (Ref1->isInnerRef() != Ref2->isInnerRef())
809 return false;
810 if (!IsStructurallyEquivalent(Context, Ref1->getPointeeTypeAsWritten(),
811 Ref2->getPointeeTypeAsWritten()))
812 return false;
813 break;
814 }
815
816 case Type::MemberPointer: {
817 const auto *MemPtr1 = cast<MemberPointerType>(T1);
818 const auto *MemPtr2 = cast<MemberPointerType>(T2);
819 if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
820 MemPtr2->getPointeeType()))
821 return false;
822 if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0),
823 QualType(MemPtr2->getClass(), 0)))
824 return false;
825 break;
826 }
827
828 case Type::ConstantArray: {
829 const auto *Array1 = cast<ConstantArrayType>(T1);
830 const auto *Array2 = cast<ConstantArrayType>(T2);
831 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
832 return false;
833
834 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
835 return false;
836 break;
837 }
838
839 case Type::IncompleteArray:
840 if (!IsArrayStructurallyEquivalent(Context, cast<ArrayType>(T1),
841 cast<ArrayType>(T2)))
842 return false;
843 break;
844
845 case Type::VariableArray: {
846 const auto *Array1 = cast<VariableArrayType>(T1);
847 const auto *Array2 = cast<VariableArrayType>(T2);
848 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
849 Array2->getSizeExpr()))
850 return false;
851
852 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
853 return false;
854
855 break;
856 }
857
858 case Type::DependentSizedArray: {
859 const auto *Array1 = cast<DependentSizedArrayType>(T1);
860 const auto *Array2 = cast<DependentSizedArrayType>(T2);
861 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
862 Array2->getSizeExpr()))
863 return false;
864
865 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
866 return false;
867
868 break;
869 }
870
871 case Type::DependentAddressSpace: {
872 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
873 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
874 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
875 DepAddressSpace2->getAddrSpaceExpr()))
876 return false;
877 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(),
878 DepAddressSpace2->getPointeeType()))
879 return false;
880
881 break;
882 }
883
884 case Type::DependentSizedExtVector: {
885 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
886 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
887 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
888 Vec2->getSizeExpr()))
889 return false;
890 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
891 Vec2->getElementType()))
892 return false;
893 break;
894 }
895
896 case Type::DependentVector: {
897 const auto *Vec1 = cast<DependentVectorType>(T1);
898 const auto *Vec2 = cast<DependentVectorType>(T2);
899 if (Vec1->getVectorKind() != Vec2->getVectorKind())
900 return false;
901 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
902 Vec2->getSizeExpr()))
903 return false;
904 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
905 Vec2->getElementType()))
906 return false;
907 break;
908 }
909
910 case Type::Vector:
911 case Type::ExtVector: {
912 const auto *Vec1 = cast<VectorType>(T1);
913 const auto *Vec2 = cast<VectorType>(T2);
914 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
915 Vec2->getElementType()))
916 return false;
917 if (Vec1->getNumElements() != Vec2->getNumElements())
918 return false;
919 if (Vec1->getVectorKind() != Vec2->getVectorKind())
920 return false;
921 break;
922 }
923
924 case Type::DependentSizedMatrix: {
925 const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(T1);
926 const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(T2);
927 // The element types, row and column expressions must be structurally
928 // equivalent.
929 if (!IsStructurallyEquivalent(Context, Mat1->getRowExpr(),
930 Mat2->getRowExpr()) ||
931 !IsStructurallyEquivalent(Context, Mat1->getColumnExpr(),
932 Mat2->getColumnExpr()) ||
934 Mat2->getElementType()))
935 return false;
936 break;
937 }
938
939 case Type::ConstantMatrix: {
940 const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(T1);
941 const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(T2);
942 // The element types must be structurally equivalent and the number of rows
943 // and columns must match.
944 if (!IsStructurallyEquivalent(Context, Mat1->getElementType(),
945 Mat2->getElementType()) ||
946 Mat1->getNumRows() != Mat2->getNumRows() ||
947 Mat1->getNumColumns() != Mat2->getNumColumns())
948 return false;
949 break;
950 }
951
952 case Type::FunctionProto: {
953 const auto *Proto1 = cast<FunctionProtoType>(T1);
954 const auto *Proto2 = cast<FunctionProtoType>(T2);
955
956 if (Proto1->getNumParams() != Proto2->getNumParams())
957 return false;
958 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
959 if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I),
960 Proto2->getParamType(I)))
961 return false;
962 }
963 if (Proto1->isVariadic() != Proto2->isVariadic())
964 return false;
965
966 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
967 return false;
968
969 // Check exceptions, this information is lost in canonical type.
970 const auto *OrigProto1 =
971 cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
972 const auto *OrigProto2 =
973 cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
974 if (!IsEquivalentExceptionSpec(Context, OrigProto1, OrigProto2))
975 return false;
976
977 // Fall through to check the bits common with FunctionNoProtoType.
978 [[fallthrough]];
979 }
980
981 case Type::FunctionNoProto: {
982 const auto *Function1 = cast<FunctionType>(T1);
983 const auto *Function2 = cast<FunctionType>(T2);
984 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
985 Function2->getReturnType()))
986 return false;
987 if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
988 Function2->getExtInfo()))
989 return false;
990 break;
991 }
992
993 case Type::UnresolvedUsing:
994 if (!IsStructurallyEquivalent(Context,
995 cast<UnresolvedUsingType>(T1)->getDecl(),
996 cast<UnresolvedUsingType>(T2)->getDecl()))
997 return false;
998 break;
999
1000 case Type::Attributed:
1001 if (!IsStructurallyEquivalent(Context,
1002 cast<AttributedType>(T1)->getModifiedType(),
1003 cast<AttributedType>(T2)->getModifiedType()))
1004 return false;
1006 Context, cast<AttributedType>(T1)->getEquivalentType(),
1007 cast<AttributedType>(T2)->getEquivalentType()))
1008 return false;
1009 break;
1010
1011 case Type::BTFTagAttributed:
1013 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1014 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1015 return false;
1016 break;
1017
1018 case Type::Paren:
1019 if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(),
1020 cast<ParenType>(T2)->getInnerType()))
1021 return false;
1022 break;
1023
1024 case Type::MacroQualified:
1026 Context, cast<MacroQualifiedType>(T1)->getUnderlyingType(),
1027 cast<MacroQualifiedType>(T2)->getUnderlyingType()))
1028 return false;
1029 break;
1030
1031 case Type::Using:
1032 if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
1033 cast<UsingType>(T2)->getFoundDecl()))
1034 return false;
1035 if (!IsStructurallyEquivalent(Context,
1036 cast<UsingType>(T1)->getUnderlyingType(),
1037 cast<UsingType>(T2)->getUnderlyingType()))
1038 return false;
1039 break;
1040
1041 case Type::Typedef:
1042 if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
1043 cast<TypedefType>(T2)->getDecl()) ||
1044 !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
1045 cast<TypedefType>(T2)->desugar()))
1046 return false;
1047 break;
1048
1049 case Type::TypeOfExpr:
1051 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1052 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1053 return false;
1054 break;
1055
1056 case Type::TypeOf:
1057 if (!IsStructurallyEquivalent(Context,
1058 cast<TypeOfType>(T1)->getUnmodifiedType(),
1059 cast<TypeOfType>(T2)->getUnmodifiedType()))
1060 return false;
1061 break;
1062
1063 case Type::UnaryTransform:
1065 Context, cast<UnaryTransformType>(T1)->getUnderlyingType(),
1066 cast<UnaryTransformType>(T2)->getUnderlyingType()))
1067 return false;
1068 break;
1069
1070 case Type::Decltype:
1071 if (!IsStructurallyEquivalent(Context,
1072 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1073 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1074 return false;
1075 break;
1076
1077 case Type::Auto: {
1078 auto *Auto1 = cast<AutoType>(T1);
1079 auto *Auto2 = cast<AutoType>(T2);
1080 if (!IsStructurallyEquivalent(Context, Auto1->getDeducedType(),
1081 Auto2->getDeducedType()))
1082 return false;
1083 if (Auto1->isConstrained() != Auto2->isConstrained())
1084 return false;
1085 if (Auto1->isConstrained()) {
1086 if (Auto1->getTypeConstraintConcept() !=
1087 Auto2->getTypeConstraintConcept())
1088 return false;
1089 if (!IsStructurallyEquivalent(Context,
1090 Auto1->getTypeConstraintArguments(),
1091 Auto2->getTypeConstraintArguments()))
1092 return false;
1093 }
1094 break;
1095 }
1096
1097 case Type::DeducedTemplateSpecialization: {
1098 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1099 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1100 if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(),
1101 DT2->getTemplateName()))
1102 return false;
1103 if (!IsStructurallyEquivalent(Context, DT1->getDeducedType(),
1104 DT2->getDeducedType()))
1105 return false;
1106 break;
1107 }
1108
1109 case Type::Record:
1110 case Type::Enum:
1111 if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(),
1112 cast<TagType>(T2)->getDecl()))
1113 return false;
1114 break;
1115
1116 case Type::TemplateTypeParm: {
1117 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1118 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1119 if (!Context.IgnoreTemplateParmDepth &&
1120 Parm1->getDepth() != Parm2->getDepth())
1121 return false;
1122 if (Parm1->getIndex() != Parm2->getIndex())
1123 return false;
1124 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1125 return false;
1126
1127 // Names of template type parameters are never significant.
1128 break;
1129 }
1130
1131 case Type::SubstTemplateTypeParm: {
1132 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1133 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1134 if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
1135 Subst2->getReplacementType()))
1136 return false;
1137 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1138 Subst2->getAssociatedDecl()))
1139 return false;
1140 if (Subst1->getIndex() != Subst2->getIndex())
1141 return false;
1142 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1143 return false;
1144 break;
1145 }
1146
1147 case Type::SubstTemplateTypeParmPack: {
1148 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1149 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1150 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1151 Subst2->getAssociatedDecl()))
1152 return false;
1153 if (Subst1->getIndex() != Subst2->getIndex())
1154 return false;
1155 if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
1156 Subst2->getArgumentPack()))
1157 return false;
1158 break;
1159 }
1160
1161 case Type::TemplateSpecialization: {
1162 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1163 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1164 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
1165 Spec2->getTemplateName()))
1166 return false;
1167 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1168 Spec2->template_arguments()))
1169 return false;
1170 break;
1171 }
1172
1173 case Type::Elaborated: {
1174 const auto *Elab1 = cast<ElaboratedType>(T1);
1175 const auto *Elab2 = cast<ElaboratedType>(T2);
1176 // CHECKME: what if a keyword is ElaboratedTypeKeyword::None or
1177 // ElaboratedTypeKeyword::Typename
1178 // ?
1179 if (Elab1->getKeyword() != Elab2->getKeyword())
1180 return false;
1181 if (!IsStructurallyEquivalent(Context, Elab1->getQualifier(),
1182 Elab2->getQualifier()))
1183 return false;
1184 if (!IsStructurallyEquivalent(Context, Elab1->getNamedType(),
1185 Elab2->getNamedType()))
1186 return false;
1187 break;
1188 }
1189
1190 case Type::InjectedClassName: {
1191 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1192 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1193 if (!IsStructurallyEquivalent(Context,
1194 Inj1->getInjectedSpecializationType(),
1195 Inj2->getInjectedSpecializationType()))
1196 return false;
1197 break;
1198 }
1199
1200 case Type::DependentName: {
1201 const auto *Typename1 = cast<DependentNameType>(T1);
1202 const auto *Typename2 = cast<DependentNameType>(T2);
1203 if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(),
1204 Typename2->getQualifier()))
1205 return false;
1206 if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
1207 Typename2->getIdentifier()))
1208 return false;
1209
1210 break;
1211 }
1212
1213 case Type::DependentTemplateSpecialization: {
1214 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1215 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1216 if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(),
1217 Spec2->getQualifier()))
1218 return false;
1219 if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
1220 Spec2->getIdentifier()))
1221 return false;
1222 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1223 Spec2->template_arguments()))
1224 return false;
1225 break;
1226 }
1227
1228 case Type::PackExpansion:
1229 if (!IsStructurallyEquivalent(Context,
1230 cast<PackExpansionType>(T1)->getPattern(),
1231 cast<PackExpansionType>(T2)->getPattern()))
1232 return false;
1233 break;
1234
1235 case Type::ObjCInterface: {
1236 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1237 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1238 if (!IsStructurallyEquivalent(Context, Iface1->getDecl(),
1239 Iface2->getDecl()))
1240 return false;
1241 break;
1242 }
1243
1244 case Type::ObjCTypeParam: {
1245 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1246 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1247 if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), Obj2->getDecl()))
1248 return false;
1249
1250 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1251 return false;
1252 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1253 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1254 Obj2->getProtocol(I)))
1255 return false;
1256 }
1257 break;
1258 }
1259
1260 case Type::ObjCObject: {
1261 const auto *Obj1 = cast<ObjCObjectType>(T1);
1262 const auto *Obj2 = cast<ObjCObjectType>(T2);
1263 if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(),
1264 Obj2->getBaseType()))
1265 return false;
1266 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1267 return false;
1268 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1269 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1270 Obj2->getProtocol(I)))
1271 return false;
1272 }
1273 break;
1274 }
1275
1276 case Type::ObjCObjectPointer: {
1277 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1278 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1279 if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(),
1280 Ptr2->getPointeeType()))
1281 return false;
1282 break;
1283 }
1284
1285 case Type::Atomic:
1286 if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(),
1287 cast<AtomicType>(T2)->getValueType()))
1288 return false;
1289 break;
1290
1291 case Type::Pipe:
1292 if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(),
1293 cast<PipeType>(T2)->getElementType()))
1294 return false;
1295 break;
1296 case Type::BitInt: {
1297 const auto *Int1 = cast<BitIntType>(T1);
1298 const auto *Int2 = cast<BitIntType>(T2);
1299
1300 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1301 Int1->getNumBits() != Int2->getNumBits())
1302 return false;
1303 break;
1304 }
1305 case Type::DependentBitInt: {
1306 const auto *Int1 = cast<DependentBitIntType>(T1);
1307 const auto *Int2 = cast<DependentBitIntType>(T2);
1308
1309 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1310 !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
1311 Int2->getNumBitsExpr()))
1312 return false;
1313 break;
1314 }
1315 } // end switch
1316
1317 return true;
1318}
1319
1321 VarDecl *D1, VarDecl *D2) {
1322 if (D1->getStorageClass() != D2->getStorageClass())
1323 return false;
1324
1325 IdentifierInfo *Name1 = D1->getIdentifier();
1326 IdentifierInfo *Name2 = D2->getIdentifier();
1327 if (!::IsStructurallyEquivalent(Name1, Name2))
1328 return false;
1329
1330 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
1331 return false;
1332
1333 return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit());
1334}
1335
1337 FieldDecl *Field1, FieldDecl *Field2,
1338 QualType Owner2Type) {
1339 const auto *Owner2 = cast<Decl>(Field2->getDeclContext());
1340
1341 // For anonymous structs/unions, match up the anonymous struct/union type
1342 // declarations directly, so that we don't go off searching for anonymous
1343 // types
1344 if (Field1->isAnonymousStructOrUnion() &&
1345 Field2->isAnonymousStructOrUnion()) {
1346 RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1347 RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1348 return IsStructurallyEquivalent(Context, D1, D2);
1349 }
1350
1351 // Check for equivalent field names.
1352 IdentifierInfo *Name1 = Field1->getIdentifier();
1353 IdentifierInfo *Name2 = Field2->getIdentifier();
1354 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1355 if (Context.Complain) {
1356 Context.Diag2(
1357 Owner2->getLocation(),
1358 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1359 << Owner2Type;
1360 Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
1361 << Field2->getDeclName();
1362 Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
1363 << Field1->getDeclName();
1364 }
1365 return false;
1366 }
1367
1368 if (!IsStructurallyEquivalent(Context, Field1->getType(),
1369 Field2->getType())) {
1370 if (Context.Complain) {
1371 Context.Diag2(
1372 Owner2->getLocation(),
1373 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1374 << Owner2Type;
1375 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1376 << Field2->getDeclName() << Field2->getType();
1377 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1378 << Field1->getDeclName() << Field1->getType();
1379 }
1380 return false;
1381 }
1382
1383 if (Field1->isBitField())
1384 return IsStructurallyEquivalent(Context, Field1->getBitWidth(),
1385 Field2->getBitWidth());
1386
1387 return true;
1388}
1389
1390/// Determine structural equivalence of two fields.
1392 FieldDecl *Field1, FieldDecl *Field2) {
1393 const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
1394 return IsStructurallyEquivalent(Context, Field1, Field2,
1395 Context.ToCtx.getTypeDeclType(Owner2));
1396}
1397
1398/// Determine structural equivalence of two methods.
1400 CXXMethodDecl *Method1,
1401 CXXMethodDecl *Method2) {
1402 bool PropertiesEqual =
1403 Method1->getDeclKind() == Method2->getDeclKind() &&
1404 Method1->getRefQualifier() == Method2->getRefQualifier() &&
1405 Method1->getAccess() == Method2->getAccess() &&
1406 Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1407 Method1->isStatic() == Method2->isStatic() &&
1408 Method1->isImplicitObjectMemberFunction() ==
1409 Method2->isImplicitObjectMemberFunction() &&
1410 Method1->isConst() == Method2->isConst() &&
1411 Method1->isVolatile() == Method2->isVolatile() &&
1412 Method1->isVirtual() == Method2->isVirtual() &&
1413 Method1->isPure() == Method2->isPure() &&
1414 Method1->isDefaulted() == Method2->isDefaulted() &&
1415 Method1->isDeleted() == Method2->isDeleted();
1416 if (!PropertiesEqual)
1417 return false;
1418 // FIXME: Check for 'final'.
1419
1420 if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1421 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1422 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1423 Constructor2->getExplicitSpecifier()))
1424 return false;
1425 }
1426
1427 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1428 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1429 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1430 Conversion2->getExplicitSpecifier()))
1431 return false;
1432 if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
1433 Conversion2->getConversionType()))
1434 return false;
1435 }
1436
1437 const IdentifierInfo *Name1 = Method1->getIdentifier();
1438 const IdentifierInfo *Name2 = Method2->getIdentifier();
1439 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1440 return false;
1441 // TODO: Names do not match, add warning like at check for FieldDecl.
1442 }
1443
1444 // Check the prototypes.
1445 if (!::IsStructurallyEquivalent(Context,
1446 Method1->getType(), Method2->getType()))
1447 return false;
1448
1449 return true;
1450}
1451
1452/// Determine structural equivalence of two lambda classes.
1453static bool
1455 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1456 assert(D1->isLambda() && D2->isLambda() &&
1457 "Must be called on lambda classes");
1459 D2->getLambdaCallOperator()))
1460 return false;
1461
1462 return true;
1463}
1464
1465/// Determine if context of a class is equivalent.
1467 RecordDecl *D2) {
1468 // The context should be completely equal, including anonymous and inline
1469 // namespaces.
1470 // We compare objects as part of full translation units, not subtrees of
1471 // translation units.
1474 while (true) {
1475 // Special case: We allow a struct defined in a function to be equivalent
1476 // with a similar struct defined outside of a function.
1477 if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1478 (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1479 return true;
1480
1481 if (DC1->getDeclKind() != DC2->getDeclKind())
1482 return false;
1483 if (DC1->isTranslationUnit())
1484 break;
1485 if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1486 return false;
1487 if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1488 const auto *ND2 = cast<NamedDecl>(DC2);
1489 if (!DC1->isInlineNamespace() &&
1490 !IsStructurallyEquivalent(ND1->getIdentifier(), ND2->getIdentifier()))
1491 return false;
1492 }
1493
1494 DC1 = DC1->getParent()->getNonTransparentContext();
1495 DC2 = DC2->getParent()->getNonTransparentContext();
1496 }
1497
1498 return true;
1499}
1500
1501static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1502 auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1503 if (const IdentifierInfo *Name = D.getIdentifier())
1504 return Name;
1505 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1506 return TypedefName->getIdentifier();
1507 return nullptr;
1508 };
1509 return IsStructurallyEquivalent(GetName(D1), GetName(D2));
1510}
1511
1512/// Determine structural equivalence of two records.
1514 RecordDecl *D1, RecordDecl *D2) {
1515 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1516 return false;
1517 }
1518
1519 if (D1->isUnion() != D2->isUnion()) {
1520 if (Context.Complain) {
1521 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1522 diag::err_odr_tag_type_inconsistent))
1523 << Context.ToCtx.getTypeDeclType(D2);
1524 Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
1525 << D1->getDeclName() << (unsigned)D1->getTagKind();
1526 }
1527 return false;
1528 }
1529
1530 if (!D1->getDeclName() && !D2->getDeclName()) {
1531 // If both anonymous structs/unions are in a record context, make sure
1532 // they occur in the same location in the context records.
1533 if (std::optional<unsigned> Index1 =
1535 if (std::optional<unsigned> Index2 =
1537 D2)) {
1538 if (*Index1 != *Index2)
1539 return false;
1540 }
1541 }
1542 }
1543
1544 // If the records occur in different context (namespace), these should be
1545 // different. This is specially important if the definition of one or both
1546 // records is missing.
1548 return false;
1549
1550 // If both declarations are class template specializations, we know
1551 // the ODR applies, so check the template and template arguments.
1552 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1553 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1554 if (Spec1 && Spec2) {
1555 // Check that the specialized templates are the same.
1556 if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
1557 Spec2->getSpecializedTemplate()))
1558 return false;
1559
1560 // Check that the template arguments are the same.
1561 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1562 return false;
1563
1564 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1565 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateArgs().get(I),
1566 Spec2->getTemplateArgs().get(I)))
1567 return false;
1568 }
1569 // If one is a class template specialization and the other is not, these
1570 // structures are different.
1571 else if (Spec1 || Spec2)
1572 return false;
1573
1574 // Compare the definitions of these two records. If either or both are
1575 // incomplete (i.e. it is a forward decl), we assume that they are
1576 // equivalent.
1577 D1 = D1->getDefinition();
1578 D2 = D2->getDefinition();
1579 if (!D1 || !D2)
1580 return true;
1581
1582 // If any of the records has external storage and we do a minimal check (or
1583 // AST import) we assume they are equivalent. (If we didn't have this
1584 // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1585 // another AST import which in turn would call the structural equivalency
1586 // check again and finally we'd have an improper result.)
1587 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1589 return true;
1590
1591 // If one definition is currently being defined, we do not compare for
1592 // equality and we assume that the decls are equal.
1593 if (D1->isBeingDefined() || D2->isBeingDefined())
1594 return true;
1595
1596 if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1597 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1598 if (D1CXX->hasExternalLexicalStorage() &&
1599 !D1CXX->isCompleteDefinition()) {
1600 D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1601 }
1602
1603 if (D1CXX->isLambda() != D2CXX->isLambda())
1604 return false;
1605 if (D1CXX->isLambda()) {
1606 if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX))
1607 return false;
1608 }
1609
1610 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1611 if (Context.Complain) {
1612 Context.Diag2(D2->getLocation(),
1613 Context.getApplicableDiagnostic(
1614 diag::err_odr_tag_type_inconsistent))
1615 << Context.ToCtx.getTypeDeclType(D2);
1616 Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
1617 << D2CXX->getNumBases();
1618 Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
1619 << D1CXX->getNumBases();
1620 }
1621 return false;
1622 }
1623
1624 // Check the base classes.
1625 for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1626 BaseEnd1 = D1CXX->bases_end(),
1627 Base2 = D2CXX->bases_begin();
1628 Base1 != BaseEnd1; ++Base1, ++Base2) {
1629 if (!IsStructurallyEquivalent(Context, Base1->getType(),
1630 Base2->getType())) {
1631 if (Context.Complain) {
1632 Context.Diag2(D2->getLocation(),
1633 Context.getApplicableDiagnostic(
1634 diag::err_odr_tag_type_inconsistent))
1635 << Context.ToCtx.getTypeDeclType(D2);
1636 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1637 << Base2->getType() << Base2->getSourceRange();
1638 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1639 << Base1->getType() << Base1->getSourceRange();
1640 }
1641 return false;
1642 }
1643
1644 // Check virtual vs. non-virtual inheritance mismatch.
1645 if (Base1->isVirtual() != Base2->isVirtual()) {
1646 if (Context.Complain) {
1647 Context.Diag2(D2->getLocation(),
1648 Context.getApplicableDiagnostic(
1649 diag::err_odr_tag_type_inconsistent))
1650 << Context.ToCtx.getTypeDeclType(D2);
1651 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1652 << Base2->isVirtual() << Base2->getSourceRange();
1653 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1654 << Base1->isVirtual() << Base1->getSourceRange();
1655 }
1656 return false;
1657 }
1658 }
1659
1660 // Check the friends for consistency.
1661 CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
1662 Friend2End = D2CXX->friend_end();
1663 for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
1664 Friend1End = D1CXX->friend_end();
1665 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1666 if (Friend2 == Friend2End) {
1667 if (Context.Complain) {
1668 Context.Diag2(D2->getLocation(),
1669 Context.getApplicableDiagnostic(
1670 diag::err_odr_tag_type_inconsistent))
1671 << Context.ToCtx.getTypeDeclType(D2CXX);
1672 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1673 Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
1674 }
1675 return false;
1676 }
1677
1678 if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) {
1679 if (Context.Complain) {
1680 Context.Diag2(D2->getLocation(),
1681 Context.getApplicableDiagnostic(
1682 diag::err_odr_tag_type_inconsistent))
1683 << Context.ToCtx.getTypeDeclType(D2CXX);
1684 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1685 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1686 }
1687 return false;
1688 }
1689 }
1690
1691 if (Friend2 != Friend2End) {
1692 if (Context.Complain) {
1693 Context.Diag2(D2->getLocation(),
1694 Context.getApplicableDiagnostic(
1695 diag::err_odr_tag_type_inconsistent))
1696 << Context.ToCtx.getTypeDeclType(D2);
1697 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1698 Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
1699 }
1700 return false;
1701 }
1702 } else if (D1CXX->getNumBases() > 0) {
1703 if (Context.Complain) {
1704 Context.Diag2(D2->getLocation(),
1705 Context.getApplicableDiagnostic(
1706 diag::err_odr_tag_type_inconsistent))
1707 << Context.ToCtx.getTypeDeclType(D2);
1708 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
1709 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1710 << Base1->getType() << Base1->getSourceRange();
1711 Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
1712 }
1713 return false;
1714 }
1715 }
1716
1717 // Check the fields for consistency.
1718 QualType D2Type = Context.ToCtx.getTypeDeclType(D2);
1720 Field2End = D2->field_end();
1721 for (RecordDecl::field_iterator Field1 = D1->field_begin(),
1722 Field1End = D1->field_end();
1723 Field1 != Field1End; ++Field1, ++Field2) {
1724 if (Field2 == Field2End) {
1725 if (Context.Complain) {
1726 Context.Diag2(D2->getLocation(),
1727 Context.getApplicableDiagnostic(
1728 diag::err_odr_tag_type_inconsistent))
1729 << Context.ToCtx.getTypeDeclType(D2);
1730 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1731 << Field1->getDeclName() << Field1->getType();
1732 Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
1733 }
1734 return false;
1735 }
1736
1737 if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type))
1738 return false;
1739 }
1740
1741 if (Field2 != Field2End) {
1742 if (Context.Complain) {
1743 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1744 diag::err_odr_tag_type_inconsistent))
1745 << Context.ToCtx.getTypeDeclType(D2);
1746 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1747 << Field2->getDeclName() << Field2->getType();
1748 Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
1749 }
1750 return false;
1751 }
1752
1753 return true;
1754}
1755
1757 EnumConstantDecl *D1,
1758 EnumConstantDecl *D2) {
1759 const llvm::APSInt &FromVal = D1->getInitVal();
1760 const llvm::APSInt &ToVal = D2->getInitVal();
1761 if (FromVal.isSigned() != ToVal.isSigned())
1762 return false;
1763 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1764 return false;
1765 if (FromVal != ToVal)
1766 return false;
1767
1769 return false;
1770
1771 // Init expressions are the most expensive check, so do them last.
1772 return IsStructurallyEquivalent(Context, D1->getInitExpr(),
1773 D2->getInitExpr());
1774}
1775
1776/// Determine structural equivalence of two enums.
1778 EnumDecl *D1, EnumDecl *D2) {
1779 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1780 return false;
1781 }
1782
1783 // Compare the definitions of these two enums. If either or both are
1784 // incomplete (i.e. forward declared), we assume that they are equivalent.
1785 D1 = D1->getDefinition();
1786 D2 = D2->getDefinition();
1787 if (!D1 || !D2)
1788 return true;
1789
1791 EC2End = D2->enumerator_end();
1793 EC1End = D1->enumerator_end();
1794 EC1 != EC1End; ++EC1, ++EC2) {
1795 if (EC2 == EC2End) {
1796 if (Context.Complain) {
1797 Context.Diag2(D2->getLocation(),
1798 Context.getApplicableDiagnostic(
1799 diag::err_odr_tag_type_inconsistent))
1800 << Context.ToCtx.getTypeDeclType(D2);
1801 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1802 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1803 Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
1804 }
1805 return false;
1806 }
1807
1808 llvm::APSInt Val1 = EC1->getInitVal();
1809 llvm::APSInt Val2 = EC2->getInitVal();
1810 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1811 !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
1812 if (Context.Complain) {
1813 Context.Diag2(D2->getLocation(),
1814 Context.getApplicableDiagnostic(
1815 diag::err_odr_tag_type_inconsistent))
1816 << Context.ToCtx.getTypeDeclType(D2);
1817 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1818 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1819 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1820 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1821 }
1822 return false;
1823 }
1824 }
1825
1826 if (EC2 != EC2End) {
1827 if (Context.Complain) {
1828 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1829 diag::err_odr_tag_type_inconsistent))
1830 << Context.ToCtx.getTypeDeclType(D2);
1831 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1832 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1833 Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
1834 }
1835 return false;
1836 }
1837
1838 return true;
1839}
1840
1842 TemplateParameterList *Params1,
1843 TemplateParameterList *Params2) {
1844 if (Params1->size() != Params2->size()) {
1845 if (Context.Complain) {
1846 Context.Diag2(Params2->getTemplateLoc(),
1847 Context.getApplicableDiagnostic(
1848 diag::err_odr_different_num_template_parameters))
1849 << Params1->size() << Params2->size();
1850 Context.Diag1(Params1->getTemplateLoc(),
1851 diag::note_odr_template_parameter_list);
1852 }
1853 return false;
1854 }
1855
1856 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
1857 if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
1858 if (Context.Complain) {
1859 Context.Diag2(Params2->getParam(I)->getLocation(),
1860 Context.getApplicableDiagnostic(
1861 diag::err_odr_different_template_parameter_kind));
1862 Context.Diag1(Params1->getParam(I)->getLocation(),
1863 diag::note_odr_template_parameter_here);
1864 }
1865 return false;
1866 }
1867
1868 if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
1869 Params2->getParam(I)))
1870 return false;
1871 }
1872
1873 return true;
1874}
1875
1879 if (D1->isParameterPack() != D2->isParameterPack()) {
1880 if (Context.Complain) {
1881 Context.Diag2(D2->getLocation(),
1882 Context.getApplicableDiagnostic(
1883 diag::err_odr_parameter_pack_non_pack))
1884 << D2->isParameterPack();
1885 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1886 << D1->isParameterPack();
1887 }
1888 return false;
1889 }
1890
1891 return true;
1892}
1893
1897 if (D1->isParameterPack() != D2->isParameterPack()) {
1898 if (Context.Complain) {
1899 Context.Diag2(D2->getLocation(),
1900 Context.getApplicableDiagnostic(
1901 diag::err_odr_parameter_pack_non_pack))
1902 << D2->isParameterPack();
1903 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1904 << D1->isParameterPack();
1905 }
1906 return false;
1907 }
1908
1909 // Check types.
1910 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
1911 if (Context.Complain) {
1912 Context.Diag2(D2->getLocation(),
1913 Context.getApplicableDiagnostic(
1914 diag::err_odr_non_type_parameter_type_inconsistent))
1915 << D2->getType() << D1->getType();
1916 Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
1917 << D1->getType();
1918 }
1919 return false;
1920 }
1921
1922 return true;
1923}
1924
1928 if (D1->isParameterPack() != D2->isParameterPack()) {
1929 if (Context.Complain) {
1930 Context.Diag2(D2->getLocation(),
1931 Context.getApplicableDiagnostic(
1932 diag::err_odr_parameter_pack_non_pack))
1933 << D2->isParameterPack();
1934 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1935 << D1->isParameterPack();
1936 }
1937 return false;
1938 }
1939
1940 // Check template parameter lists.
1941 return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
1942 D2->getTemplateParameters());
1943}
1944
1948 return false;
1949 if (!D1->getIdentifier()) // Special name
1950 if (D1->getNameAsString() != D2->getNameAsString())
1951 return false;
1953 D2->getTemplateParameters());
1954}
1955
1958 ClassTemplateDecl *D2) {
1959 // Check template parameters.
1960 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
1961 return false;
1962
1963 // Check the templated declaration.
1964 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
1965 D2->getTemplatedDecl());
1966}
1967
1971 // Check template parameters.
1972 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
1973 return false;
1974
1975 // Check the templated declaration.
1976 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
1977 D2->getTemplatedDecl()->getType());
1978}
1979
1981 ConceptDecl *D1,
1982 ConceptDecl *D2) {
1983 // Check template parameters.
1984 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
1985 return false;
1986
1987 // Check the constraint expression.
1988 return IsStructurallyEquivalent(Context, D1->getConstraintExpr(),
1989 D2->getConstraintExpr());
1990}
1991
1993 FriendDecl *D1, FriendDecl *D2) {
1994 if ((D1->getFriendType() && D2->getFriendDecl()) ||
1995 (D1->getFriendDecl() && D2->getFriendType())) {
1996 return false;
1997 }
1998 if (D1->getFriendType() && D2->getFriendType())
1999 return IsStructurallyEquivalent(Context,
2000 D1->getFriendType()->getType(),
2001 D2->getFriendType()->getType());
2002 if (D1->getFriendDecl() && D2->getFriendDecl())
2003 return IsStructurallyEquivalent(Context, D1->getFriendDecl(),
2004 D2->getFriendDecl());
2005 return false;
2006}
2007
2011 return false;
2012
2013 return IsStructurallyEquivalent(Context, D1->getUnderlyingType(),
2014 D2->getUnderlyingType());
2015}
2016
2018 FunctionDecl *D1, FunctionDecl *D2) {
2020 return false;
2021
2022 if (D1->isOverloadedOperator()) {
2023 if (!D2->isOverloadedOperator())
2024 return false;
2026 return false;
2027 }
2028
2029 // FIXME: Consider checking for function attributes as well.
2030 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
2031 return false;
2032
2033 return true;
2034}
2035
2037 ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2038 QualType Owner2Type) {
2039 if (D1->getAccessControl() != D2->getAccessControl())
2040 return false;
2041
2042 return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1),
2043 cast<FieldDecl>(D2), Owner2Type);
2044}
2045
2047 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2048 QualType Owner2Type =
2049 Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface());
2050 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2051}
2052
2054 ObjCMethodDecl *Method1,
2055 ObjCMethodDecl *Method2) {
2056 bool PropertiesEqual =
2057 Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2058 Method1->isVariadic() == Method2->isVariadic() &&
2059 Method1->isDirectMethod() == Method2->isDirectMethod();
2060 if (!PropertiesEqual)
2061 return false;
2062
2063 // Compare selector slot names.
2064 Selector Selector1 = Method1->getSelector(),
2065 Selector2 = Method2->getSelector();
2066 unsigned NumArgs = Selector1.getNumArgs();
2067 if (NumArgs != Selector2.getNumArgs())
2068 return false;
2069 // Compare all selector slots. For selectors with arguments it means all arg
2070 // slots. And if there are no arguments, compare the first-and-only slot.
2071 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2072 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2074 Selector2.getIdentifierInfoForSlot(I)))
2075 return false;
2076 }
2077
2078 // Compare types.
2079 if (!IsStructurallyEquivalent(Context, Method1->getReturnType(),
2080 Method2->getReturnType()))
2081 return false;
2082 assert(
2083 Method1->param_size() == Method2->param_size() &&
2084 "Same number of arguments should be already enforced in Selector checks");
2086 ParamT1 = Method1->param_type_begin(),
2087 ParamT1End = Method1->param_type_end(),
2088 ParamT2 = Method2->param_type_begin(),
2089 ParamT2End = Method2->param_type_end();
2090 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2091 ++ParamT1, ++ParamT2) {
2092 if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2))
2093 return false;
2094 }
2095
2096 return true;
2097}
2098
2100 ObjCCategoryDecl *D1,
2101 ObjCCategoryDecl *D2) {
2103 return false;
2104
2105 const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2106 *Intf2 = D2->getClassInterface();
2107 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2108 return false;
2109
2110 if (Intf1 &&
2111 !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier()))
2112 return false;
2113
2114 // Compare protocols.
2116 Protocol2End = D2->protocol_end();
2118 Protocol1End = D1->protocol_end();
2119 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2120 if (Protocol2 == Protocol2End)
2121 return false;
2122 if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(),
2123 (*Protocol2)->getIdentifier()))
2124 return false;
2125 }
2126 if (Protocol2 != Protocol2End)
2127 return false;
2128
2129 // Compare ivars.
2130 QualType D2Type =
2131 Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType();
2133 Ivar2End = D2->ivar_end();
2135 Ivar1End = D1->ivar_end();
2136 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2137 if (Ivar2 == Ivar2End)
2138 return false;
2139 if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type))
2140 return false;
2141 }
2142 if (Ivar2 != Ivar2End)
2143 return false;
2144
2145 // Compare methods.
2147 Method2End = D2->meth_end();
2148 for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2149 Method1End = D1->meth_end();
2150 Method1 != Method1End; ++Method1, ++Method2) {
2151 if (Method2 == Method2End)
2152 return false;
2153 if (!IsStructurallyEquivalent(Context, *Method1, *Method2))
2154 return false;
2155 }
2156 if (Method2 != Method2End)
2157 return false;
2158
2159 return true;
2160}
2161
2162/// Determine structural equivalence of two declarations.
2164 Decl *D1, Decl *D2) {
2165 // FIXME: Check for known structural equivalences via a callback of some sort.
2166
2167 D1 = D1->getCanonicalDecl();
2168 D2 = D2->getCanonicalDecl();
2169 std::pair<Decl *, Decl *> P{D1, D2};
2170
2171 // Check whether we already know that these two declarations are not
2172 // structurally equivalent.
2173 if (Context.NonEquivalentDecls.count(P))
2174 return false;
2175
2176 // Check if a check for these declarations is already pending.
2177 // If yes D1 and D2 will be checked later (from DeclsToCheck),
2178 // or these are already checked (and equivalent).
2179 bool Inserted = Context.VisitedDecls.insert(P).second;
2180 if (!Inserted)
2181 return true;
2182
2183 Context.DeclsToCheck.push(P);
2184
2185 return true;
2186}
2187
2189 unsigned DiagID) {
2190 assert(Complain && "Not allowed to complain");
2191 if (LastDiagFromC2)
2193 LastDiagFromC2 = false;
2194 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2195}
2196
2198 unsigned DiagID) {
2199 assert(Complain && "Not allowed to complain");
2200 if (!LastDiagFromC2)
2202 LastDiagFromC2 = true;
2203 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2204}
2205
2206std::optional<unsigned>
2208 ASTContext &Context = Anon->getASTContext();
2209 QualType AnonTy = Context.getRecordType(Anon);
2210
2211 const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
2212 if (!Owner)
2213 return std::nullopt;
2214
2215 unsigned Index = 0;
2216 for (const auto *D : Owner->noload_decls()) {
2217 const auto *F = dyn_cast<FieldDecl>(D);
2218 if (!F)
2219 continue;
2220
2221 if (F->isAnonymousStructOrUnion()) {
2222 if (Context.hasSameType(F->getType(), AnonTy))
2223 break;
2224 ++Index;
2225 continue;
2226 }
2227
2228 // If the field looks like this:
2229 // struct { ... } A;
2230 QualType FieldType = F->getType();
2231 // In case of nested structs.
2232 while (const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2233 FieldType = ElabType->getNamedType();
2234
2235 if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2236 const RecordDecl *RecDecl = RecType->getDecl();
2237 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2238 if (Context.hasSameType(FieldType, AnonTy))
2239 break;
2240 ++Index;
2241 continue;
2242 }
2243 }
2244 }
2245
2246 return Index;
2247}
2248
2250 unsigned ErrorDiagnostic) {
2252 return ErrorDiagnostic;
2253
2254 switch (ErrorDiagnostic) {
2255 case diag::err_odr_variable_type_inconsistent:
2256 return diag::warn_odr_variable_type_inconsistent;
2257 case diag::err_odr_variable_multiple_def:
2258 return diag::warn_odr_variable_multiple_def;
2259 case diag::err_odr_function_type_inconsistent:
2260 return diag::warn_odr_function_type_inconsistent;
2261 case diag::err_odr_tag_type_inconsistent:
2262 return diag::warn_odr_tag_type_inconsistent;
2263 case diag::err_odr_field_type_inconsistent:
2264 return diag::warn_odr_field_type_inconsistent;
2265 case diag::err_odr_ivar_type_inconsistent:
2266 return diag::warn_odr_ivar_type_inconsistent;
2267 case diag::err_odr_objc_superclass_inconsistent:
2268 return diag::warn_odr_objc_superclass_inconsistent;
2269 case diag::err_odr_objc_method_result_type_inconsistent:
2270 return diag::warn_odr_objc_method_result_type_inconsistent;
2271 case diag::err_odr_objc_method_num_params_inconsistent:
2272 return diag::warn_odr_objc_method_num_params_inconsistent;
2273 case diag::err_odr_objc_method_param_type_inconsistent:
2274 return diag::warn_odr_objc_method_param_type_inconsistent;
2275 case diag::err_odr_objc_method_variadic_inconsistent:
2276 return diag::warn_odr_objc_method_variadic_inconsistent;
2277 case diag::err_odr_objc_property_type_inconsistent:
2278 return diag::warn_odr_objc_property_type_inconsistent;
2279 case diag::err_odr_objc_property_impl_kind_inconsistent:
2280 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2281 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2282 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2283 case diag::err_odr_different_num_template_parameters:
2284 return diag::warn_odr_different_num_template_parameters;
2285 case diag::err_odr_different_template_parameter_kind:
2286 return diag::warn_odr_different_template_parameter_kind;
2287 case diag::err_odr_parameter_pack_non_pack:
2288 return diag::warn_odr_parameter_pack_non_pack;
2289 case diag::err_odr_non_type_parameter_type_inconsistent:
2290 return diag::warn_odr_non_type_parameter_type_inconsistent;
2291 }
2292 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2293}
2294
2296
2297 // Ensure that the implementation functions (all static functions in this TU)
2298 // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2299 // because that will wreak havoc the internal state (DeclsToCheck and
2300 // VisitedDecls members) and can cause faulty behaviour.
2301 // In other words: Do not start a graph search from a new node with the
2302 // internal data of another search in progress.
2303 // FIXME: Better encapsulation and separation of internal and public
2304 // functionality.
2305 assert(DeclsToCheck.empty());
2306 assert(VisitedDecls.empty());
2307
2308 if (!::IsStructurallyEquivalent(*this, D1, D2))
2309 return false;
2310
2311 return !Finish();
2312}
2313
2315 assert(DeclsToCheck.empty());
2316 assert(VisitedDecls.empty());
2317 if (!::IsStructurallyEquivalent(*this, T1, T2))
2318 return false;
2319
2320 return !Finish();
2321}
2322
2324 assert(DeclsToCheck.empty());
2325 assert(VisitedDecls.empty());
2326 if (!::IsStructurallyEquivalent(*this, S1, S2))
2327 return false;
2328
2329 return !Finish();
2330}
2331
2332bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2333 // Check for equivalent described template.
2334 TemplateDecl *Template1 = D1->getDescribedTemplate();
2335 TemplateDecl *Template2 = D2->getDescribedTemplate();
2336 if ((Template1 != nullptr) != (Template2 != nullptr))
2337 return false;
2338 if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2))
2339 return false;
2340
2341 // FIXME: Move check for identifier names into this function.
2342
2343 return true;
2344}
2345
2346bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2347 Decl *D1, Decl *D2) {
2348
2349 // Kind mismatch.
2350 if (D1->getKind() != D2->getKind())
2351 return false;
2352
2353 // Cast the Decls to their actual subclass so that the right overload of
2354 // IsStructurallyEquivalent is called.
2355 switch (D1->getKind()) {
2356#define ABSTRACT_DECL(DECL)
2357#define DECL(DERIVED, BASE) \
2358 case Decl::Kind::DERIVED: \
2359 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2360 static_cast<DERIVED##Decl *>(D2));
2361#include "clang/AST/DeclNodes.inc"
2362 }
2363 return true;
2364}
2365
2366bool StructuralEquivalenceContext::Finish() {
2367 while (!DeclsToCheck.empty()) {
2368 // Check the next declaration.
2369 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2370 DeclsToCheck.pop();
2371
2372 Decl *D1 = P.first;
2373 Decl *D2 = P.second;
2374
2375 bool Equivalent =
2376 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2377
2378 if (!Equivalent) {
2379 // Note that these two declarations are not equivalent (and we already
2380 // know about it).
2381 NonEquivalentDecls.insert(P);
2382
2383 return true;
2384 }
2385 }
2386
2387 return false;
2388}
Defines the clang::ASTContext interface.
StringRef P
static bool IsTemplateDeclCommonStructurallyEquivalent(StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2)
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 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 bool IsRecordContextStructurallyEquivalent(RecordDecl *D1, RecordDecl *D2)
Determine if context of a class is equivalent.
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1117
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
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 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 OpenMP AST classes for executable directives and clauses.
C Language Family Type Representation.
llvm::APInt getValue() const
Definition: Expr.h:1517
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.
QualType getRecordType(const RecordDecl *Decl) const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2535
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2551
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1572
DiagnosticsEngine & getDiagnostics() const
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
Definition: ASTContext.h:1179
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition: Expr.h:4360
LabelDecl * getLabel() const
Definition: Expr.h:4383
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3143
ArraySizeModifier getSizeModifier() const
Definition: Type.h:3157
Qualifiers getIndexTypeQualifiers() const
Definition: Type.h:3161
QualType getElementType() const
Definition: Type.h:3155
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.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition: Expr.h:6448
AtomicOp getOp() const
Definition: Expr.h:6512
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3862
Opcode getOpcode() const
Definition: Expr.h:3906
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
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition: ExprCXX.h:720
bool getValue() const
Definition: ExprCXX.h:737
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2053
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:2420
bool isVirtual() const
Definition: DeclCXX.h:2108
bool isVolatile() const
Definition: DeclCXX.h:2106
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this method.
Definition: DeclCXX.h:2229
bool isConst() const
Definition: DeclCXX.h:2105
bool isStatic() const
Definition: DeclCXX.cpp:2145
An iterator over the friend declarations of a class.
Definition: DeclFriend.h:186
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool isLambda() const
Determine whether this class describes a lambda function object.
Definition: DeclCXX.h:1021
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition: DeclCXX.cpp:1553
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2847
Decl * getCalleeDecl()
Definition: Expr.h:3011
unsigned getValue() const
Definition: Expr.h:1649
CharacterLiteralKind getKind() const
Definition: Expr.h:1642
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Definition: Expr.h:4580
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1602
unsigned size() const
Definition: Stmt.h:1645
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents a concrete matrix type with constant number of rows and columns.
Definition: Type.h:3703
unsigned getNumColumns() const
Returns the number of columns in the matrix.
Definition: Type.h:3724
unsigned getNumRows() const
Returns the number of rows in the matrix.
Definition: Type.h:3721
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
Definition: DeclBase.h:2340
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2065
bool isTranslationUnit() const
Definition: DeclBase.h:2140
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Definition: DeclBase.h:2635
bool isInlineNamespace() const
Definition: DeclBase.cpp:1257
bool isFunctionOrMethod() const
Definition: DeclBase.h:2117
Decl::Kind getDeclKind() const
Definition: DeclBase.h:2058
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1359
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1248
ValueDecl * getDecl()
Definition: Expr.h:1316
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:85
TemplateDecl * getDescribedTemplate() const
If this is a declaration that describes some template, this method returns that template declaration.
Definition: DeclBase.cpp:239
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:501
SourceLocation getLocation() const
Definition: DeclBase.h:444
DeclContext * getDeclContext()
Definition: DeclBase.h:453
AccessSpecifier getAccess() const
Definition: DeclBase.h:512
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:967
Kind getKind() const
Definition: DeclBase.h:447
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.
A qualified reference to a name whose declaration cannot yet be resolved.
Definition: ExprCXX.h:3298
NestedNameSpecifier * getQualifier() const
Retrieve the nested-name-specifier that qualifies this declaration.
Definition: ExprCXX.h:3350
DeclarationName getDeclName() const
Retrieve the name that this expression refers to.
Definition: ExprCXX.h:3337
Represents a matrix type where the type and the number of rows and columns is dependent on a template...
Definition: Type.h:3762
Expr * getColumnExpr() const
Definition: Type.h:3775
Expr * getRowExpr() const
Definition: Type.h:3774
Represents a dependent template name that cannot be resolved prior to template instantiation.
Definition: TemplateName.h:488
OverloadedOperatorKind getOperator() const
Return the overloaded operator to which this template name refers.
Definition: TemplateName.h:560
bool isIdentifier() const
Determine whether this template name refers to an identifier.
Definition: TemplateName.h:547
NestedNameSpecifier * getQualifier() const
Return the nested name specifier that qualifies this name.
Definition: TemplateName.h:544
const IdentifierInfo * getIdentifier() const
Returns the identifier to which this template name refers.
Definition: TemplateName.h:550
bool isOverloadedOperator() const
Determine whether this template name refers to an overloaded operator.
Definition: TemplateName.h:557
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1271
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1547
void notePriorDiagnosticFrom(const DiagnosticsEngine &Other)
Note that the prior diagnostic was emitted by some other DiagnosticsEngine, and we may be attaching a...
Definition: Diagnostic.h:896
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3253
const Expr * getInitExpr() const
Definition: Decl.h:3272
const llvm::APSInt & getInitVal() const
Definition: Decl.h:3274
Represents an enum.
Definition: Decl.h:3816
enumerator_iterator enumerator_begin() const
Definition: Decl.h:3953
EnumDecl * getDefinition() const
Definition: Decl.h:3919
enumerator_iterator enumerator_end() const
Definition: Decl.h:3960
This represents one expression.
Definition: Expr.h:110
QualType getType() const
Definition: Expr.h:142
An expression trait intrinsic.
Definition: ExprCXX.h:2920
ExpressionTrait getTrait() const
Definition: ExprCXX.h:2957
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
Represents a member of a struct/union/class.
Definition: Decl.h:3015
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3106
bool isAnonymousStructOrUnion() const
Determines whether this field is a representative for an anonymous struct or union.
Definition: Decl.cpp:4498
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Definition: Decl.h:3119
llvm::APFloat getValue() const
Definition: Expr.h:1686
bool isExact() const
Definition: Expr.h:1719
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:137
TypeSourceInfo * getFriendType() const
If this friend declaration names an (untemplated but possibly dependent) type, return the type; other...
Definition: DeclFriend.h:122
Represents a function declaration or definition.
Definition: Decl.h:1957
bool isPure() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2295
bool isDeleted() const
Whether this function has been deleted.
Definition: Decl.h:2475
bool isDefaulted() const
Whether this function is defaulted.
Definition: Decl.h:2320
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Definition: Decl.h:2800
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition: Decl.cpp:3916
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4158
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition: Type.h:4401
QualType getExceptionType(unsigned i) const
Return the ith exception type, where 0 <= i < getNumExceptions().
Definition: Type.h:4452
unsigned getNumExceptions() const
Return the number of types in the exception specification.
Definition: Type.h:4444
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Definition: Type.h:4459
Declaration of a template function.
Definition: DeclTemplate.h:977
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
A class which abstracts out some details necessary for making a call.
Definition: Type.h:3903
CallingConv getCC() const
Definition: Type.h:3965
bool getNoCfCheck() const
Definition: Type.h:3955
unsigned getRegParm() const
Definition: Type.h:3958
bool getNoCallerSavedRegs() const
Definition: Type.h:3954
bool getHasRegParm() const
Definition: Type.h:3956
bool getProducesResult() const
Definition: Type.h:3952
Represents a C11 generic selection.
Definition: Expr.h:5736
ArrayRef< TypeSourceInfo * > getAssocTypeSourceInfos() const
Definition: Expr.h:6036
GotoStmt - This represents a direct goto.
Definition: Stmt.h:2856
LabelDecl * getLabel() const
Definition: Stmt.h:2869
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition: Expr.h:3677
Represents the declaration of a label.
Definition: Decl.h:497
QualType getElementType() const
Returns type of the elements being stored in the matrix.
Definition: Type.h:3681
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3210
DeclAccessPair getFoundDecl() const
Retrieves the declaration found by lookup.
Definition: Expr.h:3293
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:269
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:314
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:291
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier.
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
IdentifierInfo * getAsIdentifier() const
Retrieve the identifier stored in this nested name specifier.
NestedNameSpecifier * getPrefix() const
Return the prefix of this nested name specifier.
@ NamespaceAlias
A namespace alias, stored as a NamespaceAliasDecl*.
@ TypeSpec
A type, stored as a Type*.
@ TypeSpecWithTemplate
A type that was preceded by the 'template' keyword, stored as a Type*.
@ Super
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Identifier
An identifier, stored as an IdentifierInfo*.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace, stored as a NamespaceDecl*.
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2323
ivar_iterator ivar_begin() const
Definition: DeclObjC.h:2440
ivar_iterator ivar_end() const
Definition: DeclObjC.h:2444
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.h:2368
protocol_iterator protocol_end() const
Definition: DeclObjC.h:2407
protocol_iterator protocol_begin() const
Definition: DeclObjC.h:2403
ObjCProtocolList::iterator protocol_iterator
Definition: DeclObjC.h:2396
method_iterator meth_begin() const
Definition: DeclObjC.h:1016
method_iterator meth_end() const
Definition: DeclObjC.h:1020
Represents an ObjC class declaration.
Definition: DeclObjC.h:1150
ObjCIvarDecl - Represents an ObjC instance variable.
Definition: DeclObjC.h:1947
AccessControl getAccessControl() const
Definition: DeclObjC.h:1996
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
Definition: DeclObjC.cpp:1881
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:871
llvm::mapped_iterator< param_const_iterator, GetTypeFn > param_type_iterator
Definition: DeclObjC.h:397
Selector getSelector() const
Definition: DeclObjC.h:327
bool isInstanceMethod() const
Definition: DeclObjC.h:426
QualType getReturnType() const
Definition: DeclObjC.h:329
ObjCStringLiteral, used for Objective-C string literals i.e.
Definition: ExprObjC.h:51
A reference to an overloaded function set, either an UnresolvedLookupExpr or an UnresolvedMemberExpr.
Definition: ExprCXX.h:2979
NestedNameSpecifier * getQualifier() const
Fetches the nested-name qualifier, if one was given.
Definition: ExprCXX.h:3094
TemplateArgumentLoc const * getTemplateArgs() const
Definition: ExprCXX.h:3132
unsigned getNumTemplateArgs() const
Definition: ExprCXX.h:3138
DeclarationName getName() const
Gets the name looked up.
Definition: ExprCXX.h:3088
A structure for storing the information associated with an overloaded template name.
Definition: TemplateName.h:108
A (possibly-)qualified type.
Definition: Type.h:736
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition: Type.h:1084
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:803
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:6819
Represents a struct/union/class.
Definition: Decl.h:4117
field_iterator field_end() const
Definition: Decl.h:4326
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:4308
field_iterator field_begin() const
Definition: Decl.cpp:5006
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4969
Smart pointer class that efficiently represents Objective-C method names.
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
unsigned getNumArgs() const
Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), __builtin_FUNCTION(),...
Definition: Expr.h:4749
SourceLocIdentKind getIdentKind() const
Definition: Expr.h:4769
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
Definition: Expr.h:4405
unsigned getTemplateDepth() const
Definition: Expr.h:4434
Stmt - This represents one statement.
Definition: Stmt.h:84
@ NoStmtClass
Definition: Stmt.h:87
child_range children()
Definition: Stmt.cpp:286
StmtClass getStmtClass() const
Definition: Stmt.h:1354
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1812
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
Definition: Expr.h:1897
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Definition: ExprCXX.h:4349
std::optional< unsigned > getPackIndex() const
Definition: ExprCXX.h:4397
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
Definition: ExprCXX.h:4391
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Definition: ExprCXX.h:4395
Represents a reference to a non-type template parameter pack that has been substituted with a non-tem...
Definition: ExprCXX.h:4434
TemplateArgument getArgumentPack() const
Retrieve the template argument pack containing the substituted template arguments.
Definition: ExprCXX.cpp:1694
A structure for storing an already-substituted template template parameter pack.
Definition: TemplateName.h:141
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.
Definition: TemplateName.h:156
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3533
bool isBeingDefined() const
Return true if this decl is currently being defined.
Definition: Decl.h:3656
bool isUnion() const
Definition: Decl.h:3739
TagKind getTagKind() const
Definition: Decl.h:3728
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:495
const TemplateArgument & getArgument() const
Definition: TemplateBase.h:544
Represents a template argument.
Definition: TemplateBase.h:60
Expr * getAsExpr() const
Retrieve the template argument as an expression.
Definition: TemplateBase.h:379
QualType getAsType() const
Retrieve the type for a type template argument.
Definition: TemplateBase.h:298
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
Definition: TemplateBase.h:342
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
Definition: TemplateBase.h:322
QualType getIntegralType() const
Retrieve the type of the integral value.
Definition: TemplateBase.h:356
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
Definition: TemplateBase.h:305
ArrayRef< TemplateArgument > pack_elements() const
Iterator range referencing all of the elements of a template argument pack.
Definition: TemplateBase.h:403
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
Definition: TemplateBase.h:73
@ Template
The template argument is a template name that was provided for a template template parameter.
Definition: TemplateBase.h:85
@ Pack
The template argument is actually a parameter pack.
Definition: TemplateBase.h:99
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
Definition: TemplateBase.h:89
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
Definition: TemplateBase.h:77
@ Type
The template argument is a type.
Definition: TemplateBase.h:69
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
Definition: TemplateBase.h:66
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
Definition: TemplateBase.h:81
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
Definition: TemplateBase.h:95
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:274
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
Definition: TemplateBase.h:329
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:413
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:432
Represents a C++ template name within the type system.
Definition: TemplateName.h:202
TemplateDecl * getAsTemplateDecl() 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...
Definition: TemplateName.h:247
@ OverloadedTemplate
A set of overloaded template declarations.
Definition: TemplateName.h:222
@ Template
A single template declaration.
Definition: TemplateName.h:219
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
Definition: TemplateName.h:234
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
Definition: TemplateName.h:238
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
Definition: TemplateName.h:243
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
Definition: TemplateName.h:230
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
Definition: TemplateName.h:226
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.
Definition: DeclTemplate.h:73
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:143
SourceLocation getTemplateLoc() const
Definition: DeclTemplate.h:198
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
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.
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:6761
A type trait used in the implementation of various C++11 and Library TR1 trait templates.
Definition: ExprCXX.h:2764
ArrayRef< TypeSourceInfo * > getArgs() const
Retrieve the argument types.
Definition: ExprCXX.h:2820
TypeTrait getTrait() const
Determine which type trait this expression uses.
Definition: ExprCXX.h:2801
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:7615
TypeClass getTypeClass() const
Definition: Type.h:2070
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3383
QualType getUnderlyingType() const
Definition: Decl.h:3438
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition: Expr.h:2595
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition: Expr.h:2664
UnaryExprOrTypeTrait getKind() const
Definition: Expr.h:2627
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2210
Opcode getOpcode() const
Definition: Expr.h:2250
Represents a call to the builtin function __builtin_va_arg.
Definition: Expr.h:4689
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:704
QualType getType() const
Definition: Decl.h:715
Represents a variable declaration or definition.
Definition: Decl.h:916
const Expr * getInit() const
Definition: Decl.h:1350
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1150
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
bool isComputedNoexcept(ExceptionSpecificationType ESpecType)
@ EST_Dynamic
throw(T1, T2)
llvm::DenseSet< std::pair< Decl *, Decl * > > & NonEquivalentDecls
Declaration (from, to) pairs that are known not to be equivalent (which we have already complained ab...
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
bool ErrorOnTagTypeMismatch
Whether warn or error on tag type mismatches.
static std::optional< unsigned > findUntaggedStructOrUnionIndex(RecordDecl *Anon)
Find the index of the given anonymous struct/union within its context.
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.