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