Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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"
79#include "clang/AST/StmtSYCL.h"
82#include "clang/AST/Type.h"
85#include "clang/Basic/LLVM.h"
87#include "llvm/ADT/APInt.h"
88#include "llvm/ADT/APSInt.h"
89#include "llvm/ADT/StringExtras.h"
90#include "llvm/Support/Compiler.h"
91#include "llvm/Support/ErrorHandling.h"
92#include <cassert>
93#include <optional>
94#include <utility>
95
96using namespace clang;
97
99 QualType T1, QualType T2);
101 Decl *D1, Decl *D2);
103 const Stmt *S1, const Stmt *S2);
105 const TemplateArgument &Arg1,
106 const TemplateArgument &Arg2);
108 const TemplateArgumentLoc &Arg1,
109 const TemplateArgumentLoc &Arg2);
112 NestedNameSpecifier *NNS2);
113static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
114 const IdentifierInfo *Name2);
115
117 const DeclarationName Name1,
118 const DeclarationName Name2) {
119 if (Name1.getNameKind() != Name2.getNameKind())
120 return false;
121
122 switch (Name1.getNameKind()) {
123
126 Name2.getAsIdentifierInfo());
127
131 return IsStructurallyEquivalent(Context, Name1.getCXXNameType(),
132 Name2.getCXXNameType());
133
136 Context, Name1.getCXXDeductionGuideTemplate()->getDeclName(),
138 return false;
139 return IsStructurallyEquivalent(Context,
142 }
143
145 return Name1.getCXXOverloadedOperator() == Name2.getCXXOverloadedOperator();
146
150
152 return true; // FIXME When do we consider two using directives equal?
153
157 return true; // FIXME
158 }
159
160 llvm_unreachable("Unhandled kind of DeclarationName");
161 return true;
162}
163
164namespace {
165/// Encapsulates Stmt comparison logic.
166class StmtComparer {
168
169 // IsStmtEquivalent overloads. Each overload compares a specific statement
170 // and only has to compare the data that is specific to the specific statement
171 // class. Should only be called from TraverseStmt.
172
173 bool IsStmtEquivalent(const AddrLabelExpr *E1, const AddrLabelExpr *E2) {
174 return IsStructurallyEquivalent(Context, E1->getLabel(), E2->getLabel());
175 }
176
177 bool IsStmtEquivalent(const AtomicExpr *E1, const AtomicExpr *E2) {
178 return E1->getOp() == E2->getOp();
179 }
180
181 bool IsStmtEquivalent(const BinaryOperator *E1, const BinaryOperator *E2) {
182 return E1->getOpcode() == E2->getOpcode();
183 }
184
185 bool IsStmtEquivalent(const CallExpr *E1, const CallExpr *E2) {
186 // FIXME: IsStructurallyEquivalent requires non-const Decls.
187 Decl *Callee1 = const_cast<Decl *>(E1->getCalleeDecl());
188 Decl *Callee2 = const_cast<Decl *>(E2->getCalleeDecl());
189
190 // Compare whether both calls know their callee.
191 if (static_cast<bool>(Callee1) != static_cast<bool>(Callee2))
192 return false;
193
194 // Both calls have no callee, so nothing to do.
195 if (!static_cast<bool>(Callee1))
196 return true;
197
198 assert(Callee2);
199 return IsStructurallyEquivalent(Context, Callee1, Callee2);
200 }
201
202 bool IsStmtEquivalent(const CharacterLiteral *E1,
203 const CharacterLiteral *E2) {
204 return E1->getValue() == E2->getValue() && E1->getKind() == E2->getKind();
205 }
206
207 bool IsStmtEquivalent(const ChooseExpr *E1, const ChooseExpr *E2) {
208 return true; // Semantics only depend on children.
209 }
210
211 bool IsStmtEquivalent(const CompoundStmt *E1, const CompoundStmt *E2) {
212 // Number of children is actually checked by the generic children comparison
213 // code, but a CompoundStmt is one of the few statements where the number of
214 // children frequently differs and the number of statements is also always
215 // precomputed. Directly comparing the number of children here is thus
216 // just an optimization.
217 return E1->size() == E2->size();
218 }
219
220 bool IsStmtEquivalent(const DeclRefExpr *DRE1, const DeclRefExpr *DRE2) {
221 const ValueDecl *Decl1 = DRE1->getDecl();
222 const ValueDecl *Decl2 = DRE2->getDecl();
223 if (!Decl1 || !Decl2)
224 return false;
225 return IsStructurallyEquivalent(Context, const_cast<ValueDecl *>(Decl1),
226 const_cast<ValueDecl *>(Decl2));
227 }
228
229 bool IsStmtEquivalent(const DependentScopeDeclRefExpr *DE1,
230 const DependentScopeDeclRefExpr *DE2) {
231 if (!IsStructurallyEquivalent(Context, DE1->getDeclName(),
232 DE2->getDeclName()))
233 return false;
234 return IsStructurallyEquivalent(Context, DE1->getQualifier(),
235 DE2->getQualifier());
236 }
237
238 bool IsStmtEquivalent(const Expr *E1, const Expr *E2) {
239 return IsStructurallyEquivalent(Context, E1->getType(), E2->getType());
240 }
241
242 bool IsStmtEquivalent(const ExpressionTraitExpr *E1,
243 const ExpressionTraitExpr *E2) {
244 return E1->getTrait() == E2->getTrait() && E1->getValue() == E2->getValue();
245 }
246
247 bool IsStmtEquivalent(const FloatingLiteral *E1, const FloatingLiteral *E2) {
248 return E1->isExact() == E2->isExact() && E1->getValue() == E2->getValue();
249 }
250
251 bool IsStmtEquivalent(const GenericSelectionExpr *E1,
252 const GenericSelectionExpr *E2) {
253 for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
255 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
256 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
257 // Skip this case if there are a different number of associated types.
258 if (!Child1 || !Child2)
259 return false;
260
261 if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
262 (*Child2)->getType()))
263 return false;
264 }
265
266 return true;
267 }
268
269 bool IsStmtEquivalent(const ImplicitCastExpr *CastE1,
270 const ImplicitCastExpr *CastE2) {
271 return IsStructurallyEquivalent(Context, CastE1->getType(),
272 CastE2->getType());
273 }
274
275 bool IsStmtEquivalent(const IntegerLiteral *E1, const IntegerLiteral *E2) {
276 return E1->getValue() == E2->getValue();
277 }
278
279 bool IsStmtEquivalent(const MemberExpr *E1, const MemberExpr *E2) {
280 return IsStructurallyEquivalent(Context, E1->getFoundDecl(),
281 E2->getFoundDecl());
282 }
283
284 bool IsStmtEquivalent(const ObjCStringLiteral *E1,
285 const ObjCStringLiteral *E2) {
286 // Just wraps a StringLiteral child.
287 return true;
288 }
289
290 bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }
291
292 bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) {
293 LabelDecl *L1 = S1->getLabel();
294 LabelDecl *L2 = S2->getLabel();
295 if (!L1 || !L2)
296 return L1 == L2;
297
298 IdentifierInfo *Name1 = L1->getIdentifier();
299 IdentifierInfo *Name2 = L2->getIdentifier();
300 return ::IsStructurallyEquivalent(Name1, Name2);
301 }
302
303 bool IsStmtEquivalent(const SourceLocExpr *E1, const SourceLocExpr *E2) {
304 return E1->getIdentKind() == E2->getIdentKind();
305 }
306
307 bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) {
308 return E1->getTemplateDepth() == E2->getTemplateDepth();
309 }
310
311 bool IsStmtEquivalent(const StringLiteral *E1, const StringLiteral *E2) {
312 return E1->getBytes() == E2->getBytes();
313 }
314
315 bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
318 E2->getAssociatedDecl()))
319 return false;
320 if (E1->getIndex() != E2->getIndex())
321 return false;
322 if (E1->getPackIndex() != E2->getPackIndex())
323 return false;
324 return true;
325 }
326
327 bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
329 return IsStructurallyEquivalent(Context, E1->getArgumentPack(),
330 E2->getArgumentPack());
331 }
332
333 bool IsStmtEquivalent(const TypeTraitExpr *E1, const TypeTraitExpr *E2) {
334 if (E1->getTrait() != E2->getTrait())
335 return false;
336
337 for (auto Pair : zip_longest(E1->getArgs(), E2->getArgs())) {
338 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
339 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
340 // Different number of args.
341 if (!Child1 || !Child2)
342 return false;
343
344 if (!IsStructurallyEquivalent(Context, (*Child1)->getType(),
345 (*Child2)->getType()))
346 return false;
347 }
348 return true;
349 }
350
351 bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1,
352 const CXXDependentScopeMemberExpr *E2) {
353 if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) {
354 return false;
355 }
356 return IsStructurallyEquivalent(Context, E1->getBaseType(),
357 E2->getBaseType());
358 }
359
360 bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
361 const UnaryExprOrTypeTraitExpr *E2) {
362 if (E1->getKind() != E2->getKind())
363 return false;
364 return IsStructurallyEquivalent(Context, E1->getTypeOfArgument(),
365 E2->getTypeOfArgument());
366 }
367
368 bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) {
369 return E1->getOpcode() == E2->getOpcode();
370 }
371
372 bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) {
373 // Semantics only depend on children.
374 return true;
375 }
376
377 bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
378 if (!IsStructurallyEquivalent(Context, E1->getName(), E2->getName()))
379 return false;
380
381 if (static_cast<bool>(E1->getQualifier()) !=
382 static_cast<bool>(E2->getQualifier()))
383 return false;
384 if (E1->getQualifier() &&
386 E2->getQualifier()))
387 return false;
388
389 if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs())
390 return false;
391 const TemplateArgumentLoc *Args1 = E1->getTemplateArgs();
392 const TemplateArgumentLoc *Args2 = E2->getTemplateArgs();
393 for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
394 ++ArgI)
395 if (!IsStructurallyEquivalent(Context, Args1[ArgI], Args2[ArgI]))
396 return false;
397
398 return true;
399 }
400
401 bool IsStmtEquivalent(const CXXBoolLiteralExpr *E1, const CXXBoolLiteralExpr *E2) {
402 return E1->getValue() == E2->getValue();
403 }
404
405 /// End point of the traversal chain.
406 bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
407
408 // Create traversal methods that traverse the class hierarchy and return
409 // the accumulated result of the comparison. Each TraverseStmt overload
410 // calls the TraverseStmt overload of the parent class. For example,
411 // the TraverseStmt overload for 'BinaryOperator' calls the TraverseStmt
412 // overload of 'Expr' which then calls the overload for 'Stmt'.
413#define STMT(CLASS, PARENT) \
414 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
415 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
416 static_cast<const PARENT *>(S2))) \
417 return false; \
418 return IsStmtEquivalent(S1, S2); \
419 }
420#include "clang/AST/StmtNodes.inc"
421
422public:
423 StmtComparer(StructuralEquivalenceContext &C) : Context(C) {}
424
425 /// Determine whether two statements are equivalent. The statements have to
426 /// be of the same kind. The children of the statements and their properties
427 /// are not compared by this function.
428 bool IsEquivalent(const Stmt *S1, const Stmt *S2) {
429 if (S1->getStmtClass() != S2->getStmtClass())
430 return false;
431
432 // Each TraverseStmt walks the class hierarchy from the leaf class to
433 // the root class 'Stmt' (e.g. 'BinaryOperator' -> 'Expr' -> 'Stmt'). Cast
434 // the Stmt we have here to its specific subclass so that we call the
435 // overload that walks the whole class hierarchy from leaf to root (e.g.,
436 // cast to 'BinaryOperator' so that 'Expr' and 'Stmt' is traversed).
437 switch (S1->getStmtClass()) {
439 llvm_unreachable("Can't traverse NoStmtClass");
440#define STMT(CLASS, PARENT) \
441 case Stmt::StmtClass::CLASS##Class: \
442 return TraverseStmt(static_cast<const CLASS *>(S1), \
443 static_cast<const CLASS *>(S2));
444#define ABSTRACT_STMT(S)
445#include "clang/AST/StmtNodes.inc"
446 }
447 llvm_unreachable("Invalid statement kind");
448 }
449};
450} // namespace
451
453 const UnaryOperator *E1,
454 const CXXOperatorCallExpr *E2) {
456 E2->getOperator() &&
457 IsStructurallyEquivalent(Context, E1->getSubExpr(), E2->getArg(0));
458}
459
461 const CXXOperatorCallExpr *E1,
462 const UnaryOperator *E2) {
463 return E1->getOperator() ==
465 IsStructurallyEquivalent(Context, E1->getArg(0), E2->getSubExpr());
466}
467
469 const BinaryOperator *E1,
470 const CXXOperatorCallExpr *E2) {
472 E2->getOperator() &&
473 IsStructurallyEquivalent(Context, E1->getLHS(), E2->getArg(0)) &&
474 IsStructurallyEquivalent(Context, E1->getRHS(), E2->getArg(1));
475}
476
478 const CXXOperatorCallExpr *E1,
479 const BinaryOperator *E2) {
480 return E1->getOperator() ==
482 IsStructurallyEquivalent(Context, E1->getArg(0), E2->getLHS()) &&
483 IsStructurallyEquivalent(Context, E1->getArg(1), E2->getRHS());
484}
485
486/// Determine structural equivalence of two statements.
488 const Stmt *S1, const Stmt *S2) {
489 if (!S1 || !S2)
490 return S1 == S2;
491
492 // Check for statements with similar syntax but different AST.
493 // A UnaryOperator node is more lightweight than a CXXOperatorCallExpr node.
494 // The more heavyweight node is only created if the definition-time name
495 // lookup had any results. The lookup results are stored CXXOperatorCallExpr
496 // only. The lookup results can be different in a "From" and "To" AST even if
497 // the compared structure is otherwise equivalent. For this reason we must
498 // treat a similar unary/binary operator node and CXXOperatorCall node as
499 // equivalent.
500 if (const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
501 if (const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
502 return IsStructurallyEquivalent(Context, E1Unary, E2CXXOperatorCall);
503 if (const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
504 return IsStructurallyEquivalent(Context, E1Binary, E2CXXOperatorCall);
505 }
506 if (const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
507 if (const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
508 return IsStructurallyEquivalent(Context, E1CXXOperatorCall, E2Unary);
509 if (const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
510 return IsStructurallyEquivalent(Context, E1CXXOperatorCall, E2Binary);
511 }
512
513 // Compare the statements itself.
514 StmtComparer Comparer(Context);
515 if (!Comparer.IsEquivalent(S1, S2))
516 return false;
517
518 // Iterate over the children of both statements and also compare them.
519 for (auto Pair : zip_longest(S1->children(), S2->children())) {
520 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
521 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
522 // One of the statements has a different amount of children than the other,
523 // so the statements can't be equivalent.
524 if (!Child1 || !Child2)
525 return false;
526 if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
527 return false;
528 }
529 return true;
530}
531
532/// Determine whether two identifiers are equivalent.
534 const IdentifierInfo *Name2) {
535 if (!Name1 || !Name2)
536 return Name1 == Name2;
537
538 return Name1->getName() == Name2->getName();
539}
540
541/// Determine whether two nested-name-specifiers are equivalent.
544 NestedNameSpecifier *NNS2) {
545 if (NNS1->getKind() != NNS2->getKind())
546 return false;
547
548 NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
549 *Prefix2 = NNS2->getPrefix();
550 if ((bool)Prefix1 != (bool)Prefix2)
551 return false;
552
553 if (Prefix1)
554 if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
555 return false;
556
557 switch (NNS1->getKind()) {
560 NNS2->getAsIdentifier());
562 return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
563 NNS2->getAsNamespace());
565 return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(),
566 NNS2->getAsNamespaceAlias());
569 return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
570 QualType(NNS2->getAsType(), 0));
572 return true;
574 return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
575 NNS2->getAsRecordDecl());
576 }
577 return false;
578}
579
581 const TemplateName &N1,
582 const TemplateName &N2) {
583 TemplateDecl *TemplateDeclN1 = N1.getAsTemplateDecl();
584 TemplateDecl *TemplateDeclN2 = N2.getAsTemplateDecl();
585 if (TemplateDeclN1 && TemplateDeclN2) {
586 if (!IsStructurallyEquivalent(Context, TemplateDeclN1, TemplateDeclN2))
587 return false;
588 // If the kind is different we compare only the template decl.
589 if (N1.getKind() != N2.getKind())
590 return true;
591 } else if (TemplateDeclN1 || TemplateDeclN2)
592 return false;
593 else if (N1.getKind() != N2.getKind())
594 return false;
595
596 // Check for special case incompatibilities.
597 switch (N1.getKind()) {
598
601 *OS2 = N2.getAsOverloadedTemplate();
602 OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(),
603 E1 = OS1->end(), E2 = OS2->end();
604 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
605 if (!IsStructurallyEquivalent(Context, *I1, *I2))
606 return false;
607 return I1 == E1 && I2 == E2;
608 }
609
612 *TN2 = N1.getAsAssumedTemplateName();
613 return TN1->getDeclName() == TN2->getDeclName();
614 }
615
618 *DN2 = N2.getAsDependentTemplateName();
619 if (!IsStructurallyEquivalent(Context, DN1->getQualifier(),
620 DN2->getQualifier()))
621 return false;
622 if (DN1->isIdentifier() && DN2->isIdentifier())
624 DN2->getIdentifier());
625 else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator())
626 return DN1->getOperator() == DN2->getOperator();
627 return false;
628 }
629
634 return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
635 P2->getArgumentPack()) &&
637 P2->getAssociatedDecl()) &&
638 P1->getIndex() == P2->getIndex();
639 }
640
645 // It is sufficient to check value of getAsTemplateDecl.
646 break;
647
649 // FIXME: We can't reach here.
650 llvm_unreachable("unimplemented");
651 }
652
653 return true;
654}
655
659
660/// Determine whether two template arguments are equivalent.
662 const TemplateArgument &Arg1,
663 const TemplateArgument &Arg2) {
664 if (Arg1.getKind() != Arg2.getKind())
665 return false;
666
667 switch (Arg1.getKind()) {
669 return true;
670
672 return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
673
675 if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
676 Arg2.getIntegralType()))
677 return false;
678
679 return llvm::APSInt::isSameValue(Arg1.getAsIntegral(),
680 Arg2.getAsIntegral());
681
683 return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
684
686 return true; // FIXME: Is this correct?
687
689 return IsStructurallyEquivalent(Context, Arg1.getAsTemplate(),
690 Arg2.getAsTemplate());
691
693 return IsStructurallyEquivalent(Context,
696
698 return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
699 Arg2.getAsExpr());
700
702 return Arg1.structurallyEquals(Arg2);
703
705 return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
706 Arg2.pack_elements());
707 }
708
709 llvm_unreachable("Invalid template argument kind");
710}
711
712/// Determine structural equivalence of two template argument lists.
716 if (Args1.size() != Args2.size())
717 return false;
718 for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
719 if (!IsStructurallyEquivalent(Context, Args1[I], Args2[I]))
720 return false;
721 }
722 return true;
723}
724
725/// Determine whether two template argument locations are equivalent.
727 const TemplateArgumentLoc &Arg1,
728 const TemplateArgumentLoc &Arg2) {
729 return IsStructurallyEquivalent(Context, Arg1.getArgument(),
730 Arg2.getArgument());
731}
732
733/// Determine structural equivalence for the common part of array
734/// types.
736 const ArrayType *Array1,
737 const ArrayType *Array2) {
738 if (!IsStructurallyEquivalent(Context, Array1->getElementType(),
739 Array2->getElementType()))
740 return false;
741 if (Array1->getSizeModifier() != Array2->getSizeModifier())
742 return false;
743 if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
744 return false;
745
746 return true;
747}
748
749/// Determine structural equivalence based on the ExtInfo of functions. This
750/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
751/// conventions bits but must not compare some other bits.
755 // Compatible functions must have compatible calling conventions.
756 if (EI1.getCC() != EI2.getCC())
757 return false;
758
759 // Regparm is part of the calling convention.
760 if (EI1.getHasRegParm() != EI2.getHasRegParm())
761 return false;
762 if (EI1.getRegParm() != EI2.getRegParm())
763 return false;
764
765 if (EI1.getProducesResult() != EI2.getProducesResult())
766 return false;
768 return false;
769 if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
770 return false;
771
772 return true;
773}
774
775/// Check the equivalence of exception specifications.
777 const FunctionProtoType *Proto1,
778 const FunctionProtoType *Proto2) {
779
780 auto Spec1 = Proto1->getExceptionSpecType();
781 auto Spec2 = Proto2->getExceptionSpecType();
782
784 return true;
785
786 if (Spec1 != Spec2)
787 return false;
788 if (Spec1 == EST_Dynamic) {
789 if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
790 return false;
791 for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
792 if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
793 Proto2->getExceptionType(I)))
794 return false;
795 }
796 } else if (isComputedNoexcept(Spec1)) {
797 if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
798 Proto2->getNoexceptExpr()))
799 return false;
800 }
801
802 return true;
803}
804
805/// Determine structural equivalence of two types.
807 QualType T1, QualType T2) {
808 if (T1.isNull() || T2.isNull())
809 return T1.isNull() && T2.isNull();
810
811 QualType OrigT1 = T1;
812 QualType OrigT2 = T2;
813
814 if (!Context.StrictTypeSpelling) {
815 // We aren't being strict about token-to-token equivalence of types,
816 // so map down to the canonical type.
817 T1 = Context.FromCtx.getCanonicalType(T1);
818 T2 = Context.ToCtx.getCanonicalType(T2);
819 }
820
821 if (T1.getQualifiers() != T2.getQualifiers())
822 return false;
823
824 Type::TypeClass TC = T1->getTypeClass();
825
826 if (T1->getTypeClass() != T2->getTypeClass()) {
827 // Compare function types with prototypes vs. without prototypes as if
828 // both did not have prototypes.
829 if (T1->getTypeClass() == Type::FunctionProto &&
830 T2->getTypeClass() == Type::FunctionNoProto)
831 TC = Type::FunctionNoProto;
832 else if (T1->getTypeClass() == Type::FunctionNoProto &&
833 T2->getTypeClass() == Type::FunctionProto)
834 TC = Type::FunctionNoProto;
835 else
836 return false;
837 }
838
839 switch (TC) {
840 case Type::Builtin:
841 // FIXME: Deal with Char_S/Char_U.
842 if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind())
843 return false;
844 break;
845
846 case Type::Complex:
847 if (!IsStructurallyEquivalent(Context,
848 cast<ComplexType>(T1)->getElementType(),
849 cast<ComplexType>(T2)->getElementType()))
850 return false;
851 break;
852
853 case Type::Adjusted:
854 case Type::Decayed:
855 case Type::ArrayParameter:
856 if (!IsStructurallyEquivalent(Context,
857 cast<AdjustedType>(T1)->getOriginalType(),
858 cast<AdjustedType>(T2)->getOriginalType()))
859 return false;
860 break;
861
862 case Type::Pointer:
863 if (!IsStructurallyEquivalent(Context,
864 cast<PointerType>(T1)->getPointeeType(),
865 cast<PointerType>(T2)->getPointeeType()))
866 return false;
867 break;
868
869 case Type::BlockPointer:
870 if (!IsStructurallyEquivalent(Context,
871 cast<BlockPointerType>(T1)->getPointeeType(),
872 cast<BlockPointerType>(T2)->getPointeeType()))
873 return false;
874 break;
875
876 case Type::LValueReference:
877 case Type::RValueReference: {
878 const auto *Ref1 = cast<ReferenceType>(T1);
879 const auto *Ref2 = cast<ReferenceType>(T2);
880 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
881 return false;
882 if (Ref1->isInnerRef() != Ref2->isInnerRef())
883 return false;
884 if (!IsStructurallyEquivalent(Context, Ref1->getPointeeTypeAsWritten(),
885 Ref2->getPointeeTypeAsWritten()))
886 return false;
887 break;
888 }
889
890 case Type::MemberPointer: {
891 const auto *MemPtr1 = cast<MemberPointerType>(T1);
892 const auto *MemPtr2 = cast<MemberPointerType>(T2);
893 if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
894 MemPtr2->getPointeeType()))
895 return false;
896 if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0),
897 QualType(MemPtr2->getClass(), 0)))
898 return false;
899 break;
900 }
901
902 case Type::ConstantArray: {
903 const auto *Array1 = cast<ConstantArrayType>(T1);
904 const auto *Array2 = cast<ConstantArrayType>(T2);
905 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
906 return false;
907
908 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
909 return false;
910 break;
911 }
912
913 case Type::IncompleteArray:
914 if (!IsArrayStructurallyEquivalent(Context, cast<ArrayType>(T1),
915 cast<ArrayType>(T2)))
916 return false;
917 break;
918
919 case Type::VariableArray: {
920 const auto *Array1 = cast<VariableArrayType>(T1);
921 const auto *Array2 = cast<VariableArrayType>(T2);
922 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
923 Array2->getSizeExpr()))
924 return false;
925
926 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
927 return false;
928
929 break;
930 }
931
932 case Type::DependentSizedArray: {
933 const auto *Array1 = cast<DependentSizedArrayType>(T1);
934 const auto *Array2 = cast<DependentSizedArrayType>(T2);
935 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
936 Array2->getSizeExpr()))
937 return false;
938
939 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
940 return false;
941
942 break;
943 }
944
945 case Type::DependentAddressSpace: {
946 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
947 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
948 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
949 DepAddressSpace2->getAddrSpaceExpr()))
950 return false;
951 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(),
952 DepAddressSpace2->getPointeeType()))
953 return false;
954
955 break;
956 }
957
958 case Type::DependentSizedExtVector: {
959 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
960 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
961 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
962 Vec2->getSizeExpr()))
963 return false;
964 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
965 Vec2->getElementType()))
966 return false;
967 break;
968 }
969
970 case Type::DependentVector: {
971 const auto *Vec1 = cast<DependentVectorType>(T1);
972 const auto *Vec2 = cast<DependentVectorType>(T2);
973 if (Vec1->getVectorKind() != Vec2->getVectorKind())
974 return false;
975 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
976 Vec2->getSizeExpr()))
977 return false;
978 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
979 Vec2->getElementType()))
980 return false;
981 break;
982 }
983
984 case Type::Vector:
985 case Type::ExtVector: {
986 const auto *Vec1 = cast<VectorType>(T1);
987 const auto *Vec2 = cast<VectorType>(T2);
988 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
989 Vec2->getElementType()))
990 return false;
991 if (Vec1->getNumElements() != Vec2->getNumElements())
992 return false;
993 if (Vec1->getVectorKind() != Vec2->getVectorKind())
994 return false;
995 break;
996 }
997
998 case Type::DependentSizedMatrix: {
999 const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(T1);
1000 const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(T2);
1001 // The element types, row and column expressions must be structurally
1002 // equivalent.
1003 if (!IsStructurallyEquivalent(Context, Mat1->getRowExpr(),
1004 Mat2->getRowExpr()) ||
1005 !IsStructurallyEquivalent(Context, Mat1->getColumnExpr(),
1006 Mat2->getColumnExpr()) ||
1007 !IsStructurallyEquivalent(Context, Mat1->getElementType(),
1008 Mat2->getElementType()))
1009 return false;
1010 break;
1011 }
1012
1013 case Type::ConstantMatrix: {
1014 const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(T1);
1015 const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(T2);
1016 // The element types must be structurally equivalent and the number of rows
1017 // and columns must match.
1018 if (!IsStructurallyEquivalent(Context, Mat1->getElementType(),
1019 Mat2->getElementType()) ||
1020 Mat1->getNumRows() != Mat2->getNumRows() ||
1021 Mat1->getNumColumns() != Mat2->getNumColumns())
1022 return false;
1023 break;
1024 }
1025
1026 case Type::FunctionProto: {
1027 const auto *Proto1 = cast<FunctionProtoType>(T1);
1028 const auto *Proto2 = cast<FunctionProtoType>(T2);
1029
1030 if (Proto1->getNumParams() != Proto2->getNumParams())
1031 return false;
1032 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1033 if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I),
1034 Proto2->getParamType(I)))
1035 return false;
1036 }
1037 if (Proto1->isVariadic() != Proto2->isVariadic())
1038 return false;
1039
1040 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1041 return false;
1042
1043 // Check exceptions, this information is lost in canonical type.
1044 const auto *OrigProto1 =
1045 cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
1046 const auto *OrigProto2 =
1047 cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
1048 if (!IsEquivalentExceptionSpec(Context, OrigProto1, OrigProto2))
1049 return false;
1050
1051 // Fall through to check the bits common with FunctionNoProtoType.
1052 [[fallthrough]];
1053 }
1054
1055 case Type::FunctionNoProto: {
1056 const auto *Function1 = cast<FunctionType>(T1);
1057 const auto *Function2 = cast<FunctionType>(T2);
1058 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
1059 Function2->getReturnType()))
1060 return false;
1061 if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
1062 Function2->getExtInfo()))
1063 return false;
1064 break;
1065 }
1066
1067 case Type::UnresolvedUsing:
1068 if (!IsStructurallyEquivalent(Context,
1069 cast<UnresolvedUsingType>(T1)->getDecl(),
1070 cast<UnresolvedUsingType>(T2)->getDecl()))
1071 return false;
1072 break;
1073
1074 case Type::Attributed:
1075 if (!IsStructurallyEquivalent(Context,
1076 cast<AttributedType>(T1)->getModifiedType(),
1077 cast<AttributedType>(T2)->getModifiedType()))
1078 return false;
1080 Context, cast<AttributedType>(T1)->getEquivalentType(),
1081 cast<AttributedType>(T2)->getEquivalentType()))
1082 return false;
1083 break;
1084
1085 case Type::CountAttributed:
1086 if (!IsStructurallyEquivalent(Context,
1087 cast<CountAttributedType>(T1)->desugar(),
1088 cast<CountAttributedType>(T2)->desugar()))
1089 return false;
1090 break;
1091
1092 case Type::BTFTagAttributed:
1094 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1095 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1096 return false;
1097 break;
1098
1099 case Type::HLSLAttributedResource:
1101 Context, cast<HLSLAttributedResourceType>(T1)->getWrappedType(),
1102 cast<HLSLAttributedResourceType>(T2)->getWrappedType()))
1103 return false;
1105 Context, cast<HLSLAttributedResourceType>(T1)->getContainedType(),
1106 cast<HLSLAttributedResourceType>(T2)->getContainedType()))
1107 return false;
1108 if (cast<HLSLAttributedResourceType>(T1)->getAttrs() !=
1109 cast<HLSLAttributedResourceType>(T2)->getAttrs())
1110 return false;
1111 break;
1112
1113 case Type::Paren:
1114 if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(),
1115 cast<ParenType>(T2)->getInnerType()))
1116 return false;
1117 break;
1118
1119 case Type::MacroQualified:
1121 Context, cast<MacroQualifiedType>(T1)->getUnderlyingType(),
1122 cast<MacroQualifiedType>(T2)->getUnderlyingType()))
1123 return false;
1124 break;
1125
1126 case Type::Using:
1127 if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
1128 cast<UsingType>(T2)->getFoundDecl()))
1129 return false;
1130 if (!IsStructurallyEquivalent(Context,
1131 cast<UsingType>(T1)->getUnderlyingType(),
1132 cast<UsingType>(T2)->getUnderlyingType()))
1133 return false;
1134 break;
1135
1136 case Type::Typedef:
1137 if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
1138 cast<TypedefType>(T2)->getDecl()) ||
1139 !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
1140 cast<TypedefType>(T2)->desugar()))
1141 return false;
1142 break;
1143
1144 case Type::TypeOfExpr:
1146 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1147 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1148 return false;
1149 break;
1150
1151 case Type::TypeOf:
1152 if (!IsStructurallyEquivalent(Context,
1153 cast<TypeOfType>(T1)->getUnmodifiedType(),
1154 cast<TypeOfType>(T2)->getUnmodifiedType()))
1155 return false;
1156 break;
1157
1158 case Type::UnaryTransform:
1160 Context, cast<UnaryTransformType>(T1)->getUnderlyingType(),
1161 cast<UnaryTransformType>(T2)->getUnderlyingType()))
1162 return false;
1163 break;
1164
1165 case Type::Decltype:
1166 if (!IsStructurallyEquivalent(Context,
1167 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1168 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1169 return false;
1170 break;
1171
1172 case Type::Auto: {
1173 auto *Auto1 = cast<AutoType>(T1);
1174 auto *Auto2 = cast<AutoType>(T2);
1175 if (!IsStructurallyEquivalent(Context, Auto1->getDeducedType(),
1176 Auto2->getDeducedType()))
1177 return false;
1178 if (Auto1->isConstrained() != Auto2->isConstrained())
1179 return false;
1180 if (Auto1->isConstrained()) {
1181 if (Auto1->getTypeConstraintConcept() !=
1182 Auto2->getTypeConstraintConcept())
1183 return false;
1184 if (!IsStructurallyEquivalent(Context,
1185 Auto1->getTypeConstraintArguments(),
1186 Auto2->getTypeConstraintArguments()))
1187 return false;
1188 }
1189 break;
1190 }
1191
1192 case Type::DeducedTemplateSpecialization: {
1193 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1194 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1195 if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(),
1196 DT2->getTemplateName()))
1197 return false;
1198 if (!IsStructurallyEquivalent(Context, DT1->getDeducedType(),
1199 DT2->getDeducedType()))
1200 return false;
1201 break;
1202 }
1203
1204 case Type::Record:
1205 case Type::Enum:
1206 if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(),
1207 cast<TagType>(T2)->getDecl()))
1208 return false;
1209 break;
1210
1211 case Type::TemplateTypeParm: {
1212 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1213 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1214 if (!Context.IgnoreTemplateParmDepth &&
1215 Parm1->getDepth() != Parm2->getDepth())
1216 return false;
1217 if (Parm1->getIndex() != Parm2->getIndex())
1218 return false;
1219 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1220 return false;
1221
1222 // Names of template type parameters are never significant.
1223 break;
1224 }
1225
1226 case Type::SubstTemplateTypeParm: {
1227 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1228 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1229 if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
1230 Subst2->getReplacementType()))
1231 return false;
1232 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1233 Subst2->getAssociatedDecl()))
1234 return false;
1235 if (Subst1->getIndex() != Subst2->getIndex())
1236 return false;
1237 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1238 return false;
1239 break;
1240 }
1241
1242 case Type::SubstTemplateTypeParmPack: {
1243 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1244 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1245 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1246 Subst2->getAssociatedDecl()))
1247 return false;
1248 if (Subst1->getIndex() != Subst2->getIndex())
1249 return false;
1250 if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
1251 Subst2->getArgumentPack()))
1252 return false;
1253 break;
1254 }
1255
1256 case Type::TemplateSpecialization: {
1257 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1258 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1259 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
1260 Spec2->getTemplateName()))
1261 return false;
1262 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1263 Spec2->template_arguments()))
1264 return false;
1265 break;
1266 }
1267
1268 case Type::Elaborated: {
1269 const auto *Elab1 = cast<ElaboratedType>(T1);
1270 const auto *Elab2 = cast<ElaboratedType>(T2);
1271 // CHECKME: what if a keyword is ElaboratedTypeKeyword::None or
1272 // ElaboratedTypeKeyword::Typename
1273 // ?
1274 if (Elab1->getKeyword() != Elab2->getKeyword())
1275 return false;
1276 if (!IsStructurallyEquivalent(Context, Elab1->getQualifier(),
1277 Elab2->getQualifier()))
1278 return false;
1279 if (!IsStructurallyEquivalent(Context, Elab1->getNamedType(),
1280 Elab2->getNamedType()))
1281 return false;
1282 break;
1283 }
1284
1285 case Type::InjectedClassName: {
1286 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1287 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1288 if (!IsStructurallyEquivalent(Context,
1289 Inj1->getInjectedSpecializationType(),
1290 Inj2->getInjectedSpecializationType()))
1291 return false;
1292 break;
1293 }
1294
1295 case Type::DependentName: {
1296 const auto *Typename1 = cast<DependentNameType>(T1);
1297 const auto *Typename2 = cast<DependentNameType>(T2);
1298 if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(),
1299 Typename2->getQualifier()))
1300 return false;
1301 if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
1302 Typename2->getIdentifier()))
1303 return false;
1304
1305 break;
1306 }
1307
1308 case Type::DependentTemplateSpecialization: {
1309 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1310 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1311 if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(),
1312 Spec2->getQualifier()))
1313 return false;
1314 if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
1315 Spec2->getIdentifier()))
1316 return false;
1317 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1318 Spec2->template_arguments()))
1319 return false;
1320 break;
1321 }
1322
1323 case Type::PackExpansion:
1324 if (!IsStructurallyEquivalent(Context,
1325 cast<PackExpansionType>(T1)->getPattern(),
1326 cast<PackExpansionType>(T2)->getPattern()))
1327 return false;
1328 break;
1329
1330 case Type::PackIndexing:
1331 if (!IsStructurallyEquivalent(Context,
1332 cast<PackIndexingType>(T1)->getPattern(),
1333 cast<PackIndexingType>(T2)->getPattern()))
1334 if (!IsStructurallyEquivalent(Context,
1335 cast<PackIndexingType>(T1)->getIndexExpr(),
1336 cast<PackIndexingType>(T2)->getIndexExpr()))
1337 return false;
1338 break;
1339
1340 case Type::ObjCInterface: {
1341 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1342 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1343 if (!IsStructurallyEquivalent(Context, Iface1->getDecl(),
1344 Iface2->getDecl()))
1345 return false;
1346 break;
1347 }
1348
1349 case Type::ObjCTypeParam: {
1350 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1351 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1352 if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), Obj2->getDecl()))
1353 return false;
1354
1355 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1356 return false;
1357 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1358 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1359 Obj2->getProtocol(I)))
1360 return false;
1361 }
1362 break;
1363 }
1364
1365 case Type::ObjCObject: {
1366 const auto *Obj1 = cast<ObjCObjectType>(T1);
1367 const auto *Obj2 = cast<ObjCObjectType>(T2);
1368 if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(),
1369 Obj2->getBaseType()))
1370 return false;
1371 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1372 return false;
1373 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1374 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1375 Obj2->getProtocol(I)))
1376 return false;
1377 }
1378 break;
1379 }
1380
1381 case Type::ObjCObjectPointer: {
1382 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1383 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1384 if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(),
1385 Ptr2->getPointeeType()))
1386 return false;
1387 break;
1388 }
1389
1390 case Type::Atomic:
1391 if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(),
1392 cast<AtomicType>(T2)->getValueType()))
1393 return false;
1394 break;
1395
1396 case Type::Pipe:
1397 if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(),
1398 cast<PipeType>(T2)->getElementType()))
1399 return false;
1400 break;
1401 case Type::BitInt: {
1402 const auto *Int1 = cast<BitIntType>(T1);
1403 const auto *Int2 = cast<BitIntType>(T2);
1404
1405 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1406 Int1->getNumBits() != Int2->getNumBits())
1407 return false;
1408 break;
1409 }
1410 case Type::DependentBitInt: {
1411 const auto *Int1 = cast<DependentBitIntType>(T1);
1412 const auto *Int2 = cast<DependentBitIntType>(T2);
1413
1414 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1415 !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
1416 Int2->getNumBitsExpr()))
1417 return false;
1418 break;
1419 }
1420 } // end switch
1421
1422 return true;
1423}
1424
1426 VarDecl *D1, VarDecl *D2) {
1427 IdentifierInfo *Name1 = D1->getIdentifier();
1428 IdentifierInfo *Name2 = D2->getIdentifier();
1429 if (!::IsStructurallyEquivalent(Name1, Name2))
1430 return false;
1431
1432 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
1433 return false;
1434
1435 // Compare storage class and initializer only if none or both are a
1436 // definition. Like a forward-declaration matches a class definition, variable
1437 // declarations that are not definitions should match with the definitions.
1439 return true;
1440
1441 if (D1->getStorageClass() != D2->getStorageClass())
1442 return false;
1443
1444 return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit());
1445}
1446
1448 FieldDecl *Field1, FieldDecl *Field2,
1449 QualType Owner2Type) {
1450 const auto *Owner2 = cast<Decl>(Field2->getDeclContext());
1451
1452 // For anonymous structs/unions, match up the anonymous struct/union type
1453 // declarations directly, so that we don't go off searching for anonymous
1454 // types
1455 if (Field1->isAnonymousStructOrUnion() &&
1456 Field2->isAnonymousStructOrUnion()) {
1457 RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1458 RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1459 return IsStructurallyEquivalent(Context, D1, D2);
1460 }
1461
1462 // Check for equivalent field names.
1463 IdentifierInfo *Name1 = Field1->getIdentifier();
1464 IdentifierInfo *Name2 = Field2->getIdentifier();
1465 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1466 if (Context.Complain) {
1467 Context.Diag2(
1468 Owner2->getLocation(),
1469 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1470 << Owner2Type;
1471 Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
1472 << Field2->getDeclName();
1473 Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
1474 << Field1->getDeclName();
1475 }
1476 return false;
1477 }
1478
1479 if (!IsStructurallyEquivalent(Context, Field1->getType(),
1480 Field2->getType())) {
1481 if (Context.Complain) {
1482 Context.Diag2(
1483 Owner2->getLocation(),
1484 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1485 << Owner2Type;
1486 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1487 << Field2->getDeclName() << Field2->getType();
1488 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1489 << Field1->getDeclName() << Field1->getType();
1490 }
1491 return false;
1492 }
1493
1494 if (Field1->isBitField())
1495 return IsStructurallyEquivalent(Context, Field1->getBitWidth(),
1496 Field2->getBitWidth());
1497
1498 return true;
1499}
1500
1501/// Determine structural equivalence of two fields.
1503 FieldDecl *Field1, FieldDecl *Field2) {
1504 const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
1505 return IsStructurallyEquivalent(Context, Field1, Field2,
1506 Context.ToCtx.getTypeDeclType(Owner2));
1507}
1508
1509/// Determine structural equivalence of two methods.
1511 CXXMethodDecl *Method1,
1512 CXXMethodDecl *Method2) {
1513 bool PropertiesEqual =
1514 Method1->getDeclKind() == Method2->getDeclKind() &&
1515 Method1->getRefQualifier() == Method2->getRefQualifier() &&
1516 Method1->getAccess() == Method2->getAccess() &&
1517 Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1518 Method1->isStatic() == Method2->isStatic() &&
1519 Method1->isImplicitObjectMemberFunction() ==
1520 Method2->isImplicitObjectMemberFunction() &&
1521 Method1->isConst() == Method2->isConst() &&
1522 Method1->isVolatile() == Method2->isVolatile() &&
1523 Method1->isVirtual() == Method2->isVirtual() &&
1524 Method1->isPureVirtual() == Method2->isPureVirtual() &&
1525 Method1->isDefaulted() == Method2->isDefaulted() &&
1526 Method1->isDeleted() == Method2->isDeleted();
1527 if (!PropertiesEqual)
1528 return false;
1529 // FIXME: Check for 'final'.
1530
1531 if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1532 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1533 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1534 Constructor2->getExplicitSpecifier()))
1535 return false;
1536 }
1537
1538 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1539 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1540 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1541 Conversion2->getExplicitSpecifier()))
1542 return false;
1543 if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
1544 Conversion2->getConversionType()))
1545 return false;
1546 }
1547
1548 const IdentifierInfo *Name1 = Method1->getIdentifier();
1549 const IdentifierInfo *Name2 = Method2->getIdentifier();
1550 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1551 return false;
1552 // TODO: Names do not match, add warning like at check for FieldDecl.
1553 }
1554
1555 // Check the prototypes.
1556 if (!::IsStructurallyEquivalent(Context,
1557 Method1->getType(), Method2->getType()))
1558 return false;
1559
1560 return true;
1561}
1562
1563/// Determine structural equivalence of two lambda classes.
1564static bool
1566 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1567 assert(D1->isLambda() && D2->isLambda() &&
1568 "Must be called on lambda classes");
1570 D2->getLambdaCallOperator()))
1571 return false;
1572
1573 return true;
1574}
1575
1576/// Determine if context of a class is equivalent.
1577static bool
1579 RecordDecl *D1, RecordDecl *D2) {
1580 // The context should be completely equal, including anonymous and inline
1581 // namespaces.
1582 // We compare objects as part of full translation units, not subtrees of
1583 // translation units.
1586 while (true) {
1587 // Special case: We allow a struct defined in a function to be equivalent
1588 // with a similar struct defined outside of a function.
1589 if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1590 (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1591 return true;
1592
1593 if (DC1->getDeclKind() != DC2->getDeclKind())
1594 return false;
1595 if (DC1->isTranslationUnit())
1596 break;
1597 if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1598 return false;
1599 if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1600 const auto *ND2 = cast<NamedDecl>(DC2);
1601 if (!DC1->isInlineNamespace() &&
1602 !IsStructurallyEquivalent(ND1->getIdentifier(), ND2->getIdentifier()))
1603 return false;
1604 }
1605
1606 if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1607 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1608 if (!IsStructurallyEquivalent(Context, D1Spec, D2Spec))
1609 return false;
1610 }
1611
1612 DC1 = DC1->getParent()->getNonTransparentContext();
1613 DC2 = DC2->getParent()->getNonTransparentContext();
1614 }
1615
1616 return true;
1617}
1618
1619static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1620 auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1621 if (const IdentifierInfo *Name = D.getIdentifier())
1622 return Name;
1623 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1624 return TypedefName->getIdentifier();
1625 return nullptr;
1626 };
1627 return IsStructurallyEquivalent(GetName(D1), GetName(D2));
1628}
1629
1630/// Determine structural equivalence of two records.
1632 RecordDecl *D1, RecordDecl *D2) {
1633 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1634 return false;
1635 }
1636
1637 if (D1->isUnion() != D2->isUnion()) {
1638 if (Context.Complain) {
1639 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1640 diag::err_odr_tag_type_inconsistent))
1641 << Context.ToCtx.getTypeDeclType(D2);
1642 Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
1643 << D1->getDeclName() << (unsigned)D1->getTagKind();
1644 }
1645 return false;
1646 }
1647
1648 if (!D1->getDeclName() && !D2->getDeclName()) {
1649 // If both anonymous structs/unions are in a record context, make sure
1650 // they occur in the same location in the context records.
1651 if (std::optional<unsigned> Index1 =
1653 if (std::optional<unsigned> Index2 =
1655 D2)) {
1656 if (*Index1 != *Index2)
1657 return false;
1658 }
1659 }
1660 }
1661
1662 // If the records occur in different context (namespace), these should be
1663 // different. This is specially important if the definition of one or both
1664 // records is missing.
1665 if (!IsRecordContextStructurallyEquivalent(Context, D1, D2))
1666 return false;
1667
1668 // If both declarations are class template specializations, we know
1669 // the ODR applies, so check the template and template arguments.
1670 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1671 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1672 if (Spec1 && Spec2) {
1673 // Check that the specialized templates are the same.
1674 if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
1675 Spec2->getSpecializedTemplate()))
1676 return false;
1677
1678 // Check that the template arguments are the same.
1679 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1680 return false;
1681
1682 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1683 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateArgs().get(I),
1684 Spec2->getTemplateArgs().get(I)))
1685 return false;
1686 }
1687 // If one is a class template specialization and the other is not, these
1688 // structures are different.
1689 else if (Spec1 || Spec2)
1690 return false;
1691
1692 // Compare the definitions of these two records. If either or both are
1693 // incomplete (i.e. it is a forward decl), we assume that they are
1694 // equivalent.
1695 D1 = D1->getDefinition();
1696 D2 = D2->getDefinition();
1697 if (!D1 || !D2)
1698 return true;
1699
1700 // If any of the records has external storage and we do a minimal check (or
1701 // AST import) we assume they are equivalent. (If we didn't have this
1702 // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1703 // another AST import which in turn would call the structural equivalency
1704 // check again and finally we'd have an improper result.)
1705 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1707 return true;
1708
1709 // If one definition is currently being defined, we do not compare for
1710 // equality and we assume that the decls are equal.
1711 if (D1->isBeingDefined() || D2->isBeingDefined())
1712 return true;
1713
1714 if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1715 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1716 if (D1CXX->hasExternalLexicalStorage() &&
1717 !D1CXX->isCompleteDefinition()) {
1718 D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1719 }
1720
1721 if (D1CXX->isLambda() != D2CXX->isLambda())
1722 return false;
1723 if (D1CXX->isLambda()) {
1724 if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX))
1725 return false;
1726 }
1727
1728 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1729 if (Context.Complain) {
1730 Context.Diag2(D2->getLocation(),
1731 Context.getApplicableDiagnostic(
1732 diag::err_odr_tag_type_inconsistent))
1733 << Context.ToCtx.getTypeDeclType(D2);
1734 Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
1735 << D2CXX->getNumBases();
1736 Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
1737 << D1CXX->getNumBases();
1738 }
1739 return false;
1740 }
1741
1742 // Check the base classes.
1743 for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1744 BaseEnd1 = D1CXX->bases_end(),
1745 Base2 = D2CXX->bases_begin();
1746 Base1 != BaseEnd1; ++Base1, ++Base2) {
1747 if (!IsStructurallyEquivalent(Context, Base1->getType(),
1748 Base2->getType())) {
1749 if (Context.Complain) {
1750 Context.Diag2(D2->getLocation(),
1751 Context.getApplicableDiagnostic(
1752 diag::err_odr_tag_type_inconsistent))
1753 << Context.ToCtx.getTypeDeclType(D2);
1754 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1755 << Base2->getType() << Base2->getSourceRange();
1756 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1757 << Base1->getType() << Base1->getSourceRange();
1758 }
1759 return false;
1760 }
1761
1762 // Check virtual vs. non-virtual inheritance mismatch.
1763 if (Base1->isVirtual() != Base2->isVirtual()) {
1764 if (Context.Complain) {
1765 Context.Diag2(D2->getLocation(),
1766 Context.getApplicableDiagnostic(
1767 diag::err_odr_tag_type_inconsistent))
1768 << Context.ToCtx.getTypeDeclType(D2);
1769 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1770 << Base2->isVirtual() << Base2->getSourceRange();
1771 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1772 << Base1->isVirtual() << Base1->getSourceRange();
1773 }
1774 return false;
1775 }
1776 }
1777
1778 // Check the friends for consistency.
1779 CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
1780 Friend2End = D2CXX->friend_end();
1781 for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
1782 Friend1End = D1CXX->friend_end();
1783 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1784 if (Friend2 == Friend2End) {
1785 if (Context.Complain) {
1786 Context.Diag2(D2->getLocation(),
1787 Context.getApplicableDiagnostic(
1788 diag::err_odr_tag_type_inconsistent))
1789 << Context.ToCtx.getTypeDeclType(D2CXX);
1790 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1791 Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
1792 }
1793 return false;
1794 }
1795
1796 if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) {
1797 if (Context.Complain) {
1798 Context.Diag2(D2->getLocation(),
1799 Context.getApplicableDiagnostic(
1800 diag::err_odr_tag_type_inconsistent))
1801 << Context.ToCtx.getTypeDeclType(D2CXX);
1802 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1803 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1804 }
1805 return false;
1806 }
1807 }
1808
1809 if (Friend2 != Friend2End) {
1810 if (Context.Complain) {
1811 Context.Diag2(D2->getLocation(),
1812 Context.getApplicableDiagnostic(
1813 diag::err_odr_tag_type_inconsistent))
1814 << Context.ToCtx.getTypeDeclType(D2);
1815 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1816 Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
1817 }
1818 return false;
1819 }
1820 } else if (D1CXX->getNumBases() > 0) {
1821 if (Context.Complain) {
1822 Context.Diag2(D2->getLocation(),
1823 Context.getApplicableDiagnostic(
1824 diag::err_odr_tag_type_inconsistent))
1825 << Context.ToCtx.getTypeDeclType(D2);
1826 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
1827 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1828 << Base1->getType() << Base1->getSourceRange();
1829 Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
1830 }
1831 return false;
1832 }
1833 }
1834
1835 // Check the fields for consistency.
1836 QualType D2Type = Context.ToCtx.getTypeDeclType(D2);
1838 Field2End = D2->field_end();
1839 for (RecordDecl::field_iterator Field1 = D1->field_begin(),
1840 Field1End = D1->field_end();
1841 Field1 != Field1End; ++Field1, ++Field2) {
1842 if (Field2 == Field2End) {
1843 if (Context.Complain) {
1844 Context.Diag2(D2->getLocation(),
1845 Context.getApplicableDiagnostic(
1846 diag::err_odr_tag_type_inconsistent))
1847 << Context.ToCtx.getTypeDeclType(D2);
1848 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1849 << Field1->getDeclName() << Field1->getType();
1850 Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
1851 }
1852 return false;
1853 }
1854
1855 if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type))
1856 return false;
1857 }
1858
1859 if (Field2 != Field2End) {
1860 if (Context.Complain) {
1861 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1862 diag::err_odr_tag_type_inconsistent))
1863 << Context.ToCtx.getTypeDeclType(D2);
1864 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1865 << Field2->getDeclName() << Field2->getType();
1866 Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
1867 }
1868 return false;
1869 }
1870
1871 return true;
1872}
1873
1875 EnumConstantDecl *D1,
1876 EnumConstantDecl *D2) {
1877 const llvm::APSInt &FromVal = D1->getInitVal();
1878 const llvm::APSInt &ToVal = D2->getInitVal();
1879 if (FromVal.isSigned() != ToVal.isSigned())
1880 return false;
1881 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1882 return false;
1883 if (FromVal != ToVal)
1884 return false;
1885
1887 return false;
1888
1889 // Init expressions are the most expensive check, so do them last.
1890 return IsStructurallyEquivalent(Context, D1->getInitExpr(),
1891 D2->getInitExpr());
1892}
1893
1894/// Determine structural equivalence of two enums.
1896 EnumDecl *D1, EnumDecl *D2) {
1897 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1898 return false;
1899 }
1900
1901 // Compare the definitions of these two enums. If either or both are
1902 // incomplete (i.e. forward declared), we assume that they are equivalent.
1903 D1 = D1->getDefinition();
1904 D2 = D2->getDefinition();
1905 if (!D1 || !D2)
1906 return true;
1907
1909 EC2End = D2->enumerator_end();
1911 EC1End = D1->enumerator_end();
1912 EC1 != EC1End; ++EC1, ++EC2) {
1913 if (EC2 == EC2End) {
1914 if (Context.Complain) {
1915 Context.Diag2(D2->getLocation(),
1916 Context.getApplicableDiagnostic(
1917 diag::err_odr_tag_type_inconsistent))
1918 << Context.ToCtx.getTypeDeclType(D2);
1919 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1920 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1921 Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
1922 }
1923 return false;
1924 }
1925
1926 llvm::APSInt Val1 = EC1->getInitVal();
1927 llvm::APSInt Val2 = EC2->getInitVal();
1928 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1929 !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
1930 if (Context.Complain) {
1931 Context.Diag2(D2->getLocation(),
1932 Context.getApplicableDiagnostic(
1933 diag::err_odr_tag_type_inconsistent))
1934 << Context.ToCtx.getTypeDeclType(D2);
1935 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1936 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1937 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1938 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1939 }
1940 return false;
1941 }
1942 }
1943
1944 if (EC2 != EC2End) {
1945 if (Context.Complain) {
1946 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1947 diag::err_odr_tag_type_inconsistent))
1948 << Context.ToCtx.getTypeDeclType(D2);
1949 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1950 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1951 Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
1952 }
1953 return false;
1954 }
1955
1956 return true;
1957}
1958
1960 TemplateParameterList *Params1,
1961 TemplateParameterList *Params2) {
1962 if (Params1->size() != Params2->size()) {
1963 if (Context.Complain) {
1964 Context.Diag2(Params2->getTemplateLoc(),
1965 Context.getApplicableDiagnostic(
1966 diag::err_odr_different_num_template_parameters))
1967 << Params1->size() << Params2->size();
1968 Context.Diag1(Params1->getTemplateLoc(),
1969 diag::note_odr_template_parameter_list);
1970 }
1971 return false;
1972 }
1973
1974 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
1975 if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
1976 if (Context.Complain) {
1977 Context.Diag2(Params2->getParam(I)->getLocation(),
1978 Context.getApplicableDiagnostic(
1979 diag::err_odr_different_template_parameter_kind));
1980 Context.Diag1(Params1->getParam(I)->getLocation(),
1981 diag::note_odr_template_parameter_here);
1982 }
1983 return false;
1984 }
1985
1986 if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
1987 Params2->getParam(I)))
1988 return false;
1989 }
1990
1991 return true;
1992}
1993
1997 if (D1->isParameterPack() != D2->isParameterPack()) {
1998 if (Context.Complain) {
1999 Context.Diag2(D2->getLocation(),
2000 Context.getApplicableDiagnostic(
2001 diag::err_odr_parameter_pack_non_pack))
2002 << D2->isParameterPack();
2003 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2004 << D1->isParameterPack();
2005 }
2006 return false;
2007 }
2008
2009 return true;
2010}
2011
2015 if (D1->isParameterPack() != D2->isParameterPack()) {
2016 if (Context.Complain) {
2017 Context.Diag2(D2->getLocation(),
2018 Context.getApplicableDiagnostic(
2019 diag::err_odr_parameter_pack_non_pack))
2020 << D2->isParameterPack();
2021 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2022 << D1->isParameterPack();
2023 }
2024 return false;
2025 }
2026 if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
2027 return false;
2028 if (D1->getIndex() != D2->getIndex())
2029 return false;
2030 // Check types.
2031 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
2032 if (Context.Complain) {
2033 Context.Diag2(D2->getLocation(),
2034 Context.getApplicableDiagnostic(
2035 diag::err_odr_non_type_parameter_type_inconsistent))
2036 << D2->getType() << D1->getType();
2037 Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
2038 << D1->getType();
2039 }
2040 return false;
2041 }
2042
2043 return true;
2044}
2045
2049 if (D1->isParameterPack() != D2->isParameterPack()) {
2050 if (Context.Complain) {
2051 Context.Diag2(D2->getLocation(),
2052 Context.getApplicableDiagnostic(
2053 diag::err_odr_parameter_pack_non_pack))
2054 << D2->isParameterPack();
2055 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2056 << D1->isParameterPack();
2057 }
2058 return false;
2059 }
2060
2061 // Check template parameter lists.
2062 return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
2063 D2->getTemplateParameters());
2064}
2065
2069 return false;
2070 if (!D1->getIdentifier()) // Special name
2071 if (D1->getNameAsString() != D2->getNameAsString())
2072 return false;
2074 D2->getTemplateParameters());
2075}
2076
2079 ClassTemplateDecl *D2) {
2080 // Check template parameters.
2081 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2082 return false;
2083
2084 // Check the templated declaration.
2085 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
2086 D2->getTemplatedDecl());
2087}
2088
2092 // Check template parameters.
2093 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2094 return false;
2095
2096 // Check the templated declaration.
2097 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
2098 D2->getTemplatedDecl()->getType());
2099}
2100
2104 // Check template parameters.
2105 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2106 return false;
2107
2108 // Check the templated declaration.
2109 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
2110 D2->getTemplatedDecl());
2111}
2112
2114 ConceptDecl *D1,
2115 ConceptDecl *D2) {
2116 // Check template parameters.
2117 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2118 return false;
2119
2120 // Check the constraint expression.
2121 return IsStructurallyEquivalent(Context, D1->getConstraintExpr(),
2122 D2->getConstraintExpr());
2123}
2124
2126 FriendDecl *D1, FriendDecl *D2) {
2127 if ((D1->getFriendType() && D2->getFriendDecl()) ||
2128 (D1->getFriendDecl() && D2->getFriendType())) {
2129 return false;
2130 }
2131 if (D1->getFriendType() && D2->getFriendType())
2132 return IsStructurallyEquivalent(Context,
2133 D1->getFriendType()->getType(),
2134 D2->getFriendType()->getType());
2135 if (D1->getFriendDecl() && D2->getFriendDecl())
2136 return IsStructurallyEquivalent(Context, D1->getFriendDecl(),
2137 D2->getFriendDecl());
2138 return false;
2139}
2140
2144 return false;
2145
2146 return IsStructurallyEquivalent(Context, D1->getUnderlyingType(),
2147 D2->getUnderlyingType());
2148}
2149
2151 FunctionDecl *D1, FunctionDecl *D2) {
2153 return false;
2154
2155 if (D1->isOverloadedOperator()) {
2156 if (!D2->isOverloadedOperator())
2157 return false;
2159 return false;
2160 }
2161
2162 // FIXME: Consider checking for function attributes as well.
2163 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
2164 return false;
2165
2166 return true;
2167}
2168
2170 ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2171 QualType Owner2Type) {
2172 if (D1->getAccessControl() != D2->getAccessControl())
2173 return false;
2174
2175 return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1),
2176 cast<FieldDecl>(D2), Owner2Type);
2177}
2178
2180 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2181 QualType Owner2Type =
2182 Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface());
2183 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2184}
2185
2187 ObjCMethodDecl *Method1,
2188 ObjCMethodDecl *Method2) {
2189 bool PropertiesEqual =
2190 Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2191 Method1->isVariadic() == Method2->isVariadic() &&
2192 Method1->isDirectMethod() == Method2->isDirectMethod();
2193 if (!PropertiesEqual)
2194 return false;
2195
2196 // Compare selector slot names.
2197 Selector Selector1 = Method1->getSelector(),
2198 Selector2 = Method2->getSelector();
2199 unsigned NumArgs = Selector1.getNumArgs();
2200 if (NumArgs != Selector2.getNumArgs())
2201 return false;
2202 // Compare all selector slots. For selectors with arguments it means all arg
2203 // slots. And if there are no arguments, compare the first-and-only slot.
2204 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2205 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2207 Selector2.getIdentifierInfoForSlot(I)))
2208 return false;
2209 }
2210
2211 // Compare types.
2212 if (!IsStructurallyEquivalent(Context, Method1->getReturnType(),
2213 Method2->getReturnType()))
2214 return false;
2215 assert(
2216 Method1->param_size() == Method2->param_size() &&
2217 "Same number of arguments should be already enforced in Selector checks");
2219 ParamT1 = Method1->param_type_begin(),
2220 ParamT1End = Method1->param_type_end(),
2221 ParamT2 = Method2->param_type_begin(),
2222 ParamT2End = Method2->param_type_end();
2223 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2224 ++ParamT1, ++ParamT2) {
2225 if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2))
2226 return false;
2227 }
2228
2229 return true;
2230}
2231
2233 ObjCCategoryDecl *D1,
2234 ObjCCategoryDecl *D2) {
2236 return false;
2237
2238 const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2239 *Intf2 = D2->getClassInterface();
2240 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2241 return false;
2242
2243 if (Intf1 &&
2244 !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier()))
2245 return false;
2246
2247 // Compare protocols.
2249 Protocol2End = D2->protocol_end();
2251 Protocol1End = D1->protocol_end();
2252 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2253 if (Protocol2 == Protocol2End)
2254 return false;
2255 if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(),
2256 (*Protocol2)->getIdentifier()))
2257 return false;
2258 }
2259 if (Protocol2 != Protocol2End)
2260 return false;
2261
2262 // Compare ivars.
2263 QualType D2Type =
2264 Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType();
2266 Ivar2End = D2->ivar_end();
2268 Ivar1End = D1->ivar_end();
2269 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2270 if (Ivar2 == Ivar2End)
2271 return false;
2272 if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type))
2273 return false;
2274 }
2275 if (Ivar2 != Ivar2End)
2276 return false;
2277
2278 // Compare methods.
2280 Method2End = D2->meth_end();
2281 for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2282 Method1End = D1->meth_end();
2283 Method1 != Method1End; ++Method1, ++Method2) {
2284 if (Method2 == Method2End)
2285 return false;
2286 if (!IsStructurallyEquivalent(Context, *Method1, *Method2))
2287 return false;
2288 }
2289 if (Method2 != Method2End)
2290 return false;
2291
2292 return true;
2293}
2294
2295/// Determine structural equivalence of two declarations.
2297 Decl *D1, Decl *D2) {
2298 // FIXME: Check for known structural equivalences via a callback of some sort.
2299
2300 D1 = D1->getCanonicalDecl();
2301 D2 = D2->getCanonicalDecl();
2302 std::pair<Decl *, Decl *> P{D1, D2};
2303
2304 // Check whether we already know that these two declarations are not
2305 // structurally equivalent.
2306 if (Context.NonEquivalentDecls.count(
2307 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2308 return false;
2309
2310 // Check if a check for these declarations is already pending.
2311 // If yes D1 and D2 will be checked later (from DeclsToCheck),
2312 // or these are already checked (and equivalent).
2313 bool Inserted = Context.VisitedDecls.insert(P).second;
2314 if (!Inserted)
2315 return true;
2316
2317 Context.DeclsToCheck.push(P);
2318
2319 return true;
2320}
2321
2323 unsigned DiagID) {
2324 assert(Complain && "Not allowed to complain");
2325 if (LastDiagFromC2)
2327 LastDiagFromC2 = false;
2328 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2329}
2330
2332 unsigned DiagID) {
2333 assert(Complain && "Not allowed to complain");
2334 if (!LastDiagFromC2)
2336 LastDiagFromC2 = true;
2337 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2338}
2339
2340std::optional<unsigned>
2342 ASTContext &Context = Anon->getASTContext();
2343 QualType AnonTy = Context.getRecordType(Anon);
2344
2345 const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
2346 if (!Owner)
2347 return std::nullopt;
2348
2349 unsigned Index = 0;
2350 for (const auto *D : Owner->noload_decls()) {
2351 const auto *F = dyn_cast<FieldDecl>(D);
2352 if (!F)
2353 continue;
2354
2355 if (F->isAnonymousStructOrUnion()) {
2356 if (Context.hasSameType(F->getType(), AnonTy))
2357 break;
2358 ++Index;
2359 continue;
2360 }
2361
2362 // If the field looks like this:
2363 // struct { ... } A;
2364 QualType FieldType = F->getType();
2365 // In case of nested structs.
2366 while (const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2367 FieldType = ElabType->getNamedType();
2368
2369 if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2370 const RecordDecl *RecDecl = RecType->getDecl();
2371 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2372 if (Context.hasSameType(FieldType, AnonTy))
2373 break;
2374 ++Index;
2375 continue;
2376 }
2377 }
2378 }
2379
2380 return Index;
2381}
2382
2384 unsigned ErrorDiagnostic) {
2386 return ErrorDiagnostic;
2387
2388 switch (ErrorDiagnostic) {
2389 case diag::err_odr_variable_type_inconsistent:
2390 return diag::warn_odr_variable_type_inconsistent;
2391 case diag::err_odr_variable_multiple_def:
2392 return diag::warn_odr_variable_multiple_def;
2393 case diag::err_odr_function_type_inconsistent:
2394 return diag::warn_odr_function_type_inconsistent;
2395 case diag::err_odr_tag_type_inconsistent:
2396 return diag::warn_odr_tag_type_inconsistent;
2397 case diag::err_odr_field_type_inconsistent:
2398 return diag::warn_odr_field_type_inconsistent;
2399 case diag::err_odr_ivar_type_inconsistent:
2400 return diag::warn_odr_ivar_type_inconsistent;
2401 case diag::err_odr_objc_superclass_inconsistent:
2402 return diag::warn_odr_objc_superclass_inconsistent;
2403 case diag::err_odr_objc_method_result_type_inconsistent:
2404 return diag::warn_odr_objc_method_result_type_inconsistent;
2405 case diag::err_odr_objc_method_num_params_inconsistent:
2406 return diag::warn_odr_objc_method_num_params_inconsistent;
2407 case diag::err_odr_objc_method_param_type_inconsistent:
2408 return diag::warn_odr_objc_method_param_type_inconsistent;
2409 case diag::err_odr_objc_method_variadic_inconsistent:
2410 return diag::warn_odr_objc_method_variadic_inconsistent;
2411 case diag::err_odr_objc_property_type_inconsistent:
2412 return diag::warn_odr_objc_property_type_inconsistent;
2413 case diag::err_odr_objc_property_impl_kind_inconsistent:
2414 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2415 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2416 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2417 case diag::err_odr_different_num_template_parameters:
2418 return diag::warn_odr_different_num_template_parameters;
2419 case diag::err_odr_different_template_parameter_kind:
2420 return diag::warn_odr_different_template_parameter_kind;
2421 case diag::err_odr_parameter_pack_non_pack:
2422 return diag::warn_odr_parameter_pack_non_pack;
2423 case diag::err_odr_non_type_parameter_type_inconsistent:
2424 return diag::warn_odr_non_type_parameter_type_inconsistent;
2425 }
2426 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2427}
2428
2430
2431 // Ensure that the implementation functions (all static functions in this TU)
2432 // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2433 // because that will wreak havoc the internal state (DeclsToCheck and
2434 // VisitedDecls members) and can cause faulty behaviour.
2435 // In other words: Do not start a graph search from a new node with the
2436 // internal data of another search in progress.
2437 // FIXME: Better encapsulation and separation of internal and public
2438 // functionality.
2439 assert(DeclsToCheck.empty());
2440 assert(VisitedDecls.empty());
2441
2442 if (!::IsStructurallyEquivalent(*this, D1, D2))
2443 return false;
2444
2445 return !Finish();
2446}
2447
2449 assert(DeclsToCheck.empty());
2450 assert(VisitedDecls.empty());
2451 if (!::IsStructurallyEquivalent(*this, T1, T2))
2452 return false;
2453
2454 return !Finish();
2455}
2456
2458 assert(DeclsToCheck.empty());
2459 assert(VisitedDecls.empty());
2460 if (!::IsStructurallyEquivalent(*this, S1, S2))
2461 return false;
2462
2463 return !Finish();
2464}
2465
2466bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2467 // Check for equivalent described template.
2468 TemplateDecl *Template1 = D1->getDescribedTemplate();
2469 TemplateDecl *Template2 = D2->getDescribedTemplate();
2470 if ((Template1 != nullptr) != (Template2 != nullptr))
2471 return false;
2472 if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2))
2473 return false;
2474
2475 // FIXME: Move check for identifier names into this function.
2476
2477 return true;
2478}
2479
2480bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2481 Decl *D1, Decl *D2) {
2482
2483 // Kind mismatch.
2484 if (D1->getKind() != D2->getKind())
2485 return false;
2486
2487 // Cast the Decls to their actual subclass so that the right overload of
2488 // IsStructurallyEquivalent is called.
2489 switch (D1->getKind()) {
2490#define ABSTRACT_DECL(DECL)
2491#define DECL(DERIVED, BASE) \
2492 case Decl::Kind::DERIVED: \
2493 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2494 static_cast<DERIVED##Decl *>(D2));
2495#include "clang/AST/DeclNodes.inc"
2496 }
2497 return true;
2498}
2499
2500bool StructuralEquivalenceContext::Finish() {
2501 while (!DeclsToCheck.empty()) {
2502 // Check the next declaration.
2503 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2504 DeclsToCheck.pop();
2505
2506 Decl *D1 = P.first;
2507 Decl *D2 = P.second;
2508
2509 bool Equivalent =
2510 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2511
2512 if (!Equivalent) {
2513 // Note that these two declarations are not equivalent (and we already
2514 // know about it).
2515 NonEquivalentDecls.insert(
2516 std::make_tuple(D1, D2, IgnoreTemplateParmDepth));
2517
2518 return true;
2519 }
2520 }
2521
2522 return false;
2523}
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:1181
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.
This file defines SYCL AST classes used to represent calls to SYCL kernels.
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
llvm::APInt getValue() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.
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:2723
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2739
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:2196
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:2595
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:2319
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:1700
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:2384
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1439
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2104
bool isTranslationUnit() const
Definition: DeclBase.h:2180
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Definition: DeclBase.h:2679
bool isInlineNamespace() const
Definition: DeclBase.cpp:1324
bool isFunctionOrMethod() const
Definition: DeclBase.h:2156
Decl::Kind getDeclKind() const
Definition: DeclBase.h:2097
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1426
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:266
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:528
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:971
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:3291
llvm::APSInt getInitVal() const
Definition: Decl.h:3311
const Expr * getInitExpr() const
Definition: Decl.h:3309
Represents an enum.
Definition: Decl.h:3861
enumerator_iterator enumerator_begin() const
Definition: Decl.h:3998
EnumDecl * getDefinition() const
Definition: Decl.h:3964
enumerator_iterator enumerator_end() const
Definition: Decl.h:4005
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:3136
bool isAnonymousStructOrUnion() const
Determines whether this field is a representative for an anonymous struct or union.
Definition: Decl.cpp:4581
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Definition: Decl.h:3149
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:4000
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5107
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition: Type.h:5387
QualType getExceptionType(unsigned i) const
Return the ith exception type, where 0 <= i < getNumExceptions().
Definition: Type.h:5438
unsigned getNumExceptions() const
Return the number of types in the exception specification.
Definition: Type.h:5430
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Definition: Type.h:5445
Declaration of a template function.
Definition: DeclTemplate.h:958
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:7976
Represents a struct/union/class.
Definition: Decl.h:4162
field_iterator field_end() const
Definition: Decl.h:4379
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:4361
field_iterator field_begin() const
Definition: Decl.cpp:5106
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6077
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:295
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:3578
bool isBeingDefined() const
Return true if this decl is currently being defined.
Definition: Decl.h:3701
bool isUnion() const
Definition: Decl.h:3784
TagKind getTagKind() const
Definition: Decl.h:3773
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:398
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:417
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:7918
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:8805
TypeClass getTypeClass() const
Definition: Type.h:2341
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3427
QualType getUnderlyingType() const
Definition: Decl.h:3482
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:1432
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.