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