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