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
727 // It is sufficient to check value of getAsTemplateDecl.
728 break;
729
731 // FIXME: We can't reach here.
732 llvm_unreachable("unimplemented");
733 }
734
735 return true;
736}
737
741
742/// Determine whether two template arguments are equivalent.
744 const TemplateArgument &Arg1,
745 const TemplateArgument &Arg2) {
746 if (Arg1.getKind() != Arg2.getKind())
747 return false;
748
749 switch (Arg1.getKind()) {
751 return true;
752
754 return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
755
757 if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
758 Arg2.getIntegralType()))
759 return false;
760
761 return llvm::APSInt::isSameValue(Arg1.getAsIntegral(),
762 Arg2.getAsIntegral());
763
765 return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
766
768 return true; // FIXME: Is this correct?
769
771 return IsStructurallyEquivalent(Context, Arg1.getAsTemplate(),
772 Arg2.getAsTemplate());
773
775 return IsStructurallyEquivalent(Context,
778
780 return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
781 Arg2.getAsExpr());
782
784 return Arg1.structurallyEquals(Arg2);
785
787 return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
788 Arg2.pack_elements());
789 }
790
791 llvm_unreachable("Invalid template argument kind");
792}
793
794/// Determine structural equivalence of two template argument lists.
798 if (Args1.size() != Args2.size())
799 return false;
800 for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
801 if (!IsStructurallyEquivalent(Context, Args1[I], Args2[I]))
802 return false;
803 }
804 return true;
805}
806
807/// Determine whether two template argument locations are equivalent.
809 const TemplateArgumentLoc &Arg1,
810 const TemplateArgumentLoc &Arg2) {
811 return IsStructurallyEquivalent(Context, Arg1.getArgument(),
812 Arg2.getArgument());
813}
814
815/// Determine structural equivalence for the common part of array
816/// types.
818 const ArrayType *Array1,
819 const ArrayType *Array2) {
820 if (!IsStructurallyEquivalent(Context, Array1->getElementType(),
821 Array2->getElementType()))
822 return false;
823 if (Array1->getSizeModifier() != Array2->getSizeModifier())
824 return false;
825 if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
826 return false;
827
828 return true;
829}
830
831/// Determine structural equivalence based on the ExtInfo of functions. This
832/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
833/// conventions bits but must not compare some other bits.
837 // Compatible functions must have compatible calling conventions.
838 if (EI1.getCC() != EI2.getCC())
839 return false;
840
841 // Regparm is part of the calling convention.
842 if (EI1.getHasRegParm() != EI2.getHasRegParm())
843 return false;
844 if (EI1.getRegParm() != EI2.getRegParm())
845 return false;
846
847 if (EI1.getProducesResult() != EI2.getProducesResult())
848 return false;
850 return false;
851 if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
852 return false;
853
854 return true;
855}
856
857/// Check the equivalence of exception specifications.
859 const FunctionProtoType *Proto1,
860 const FunctionProtoType *Proto2) {
861
862 auto Spec1 = Proto1->getExceptionSpecType();
863 auto Spec2 = Proto2->getExceptionSpecType();
864
866 return true;
867
868 if (Spec1 != Spec2)
869 return false;
870 if (Spec1 == EST_Dynamic) {
871 if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
872 return false;
873 for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
874 if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
875 Proto2->getExceptionType(I)))
876 return false;
877 }
878 } else if (isComputedNoexcept(Spec1)) {
879 if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
880 Proto2->getNoexceptExpr()))
881 return false;
882 }
883
884 return true;
885}
886
887/// Determine structural equivalence of two types.
890 if (T1.isNull() || T2.isNull())
891 return T1.isNull() && T2.isNull();
892
893 QualType OrigT1 = T1;
894 QualType OrigT2 = T2;
895
896 if (!Context.StrictTypeSpelling) {
897 // We aren't being strict about token-to-token equivalence of types,
898 // so map down to the canonical type.
899 T1 = Context.FromCtx.getCanonicalType(T1);
900 T2 = Context.ToCtx.getCanonicalType(T2);
901 }
902
903 if (T1.getQualifiers() != T2.getQualifiers())
904 return false;
905
906 Type::TypeClass TC = T1->getTypeClass();
907
908 if (T1->getTypeClass() != T2->getTypeClass()) {
909 // Compare function types with prototypes vs. without prototypes as if
910 // both did not have prototypes.
911 if (T1->getTypeClass() == Type::FunctionProto &&
912 T2->getTypeClass() == Type::FunctionNoProto)
913 TC = Type::FunctionNoProto;
914 else if (T1->getTypeClass() == Type::FunctionNoProto &&
915 T2->getTypeClass() == Type::FunctionProto)
916 TC = Type::FunctionNoProto;
917 else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
918 (T1->getTypeClass() == Type::Enum ||
919 T2->getTypeClass() == Type::Enum)) {
920 // In C23, if not being strict about token equivalence, we need to handle
921 // the case where one type is an enumeration and the other type is an
922 // integral type.
923 //
924 // C23 6.7.3.3p16: The enumerated type is compatible with the underlying
925 // type of the enumeration.
926 //
927 // Treat the enumeration as its underlying type and use the builtin type
928 // class comparison. If the enumeration is invalid, e.g., it could be a
929 // forward declaration of an enumeration without a fixed underlying type,
930 // we'll default to 'int' for error recovery. If one type is an
931 // enumeration, the other must be an enumeration or integral, otherwise
932 // they're not structurally equivalent. e.g., it could be an enum in one
933 // struct and a union in another.
934 if (T1->getTypeClass() == Type::Enum) {
935 if (!T2->isBuiltinType() && !T2->isEnumeralType())
936 return false;
937 T1 = cast<EnumType>(T1)->getDecl()->getIntegerType();
938 if (T1.isNull())
939 T1 = Context.FromCtx.IntTy;
940 } else if (T2->getTypeClass() == Type::Enum) {
941 if (!T1->isBuiltinType() && !T1->isEnumeralType())
942 return false;
943 T2 = cast<EnumType>(T2)->getDecl()->getIntegerType();
944 if (T2.isNull())
945 T2 = Context.ToCtx.IntTy;
946 }
947 TC = Type::Builtin;
948 } else
949 return false;
950 }
951
952 switch (TC) {
953 case Type::Builtin:
954 // FIXME: Deal with Char_S/Char_U.
956 return false;
957 break;
958
959 case Type::Complex:
960 if (!IsStructurallyEquivalent(Context,
961 cast<ComplexType>(T1)->getElementType(),
962 cast<ComplexType>(T2)->getElementType()))
963 return false;
964 break;
965
966 case Type::Adjusted:
967 case Type::Decayed:
968 case Type::ArrayParameter:
969 if (!IsStructurallyEquivalent(Context,
970 cast<AdjustedType>(T1)->getOriginalType(),
971 cast<AdjustedType>(T2)->getOriginalType()))
972 return false;
973 break;
974
975 case Type::Pointer:
976 if (!IsStructurallyEquivalent(Context,
979 return false;
980 break;
981
982 case Type::BlockPointer:
983 if (!IsStructurallyEquivalent(Context,
986 return false;
987 break;
988
989 case Type::LValueReference:
990 case Type::RValueReference: {
991 const auto *Ref1 = cast<ReferenceType>(T1);
992 const auto *Ref2 = cast<ReferenceType>(T2);
993 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
994 return false;
995 if (Ref1->isInnerRef() != Ref2->isInnerRef())
996 return false;
997 if (!IsStructurallyEquivalent(Context, Ref1->getPointeeTypeAsWritten(),
998 Ref2->getPointeeTypeAsWritten()))
999 return false;
1000 break;
1001 }
1002
1003 case Type::MemberPointer: {
1004 const auto *MemPtr1 = cast<MemberPointerType>(T1);
1005 const auto *MemPtr2 = cast<MemberPointerType>(T2);
1006 if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
1007 MemPtr2->getPointeeType()))
1008 return false;
1009 if (!IsStructurallyEquivalent(Context, MemPtr1->getQualifier(),
1010 MemPtr2->getQualifier()))
1011 return false;
1012 CXXRecordDecl *D1 = MemPtr1->getMostRecentCXXRecordDecl(),
1013 *D2 = MemPtr2->getMostRecentCXXRecordDecl();
1014 if (D1 == D2)
1015 break;
1016 if (!D1 || !D2 || !IsStructurallyEquivalent(Context, D1, D2))
1017 return false;
1018 break;
1019 }
1020
1021 case Type::ConstantArray: {
1022 const auto *Array1 = cast<ConstantArrayType>(T1);
1023 const auto *Array2 = cast<ConstantArrayType>(T2);
1024 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
1025 return false;
1026
1027 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1028 return false;
1029 break;
1030 }
1031
1032 case Type::IncompleteArray:
1034 cast<ArrayType>(T2)))
1035 return false;
1036 break;
1037
1038 case Type::VariableArray: {
1039 const auto *Array1 = cast<VariableArrayType>(T1);
1040 const auto *Array2 = cast<VariableArrayType>(T2);
1041 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
1042 Array2->getSizeExpr()))
1043 return false;
1044
1045 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1046 return false;
1047
1048 break;
1049 }
1050
1051 case Type::DependentSizedArray: {
1052 const auto *Array1 = cast<DependentSizedArrayType>(T1);
1053 const auto *Array2 = cast<DependentSizedArrayType>(T2);
1054 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
1055 Array2->getSizeExpr()))
1056 return false;
1057
1058 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
1059 return false;
1060
1061 break;
1062 }
1063
1064 case Type::DependentAddressSpace: {
1065 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
1066 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
1067 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
1068 DepAddressSpace2->getAddrSpaceExpr()))
1069 return false;
1070 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(),
1071 DepAddressSpace2->getPointeeType()))
1072 return false;
1073
1074 break;
1075 }
1076
1077 case Type::DependentSizedExtVector: {
1078 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
1079 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
1080 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
1081 Vec2->getSizeExpr()))
1082 return false;
1083 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
1084 Vec2->getElementType()))
1085 return false;
1086 break;
1087 }
1088
1089 case Type::DependentVector: {
1090 const auto *Vec1 = cast<DependentVectorType>(T1);
1091 const auto *Vec2 = cast<DependentVectorType>(T2);
1092 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1093 return false;
1094 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
1095 Vec2->getSizeExpr()))
1096 return false;
1097 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
1098 Vec2->getElementType()))
1099 return false;
1100 break;
1101 }
1102
1103 case Type::Vector:
1104 case Type::ExtVector: {
1105 const auto *Vec1 = cast<VectorType>(T1);
1106 const auto *Vec2 = cast<VectorType>(T2);
1107 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
1108 Vec2->getElementType()))
1109 return false;
1110 if (Vec1->getNumElements() != Vec2->getNumElements())
1111 return false;
1112 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1113 return false;
1114 break;
1115 }
1116
1117 case Type::DependentSizedMatrix: {
1120 // The element types, row and column expressions must be structurally
1121 // equivalent.
1122 if (!IsStructurallyEquivalent(Context, Mat1->getRowExpr(),
1123 Mat2->getRowExpr()) ||
1124 !IsStructurallyEquivalent(Context, Mat1->getColumnExpr(),
1125 Mat2->getColumnExpr()) ||
1126 !IsStructurallyEquivalent(Context, Mat1->getElementType(),
1127 Mat2->getElementType()))
1128 return false;
1129 break;
1130 }
1131
1132 case Type::ConstantMatrix: {
1135 // The element types must be structurally equivalent and the number of rows
1136 // and columns must match.
1137 if (!IsStructurallyEquivalent(Context, Mat1->getElementType(),
1138 Mat2->getElementType()) ||
1139 Mat1->getNumRows() != Mat2->getNumRows() ||
1140 Mat1->getNumColumns() != Mat2->getNumColumns())
1141 return false;
1142 break;
1143 }
1144
1145 case Type::FunctionProto: {
1146 const auto *Proto1 = cast<FunctionProtoType>(T1);
1147 const auto *Proto2 = cast<FunctionProtoType>(T2);
1148
1149 if (Proto1->getNumParams() != Proto2->getNumParams())
1150 return false;
1151 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1152 if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I),
1153 Proto2->getParamType(I)))
1154 return false;
1155 }
1156 if (Proto1->isVariadic() != Proto2->isVariadic())
1157 return false;
1158
1159 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1160 return false;
1161
1162 // Check exceptions, this information is lost in canonical type.
1163 const auto *OrigProto1 =
1164 cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
1165 const auto *OrigProto2 =
1166 cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
1167 if (!IsEquivalentExceptionSpec(Context, OrigProto1, OrigProto2))
1168 return false;
1169
1170 // Fall through to check the bits common with FunctionNoProtoType.
1171 [[fallthrough]];
1172 }
1173
1174 case Type::FunctionNoProto: {
1175 const auto *Function1 = cast<FunctionType>(T1);
1176 const auto *Function2 = cast<FunctionType>(T2);
1177 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
1178 Function2->getReturnType()))
1179 return false;
1180 if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
1181 Function2->getExtInfo()))
1182 return false;
1183 break;
1184 }
1185
1186 case Type::UnresolvedUsing:
1187 if (!IsStructurallyEquivalent(Context,
1188 cast<UnresolvedUsingType>(T1)->getDecl(),
1189 cast<UnresolvedUsingType>(T2)->getDecl()))
1190 return false;
1191 break;
1192
1193 case Type::Attributed:
1194 if (!IsStructurallyEquivalent(Context,
1195 cast<AttributedType>(T1)->getModifiedType(),
1196 cast<AttributedType>(T2)->getModifiedType()))
1197 return false;
1199 Context, cast<AttributedType>(T1)->getEquivalentType(),
1200 cast<AttributedType>(T2)->getEquivalentType()))
1201 return false;
1202 break;
1203
1204 case Type::CountAttributed:
1205 if (!IsStructurallyEquivalent(Context,
1206 cast<CountAttributedType>(T1)->desugar(),
1207 cast<CountAttributedType>(T2)->desugar()))
1208 return false;
1209 break;
1210
1211 case Type::LateParsedAttr:
1213 Context, cast<LateParsedAttrType>(T1)->getWrappedType(),
1214 cast<LateParsedAttrType>(T2)->getWrappedType()))
1215 return false;
1216 break;
1217
1218 case Type::BTFTagAttributed:
1220 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1221 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1222 return false;
1223 break;
1224
1225 case Type::OverflowBehavior:
1229 return false;
1230 break;
1231
1232 case Type::HLSLAttributedResource:
1234 Context, cast<HLSLAttributedResourceType>(T1)->getWrappedType(),
1235 cast<HLSLAttributedResourceType>(T2)->getWrappedType()))
1236 return false;
1238 Context, cast<HLSLAttributedResourceType>(T1)->getContainedType(),
1239 cast<HLSLAttributedResourceType>(T2)->getContainedType()))
1240 return false;
1241 {
1242 const auto *Res1 = cast<HLSLAttributedResourceType>(T1);
1243 const auto *Res2 = cast<HLSLAttributedResourceType>(T2);
1244 if (!IsStructurallyEquivalent(Context, Res1->getSampleCountExpr(),
1245 Res2->getSampleCountExpr()))
1246 return false;
1247 HLSLAttributedResourceType::Attributes Attrs1 = Res1->getAttrs();
1248 HLSLAttributedResourceType::Attributes Attrs2 = Res2->getAttrs();
1249 Attrs1.SampleCountExpr = Attrs2.SampleCountExpr = nullptr;
1250 if (Attrs1 != Attrs2)
1251 return false;
1252 }
1253 break;
1254
1255 case Type::HLSLInlineSpirv:
1256 if (cast<HLSLInlineSpirvType>(T1)->getOpcode() !=
1257 cast<HLSLInlineSpirvType>(T2)->getOpcode() ||
1258 cast<HLSLInlineSpirvType>(T1)->getSize() !=
1259 cast<HLSLInlineSpirvType>(T2)->getSize() ||
1260 cast<HLSLInlineSpirvType>(T1)->getAlignment() !=
1261 cast<HLSLInlineSpirvType>(T2)->getAlignment())
1262 return false;
1263 for (size_t I = 0; I < cast<HLSLInlineSpirvType>(T1)->getOperands().size();
1264 I++) {
1265 if (cast<HLSLInlineSpirvType>(T1)->getOperands()[I] !=
1266 cast<HLSLInlineSpirvType>(T2)->getOperands()[I]) {
1267 return false;
1268 }
1269 }
1270 break;
1271
1272 case Type::Paren:
1273 if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(),
1274 cast<ParenType>(T2)->getInnerType()))
1275 return false;
1276 break;
1277
1278 case Type::MacroQualified:
1282 return false;
1283 break;
1284
1285 case Type::Using: {
1286 auto *U1 = cast<UsingType>(T1), *U2 = cast<UsingType>(T2);
1287 if (U1->getKeyword() != U2->getKeyword())
1288 return false;
1289 if (!IsStructurallyEquivalent(Context, U1->getQualifier(),
1290 U2->getQualifier()))
1291 return false;
1292 if (!IsStructurallyEquivalent(Context, U1->getDecl(), U2->getDecl()))
1293 return false;
1294 if (!IsStructurallyEquivalent(Context, U1->desugar(), U2->desugar()))
1295 return false;
1296 break;
1297 }
1298 case Type::Typedef: {
1299 auto *U1 = cast<TypedefType>(T1), *U2 = cast<TypedefType>(T2);
1300 if (U1->getKeyword() != U2->getKeyword())
1301 return false;
1302 if (!IsStructurallyEquivalent(Context, U1->getQualifier(),
1303 U2->getQualifier()))
1304 return false;
1305 if (!IsStructurallyEquivalent(Context, U1->getDecl(), U2->getDecl()))
1306 return false;
1307 if (U1->typeMatchesDecl() != U2->typeMatchesDecl())
1308 return false;
1309 if (!U1->typeMatchesDecl() &&
1310 !IsStructurallyEquivalent(Context, U1->desugar(), U2->desugar()))
1311 return false;
1312 break;
1313 }
1314
1315 case Type::TypeOfExpr:
1317 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1318 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1319 return false;
1320 break;
1321
1322 case Type::TypeOf:
1323 if (!IsStructurallyEquivalent(Context,
1324 cast<TypeOfType>(T1)->getUnmodifiedType(),
1325 cast<TypeOfType>(T2)->getUnmodifiedType()))
1326 return false;
1327 break;
1328
1329 case Type::UnaryTransform:
1333 return false;
1334 break;
1335
1336 case Type::Decltype:
1337 if (!IsStructurallyEquivalent(Context,
1338 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1339 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1340 return false;
1341 break;
1342
1343 case Type::Auto: {
1344 auto *Auto1 = cast<AutoType>(T1);
1345 auto *Auto2 = cast<AutoType>(T2);
1346 if (!IsStructurallyEquivalent(Context, Auto1->getDeducedType(),
1347 Auto2->getDeducedType()))
1348 return false;
1349 if (Auto1->isConstrained() != Auto2->isConstrained())
1350 return false;
1351 if (Auto1->isConstrained()) {
1352 if (Auto1->getTypeConstraintConcept().getAsTemplateDecl() !=
1353 Auto2->getTypeConstraintConcept().getAsTemplateDecl())
1354 return false;
1355 if (!IsStructurallyEquivalent(Context,
1356 Auto1->getTypeConstraintArguments(),
1357 Auto2->getTypeConstraintArguments()))
1358 return false;
1359 }
1360 break;
1361 }
1362
1363 case Type::DeducedTemplateSpecialization: {
1364 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1365 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1366 if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(),
1367 DT2->getTemplateName()))
1368 return false;
1369 if (!IsStructurallyEquivalent(Context, DT1->getDeducedType(),
1370 DT2->getDeducedType()))
1371 return false;
1372 break;
1373 }
1374
1375 case Type::Record:
1376 case Type::Enum:
1377 case Type::InjectedClassName: {
1378 const auto *TT1 = cast<TagType>(T1), *TT2 = cast<TagType>(T2);
1379 if (TT1->getKeyword() != TT2->getKeyword())
1380 return false;
1381 if (TT1->isTagOwned() != TT2->isTagOwned())
1382 return false;
1383 if (!IsStructurallyEquivalent(Context, TT1->getQualifier(),
1384 TT2->getQualifier()))
1385 return false;
1386 if (!IsStructurallyEquivalent(Context, TT1->getDecl(), TT2->getDecl()))
1387 return false;
1388 break;
1389 }
1390
1391 case Type::TemplateTypeParm: {
1392 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1393 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1394 if (!Context.IgnoreTemplateParmDepth &&
1395 Parm1->getDepth() != Parm2->getDepth())
1396 return false;
1397 if (Parm1->getIndex() != Parm2->getIndex())
1398 return false;
1399 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1400 return false;
1401
1402 // Names of template type parameters are never significant.
1403 break;
1404 }
1405
1406 case Type::SubstTemplateTypeParm: {
1407 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1408 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1409 if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
1410 Subst2->getReplacementType()))
1411 return false;
1412 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1413 Subst2->getAssociatedDecl()))
1414 return false;
1415 if (Subst1->getIndex() != Subst2->getIndex())
1416 return false;
1417 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1418 return false;
1419 break;
1420 }
1421
1422 case Type::SubstBuiltinTemplatePack: {
1423 const auto *Subst1 = cast<SubstBuiltinTemplatePackType>(T1);
1424 const auto *Subst2 = cast<SubstBuiltinTemplatePackType>(T2);
1425 if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
1426 Subst2->getArgumentPack()))
1427 return false;
1428 break;
1429 }
1430 case Type::SubstTemplateTypeParmPack: {
1431 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1432 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1433 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1434 Subst2->getAssociatedDecl()))
1435 return false;
1436 if (Subst1->getIndex() != Subst2->getIndex())
1437 return false;
1438 if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
1439 Subst2->getArgumentPack()))
1440 return false;
1441 break;
1442 }
1443
1444 case Type::TemplateSpecialization: {
1445 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1446 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1447 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
1448 Spec2->getTemplateName()))
1449 return false;
1450 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1451 Spec2->template_arguments()))
1452 return false;
1453 break;
1454 }
1455
1456 case Type::DependentName: {
1457 const auto *Typename1 = cast<DependentNameType>(T1);
1458 const auto *Typename2 = cast<DependentNameType>(T2);
1459 if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(),
1460 Typename2->getQualifier()))
1461 return false;
1462 if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
1463 Typename2->getIdentifier()))
1464 return false;
1465
1466 break;
1467 }
1468
1469 case Type::PackExpansion:
1470 if (!IsStructurallyEquivalent(Context,
1471 cast<PackExpansionType>(T1)->getPattern(),
1472 cast<PackExpansionType>(T2)->getPattern()))
1473 return false;
1474 break;
1475
1476 case Type::PackIndexing:
1477 if (!IsStructurallyEquivalent(Context,
1478 cast<PackIndexingType>(T1)->getPattern(),
1479 cast<PackIndexingType>(T2)->getPattern()))
1480 if (!IsStructurallyEquivalent(Context,
1481 cast<PackIndexingType>(T1)->getIndexExpr(),
1482 cast<PackIndexingType>(T2)->getIndexExpr()))
1483 return false;
1484 break;
1485
1486 case Type::ObjCInterface: {
1487 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1488 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1489 if (!IsStructurallyEquivalent(Context, Iface1->getDecl(),
1490 Iface2->getDecl()))
1491 return false;
1492 break;
1493 }
1494
1495 case Type::ObjCTypeParam: {
1496 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1497 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1498 if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), Obj2->getDecl()))
1499 return false;
1500
1501 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1502 return false;
1503 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1504 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1505 Obj2->getProtocol(I)))
1506 return false;
1507 }
1508 break;
1509 }
1510
1511 case Type::ObjCObject: {
1512 const auto *Obj1 = cast<ObjCObjectType>(T1);
1513 const auto *Obj2 = cast<ObjCObjectType>(T2);
1514 if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(),
1515 Obj2->getBaseType()))
1516 return false;
1517 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1518 return false;
1519 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1520 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1521 Obj2->getProtocol(I)))
1522 return false;
1523 }
1524 break;
1525 }
1526
1527 case Type::ObjCObjectPointer: {
1528 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1529 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1530 if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(),
1531 Ptr2->getPointeeType()))
1532 return false;
1533 break;
1534 }
1535
1536 case Type::Atomic:
1537 if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(),
1538 cast<AtomicType>(T2)->getValueType()))
1539 return false;
1540 break;
1541
1542 case Type::Pipe:
1543 if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(),
1544 cast<PipeType>(T2)->getElementType()))
1545 return false;
1546 break;
1547 case Type::BitInt: {
1548 const auto *Int1 = cast<BitIntType>(T1);
1549 const auto *Int2 = cast<BitIntType>(T2);
1550
1551 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1552 Int1->getNumBits() != Int2->getNumBits())
1553 return false;
1554 break;
1555 }
1556 case Type::DependentBitInt: {
1557 const auto *Int1 = cast<DependentBitIntType>(T1);
1558 const auto *Int2 = cast<DependentBitIntType>(T2);
1559
1560 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1561 !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
1562 Int2->getNumBitsExpr()))
1563 return false;
1564 break;
1565 }
1566 case Type::PredefinedSugar: {
1567 const auto *TP1 = cast<PredefinedSugarType>(T1);
1568 const auto *TP2 = cast<PredefinedSugarType>(T2);
1569 if (TP1->getKind() != TP2->getKind())
1570 return false;
1571 break;
1572 }
1573 } // end switch
1574
1575 return true;
1576}
1577
1579 QualType T1, QualType T2) {
1580 return ASTStructuralEquivalence::isEquivalent(Context, T1, T2);
1581}
1582
1584 VarDecl *D1, VarDecl *D2) {
1585 IdentifierInfo *Name1 = D1->getIdentifier();
1586 IdentifierInfo *Name2 = D2->getIdentifier();
1587 if (!::IsStructurallyEquivalent(Name1, Name2))
1588 return false;
1589
1590 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
1591 return false;
1592
1593 // Compare storage class and initializer only if none or both are a
1594 // definition. Like a forward-declaration matches a class definition, variable
1595 // declarations that are not definitions should match with the definitions.
1597 return true;
1598
1599 if (D1->getStorageClass() != D2->getStorageClass())
1600 return false;
1601
1602 return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit());
1603}
1604
1606 FieldDecl *Field1, FieldDecl *Field2,
1607 QualType Owner2Type) {
1608 const auto *Owner2 = cast<Decl>(Field2->getDeclContext());
1609
1610 // In C23 mode, check for structural equivalence of attributes on the fields.
1611 // FIXME: Should this happen in C++ as well?
1612 if (Context.LangOpts.C23 &&
1613 !CheckStructurallyEquivalentAttributes(Context, Field1, Field2, Owner2))
1614 return false;
1615
1616 // For anonymous structs/unions, match up the anonymous struct/union type
1617 // declarations directly, so that we don't go off searching for anonymous
1618 // types
1619 if (Field1->isAnonymousStructOrUnion() &&
1620 Field2->isAnonymousStructOrUnion()) {
1621 RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1622 RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1623 return IsStructurallyEquivalent(Context, D1, D2);
1624 }
1625
1626 // Check for equivalent field names.
1627 IdentifierInfo *Name1 = Field1->getIdentifier();
1628 IdentifierInfo *Name2 = Field2->getIdentifier();
1629 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1630 if (Context.Complain) {
1631 Context.Diag2(
1632 Owner2->getLocation(),
1633 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1634 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1635 Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
1636 << Field2->getDeclName();
1637 Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
1638 << Field1->getDeclName();
1639 }
1640 return false;
1641 }
1642
1643 if (!IsStructurallyEquivalent(Context, Field1->getType(),
1644 Field2->getType())) {
1645 if (Context.Complain) {
1646 Context.Diag2(
1647 Owner2->getLocation(),
1648 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1649 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1650 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1651 << Field2->getDeclName() << Field2->getType();
1652 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1653 << Field1->getDeclName() << Field1->getType();
1654 }
1655 return false;
1656 }
1657
1658 if ((Field1->isBitField() || Field2->isBitField()) &&
1659 !IsStructurallyEquivalent(Context, Field1->getBitWidth(),
1660 Field2->getBitWidth())) {
1661 // Two bit-fields can be structurally unequivalent but still be okay for
1662 // the purposes of C where they simply need to have the same values, not
1663 // the same token sequences.
1664 bool Diagnose = true;
1665 if (Context.LangOpts.C23 && Field1->isBitField() && Field2->isBitField())
1666 Diagnose = Field1->getBitWidthValue() != Field2->getBitWidthValue();
1667
1668 if (Diagnose && Context.Complain) {
1669 auto DiagNote = [&](const FieldDecl *FD,
1673 if (FD->isBitField()) {
1674 (Context.*Diag)(FD->getLocation(), diag::note_odr_field_bit_width)
1675 << FD->getDeclName() << FD->getBitWidthValue();
1676 } else {
1677 (Context.*Diag)(FD->getLocation(), diag::note_odr_field_not_bit_field)
1678 << FD->getDeclName();
1679 }
1680 };
1681
1682 Context.Diag2(
1683 Owner2->getLocation(),
1684 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1685 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1686 DiagNote(Field2, &StructuralEquivalenceContext::Diag2);
1687 DiagNote(Field1, &StructuralEquivalenceContext::Diag1);
1688 }
1689 return false;
1690 }
1691
1692 return true;
1693}
1694
1695/// Determine structural equivalence of two fields.
1697 FieldDecl *Field1, FieldDecl *Field2) {
1698 const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
1699 return IsStructurallyEquivalent(Context, Field1, Field2,
1700 Context.ToCtx.getCanonicalTagType(Owner2));
1701}
1702
1703/// Determine structural equivalence of two IndirectFields.
1705 IndirectFieldDecl *ID1,
1706 IndirectFieldDecl *ID2) {
1707 return IsStructurallyEquivalent(Context, ID1->getAnonField(),
1708 ID2->getAnonField());
1709}
1710
1711/// Determine structural equivalence of two methods.
1713 CXXMethodDecl *Method1,
1714 CXXMethodDecl *Method2) {
1715 if (!Method1 && !Method2)
1716 return true;
1717 if (!Method1 || !Method2)
1718 return false;
1719
1720 bool PropertiesEqual =
1721 Method1->getDeclKind() == Method2->getDeclKind() &&
1722 Method1->getRefQualifier() == Method2->getRefQualifier() &&
1723 Method1->getAccess() == Method2->getAccess() &&
1724 Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1725 Method1->isStatic() == Method2->isStatic() &&
1726 Method1->isImplicitObjectMemberFunction() ==
1727 Method2->isImplicitObjectMemberFunction() &&
1728 Method1->isConst() == Method2->isConst() &&
1729 Method1->isVolatile() == Method2->isVolatile() &&
1730 Method1->isVirtual() == Method2->isVirtual() &&
1731 Method1->isPureVirtual() == Method2->isPureVirtual() &&
1732 Method1->isDefaulted() == Method2->isDefaulted() &&
1733 Method1->isDeleted() == Method2->isDeleted();
1734 if (!PropertiesEqual)
1735 return false;
1736 // FIXME: Check for 'final'.
1737
1738 if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1739 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1740 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1741 Constructor2->getExplicitSpecifier()))
1742 return false;
1743 }
1744
1745 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1746 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1747 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1748 Conversion2->getExplicitSpecifier()))
1749 return false;
1750 if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
1751 Conversion2->getConversionType()))
1752 return false;
1753 }
1754
1755 const IdentifierInfo *Name1 = Method1->getIdentifier();
1756 const IdentifierInfo *Name2 = Method2->getIdentifier();
1757 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1758 return false;
1759 // TODO: Names do not match, add warning like at check for FieldDecl.
1760 }
1761
1762 // Check the prototypes.
1763 if (!::IsStructurallyEquivalent(Context,
1764 Method1->getType(), Method2->getType()))
1765 return false;
1766
1767 return true;
1768}
1769
1770/// Determine structural equivalence of two lambda classes.
1771static bool
1773 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1774 assert(D1->isLambda() && D2->isLambda() &&
1775 "Must be called on lambda classes");
1777 D2->getLambdaCallOperator()))
1778 return false;
1779
1780 return true;
1781}
1782
1783/// Determine if context of a class is equivalent.
1784static bool
1786 RecordDecl *D1, RecordDecl *D2) {
1787 // The context should be completely equal, including anonymous and inline
1788 // namespaces.
1789 // We compare objects as part of full translation units, not subtrees of
1790 // translation units.
1793 while (true) {
1794 // Special case: We allow a struct defined in a function to be equivalent
1795 // with a similar struct defined outside of a function.
1796 if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1797 (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1798 return true;
1799
1800 if (DC1->getDeclKind() != DC2->getDeclKind())
1801 return false;
1802 if (DC1->isTranslationUnit())
1803 break;
1804 if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1805 return false;
1806 if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1807 const auto *ND2 = cast<NamedDecl>(DC2);
1808 if (!DC1->isInlineNamespace() &&
1809 !IsStructurallyEquivalent(ND1->getIdentifier(), ND2->getIdentifier()))
1810 return false;
1811 }
1812
1813 if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1814 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1815 if (!IsStructurallyEquivalent(Context, D1Spec, D2Spec))
1816 return false;
1817 }
1818
1819 DC1 = DC1->getParent()->getNonTransparentContext();
1820 DC2 = DC2->getParent()->getNonTransparentContext();
1821 }
1822
1823 return true;
1824}
1825
1826static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1827 auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1828 if (const IdentifierInfo *Name = D.getIdentifier())
1829 return Name;
1830 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1831 return TypedefName->getIdentifier();
1832 return nullptr;
1833 };
1834 return IsStructurallyEquivalent(GetName(D1), GetName(D2));
1835}
1836
1837/// Determine structural equivalence of two records.
1839 RecordDecl *D1, RecordDecl *D2) {
1840 // C23 6.2.7p1:
1841 // ... Moreover, two complete structure, union, or enumerated types declared
1842 // with the same tag are compatible if members satisfy the following
1843 // requirements:
1844 // - there shall be a one-to-one correspondence between their members such
1845 // that each pair of corresponding members are declared with compatible
1846 // types;
1847 // - if one member of the pair is declared with an alignment specifier, the
1848 // other is declared with an equivalent alignment specifier;
1849 // - and, if one member of the pair is declared with a name, the other is
1850 // declared with the same name.
1851 // For two structures, corresponding members shall be declared in the same
1852 // order. For two unions declared in the same translation unit, corresponding
1853 // members shall be declared in the same order. For two structures or unions,
1854 // corresponding bit-fields shall have the same widths. ... For determining
1855 // type compatibility, anonymous structures and unions are considered a
1856 // regular member of the containing structure or union type, and the type of
1857 // an anonymous structure or union is considered compatible to the type of
1858 // another anonymous structure or union, respectively, if their members
1859 // fulfill the preceding requirements. ... Otherwise, the structure, union,
1860 // or enumerated types are incompatible.
1861 if (!NameIsStructurallyEquivalent(*D1, *D2))
1862 return false;
1863
1864 if (D1->isUnion() != D2->isUnion()) {
1865 if (Context.Complain) {
1866 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1867 diag::err_odr_tag_type_inconsistent))
1868 << Context.ToCtx.getCanonicalTagType(D2)
1869 << (&Context.FromCtx != &Context.ToCtx);
1870 Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
1871 << D1->getDeclName() << (unsigned)D1->getTagKind();
1872 }
1873 return false;
1874 }
1875
1876 if (!D1->getDeclName() && !D2->getDeclName()) {
1877 // If both anonymous structs/unions are in a record context, make sure
1878 // they occur in the same location in the context records.
1879 if (UnsignedOrNone Index1 =
1881 if (UnsignedOrNone Index2 =
1883 D2)) {
1884 if (*Index1 != *Index2)
1885 return false;
1886 }
1887 }
1888 }
1889
1890 // If the records occur in different context (namespace), these should be
1891 // different. This is specially important if the definition of one or both
1892 // records is missing. In C23, different contexts do not make for a different
1893 // structural type (a local struct definition can be a valid redefinition of
1894 // a file scope struct definition).
1895 if (!Context.LangOpts.C23 &&
1896 !IsRecordContextStructurallyEquivalent(Context, D1, D2))
1897 return false;
1898
1899 // If both declarations are class template specializations, we know
1900 // the ODR applies, so check the template and template arguments.
1901 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1902 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1903 if (Spec1 && Spec2) {
1904 // Check that the specialized templates are the same.
1905 if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
1906 Spec2->getSpecializedTemplate()))
1907 return false;
1908
1909 // Check that the template arguments are the same.
1910 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1911 return false;
1912
1913 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1914 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateArgs().get(I),
1915 Spec2->getTemplateArgs().get(I)))
1916 return false;
1917 }
1918 // If one is a class template specialization and the other is not, these
1919 // structures are different.
1920 else if (Spec1 || Spec2)
1921 return false;
1922
1923 // Compare the definitions of these two records. If either or both are
1924 // incomplete (i.e. it is a forward decl), we assume that they are
1925 // equivalent. except in C23 mode.
1926 D1 = D1->getDefinition();
1927 D2 = D2->getDefinition();
1928 if (!D1 || !D2)
1929 return !Context.LangOpts.C23;
1930
1931 // In C23 mode, check for structural equivalence of attributes on the record
1932 // itself. FIXME: Should this happen in C++ as well?
1933 if (Context.LangOpts.C23 &&
1934 !CheckStructurallyEquivalentAttributes(Context, D1, D2))
1935 return false;
1936
1937 // If any of the records has external storage and we do a minimal check (or
1938 // AST import) we assume they are equivalent. (If we didn't have this
1939 // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1940 // another AST import which in turn would call the structural equivalency
1941 // check again and finally we'd have an improper result.)
1942 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1944 return true;
1945
1946 // If one definition is currently being defined, we do not compare for
1947 // equality and we assume that the decls are equal.
1948 if (D1->isBeingDefined() || D2->isBeingDefined())
1949 return true;
1950
1951 if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1952 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1953 if (D1CXX->hasExternalLexicalStorage() &&
1954 !D1CXX->isCompleteDefinition()) {
1955 D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1956 }
1957
1958 if (D1CXX->isLambda() != D2CXX->isLambda())
1959 return false;
1960 if (D1CXX->isLambda()) {
1961 if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX))
1962 return false;
1963 }
1964
1965 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1966 if (Context.Complain) {
1967 Context.Diag2(D2->getLocation(),
1968 Context.getApplicableDiagnostic(
1969 diag::err_odr_tag_type_inconsistent))
1970 << Context.ToCtx.getCanonicalTagType(D2)
1971 << (&Context.FromCtx != &Context.ToCtx);
1972 Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
1973 << D2CXX->getNumBases();
1974 Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
1975 << D1CXX->getNumBases();
1976 }
1977 return false;
1978 }
1979
1980 // Check the base classes.
1981 for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1982 BaseEnd1 = D1CXX->bases_end(),
1983 Base2 = D2CXX->bases_begin();
1984 Base1 != BaseEnd1; ++Base1, ++Base2) {
1985 if (!IsStructurallyEquivalent(Context, Base1->getType(),
1986 Base2->getType())) {
1987 if (Context.Complain) {
1988 Context.Diag2(D2->getLocation(),
1989 Context.getApplicableDiagnostic(
1990 diag::err_odr_tag_type_inconsistent))
1991 << Context.ToCtx.getCanonicalTagType(D2)
1992 << (&Context.FromCtx != &Context.ToCtx);
1993 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1994 << Base2->getType() << Base2->getSourceRange();
1995 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1996 << Base1->getType() << Base1->getSourceRange();
1997 }
1998 return false;
1999 }
2000
2001 // Check virtual vs. non-virtual inheritance mismatch.
2002 if (Base1->isVirtual() != Base2->isVirtual()) {
2003 if (Context.Complain) {
2004 Context.Diag2(D2->getLocation(),
2005 Context.getApplicableDiagnostic(
2006 diag::err_odr_tag_type_inconsistent))
2007 << Context.ToCtx.getCanonicalTagType(D2)
2008 << (&Context.FromCtx != &Context.ToCtx);
2009 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
2010 << Base2->isVirtual() << Base2->getSourceRange();
2011 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
2012 << Base1->isVirtual() << Base1->getSourceRange();
2013 }
2014 return false;
2015 }
2016 }
2017
2018 // Check the friends for consistency.
2019 CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
2020 Friend2End = D2CXX->friend_end();
2021 for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
2022 Friend1End = D1CXX->friend_end();
2023 Friend1 != Friend1End; ++Friend1, ++Friend2) {
2024 if (Friend2 == Friend2End) {
2025 if (Context.Complain) {
2026 Context.Diag2(D2->getLocation(),
2027 Context.getApplicableDiagnostic(
2028 diag::err_odr_tag_type_inconsistent))
2029 << Context.ToCtx.getCanonicalTagType(D2CXX)
2030 << (&Context.FromCtx != &Context.ToCtx);
2031 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
2032 Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
2033 }
2034 return false;
2035 }
2036
2037 if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) {
2038 if (Context.Complain) {
2039 Context.Diag2(D2->getLocation(),
2040 Context.getApplicableDiagnostic(
2041 diag::err_odr_tag_type_inconsistent))
2042 << Context.ToCtx.getCanonicalTagType(D2CXX)
2043 << (&Context.FromCtx != &Context.ToCtx);
2044 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
2045 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
2046 }
2047 return false;
2048 }
2049 }
2050
2051 if (Friend2 != Friend2End) {
2052 if (Context.Complain) {
2053 Context.Diag2(D2->getLocation(),
2054 Context.getApplicableDiagnostic(
2055 diag::err_odr_tag_type_inconsistent))
2056 << Context.ToCtx.getCanonicalTagType(D2)
2057 << (&Context.FromCtx != &Context.ToCtx);
2058 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
2059 Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
2060 }
2061 return false;
2062 }
2063 } else if (D1CXX->getNumBases() > 0) {
2064 if (Context.Complain) {
2065 Context.Diag2(D2->getLocation(),
2066 Context.getApplicableDiagnostic(
2067 diag::err_odr_tag_type_inconsistent))
2068 << Context.ToCtx.getCanonicalTagType(D2)
2069 << (&Context.FromCtx != &Context.ToCtx);
2070 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
2071 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
2072 << Base1->getType() << Base1->getSourceRange();
2073 Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
2074 }
2075 return false;
2076 }
2077 }
2078
2079 // Check the fields for consistency.
2080 CanQualType D2Type = Context.ToCtx.getCanonicalTagType(D2);
2082 Field2End = D2->field_end();
2083 for (RecordDecl::field_iterator Field1 = D1->field_begin(),
2084 Field1End = D1->field_end();
2085 Field1 != Field1End; ++Field1, ++Field2) {
2086 if (Field2 == Field2End) {
2087 if (Context.Complain) {
2088 Context.Diag2(D2->getLocation(),
2089 Context.getApplicableDiagnostic(
2090 diag::err_odr_tag_type_inconsistent))
2091 << Context.ToCtx.getCanonicalTagType(D2)
2092 << (&Context.FromCtx != &Context.ToCtx);
2093 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
2094 << Field1->getDeclName() << Field1->getType();
2095 Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
2096 }
2097 return false;
2098 }
2099
2100 if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type))
2101 return false;
2102 }
2103
2104 if (Field2 != Field2End) {
2105 if (Context.Complain) {
2106 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
2107 diag::err_odr_tag_type_inconsistent))
2108 << Context.ToCtx.getCanonicalTagType(D2)
2109 << (&Context.FromCtx != &Context.ToCtx);
2110 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
2111 << Field2->getDeclName() << Field2->getType();
2112 Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
2113 }
2114 return false;
2115 }
2116
2117 return true;
2118}
2119
2121 EnumConstantDecl *D1,
2122 EnumConstantDecl *D2) {
2123 const llvm::APSInt &FromVal = D1->getInitVal();
2124 const llvm::APSInt &ToVal = D2->getInitVal();
2125 if (FromVal.isSigned() != ToVal.isSigned())
2126 return false;
2127 if (FromVal.getBitWidth() != ToVal.getBitWidth())
2128 return false;
2129 if (FromVal != ToVal)
2130 return false;
2131
2133 return false;
2134
2135 // Init expressions are the most expensive check, so do them last.
2136 return IsStructurallyEquivalent(Context, D1->getInitExpr(),
2137 D2->getInitExpr());
2138}
2139
2140/// Determine structural equivalence of two enums.
2142 EnumDecl *D1, EnumDecl *D2) {
2143 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
2144 return false;
2145 }
2146
2147 // Compare the definitions of these two enums. If either or both are
2148 // incomplete (i.e. forward declared), we assume that they are equivalent.
2149 // In C23, the order of the enumerations does not matter, only the names and
2150 // values do.
2151 D1 = D1->getDefinition();
2152 D2 = D2->getDefinition();
2153 if (!D1 || !D2)
2154 return true;
2155
2156 if (Context.LangOpts.C23 &&
2157 !CheckStructurallyEquivalentAttributes(Context, D1, D2))
2158 return false;
2159
2160 // In C23, if one enumeration has a fixed underlying type, the other shall
2161 // have a compatible fixed underlying type (6.2.7).
2162 if (Context.LangOpts.C23) {
2163 if (D1->isFixed() != D2->isFixed()) {
2164 if (Context.Complain) {
2165 Context.Diag2(D2->getLocation(),
2166 Context.getApplicableDiagnostic(
2167 diag::err_odr_tag_type_inconsistent))
2168 << Context.ToCtx.getCanonicalTagType(D2)
2169 << (&Context.FromCtx != &Context.ToCtx);
2170 Context.Diag1(D1->getLocation(),
2171 D1->isFixed()
2172 ? diag::note_odr_fixed_underlying_type
2173 : diag::note_odr_missing_fixed_underlying_type)
2174 << D1;
2175 Context.Diag2(D2->getLocation(),
2176 D2->isFixed()
2177 ? diag::note_odr_fixed_underlying_type
2178 : diag::note_odr_missing_fixed_underlying_type)
2179 << D2;
2180 }
2181 return false;
2182 }
2183 if (D1->isFixed()) {
2184 assert(D2->isFixed() && "enums expected to have fixed underlying types");
2185 if (!IsStructurallyEquivalent(Context, D1->getIntegerType(),
2186 D2->getIntegerType())) {
2187 if (Context.Complain) {
2188 Context.Diag2(D2->getLocation(),
2189 Context.getApplicableDiagnostic(
2190 diag::err_odr_tag_type_inconsistent))
2191 << Context.ToCtx.getCanonicalTagType(D2)
2192 << (&Context.FromCtx != &Context.ToCtx);
2193 Context.Diag2(D2->getLocation(),
2194 diag::note_odr_incompatible_fixed_underlying_type)
2195 << D2 << D2->getIntegerType() << D1->getIntegerType();
2196 }
2197 return false;
2198 }
2199 }
2200 }
2201
2203 auto CopyEnumerators =
2204 [](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
2205 for (const EnumConstantDecl *ECD : Range)
2206 Cont.push_back(ECD);
2207 };
2208 CopyEnumerators(D1->enumerators(), D1Enums);
2209 CopyEnumerators(D2->enumerators(), D2Enums);
2210
2211 // In C23 mode, the order of the enumerations does not matter, so sort them
2212 // by name to get them both into a consistent ordering.
2213 if (Context.LangOpts.C23) {
2214 auto Sorter = [](const EnumConstantDecl *LHS, const EnumConstantDecl *RHS) {
2215 return LHS->getName() < RHS->getName();
2216 };
2217 llvm::sort(D1Enums, Sorter);
2218 llvm::sort(D2Enums, Sorter);
2219 }
2220
2221 auto EC2 = D2Enums.begin(), EC2End = D2Enums.end();
2222 for (auto EC1 = D1Enums.begin(), EC1End = D1Enums.end(); EC1 != EC1End;
2223 ++EC1, ++EC2) {
2224 if (EC2 == EC2End) {
2225 if (Context.Complain) {
2226 Context.Diag2(D2->getLocation(),
2227 Context.getApplicableDiagnostic(
2228 diag::err_odr_tag_type_inconsistent))
2229 << Context.ToCtx.getCanonicalTagType(D2)
2230 << (&Context.FromCtx != &Context.ToCtx);
2231 Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
2232 << (*EC1)->getDeclName() << toString((*EC1)->getInitVal(), 10);
2233 Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
2234 }
2235 return false;
2236 }
2237
2238 llvm::APSInt Val1 = (*EC1)->getInitVal();
2239 llvm::APSInt Val2 = (*EC2)->getInitVal();
2240 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
2241 !IsStructurallyEquivalent((*EC1)->getIdentifier(),
2242 (*EC2)->getIdentifier())) {
2243 if (Context.Complain) {
2244 Context.Diag2(D2->getLocation(),
2245 Context.getApplicableDiagnostic(
2246 diag::err_odr_tag_type_inconsistent))
2247 << Context.ToCtx.getCanonicalTagType(D2)
2248 << (&Context.FromCtx != &Context.ToCtx);
2249 Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
2250 << (*EC2)->getDeclName() << toString((*EC2)->getInitVal(), 10);
2251 Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
2252 << (*EC1)->getDeclName() << toString((*EC1)->getInitVal(), 10);
2253 }
2254 return false;
2255 }
2256 if (Context.LangOpts.C23 &&
2257 !CheckStructurallyEquivalentAttributes(Context, *EC1, *EC2, D2))
2258 return false;
2259 }
2260
2261 if (EC2 != EC2End) {
2262 if (Context.Complain) {
2263 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
2264 diag::err_odr_tag_type_inconsistent))
2265 << Context.ToCtx.getCanonicalTagType(D2)
2266 << (&Context.FromCtx != &Context.ToCtx);
2267 Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
2268 << (*EC2)->getDeclName() << toString((*EC2)->getInitVal(), 10);
2269 Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
2270 }
2271 return false;
2272 }
2273
2274 return true;
2275}
2276
2278 TemplateParameterList *Params1,
2279 TemplateParameterList *Params2) {
2280 if (Params1->size() != Params2->size()) {
2281 if (Context.Complain) {
2282 Context.Diag2(Params2->getTemplateLoc(),
2283 Context.getApplicableDiagnostic(
2284 diag::err_odr_different_num_template_parameters))
2285 << Params1->size() << Params2->size();
2286 Context.Diag1(Params1->getTemplateLoc(),
2287 diag::note_odr_template_parameter_list);
2288 }
2289 return false;
2290 }
2291
2292 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
2293 if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
2294 if (Context.Complain) {
2295 Context.Diag2(Params2->getParam(I)->getLocation(),
2296 Context.getApplicableDiagnostic(
2297 diag::err_odr_different_template_parameter_kind));
2298 Context.Diag1(Params1->getParam(I)->getLocation(),
2299 diag::note_odr_template_parameter_here);
2300 }
2301 return false;
2302 }
2303
2304 if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
2305 Params2->getParam(I)))
2306 return false;
2307 }
2308
2309 return IsStructurallyEquivalent(Context, Params1->getRequiresClause(),
2310 Params2->getRequiresClause());
2311}
2312
2316 if (D1->isParameterPack() != D2->isParameterPack()) {
2317 if (Context.Complain) {
2318 Context.Diag2(D2->getLocation(),
2319 Context.getApplicableDiagnostic(
2320 diag::err_odr_parameter_pack_non_pack))
2321 << D2->isParameterPack();
2322 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2323 << D1->isParameterPack();
2324 }
2325 return false;
2326 }
2327
2328 return true;
2329}
2330
2334 if (D1->isParameterPack() != D2->isParameterPack()) {
2335 if (Context.Complain) {
2336 Context.Diag2(D2->getLocation(),
2337 Context.getApplicableDiagnostic(
2338 diag::err_odr_parameter_pack_non_pack))
2339 << D2->isParameterPack();
2340 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2341 << D1->isParameterPack();
2342 }
2343 return false;
2344 }
2345 if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
2346 return false;
2347 if (D1->getIndex() != D2->getIndex())
2348 return false;
2349 // Check types.
2350 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
2351 if (Context.Complain) {
2352 Context.Diag2(D2->getLocation(),
2353 Context.getApplicableDiagnostic(
2354 diag::err_odr_non_type_parameter_type_inconsistent))
2355 << D2->getType() << D1->getType();
2356 Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
2357 << D1->getType();
2358 }
2359 return false;
2360 }
2361
2362 return true;
2363}
2364
2368 if (D1->isParameterPack() != D2->isParameterPack()) {
2369 if (Context.Complain) {
2370 Context.Diag2(D2->getLocation(),
2371 Context.getApplicableDiagnostic(
2372 diag::err_odr_parameter_pack_non_pack))
2373 << D2->isParameterPack();
2374 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2375 << D1->isParameterPack();
2376 }
2377 return false;
2378 }
2379
2380 // Check template parameter lists.
2381 return D1->templateParameterKind() == D2->templateParameterKind() &&
2383 D2->getTemplateParameters());
2384}
2385
2389 return false;
2390 if (!D1->getIdentifier()) // Special name
2391 if (D1->getNameAsString() != D2->getNameAsString())
2392 return false;
2394 D2->getTemplateParameters());
2395}
2396
2399 ClassTemplateDecl *D2) {
2400 // Check template parameters.
2401 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2402 return false;
2403
2404 // Check the templated declaration.
2405 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
2406 D2->getTemplatedDecl());
2407}
2408
2412 // Check template parameters.
2413 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2414 return false;
2415
2416 // Check the templated declaration.
2417 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
2418 D2->getTemplatedDecl()->getType());
2419}
2420
2424 // Check template parameters.
2425 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2426 return false;
2427
2428 // Check the templated declaration.
2429 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
2430 D2->getTemplatedDecl());
2431}
2432
2434 ConceptDecl *D1,
2435 ConceptDecl *D2) {
2436 // Check template parameters.
2437 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2438 return false;
2439
2440 // Check the constraint expression.
2441 return IsStructurallyEquivalent(Context, D1->getConstraintExpr(),
2442 D2->getConstraintExpr());
2443}
2444
2446 FriendDecl *D1, FriendDecl *D2) {
2447 if (D1->isPackExpansion() != D2->isPackExpansion())
2448 return false;
2449
2450 if ((D1->getFriendType() && D2->getFriendDecl()) ||
2451 (D1->getFriendDecl() && D2->getFriendType()))
2452 return false;
2453 if (D1->getFriendType() && D2->getFriendType())
2454 return IsStructurallyEquivalent(Context,
2455 D1->getFriendType()->getType(),
2456 D2->getFriendType()->getType());
2457 if (D1->getFriendDecl() && D2->getFriendDecl())
2458 return IsStructurallyEquivalent(Context, D1->getFriendDecl(),
2459 D2->getFriendDecl());
2460 return false;
2461}
2462
2464 FriendTemplateDecl *FTD1,
2465 FriendTemplateDecl *FTD2) {
2466 if (FTD1->isPackExpansion() != FTD2->isPackExpansion())
2467 return false;
2468
2471 if (!llvm::equal(
2472 TPL1, TPL2,
2473 [&Context](TemplateParameterList *LHS, TemplateParameterList *RHS) {
2474 return IsStructurallyEquivalent(Context, LHS, RHS);
2475 }))
2476 return false;
2477
2478 auto FK1 = FTD1->getFriendKind();
2479 auto FK2 = FTD2->getFriendKind();
2480 if (FK1 != FK2)
2481 return false;
2482
2483 switch (FK1) {
2485 const TemplateName TN1 = FTD1->getFriendTemplateName();
2486 const TemplateName TN2 = FTD2->getFriendTemplateName();
2487 if (TN1.isNull() != TN2.isNull())
2488 return false;
2489 if (!IsStructurallyEquivalent(Context, FTD1->getFriendType()->getType(),
2490 FTD2->getFriendType()->getType()))
2491 return false;
2492 return TN1.isNull() || IsStructurallyEquivalent(Context, TN1, TN2);
2493 }
2495 return IsStructurallyEquivalent(Context, FTD1->getFriendTemplateName(),
2496 FTD2->getFriendTemplateName());
2498 return IsStructurallyEquivalent(Context, static_cast<FriendDecl *>(FTD1),
2499 static_cast<FriendDecl *>(FTD2));
2500 }
2501 llvm_unreachable("unknown friend template kind");
2502}
2503
2507 return false;
2508
2509 return IsStructurallyEquivalent(Context, D1->getUnderlyingType(),
2510 D2->getUnderlyingType());
2511}
2512
2514 FunctionDecl *D1, FunctionDecl *D2) {
2516 return false;
2517
2518 if (D1->isOverloadedOperator()) {
2519 if (!D2->isOverloadedOperator())
2520 return false;
2522 return false;
2523 }
2524
2525 // FIXME: Consider checking for function attributes as well.
2526 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
2527 return false;
2528
2529 return true;
2530}
2531
2533 ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2534 QualType Owner2Type) {
2535 if (D1->getAccessControl() != D2->getAccessControl())
2536 return false;
2537
2538 return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1),
2539 cast<FieldDecl>(D2), Owner2Type);
2540}
2541
2543 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2544 QualType Owner2Type =
2545 Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface());
2546 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2547}
2548
2550 ObjCMethodDecl *Method1,
2551 ObjCMethodDecl *Method2) {
2552 bool PropertiesEqual =
2553 Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2554 Method1->isVariadic() == Method2->isVariadic() &&
2555 Method1->isDirectMethod() == Method2->isDirectMethod();
2556 if (!PropertiesEqual)
2557 return false;
2558
2559 // Compare selector slot names.
2560 Selector Selector1 = Method1->getSelector(),
2561 Selector2 = Method2->getSelector();
2562 unsigned NumArgs = Selector1.getNumArgs();
2563 if (NumArgs != Selector2.getNumArgs())
2564 return false;
2565 // Compare all selector slots. For selectors with arguments it means all arg
2566 // slots. And if there are no arguments, compare the first-and-only slot.
2567 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2568 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2570 Selector2.getIdentifierInfoForSlot(I)))
2571 return false;
2572 }
2573
2574 // Compare types.
2575 if (!IsStructurallyEquivalent(Context, Method1->getReturnType(),
2576 Method2->getReturnType()))
2577 return false;
2578 assert(
2579 Method1->param_size() == Method2->param_size() &&
2580 "Same number of arguments should be already enforced in Selector checks");
2582 ParamT1 = Method1->param_type_begin(),
2583 ParamT1End = Method1->param_type_end(),
2584 ParamT2 = Method2->param_type_begin(),
2585 ParamT2End = Method2->param_type_end();
2586 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2587 ++ParamT1, ++ParamT2) {
2588 if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2))
2589 return false;
2590 }
2591
2592 return true;
2593}
2594
2596 ObjCCategoryDecl *D1,
2597 ObjCCategoryDecl *D2) {
2599 return false;
2600
2601 const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2602 *Intf2 = D2->getClassInterface();
2603 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2604 return false;
2605
2606 if (Intf1 &&
2607 !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier()))
2608 return false;
2609
2610 // Compare protocols.
2612 Protocol2End = D2->protocol_end();
2614 Protocol1End = D1->protocol_end();
2615 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2616 if (Protocol2 == Protocol2End)
2617 return false;
2618 if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(),
2619 (*Protocol2)->getIdentifier()))
2620 return false;
2621 }
2622 if (Protocol2 != Protocol2End)
2623 return false;
2624
2625 // Compare ivars.
2626 QualType D2Type =
2627 Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType();
2629 Ivar2End = D2->ivar_end();
2631 Ivar1End = D1->ivar_end();
2632 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2633 if (Ivar2 == Ivar2End)
2634 return false;
2635 if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type))
2636 return false;
2637 }
2638 if (Ivar2 != Ivar2End)
2639 return false;
2640
2641 // Compare methods.
2643 Method2End = D2->meth_end();
2644 for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2645 Method1End = D1->meth_end();
2646 Method1 != Method1End; ++Method1, ++Method2) {
2647 if (Method2 == Method2End)
2648 return false;
2649 if (!IsStructurallyEquivalent(Context, *Method1, *Method2))
2650 return false;
2651 }
2652 if (Method2 != Method2End)
2653 return false;
2654
2655 return true;
2656}
2657
2658/// Determine structural equivalence of two declarations.
2660 Decl *D1, Decl *D2) {
2661 // FIXME: Check for known structural equivalences via a callback of some sort.
2662
2663 D1 = D1->getCanonicalDecl();
2664 D2 = D2->getCanonicalDecl();
2665
2666 if (D1 == D2)
2667 return true;
2668
2669 std::pair<Decl *, Decl *> P{D1, D2};
2670
2671 // Check whether we already know that these two declarations are not
2672 // structurally equivalent.
2673 if (Context.NonEquivalentDecls.count(
2674 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2675 return false;
2676
2677 // Check if a check for these declarations is already pending.
2678 // If yes D1 and D2 will be checked later (from DeclsToCheck),
2679 // or these are already checked (and equivalent).
2680 bool Inserted = Context.VisitedDecls.insert(P).second;
2681 if (!Inserted)
2682 return true;
2683
2684 Context.DeclsToCheck.push(P);
2685
2686 return true;
2687}
2688
2690 unsigned DiagID) {
2691 assert(Complain && "Not allowed to complain");
2692 if (LastDiagFromC2)
2693 FromCtx.getDiagnostics().notePriorDiagnosticFrom(ToCtx.getDiagnostics());
2694 LastDiagFromC2 = false;
2695 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2696}
2697
2699 unsigned DiagID) {
2700 assert(Complain && "Not allowed to complain");
2701 if (!LastDiagFromC2)
2702 ToCtx.getDiagnostics().notePriorDiagnosticFrom(FromCtx.getDiagnostics());
2703 LastDiagFromC2 = true;
2704 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2705}
2706
2709 ASTContext &Context = Anon->getASTContext();
2710 CanQualType AnonTy = Context.getCanonicalTagType(Anon);
2711
2712 const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
2713 if (!Owner)
2714 return std::nullopt;
2715
2716 unsigned Index = 0;
2717 for (const auto *D : Owner->noload_decls()) {
2718 const auto *F = dyn_cast<FieldDecl>(D);
2719 if (!F)
2720 continue;
2721
2722 if (F->isAnonymousStructOrUnion()) {
2723 if (Context.hasSameType(F->getType(), AnonTy))
2724 break;
2725 ++Index;
2726 continue;
2727 }
2728
2729 // If the field looks like this:
2730 // struct { ... } A;
2731 QualType FieldType = F->getType();
2732 if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2733 const RecordDecl *RecDecl = RecType->getDecl();
2734 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2735 if (Context.hasSameType(FieldType, AnonTy))
2736 break;
2737 ++Index;
2738 continue;
2739 }
2740 }
2741 }
2742
2743 return Index;
2744}
2745
2747 unsigned ErrorDiagnostic) {
2749 return ErrorDiagnostic;
2750
2751 switch (ErrorDiagnostic) {
2752 case diag::err_odr_variable_type_inconsistent:
2753 return diag::warn_odr_variable_type_inconsistent;
2754 case diag::err_odr_variable_multiple_def:
2755 return diag::warn_odr_variable_multiple_def;
2756 case diag::err_odr_function_type_inconsistent:
2757 return diag::warn_odr_function_type_inconsistent;
2758 case diag::err_odr_tag_type_inconsistent:
2759 return diag::warn_odr_tag_type_inconsistent;
2760 case diag::err_odr_field_type_inconsistent:
2761 return diag::warn_odr_field_type_inconsistent;
2762 case diag::err_odr_ivar_type_inconsistent:
2763 return diag::warn_odr_ivar_type_inconsistent;
2764 case diag::err_odr_objc_superclass_inconsistent:
2765 return diag::warn_odr_objc_superclass_inconsistent;
2766 case diag::err_odr_objc_method_result_type_inconsistent:
2767 return diag::warn_odr_objc_method_result_type_inconsistent;
2768 case diag::err_odr_objc_method_num_params_inconsistent:
2769 return diag::warn_odr_objc_method_num_params_inconsistent;
2770 case diag::err_odr_objc_method_param_type_inconsistent:
2771 return diag::warn_odr_objc_method_param_type_inconsistent;
2772 case diag::err_odr_objc_method_variadic_inconsistent:
2773 return diag::warn_odr_objc_method_variadic_inconsistent;
2774 case diag::err_odr_objc_property_type_inconsistent:
2775 return diag::warn_odr_objc_property_type_inconsistent;
2776 case diag::err_odr_objc_property_impl_kind_inconsistent:
2777 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2778 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2779 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2780 case diag::err_odr_different_num_template_parameters:
2781 return diag::warn_odr_different_num_template_parameters;
2782 case diag::err_odr_different_template_parameter_kind:
2783 return diag::warn_odr_different_template_parameter_kind;
2784 case diag::err_odr_parameter_pack_non_pack:
2785 return diag::warn_odr_parameter_pack_non_pack;
2786 case diag::err_odr_non_type_parameter_type_inconsistent:
2787 return diag::warn_odr_non_type_parameter_type_inconsistent;
2788 }
2789 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2790}
2791
2793
2794 // Ensure that the implementation functions (all static functions in this TU)
2795 // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2796 // because that will wreak havoc the internal state (DeclsToCheck and
2797 // VisitedDecls members) and can cause faulty behaviour.
2798 // In other words: Do not start a graph search from a new node with the
2799 // internal data of another search in progress.
2800 // FIXME: Better encapsulation and separation of internal and public
2801 // functionality.
2802 assert(DeclsToCheck.empty());
2803 assert(VisitedDecls.empty());
2804
2805 if (!::IsStructurallyEquivalent(*this, D1, D2))
2806 return false;
2807
2808 return !Finish();
2809}
2810
2812 assert(DeclsToCheck.empty());
2813 assert(VisitedDecls.empty());
2814 if (!::IsStructurallyEquivalent(*this, T1, T2))
2815 return false;
2816
2817 return !Finish();
2818}
2819
2821 assert(DeclsToCheck.empty());
2822 assert(VisitedDecls.empty());
2823 if (!::IsStructurallyEquivalent(*this, S1, S2))
2824 return false;
2825
2826 return !Finish();
2827}
2828
2829bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2830 // Check for equivalent described template.
2831 TemplateDecl *Template1 = D1->getDescribedTemplate();
2832 TemplateDecl *Template2 = D2->getDescribedTemplate();
2833 if ((Template1 != nullptr) != (Template2 != nullptr))
2834 return false;
2835 if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2))
2836 return false;
2837
2838 // FIXME: Move check for identifier names into this function.
2839
2840 return true;
2841}
2842
2843bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2844 Decl *D1, Decl *D2) {
2845
2846 // Kind mismatch.
2847 if (D1->getKind() != D2->getKind())
2848 return false;
2849
2850 // Cast the Decls to their actual subclass so that the right overload of
2851 // IsStructurallyEquivalent is called.
2852 switch (D1->getKind()) {
2853#define ABSTRACT_DECL(DECL)
2854#define DECL(DERIVED, BASE) \
2855 case Decl::Kind::DERIVED: \
2856 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2857 static_cast<DERIVED##Decl *>(D2));
2858#include "clang/AST/DeclNodes.inc"
2859 }
2860 return true;
2861}
2862
2864 while (!DeclsToCheck.empty()) {
2865 // Check the next declaration.
2866 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2867 DeclsToCheck.pop();
2868
2869 Decl *D1 = P.first;
2870 Decl *D2 = P.second;
2871
2872 bool Equivalent =
2873 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2874
2875 if (!Equivalent) {
2876 // Note that these two declarations are not equivalent (and we already
2877 // know about it).
2878 NonEquivalentDecls.insert(
2879 std::make_tuple(D1, D2, IgnoreTemplateParmDepth));
2880
2881 return true;
2882 }
2883 }
2884
2885 return false;
2886}
2887
2888bool 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:223
LabelDecl * getLabel() const
Definition Expr.h:4617
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3836
ArraySizeModifier getSizeModifier() const
Definition TypeBase.h:3850
Qualifiers getIndexTypeQualifiers() const
Definition TypeBase.h:3854
QualType getElementType() const
Definition TypeBase.h:3848
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:7041
Attr - This represents one attribute.
Definition Attr.h:46
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4082
Expr * getLHS() const
Definition Expr.h:4132
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2211
Expr * getRHS() const
Definition Expr.h:4134
Opcode getOpcode() const
Definition Expr.h:4127
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:744
DeclarationName getMember() const
Retrieve the name of the member that this expression refers to.
Definition ExprCXX.h:4059
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
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:2200
bool isVolatile() const
Definition DeclCXX.h:2198
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this method.
Definition DeclCXX.h:2338
bool isConst() const
Definition DeclCXX.h:2197
bool isStatic() const
Definition DeclCXX.cpp:2417
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:85
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
Definition ExprCXX.h:115
An iterator over the friend declarations of a class.
Definition DeclFriend.h: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:517
bool isLambda() const
Determine whether this class describes a lambda function object.
Definition DeclCXX.h:1023
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:3191
Decl * getCalleeDecl()
Definition Expr.h:3164
unsigned getValue() const
Definition Expr.h:1649
CharacterLiteralKind getKind() const
Definition Expr.h:1642
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
unsigned size() const
Definition Stmt.h:1797
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents a concrete matrix type with constant number of rows and columns.
Definition TypeBase.h:4501
unsigned getNumColumns() const
Returns the number of columns in the matrix.
Definition TypeBase.h:4520
unsigned getNumRows() const
Returns the number of rows in the matrix.
Definition TypeBase.h:4517
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
bool isTranslationUnit() const
Definition DeclBase.h:2202
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Definition DeclBase.h:2718
bool isInlineNamespace() const
bool isFunctionOrMethod() const
Definition DeclBase.h:2178
Decl::Kind getDeclKind() const
Definition DeclBase.h:2119
DeclContext * getNonTransparentContext()
ValueDecl * getDecl()
Definition Expr.h:1358
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:601
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
attr_range attrs() const
Definition DeclBase.h:543
AccessSpecifier getAccess() const
Definition DeclBase.h:515
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:995
Kind getKind() const
Definition DeclBase.h:450
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:3613
DeclarationName getDeclName() const
Retrieve the name that this expression refers to.
Definition ExprCXX.h:3600
Represents a matrix type where the type and the number of rows and columns is dependent on a template...
Definition TypeBase.h:4587
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:3557
llvm::APSInt getInitVal() const
Definition Decl.h:3577
const Expr * getInitExpr() const
Definition Decl.h:3575
Represents an enum.
Definition Decl.h:4145
enumerator_range enumerators() const
Definition Decl.h:4291
bool isFixed() const
Returns true if this is an Objective-C, C++11, or Microsoft-style enumeration with a fixed underlying...
Definition Decl.h:4372
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
Definition Decl.h:4318
EnumDecl * getDefinition() const
Definition Decl.h:4257
QualType getType() const
Definition Expr.h:145
ExpressionTrait getTrait() const
Definition ExprCXX.h:3118
Represents a member of a struct/union/class.
Definition Decl.h:3294
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3397
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
Definition Decl.cpp:4816
bool isAnonymousStructOrUnion() const
Determines whether this field is a representative for an anonymous struct or union.
Definition Decl.cpp:4779
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Definition Decl.h:3410
llvm::APFloat getValue() const
Definition Expr.h:1686
bool isExact() const
Definition Expr.h:1719
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
Definition DeclFriend.h: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:2058
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2666
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition Decl.h:2479
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2511
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Definition Decl.h:3063
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition Decl.cpp:4174
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5728
QualType getExceptionType(unsigned i) const
Return the ith exception type, where 0 <= i < getNumExceptions().
Definition TypeBase.h:5779
unsigned getNumExceptions() const
Return the number of types in the exception specification.
Definition TypeBase.h:5771
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Definition TypeBase.h:5786
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:4728
CallingConv getCC() const
Definition TypeBase.h:4787
unsigned getRegParm() const
Definition TypeBase.h:4780
bool getNoCallerSavedRegs() const
Definition TypeBase.h:4776
ArrayRef< TypeSourceInfo * > getAssocTypeSourceInfos() const
Definition Expr.h:6534
LabelDecl * getLabel() const
Definition Stmt.h:2994
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:3601
FieldDecl * getAnonField() const
Definition Decl.h:3628
QualType getElementType() const
Returns type of the elements being stored in the matrix.
Definition TypeBase.h:4465
DeclAccessPair getFoundDecl() const
Retrieves the declaration found by lookup.
Definition Expr.h:3495
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:317
Represents C++ namespaces and their aliases.
Definition Decl.h:573
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
CXXRecordDecl * getAsMicrosoftSuper() const
NamespaceAndPrefix getAsNamespaceAndPrefix() const
@ MicrosoftSuper
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h: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:3258
TemplateArgumentLoc const * getTemplateArgs() const
Definition ExprCXX.h:3306
unsigned getNumTemplateArgs() const
Definition ExprCXX.h:3312
DeclarationName getName() const
Gets the name looked up.
Definition ExprCXX.h:3252
A structure for storing the information associated with an overloaded template name.
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:8542
QualType getCanonicalType() const
Definition TypeBase.h:8554
Represents a struct/union/class.
Definition Decl.h:4459
field_iterator field_end() const
Definition Decl.h:4665
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4643
specific_decl_iterator< FieldDecl > field_iterator
Definition Decl.h:4659
field_iterator field_begin() const
Definition Decl.cpp:5339
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:5090
Encodes a location in the source.
unsigned getTemplateDepth() const
Definition Expr.h:4668
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:1505
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
Definition Expr.h:1895
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
Definition ExprCXX.h:4760
UnsignedOrNone getPackIndex() const
Definition ExprCXX.h:4768
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Definition ExprCXX.h:4766
TemplateArgument getArgumentPack() const
Retrieve the template argument pack containing the substituted template arguments.
Definition ExprCXX.cpp:1817
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:3851
bool isBeingDefined() const
Return true if this decl is currently being defined.
Definition Decl.h:3972
bool isUnion() const
Definition Decl.h:4062
TagKind getTagKind() const
Definition Decl.h:4051
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.
@ Template
A single template declaration.
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
@ DeducedTemplate
A template name that refers to another TemplateName with deduced default arguments.
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack() const
Retrieve the substituted template template parameter pack, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
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:8484
ArrayRef< TypeSourceInfo * > getArgs() const
Retrieve the argument types.
Definition ExprCXX.h:2981
TypeTrait getTrait() const
Determine which type trait this expression uses.
Definition ExprCXX.h:2949
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9405
bool isEnumeralType() const
Definition TypeBase.h:8870
bool isBuiltinType() const
Helper methods to distinguish type categories.
Definition TypeBase.h:8862
TypeClass getTypeClass() const
Definition TypeBase.h:2449
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3696
QualType getUnderlyingType() const
Definition Decl.h:3751
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition Expr.h:2738
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2701
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2288
Expr * getSubExpr() const
Definition Expr.h:2329
Opcode getOpcode() const
Definition Expr.h:2324
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given unary opcode.
Definition Expr.cpp:1458
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2242
const Expr * getInit() const
Definition Decl.h:1391
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1174
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.