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