clang 19.0.0git
ASTStructuralEquivalence.cpp
Go to the documentation of this file.
1//===- ASTStructuralEquivalence.cpp ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implement StructuralEquivalenceContext class and helper functions
10// for layout matching.
11//
12// The structural equivalence check could have been implemented as a parallel
13// BFS on a pair of graphs. That must have been the original approach at the
14// beginning.
15// Let's consider this simple BFS algorithm from the `s` source:
16// ```
17// void bfs(Graph G, int s)
18// {
19// Queue<Integer> queue = new Queue<Integer>();
20// marked[s] = true; // Mark the source
21// queue.enqueue(s); // and put it on the queue.
22// while (!q.isEmpty()) {
23// int v = queue.dequeue(); // Remove next vertex from the queue.
24// for (int w : G.adj(v))
25// if (!marked[w]) // For every unmarked adjacent vertex,
26// {
27// marked[w] = true;
28// queue.enqueue(w);
29// }
30// }
31// }
32// ```
33// Indeed, it has it's queue, which holds pairs of nodes, one from each graph,
34// this is the `DeclsToCheck` member. `VisitedDecls` plays the role of the
35// marking (`marked`) functionality above, we use it to check whether we've
36// already seen a pair of nodes.
37//
38// We put in the elements into the queue only in the toplevel decl check
39// function:
40// ```
41// static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
42// Decl *D1, Decl *D2);
43// ```
44// The `while` loop where we iterate over the children is implemented in
45// `Finish()`. And `Finish` is called only from the two **member** functions
46// which check the equivalency of two Decls or two Types. ASTImporter (and
47// other clients) call only these functions.
48//
49// The `static` implementation functions are called from `Finish`, these push
50// the children nodes to the queue via `static bool
51// IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1,
52// Decl *D2)`. So far so good, this is almost like the BFS. However, if we
53// let a static implementation function to call `Finish` via another **member**
54// function that means we end up with two nested while loops each of them
55// working on the same queue. This is wrong and nobody can reason about it's
56// doing. Thus, static implementation functions must not call the **member**
57// functions.
58//
59//===----------------------------------------------------------------------===//
60
64#include "clang/AST/Decl.h"
65#include "clang/AST/DeclBase.h"
66#include "clang/AST/DeclCXX.h"
68#include "clang/AST/DeclObjC.h"
71#include "clang/AST/ExprCXX.h"
73#include "clang/AST/ExprObjC.h"
76#include "clang/AST/StmtObjC.h"
81#include "clang/AST/Type.h"
84#include "clang/Basic/LLVM.h"
86#include "llvm/ADT/APInt.h"
87#include "llvm/ADT/APSInt.h"
88#include "llvm/ADT/StringExtras.h"
89#include "llvm/Support/Casting.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 UnaryExprOrTypeTraitExpr *E1,
352 const UnaryExprOrTypeTraitExpr *E2) {
353 if (E1->getKind() != E2->getKind())
354 return false;
355 return IsStructurallyEquivalent(Context, E1->getTypeOfArgument(),
356 E2->getTypeOfArgument());
357 }
358
359 bool IsStmtEquivalent(const UnaryOperator *E1, const UnaryOperator *E2) {
360 return E1->getOpcode() == E2->getOpcode();
361 }
362
363 bool IsStmtEquivalent(const VAArgExpr *E1, const VAArgExpr *E2) {
364 // Semantics only depend on children.
365 return true;
366 }
367
368 bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
369 if (!IsStructurallyEquivalent(Context, E1->getName(), E2->getName()))
370 return false;
371
372 if (static_cast<bool>(E1->getQualifier()) !=
373 static_cast<bool>(E2->getQualifier()))
374 return false;
375 if (E1->getQualifier() &&
377 E2->getQualifier()))
378 return false;
379
380 if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs())
381 return false;
382 const TemplateArgumentLoc *Args1 = E1->getTemplateArgs();
383 const TemplateArgumentLoc *Args2 = E2->getTemplateArgs();
384 for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
385 ++ArgI)
386 if (!IsStructurallyEquivalent(Context, Args1[ArgI], Args2[ArgI]))
387 return false;
388
389 return true;
390 }
391
392 bool IsStmtEquivalent(const CXXBoolLiteralExpr *E1, const CXXBoolLiteralExpr *E2) {
393 return E1->getValue() == E2->getValue();
394 }
395
396 /// End point of the traversal chain.
397 bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
398
399 // Create traversal methods that traverse the class hierarchy and return
400 // the accumulated result of the comparison. Each TraverseStmt overload
401 // calls the TraverseStmt overload of the parent class. For example,
402 // the TraverseStmt overload for 'BinaryOperator' calls the TraverseStmt
403 // overload of 'Expr' which then calls the overload for 'Stmt'.
404#define STMT(CLASS, PARENT) \
405 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
406 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
407 static_cast<const PARENT *>(S2))) \
408 return false; \
409 return IsStmtEquivalent(S1, S2); \
410 }
411#include "clang/AST/StmtNodes.inc"
412
413public:
414 StmtComparer(StructuralEquivalenceContext &C) : Context(C) {}
415
416 /// Determine whether two statements are equivalent. The statements have to
417 /// be of the same kind. The children of the statements and their properties
418 /// are not compared by this function.
419 bool IsEquivalent(const Stmt *S1, const Stmt *S2) {
420 if (S1->getStmtClass() != S2->getStmtClass())
421 return false;
422
423 // Each TraverseStmt walks the class hierarchy from the leaf class to
424 // the root class 'Stmt' (e.g. 'BinaryOperator' -> 'Expr' -> 'Stmt'). Cast
425 // the Stmt we have here to its specific subclass so that we call the
426 // overload that walks the whole class hierarchy from leaf to root (e.g.,
427 // cast to 'BinaryOperator' so that 'Expr' and 'Stmt' is traversed).
428 switch (S1->getStmtClass()) {
430 llvm_unreachable("Can't traverse NoStmtClass");
431#define STMT(CLASS, PARENT) \
432 case Stmt::StmtClass::CLASS##Class: \
433 return TraverseStmt(static_cast<const CLASS *>(S1), \
434 static_cast<const CLASS *>(S2));
435#define ABSTRACT_STMT(S)
436#include "clang/AST/StmtNodes.inc"
437 }
438 llvm_unreachable("Invalid statement kind");
439 }
440};
441} // namespace
442
444 const UnaryOperator *E1,
445 const CXXOperatorCallExpr *E2) {
447 E2->getOperator() &&
448 IsStructurallyEquivalent(Context, E1->getSubExpr(), E2->getArg(0));
449}
450
452 const CXXOperatorCallExpr *E1,
453 const UnaryOperator *E2) {
454 return E1->getOperator() ==
456 IsStructurallyEquivalent(Context, E1->getArg(0), E2->getSubExpr());
457}
458
460 const BinaryOperator *E1,
461 const CXXOperatorCallExpr *E2) {
463 E2->getOperator() &&
464 IsStructurallyEquivalent(Context, E1->getLHS(), E2->getArg(0)) &&
465 IsStructurallyEquivalent(Context, E1->getRHS(), E2->getArg(1));
466}
467
469 const CXXOperatorCallExpr *E1,
470 const BinaryOperator *E2) {
471 return E1->getOperator() ==
473 IsStructurallyEquivalent(Context, E1->getArg(0), E2->getLHS()) &&
474 IsStructurallyEquivalent(Context, E1->getArg(1), E2->getRHS());
475}
476
477/// Determine structural equivalence of two statements.
479 const Stmt *S1, const Stmt *S2) {
480 if (!S1 || !S2)
481 return S1 == S2;
482
483 // Check for statements with similar syntax but different AST.
484 // A UnaryOperator node is more lightweight than a CXXOperatorCallExpr node.
485 // The more heavyweight node is only created if the definition-time name
486 // lookup had any results. The lookup results are stored CXXOperatorCallExpr
487 // only. The lookup results can be different in a "From" and "To" AST even if
488 // the compared structure is otherwise equivalent. For this reason we must
489 // treat a similar unary/binary operator node and CXXOperatorCall node as
490 // equivalent.
491 if (const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
492 if (const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
493 return IsStructurallyEquivalent(Context, E1Unary, E2CXXOperatorCall);
494 if (const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
495 return IsStructurallyEquivalent(Context, E1Binary, E2CXXOperatorCall);
496 }
497 if (const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
498 if (const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
499 return IsStructurallyEquivalent(Context, E1CXXOperatorCall, E2Unary);
500 if (const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
501 return IsStructurallyEquivalent(Context, E1CXXOperatorCall, E2Binary);
502 }
503
504 // Compare the statements itself.
505 StmtComparer Comparer(Context);
506 if (!Comparer.IsEquivalent(S1, S2))
507 return false;
508
509 // Iterate over the children of both statements and also compare them.
510 for (auto Pair : zip_longest(S1->children(), S2->children())) {
511 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
512 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
513 // One of the statements has a different amount of children than the other,
514 // so the statements can't be equivalent.
515 if (!Child1 || !Child2)
516 return false;
517 if (!IsStructurallyEquivalent(Context, *Child1, *Child2))
518 return false;
519 }
520 return true;
521}
522
523/// Determine whether two identifiers are equivalent.
525 const IdentifierInfo *Name2) {
526 if (!Name1 || !Name2)
527 return Name1 == Name2;
528
529 return Name1->getName() == Name2->getName();
530}
531
532/// Determine whether two nested-name-specifiers are equivalent.
535 NestedNameSpecifier *NNS2) {
536 if (NNS1->getKind() != NNS2->getKind())
537 return false;
538
539 NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
540 *Prefix2 = NNS2->getPrefix();
541 if ((bool)Prefix1 != (bool)Prefix2)
542 return false;
543
544 if (Prefix1)
545 if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
546 return false;
547
548 switch (NNS1->getKind()) {
551 NNS2->getAsIdentifier());
553 return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
554 NNS2->getAsNamespace());
556 return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(),
557 NNS2->getAsNamespaceAlias());
560 return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
561 QualType(NNS2->getAsType(), 0));
563 return true;
565 return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
566 NNS2->getAsRecordDecl());
567 }
568 return false;
569}
570
572 const TemplateName &N1,
573 const TemplateName &N2) {
574 TemplateDecl *TemplateDeclN1 = N1.getAsTemplateDecl();
575 TemplateDecl *TemplateDeclN2 = N2.getAsTemplateDecl();
576 if (TemplateDeclN1 && TemplateDeclN2) {
577 if (!IsStructurallyEquivalent(Context, TemplateDeclN1, TemplateDeclN2))
578 return false;
579 // If the kind is different we compare only the template decl.
580 if (N1.getKind() != N2.getKind())
581 return true;
582 } else if (TemplateDeclN1 || TemplateDeclN2)
583 return false;
584 else if (N1.getKind() != N2.getKind())
585 return false;
586
587 // Check for special case incompatibilities.
588 switch (N1.getKind()) {
589
592 *OS2 = N2.getAsOverloadedTemplate();
593 OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(),
594 E1 = OS1->end(), E2 = OS2->end();
595 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
596 if (!IsStructurallyEquivalent(Context, *I1, *I2))
597 return false;
598 return I1 == E1 && I2 == E2;
599 }
600
603 *TN2 = N1.getAsAssumedTemplateName();
604 return TN1->getDeclName() == TN2->getDeclName();
605 }
606
609 *DN2 = N2.getAsDependentTemplateName();
610 if (!IsStructurallyEquivalent(Context, DN1->getQualifier(),
611 DN2->getQualifier()))
612 return false;
613 if (DN1->isIdentifier() && DN2->isIdentifier())
615 DN2->getIdentifier());
616 else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator())
617 return DN1->getOperator() == DN2->getOperator();
618 return false;
619 }
620
625 return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
626 P2->getArgumentPack()) &&
628 P2->getAssociatedDecl()) &&
629 P1->getIndex() == P2->getIndex();
630 }
631
636 // It is sufficient to check value of getAsTemplateDecl.
637 break;
638
639 }
640
641 return true;
642}
643
647
648/// Determine whether two template arguments are equivalent.
650 const TemplateArgument &Arg1,
651 const TemplateArgument &Arg2) {
652 if (Arg1.getKind() != Arg2.getKind())
653 return false;
654
655 switch (Arg1.getKind()) {
657 return true;
658
660 return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
661
663 if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
664 Arg2.getIntegralType()))
665 return false;
666
667 return llvm::APSInt::isSameValue(Arg1.getAsIntegral(),
668 Arg2.getAsIntegral());
669
671 return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
672
674 return true; // FIXME: Is this correct?
675
677 return IsStructurallyEquivalent(Context, Arg1.getAsTemplate(),
678 Arg2.getAsTemplate());
679
681 return IsStructurallyEquivalent(Context,
684
686 return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
687 Arg2.getAsExpr());
688
690 return Arg1.structurallyEquals(Arg2);
691
693 return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
694 Arg2.pack_elements());
695 }
696
697 llvm_unreachable("Invalid template argument kind");
698}
699
700/// Determine structural equivalence of two template argument lists.
704 if (Args1.size() != Args2.size())
705 return false;
706 for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
707 if (!IsStructurallyEquivalent(Context, Args1[I], Args2[I]))
708 return false;
709 }
710 return true;
711}
712
713/// Determine whether two template argument locations are equivalent.
715 const TemplateArgumentLoc &Arg1,
716 const TemplateArgumentLoc &Arg2) {
717 return IsStructurallyEquivalent(Context, Arg1.getArgument(),
718 Arg2.getArgument());
719}
720
721/// Determine structural equivalence for the common part of array
722/// types.
724 const ArrayType *Array1,
725 const ArrayType *Array2) {
726 if (!IsStructurallyEquivalent(Context, Array1->getElementType(),
727 Array2->getElementType()))
728 return false;
729 if (Array1->getSizeModifier() != Array2->getSizeModifier())
730 return false;
731 if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
732 return false;
733
734 return true;
735}
736
737/// Determine structural equivalence based on the ExtInfo of functions. This
738/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
739/// conventions bits but must not compare some other bits.
743 // Compatible functions must have compatible calling conventions.
744 if (EI1.getCC() != EI2.getCC())
745 return false;
746
747 // Regparm is part of the calling convention.
748 if (EI1.getHasRegParm() != EI2.getHasRegParm())
749 return false;
750 if (EI1.getRegParm() != EI2.getRegParm())
751 return false;
752
753 if (EI1.getProducesResult() != EI2.getProducesResult())
754 return false;
756 return false;
757 if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
758 return false;
759
760 return true;
761}
762
763/// Check the equivalence of exception specifications.
765 const FunctionProtoType *Proto1,
766 const FunctionProtoType *Proto2) {
767
768 auto Spec1 = Proto1->getExceptionSpecType();
769 auto Spec2 = Proto2->getExceptionSpecType();
770
772 return true;
773
774 if (Spec1 != Spec2)
775 return false;
776 if (Spec1 == EST_Dynamic) {
777 if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
778 return false;
779 for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
780 if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
781 Proto2->getExceptionType(I)))
782 return false;
783 }
784 } else if (isComputedNoexcept(Spec1)) {
785 if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
786 Proto2->getNoexceptExpr()))
787 return false;
788 }
789
790 return true;
791}
792
793/// Determine structural equivalence of two types.
795 QualType T1, QualType T2) {
796 if (T1.isNull() || T2.isNull())
797 return T1.isNull() && T2.isNull();
798
799 QualType OrigT1 = T1;
800 QualType OrigT2 = T2;
801
802 if (!Context.StrictTypeSpelling) {
803 // We aren't being strict about token-to-token equivalence of types,
804 // so map down to the canonical type.
805 T1 = Context.FromCtx.getCanonicalType(T1);
806 T2 = Context.ToCtx.getCanonicalType(T2);
807 }
808
809 if (T1.getQualifiers() != T2.getQualifiers())
810 return false;
811
812 Type::TypeClass TC = T1->getTypeClass();
813
814 if (T1->getTypeClass() != T2->getTypeClass()) {
815 // Compare function types with prototypes vs. without prototypes as if
816 // both did not have prototypes.
817 if (T1->getTypeClass() == Type::FunctionProto &&
818 T2->getTypeClass() == Type::FunctionNoProto)
819 TC = Type::FunctionNoProto;
820 else if (T1->getTypeClass() == Type::FunctionNoProto &&
821 T2->getTypeClass() == Type::FunctionProto)
822 TC = Type::FunctionNoProto;
823 else
824 return false;
825 }
826
827 switch (TC) {
828 case Type::Builtin:
829 // FIXME: Deal with Char_S/Char_U.
830 if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind())
831 return false;
832 break;
833
834 case Type::Complex:
835 if (!IsStructurallyEquivalent(Context,
836 cast<ComplexType>(T1)->getElementType(),
837 cast<ComplexType>(T2)->getElementType()))
838 return false;
839 break;
840
841 case Type::Adjusted:
842 case Type::Decayed:
843 case Type::ArrayParameter:
844 if (!IsStructurallyEquivalent(Context,
845 cast<AdjustedType>(T1)->getOriginalType(),
846 cast<AdjustedType>(T2)->getOriginalType()))
847 return false;
848 break;
849
850 case Type::Pointer:
851 if (!IsStructurallyEquivalent(Context,
852 cast<PointerType>(T1)->getPointeeType(),
853 cast<PointerType>(T2)->getPointeeType()))
854 return false;
855 break;
856
857 case Type::BlockPointer:
858 if (!IsStructurallyEquivalent(Context,
859 cast<BlockPointerType>(T1)->getPointeeType(),
860 cast<BlockPointerType>(T2)->getPointeeType()))
861 return false;
862 break;
863
864 case Type::LValueReference:
865 case Type::RValueReference: {
866 const auto *Ref1 = cast<ReferenceType>(T1);
867 const auto *Ref2 = cast<ReferenceType>(T2);
868 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
869 return false;
870 if (Ref1->isInnerRef() != Ref2->isInnerRef())
871 return false;
872 if (!IsStructurallyEquivalent(Context, Ref1->getPointeeTypeAsWritten(),
873 Ref2->getPointeeTypeAsWritten()))
874 return false;
875 break;
876 }
877
878 case Type::MemberPointer: {
879 const auto *MemPtr1 = cast<MemberPointerType>(T1);
880 const auto *MemPtr2 = cast<MemberPointerType>(T2);
881 if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
882 MemPtr2->getPointeeType()))
883 return false;
884 if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0),
885 QualType(MemPtr2->getClass(), 0)))
886 return false;
887 break;
888 }
889
890 case Type::ConstantArray: {
891 const auto *Array1 = cast<ConstantArrayType>(T1);
892 const auto *Array2 = cast<ConstantArrayType>(T2);
893 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
894 return false;
895
896 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
897 return false;
898 break;
899 }
900
901 case Type::IncompleteArray:
902 if (!IsArrayStructurallyEquivalent(Context, cast<ArrayType>(T1),
903 cast<ArrayType>(T2)))
904 return false;
905 break;
906
907 case Type::VariableArray: {
908 const auto *Array1 = cast<VariableArrayType>(T1);
909 const auto *Array2 = cast<VariableArrayType>(T2);
910 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
911 Array2->getSizeExpr()))
912 return false;
913
914 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
915 return false;
916
917 break;
918 }
919
920 case Type::DependentSizedArray: {
921 const auto *Array1 = cast<DependentSizedArrayType>(T1);
922 const auto *Array2 = cast<DependentSizedArrayType>(T2);
923 if (!IsStructurallyEquivalent(Context, Array1->getSizeExpr(),
924 Array2->getSizeExpr()))
925 return false;
926
927 if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
928 return false;
929
930 break;
931 }
932
933 case Type::DependentAddressSpace: {
934 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
935 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
936 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
937 DepAddressSpace2->getAddrSpaceExpr()))
938 return false;
939 if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(),
940 DepAddressSpace2->getPointeeType()))
941 return false;
942
943 break;
944 }
945
946 case Type::DependentSizedExtVector: {
947 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
948 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
949 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
950 Vec2->getSizeExpr()))
951 return false;
952 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
953 Vec2->getElementType()))
954 return false;
955 break;
956 }
957
958 case Type::DependentVector: {
959 const auto *Vec1 = cast<DependentVectorType>(T1);
960 const auto *Vec2 = cast<DependentVectorType>(T2);
961 if (Vec1->getVectorKind() != Vec2->getVectorKind())
962 return false;
963 if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
964 Vec2->getSizeExpr()))
965 return false;
966 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
967 Vec2->getElementType()))
968 return false;
969 break;
970 }
971
972 case Type::Vector:
973 case Type::ExtVector: {
974 const auto *Vec1 = cast<VectorType>(T1);
975 const auto *Vec2 = cast<VectorType>(T2);
976 if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
977 Vec2->getElementType()))
978 return false;
979 if (Vec1->getNumElements() != Vec2->getNumElements())
980 return false;
981 if (Vec1->getVectorKind() != Vec2->getVectorKind())
982 return false;
983 break;
984 }
985
986 case Type::DependentSizedMatrix: {
987 const DependentSizedMatrixType *Mat1 = cast<DependentSizedMatrixType>(T1);
988 const DependentSizedMatrixType *Mat2 = cast<DependentSizedMatrixType>(T2);
989 // The element types, row and column expressions must be structurally
990 // equivalent.
991 if (!IsStructurallyEquivalent(Context, Mat1->getRowExpr(),
992 Mat2->getRowExpr()) ||
993 !IsStructurallyEquivalent(Context, Mat1->getColumnExpr(),
994 Mat2->getColumnExpr()) ||
996 Mat2->getElementType()))
997 return false;
998 break;
999 }
1000
1001 case Type::ConstantMatrix: {
1002 const ConstantMatrixType *Mat1 = cast<ConstantMatrixType>(T1);
1003 const ConstantMatrixType *Mat2 = cast<ConstantMatrixType>(T2);
1004 // The element types must be structurally equivalent and the number of rows
1005 // and columns must match.
1006 if (!IsStructurallyEquivalent(Context, Mat1->getElementType(),
1007 Mat2->getElementType()) ||
1008 Mat1->getNumRows() != Mat2->getNumRows() ||
1009 Mat1->getNumColumns() != Mat2->getNumColumns())
1010 return false;
1011 break;
1012 }
1013
1014 case Type::FunctionProto: {
1015 const auto *Proto1 = cast<FunctionProtoType>(T1);
1016 const auto *Proto2 = cast<FunctionProtoType>(T2);
1017
1018 if (Proto1->getNumParams() != Proto2->getNumParams())
1019 return false;
1020 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1021 if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I),
1022 Proto2->getParamType(I)))
1023 return false;
1024 }
1025 if (Proto1->isVariadic() != Proto2->isVariadic())
1026 return false;
1027
1028 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1029 return false;
1030
1031 // Check exceptions, this information is lost in canonical type.
1032 const auto *OrigProto1 =
1033 cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
1034 const auto *OrigProto2 =
1035 cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
1036 if (!IsEquivalentExceptionSpec(Context, OrigProto1, OrigProto2))
1037 return false;
1038
1039 // Fall through to check the bits common with FunctionNoProtoType.
1040 [[fallthrough]];
1041 }
1042
1043 case Type::FunctionNoProto: {
1044 const auto *Function1 = cast<FunctionType>(T1);
1045 const auto *Function2 = cast<FunctionType>(T2);
1046 if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
1047 Function2->getReturnType()))
1048 return false;
1049 if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
1050 Function2->getExtInfo()))
1051 return false;
1052 break;
1053 }
1054
1055 case Type::UnresolvedUsing:
1056 if (!IsStructurallyEquivalent(Context,
1057 cast<UnresolvedUsingType>(T1)->getDecl(),
1058 cast<UnresolvedUsingType>(T2)->getDecl()))
1059 return false;
1060 break;
1061
1062 case Type::Attributed:
1063 if (!IsStructurallyEquivalent(Context,
1064 cast<AttributedType>(T1)->getModifiedType(),
1065 cast<AttributedType>(T2)->getModifiedType()))
1066 return false;
1068 Context, cast<AttributedType>(T1)->getEquivalentType(),
1069 cast<AttributedType>(T2)->getEquivalentType()))
1070 return false;
1071 break;
1072
1073 case Type::CountAttributed:
1074 if (!IsStructurallyEquivalent(Context,
1075 cast<CountAttributedType>(T1)->desugar(),
1076 cast<CountAttributedType>(T2)->desugar()))
1077 return false;
1078 break;
1079
1080 case Type::BTFTagAttributed:
1082 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1083 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1084 return false;
1085 break;
1086
1087 case Type::Paren:
1088 if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(),
1089 cast<ParenType>(T2)->getInnerType()))
1090 return false;
1091 break;
1092
1093 case Type::MacroQualified:
1095 Context, cast<MacroQualifiedType>(T1)->getUnderlyingType(),
1096 cast<MacroQualifiedType>(T2)->getUnderlyingType()))
1097 return false;
1098 break;
1099
1100 case Type::Using:
1101 if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
1102 cast<UsingType>(T2)->getFoundDecl()))
1103 return false;
1104 if (!IsStructurallyEquivalent(Context,
1105 cast<UsingType>(T1)->getUnderlyingType(),
1106 cast<UsingType>(T2)->getUnderlyingType()))
1107 return false;
1108 break;
1109
1110 case Type::Typedef:
1111 if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
1112 cast<TypedefType>(T2)->getDecl()) ||
1113 !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
1114 cast<TypedefType>(T2)->desugar()))
1115 return false;
1116 break;
1117
1118 case Type::TypeOfExpr:
1120 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1121 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1122 return false;
1123 break;
1124
1125 case Type::TypeOf:
1126 if (!IsStructurallyEquivalent(Context,
1127 cast<TypeOfType>(T1)->getUnmodifiedType(),
1128 cast<TypeOfType>(T2)->getUnmodifiedType()))
1129 return false;
1130 break;
1131
1132 case Type::UnaryTransform:
1134 Context, cast<UnaryTransformType>(T1)->getUnderlyingType(),
1135 cast<UnaryTransformType>(T2)->getUnderlyingType()))
1136 return false;
1137 break;
1138
1139 case Type::Decltype:
1140 if (!IsStructurallyEquivalent(Context,
1141 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1142 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1143 return false;
1144 break;
1145
1146 case Type::Auto: {
1147 auto *Auto1 = cast<AutoType>(T1);
1148 auto *Auto2 = cast<AutoType>(T2);
1149 if (!IsStructurallyEquivalent(Context, Auto1->getDeducedType(),
1150 Auto2->getDeducedType()))
1151 return false;
1152 if (Auto1->isConstrained() != Auto2->isConstrained())
1153 return false;
1154 if (Auto1->isConstrained()) {
1155 if (Auto1->getTypeConstraintConcept() !=
1156 Auto2->getTypeConstraintConcept())
1157 return false;
1158 if (!IsStructurallyEquivalent(Context,
1159 Auto1->getTypeConstraintArguments(),
1160 Auto2->getTypeConstraintArguments()))
1161 return false;
1162 }
1163 break;
1164 }
1165
1166 case Type::DeducedTemplateSpecialization: {
1167 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1168 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1169 if (!IsStructurallyEquivalent(Context, DT1->getTemplateName(),
1170 DT2->getTemplateName()))
1171 return false;
1172 if (!IsStructurallyEquivalent(Context, DT1->getDeducedType(),
1173 DT2->getDeducedType()))
1174 return false;
1175 break;
1176 }
1177
1178 case Type::Record:
1179 case Type::Enum:
1180 if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(),
1181 cast<TagType>(T2)->getDecl()))
1182 return false;
1183 break;
1184
1185 case Type::TemplateTypeParm: {
1186 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1187 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1188 if (!Context.IgnoreTemplateParmDepth &&
1189 Parm1->getDepth() != Parm2->getDepth())
1190 return false;
1191 if (Parm1->getIndex() != Parm2->getIndex())
1192 return false;
1193 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1194 return false;
1195
1196 // Names of template type parameters are never significant.
1197 break;
1198 }
1199
1200 case Type::SubstTemplateTypeParm: {
1201 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1202 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1203 if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
1204 Subst2->getReplacementType()))
1205 return false;
1206 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1207 Subst2->getAssociatedDecl()))
1208 return false;
1209 if (Subst1->getIndex() != Subst2->getIndex())
1210 return false;
1211 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1212 return false;
1213 break;
1214 }
1215
1216 case Type::SubstTemplateTypeParmPack: {
1217 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1218 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1219 if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
1220 Subst2->getAssociatedDecl()))
1221 return false;
1222 if (Subst1->getIndex() != Subst2->getIndex())
1223 return false;
1224 if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
1225 Subst2->getArgumentPack()))
1226 return false;
1227 break;
1228 }
1229
1230 case Type::TemplateSpecialization: {
1231 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1232 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1233 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
1234 Spec2->getTemplateName()))
1235 return false;
1236 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1237 Spec2->template_arguments()))
1238 return false;
1239 break;
1240 }
1241
1242 case Type::Elaborated: {
1243 const auto *Elab1 = cast<ElaboratedType>(T1);
1244 const auto *Elab2 = cast<ElaboratedType>(T2);
1245 // CHECKME: what if a keyword is ElaboratedTypeKeyword::None or
1246 // ElaboratedTypeKeyword::Typename
1247 // ?
1248 if (Elab1->getKeyword() != Elab2->getKeyword())
1249 return false;
1250 if (!IsStructurallyEquivalent(Context, Elab1->getQualifier(),
1251 Elab2->getQualifier()))
1252 return false;
1253 if (!IsStructurallyEquivalent(Context, Elab1->getNamedType(),
1254 Elab2->getNamedType()))
1255 return false;
1256 break;
1257 }
1258
1259 case Type::InjectedClassName: {
1260 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1261 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1262 if (!IsStructurallyEquivalent(Context,
1263 Inj1->getInjectedSpecializationType(),
1264 Inj2->getInjectedSpecializationType()))
1265 return false;
1266 break;
1267 }
1268
1269 case Type::DependentName: {
1270 const auto *Typename1 = cast<DependentNameType>(T1);
1271 const auto *Typename2 = cast<DependentNameType>(T2);
1272 if (!IsStructurallyEquivalent(Context, Typename1->getQualifier(),
1273 Typename2->getQualifier()))
1274 return false;
1275 if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
1276 Typename2->getIdentifier()))
1277 return false;
1278
1279 break;
1280 }
1281
1282 case Type::DependentTemplateSpecialization: {
1283 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1284 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1285 if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(),
1286 Spec2->getQualifier()))
1287 return false;
1288 if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
1289 Spec2->getIdentifier()))
1290 return false;
1291 if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
1292 Spec2->template_arguments()))
1293 return false;
1294 break;
1295 }
1296
1297 case Type::PackExpansion:
1298 if (!IsStructurallyEquivalent(Context,
1299 cast<PackExpansionType>(T1)->getPattern(),
1300 cast<PackExpansionType>(T2)->getPattern()))
1301 return false;
1302 break;
1303
1304 case Type::PackIndexing:
1305 if (!IsStructurallyEquivalent(Context,
1306 cast<PackIndexingType>(T1)->getPattern(),
1307 cast<PackIndexingType>(T2)->getPattern()))
1308 if (!IsStructurallyEquivalent(Context,
1309 cast<PackIndexingType>(T1)->getIndexExpr(),
1310 cast<PackIndexingType>(T2)->getIndexExpr()))
1311 return false;
1312 break;
1313
1314 case Type::ObjCInterface: {
1315 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1316 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1317 if (!IsStructurallyEquivalent(Context, Iface1->getDecl(),
1318 Iface2->getDecl()))
1319 return false;
1320 break;
1321 }
1322
1323 case Type::ObjCTypeParam: {
1324 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1325 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1326 if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), Obj2->getDecl()))
1327 return false;
1328
1329 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1330 return false;
1331 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1332 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1333 Obj2->getProtocol(I)))
1334 return false;
1335 }
1336 break;
1337 }
1338
1339 case Type::ObjCObject: {
1340 const auto *Obj1 = cast<ObjCObjectType>(T1);
1341 const auto *Obj2 = cast<ObjCObjectType>(T2);
1342 if (!IsStructurallyEquivalent(Context, Obj1->getBaseType(),
1343 Obj2->getBaseType()))
1344 return false;
1345 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1346 return false;
1347 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1348 if (!IsStructurallyEquivalent(Context, Obj1->getProtocol(I),
1349 Obj2->getProtocol(I)))
1350 return false;
1351 }
1352 break;
1353 }
1354
1355 case Type::ObjCObjectPointer: {
1356 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1357 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1358 if (!IsStructurallyEquivalent(Context, Ptr1->getPointeeType(),
1359 Ptr2->getPointeeType()))
1360 return false;
1361 break;
1362 }
1363
1364 case Type::Atomic:
1365 if (!IsStructurallyEquivalent(Context, cast<AtomicType>(T1)->getValueType(),
1366 cast<AtomicType>(T2)->getValueType()))
1367 return false;
1368 break;
1369
1370 case Type::Pipe:
1371 if (!IsStructurallyEquivalent(Context, cast<PipeType>(T1)->getElementType(),
1372 cast<PipeType>(T2)->getElementType()))
1373 return false;
1374 break;
1375 case Type::BitInt: {
1376 const auto *Int1 = cast<BitIntType>(T1);
1377 const auto *Int2 = cast<BitIntType>(T2);
1378
1379 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1380 Int1->getNumBits() != Int2->getNumBits())
1381 return false;
1382 break;
1383 }
1384 case Type::DependentBitInt: {
1385 const auto *Int1 = cast<DependentBitIntType>(T1);
1386 const auto *Int2 = cast<DependentBitIntType>(T2);
1387
1388 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1389 !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
1390 Int2->getNumBitsExpr()))
1391 return false;
1392 break;
1393 }
1394 } // end switch
1395
1396 return true;
1397}
1398
1400 VarDecl *D1, VarDecl *D2) {
1401 IdentifierInfo *Name1 = D1->getIdentifier();
1402 IdentifierInfo *Name2 = D2->getIdentifier();
1403 if (!::IsStructurallyEquivalent(Name1, Name2))
1404 return false;
1405
1406 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
1407 return false;
1408
1409 // Compare storage class and initializer only if none or both are a
1410 // definition. Like a forward-declaration matches a class definition, variable
1411 // declarations that are not definitions should match with the definitions.
1413 return true;
1414
1415 if (D1->getStorageClass() != D2->getStorageClass())
1416 return false;
1417
1418 return IsStructurallyEquivalent(Context, D1->getInit(), D2->getInit());
1419}
1420
1422 FieldDecl *Field1, FieldDecl *Field2,
1423 QualType Owner2Type) {
1424 const auto *Owner2 = cast<Decl>(Field2->getDeclContext());
1425
1426 // For anonymous structs/unions, match up the anonymous struct/union type
1427 // declarations directly, so that we don't go off searching for anonymous
1428 // types
1429 if (Field1->isAnonymousStructOrUnion() &&
1430 Field2->isAnonymousStructOrUnion()) {
1431 RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
1432 RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
1433 return IsStructurallyEquivalent(Context, D1, D2);
1434 }
1435
1436 // Check for equivalent field names.
1437 IdentifierInfo *Name1 = Field1->getIdentifier();
1438 IdentifierInfo *Name2 = Field2->getIdentifier();
1439 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1440 if (Context.Complain) {
1441 Context.Diag2(
1442 Owner2->getLocation(),
1443 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1444 << Owner2Type;
1445 Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
1446 << Field2->getDeclName();
1447 Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
1448 << Field1->getDeclName();
1449 }
1450 return false;
1451 }
1452
1453 if (!IsStructurallyEquivalent(Context, Field1->getType(),
1454 Field2->getType())) {
1455 if (Context.Complain) {
1456 Context.Diag2(
1457 Owner2->getLocation(),
1458 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1459 << Owner2Type;
1460 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1461 << Field2->getDeclName() << Field2->getType();
1462 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1463 << Field1->getDeclName() << Field1->getType();
1464 }
1465 return false;
1466 }
1467
1468 if (Field1->isBitField())
1469 return IsStructurallyEquivalent(Context, Field1->getBitWidth(),
1470 Field2->getBitWidth());
1471
1472 return true;
1473}
1474
1475/// Determine structural equivalence of two fields.
1477 FieldDecl *Field1, FieldDecl *Field2) {
1478 const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
1479 return IsStructurallyEquivalent(Context, Field1, Field2,
1480 Context.ToCtx.getTypeDeclType(Owner2));
1481}
1482
1483/// Determine structural equivalence of two methods.
1485 CXXMethodDecl *Method1,
1486 CXXMethodDecl *Method2) {
1487 bool PropertiesEqual =
1488 Method1->getDeclKind() == Method2->getDeclKind() &&
1489 Method1->getRefQualifier() == Method2->getRefQualifier() &&
1490 Method1->getAccess() == Method2->getAccess() &&
1491 Method1->getOverloadedOperator() == Method2->getOverloadedOperator() &&
1492 Method1->isStatic() == Method2->isStatic() &&
1493 Method1->isImplicitObjectMemberFunction() ==
1494 Method2->isImplicitObjectMemberFunction() &&
1495 Method1->isConst() == Method2->isConst() &&
1496 Method1->isVolatile() == Method2->isVolatile() &&
1497 Method1->isVirtual() == Method2->isVirtual() &&
1498 Method1->isPureVirtual() == Method2->isPureVirtual() &&
1499 Method1->isDefaulted() == Method2->isDefaulted() &&
1500 Method1->isDeleted() == Method2->isDeleted();
1501 if (!PropertiesEqual)
1502 return false;
1503 // FIXME: Check for 'final'.
1504
1505 if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1506 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1507 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1508 Constructor2->getExplicitSpecifier()))
1509 return false;
1510 }
1511
1512 if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1513 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1514 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1515 Conversion2->getExplicitSpecifier()))
1516 return false;
1517 if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
1518 Conversion2->getConversionType()))
1519 return false;
1520 }
1521
1522 const IdentifierInfo *Name1 = Method1->getIdentifier();
1523 const IdentifierInfo *Name2 = Method2->getIdentifier();
1524 if (!::IsStructurallyEquivalent(Name1, Name2)) {
1525 return false;
1526 // TODO: Names do not match, add warning like at check for FieldDecl.
1527 }
1528
1529 // Check the prototypes.
1530 if (!::IsStructurallyEquivalent(Context,
1531 Method1->getType(), Method2->getType()))
1532 return false;
1533
1534 return true;
1535}
1536
1537/// Determine structural equivalence of two lambda classes.
1538static bool
1540 CXXRecordDecl *D1, CXXRecordDecl *D2) {
1541 assert(D1->isLambda() && D2->isLambda() &&
1542 "Must be called on lambda classes");
1544 D2->getLambdaCallOperator()))
1545 return false;
1546
1547 return true;
1548}
1549
1550/// Determine if context of a class is equivalent.
1551static bool
1553 RecordDecl *D1, RecordDecl *D2) {
1554 // The context should be completely equal, including anonymous and inline
1555 // namespaces.
1556 // We compare objects as part of full translation units, not subtrees of
1557 // translation units.
1560 while (true) {
1561 // Special case: We allow a struct defined in a function to be equivalent
1562 // with a similar struct defined outside of a function.
1563 if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
1564 (DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
1565 return true;
1566
1567 if (DC1->getDeclKind() != DC2->getDeclKind())
1568 return false;
1569 if (DC1->isTranslationUnit())
1570 break;
1571 if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
1572 return false;
1573 if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1574 const auto *ND2 = cast<NamedDecl>(DC2);
1575 if (!DC1->isInlineNamespace() &&
1576 !IsStructurallyEquivalent(ND1->getIdentifier(), ND2->getIdentifier()))
1577 return false;
1578 }
1579
1580 if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1581 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1582 if (!IsStructurallyEquivalent(Context, D1Spec, D2Spec))
1583 return false;
1584 }
1585
1586 DC1 = DC1->getParent()->getNonTransparentContext();
1587 DC2 = DC2->getParent()->getNonTransparentContext();
1588 }
1589
1590 return true;
1591}
1592
1593static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) {
1594 auto GetName = [](const TagDecl &D) -> const IdentifierInfo * {
1595 if (const IdentifierInfo *Name = D.getIdentifier())
1596 return Name;
1597 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1598 return TypedefName->getIdentifier();
1599 return nullptr;
1600 };
1601 return IsStructurallyEquivalent(GetName(D1), GetName(D2));
1602}
1603
1604/// Determine structural equivalence of two records.
1606 RecordDecl *D1, RecordDecl *D2) {
1607 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1608 return false;
1609 }
1610
1611 if (D1->isUnion() != D2->isUnion()) {
1612 if (Context.Complain) {
1613 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1614 diag::err_odr_tag_type_inconsistent))
1615 << Context.ToCtx.getTypeDeclType(D2);
1616 Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
1617 << D1->getDeclName() << (unsigned)D1->getTagKind();
1618 }
1619 return false;
1620 }
1621
1622 if (!D1->getDeclName() && !D2->getDeclName()) {
1623 // If both anonymous structs/unions are in a record context, make sure
1624 // they occur in the same location in the context records.
1625 if (std::optional<unsigned> Index1 =
1627 if (std::optional<unsigned> Index2 =
1629 D2)) {
1630 if (*Index1 != *Index2)
1631 return false;
1632 }
1633 }
1634 }
1635
1636 // If the records occur in different context (namespace), these should be
1637 // different. This is specially important if the definition of one or both
1638 // records is missing.
1639 if (!IsRecordContextStructurallyEquivalent(Context, D1, D2))
1640 return false;
1641
1642 // If both declarations are class template specializations, we know
1643 // the ODR applies, so check the template and template arguments.
1644 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1645 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1646 if (Spec1 && Spec2) {
1647 // Check that the specialized templates are the same.
1648 if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
1649 Spec2->getSpecializedTemplate()))
1650 return false;
1651
1652 // Check that the template arguments are the same.
1653 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1654 return false;
1655
1656 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1657 if (!IsStructurallyEquivalent(Context, Spec1->getTemplateArgs().get(I),
1658 Spec2->getTemplateArgs().get(I)))
1659 return false;
1660 }
1661 // If one is a class template specialization and the other is not, these
1662 // structures are different.
1663 else if (Spec1 || Spec2)
1664 return false;
1665
1666 // Compare the definitions of these two records. If either or both are
1667 // incomplete (i.e. it is a forward decl), we assume that they are
1668 // equivalent.
1669 D1 = D1->getDefinition();
1670 D2 = D2->getDefinition();
1671 if (!D1 || !D2)
1672 return true;
1673
1674 // If any of the records has external storage and we do a minimal check (or
1675 // AST import) we assume they are equivalent. (If we didn't have this
1676 // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
1677 // another AST import which in turn would call the structural equivalency
1678 // check again and finally we'd have an improper result.)
1679 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1681 return true;
1682
1683 // If one definition is currently being defined, we do not compare for
1684 // equality and we assume that the decls are equal.
1685 if (D1->isBeingDefined() || D2->isBeingDefined())
1686 return true;
1687
1688 if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1689 if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1690 if (D1CXX->hasExternalLexicalStorage() &&
1691 !D1CXX->isCompleteDefinition()) {
1692 D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1693 }
1694
1695 if (D1CXX->isLambda() != D2CXX->isLambda())
1696 return false;
1697 if (D1CXX->isLambda()) {
1698 if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX))
1699 return false;
1700 }
1701
1702 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1703 if (Context.Complain) {
1704 Context.Diag2(D2->getLocation(),
1705 Context.getApplicableDiagnostic(
1706 diag::err_odr_tag_type_inconsistent))
1707 << Context.ToCtx.getTypeDeclType(D2);
1708 Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
1709 << D2CXX->getNumBases();
1710 Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
1711 << D1CXX->getNumBases();
1712 }
1713 return false;
1714 }
1715
1716 // Check the base classes.
1717 for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
1718 BaseEnd1 = D1CXX->bases_end(),
1719 Base2 = D2CXX->bases_begin();
1720 Base1 != BaseEnd1; ++Base1, ++Base2) {
1721 if (!IsStructurallyEquivalent(Context, Base1->getType(),
1722 Base2->getType())) {
1723 if (Context.Complain) {
1724 Context.Diag2(D2->getLocation(),
1725 Context.getApplicableDiagnostic(
1726 diag::err_odr_tag_type_inconsistent))
1727 << Context.ToCtx.getTypeDeclType(D2);
1728 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1729 << Base2->getType() << Base2->getSourceRange();
1730 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1731 << Base1->getType() << Base1->getSourceRange();
1732 }
1733 return false;
1734 }
1735
1736 // Check virtual vs. non-virtual inheritance mismatch.
1737 if (Base1->isVirtual() != Base2->isVirtual()) {
1738 if (Context.Complain) {
1739 Context.Diag2(D2->getLocation(),
1740 Context.getApplicableDiagnostic(
1741 diag::err_odr_tag_type_inconsistent))
1742 << Context.ToCtx.getTypeDeclType(D2);
1743 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1744 << Base2->isVirtual() << Base2->getSourceRange();
1745 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1746 << Base1->isVirtual() << Base1->getSourceRange();
1747 }
1748 return false;
1749 }
1750 }
1751
1752 // Check the friends for consistency.
1753 CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
1754 Friend2End = D2CXX->friend_end();
1755 for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
1756 Friend1End = D1CXX->friend_end();
1757 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1758 if (Friend2 == Friend2End) {
1759 if (Context.Complain) {
1760 Context.Diag2(D2->getLocation(),
1761 Context.getApplicableDiagnostic(
1762 diag::err_odr_tag_type_inconsistent))
1763 << Context.ToCtx.getTypeDeclType(D2CXX);
1764 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1765 Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
1766 }
1767 return false;
1768 }
1769
1770 if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) {
1771 if (Context.Complain) {
1772 Context.Diag2(D2->getLocation(),
1773 Context.getApplicableDiagnostic(
1774 diag::err_odr_tag_type_inconsistent))
1775 << Context.ToCtx.getTypeDeclType(D2CXX);
1776 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1777 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1778 }
1779 return false;
1780 }
1781 }
1782
1783 if (Friend2 != Friend2End) {
1784 if (Context.Complain) {
1785 Context.Diag2(D2->getLocation(),
1786 Context.getApplicableDiagnostic(
1787 diag::err_odr_tag_type_inconsistent))
1788 << Context.ToCtx.getTypeDeclType(D2);
1789 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1790 Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
1791 }
1792 return false;
1793 }
1794 } else if (D1CXX->getNumBases() > 0) {
1795 if (Context.Complain) {
1796 Context.Diag2(D2->getLocation(),
1797 Context.getApplicableDiagnostic(
1798 diag::err_odr_tag_type_inconsistent))
1799 << Context.ToCtx.getTypeDeclType(D2);
1800 const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
1801 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1802 << Base1->getType() << Base1->getSourceRange();
1803 Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
1804 }
1805 return false;
1806 }
1807 }
1808
1809 // Check the fields for consistency.
1810 QualType D2Type = Context.ToCtx.getTypeDeclType(D2);
1812 Field2End = D2->field_end();
1813 for (RecordDecl::field_iterator Field1 = D1->field_begin(),
1814 Field1End = D1->field_end();
1815 Field1 != Field1End; ++Field1, ++Field2) {
1816 if (Field2 == Field2End) {
1817 if (Context.Complain) {
1818 Context.Diag2(D2->getLocation(),
1819 Context.getApplicableDiagnostic(
1820 diag::err_odr_tag_type_inconsistent))
1821 << Context.ToCtx.getTypeDeclType(D2);
1822 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1823 << Field1->getDeclName() << Field1->getType();
1824 Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
1825 }
1826 return false;
1827 }
1828
1829 if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type))
1830 return false;
1831 }
1832
1833 if (Field2 != Field2End) {
1834 if (Context.Complain) {
1835 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1836 diag::err_odr_tag_type_inconsistent))
1837 << Context.ToCtx.getTypeDeclType(D2);
1838 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1839 << Field2->getDeclName() << Field2->getType();
1840 Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
1841 }
1842 return false;
1843 }
1844
1845 return true;
1846}
1847
1849 EnumConstantDecl *D1,
1850 EnumConstantDecl *D2) {
1851 const llvm::APSInt &FromVal = D1->getInitVal();
1852 const llvm::APSInt &ToVal = D2->getInitVal();
1853 if (FromVal.isSigned() != ToVal.isSigned())
1854 return false;
1855 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1856 return false;
1857 if (FromVal != ToVal)
1858 return false;
1859
1861 return false;
1862
1863 // Init expressions are the most expensive check, so do them last.
1864 return IsStructurallyEquivalent(Context, D1->getInitExpr(),
1865 D2->getInitExpr());
1866}
1867
1868/// Determine structural equivalence of two enums.
1870 EnumDecl *D1, EnumDecl *D2) {
1871 if (!NameIsStructurallyEquivalent(*D1, *D2)) {
1872 return false;
1873 }
1874
1875 // Compare the definitions of these two enums. If either or both are
1876 // incomplete (i.e. forward declared), we assume that they are equivalent.
1877 D1 = D1->getDefinition();
1878 D2 = D2->getDefinition();
1879 if (!D1 || !D2)
1880 return true;
1881
1883 EC2End = D2->enumerator_end();
1885 EC1End = D1->enumerator_end();
1886 EC1 != EC1End; ++EC1, ++EC2) {
1887 if (EC2 == EC2End) {
1888 if (Context.Complain) {
1889 Context.Diag2(D2->getLocation(),
1890 Context.getApplicableDiagnostic(
1891 diag::err_odr_tag_type_inconsistent))
1892 << Context.ToCtx.getTypeDeclType(D2);
1893 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1894 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1895 Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
1896 }
1897 return false;
1898 }
1899
1900 llvm::APSInt Val1 = EC1->getInitVal();
1901 llvm::APSInt Val2 = EC2->getInitVal();
1902 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1903 !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
1904 if (Context.Complain) {
1905 Context.Diag2(D2->getLocation(),
1906 Context.getApplicableDiagnostic(
1907 diag::err_odr_tag_type_inconsistent))
1908 << Context.ToCtx.getTypeDeclType(D2);
1909 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1910 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1911 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1912 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1913 }
1914 return false;
1915 }
1916 }
1917
1918 if (EC2 != EC2End) {
1919 if (Context.Complain) {
1920 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1921 diag::err_odr_tag_type_inconsistent))
1922 << Context.ToCtx.getTypeDeclType(D2);
1923 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1924 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1925 Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
1926 }
1927 return false;
1928 }
1929
1930 return true;
1931}
1932
1934 TemplateParameterList *Params1,
1935 TemplateParameterList *Params2) {
1936 if (Params1->size() != Params2->size()) {
1937 if (Context.Complain) {
1938 Context.Diag2(Params2->getTemplateLoc(),
1939 Context.getApplicableDiagnostic(
1940 diag::err_odr_different_num_template_parameters))
1941 << Params1->size() << Params2->size();
1942 Context.Diag1(Params1->getTemplateLoc(),
1943 diag::note_odr_template_parameter_list);
1944 }
1945 return false;
1946 }
1947
1948 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
1949 if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
1950 if (Context.Complain) {
1951 Context.Diag2(Params2->getParam(I)->getLocation(),
1952 Context.getApplicableDiagnostic(
1953 diag::err_odr_different_template_parameter_kind));
1954 Context.Diag1(Params1->getParam(I)->getLocation(),
1955 diag::note_odr_template_parameter_here);
1956 }
1957 return false;
1958 }
1959
1960 if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
1961 Params2->getParam(I)))
1962 return false;
1963 }
1964
1965 return true;
1966}
1967
1971 if (D1->isParameterPack() != D2->isParameterPack()) {
1972 if (Context.Complain) {
1973 Context.Diag2(D2->getLocation(),
1974 Context.getApplicableDiagnostic(
1975 diag::err_odr_parameter_pack_non_pack))
1976 << D2->isParameterPack();
1977 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1978 << D1->isParameterPack();
1979 }
1980 return false;
1981 }
1982
1983 return true;
1984}
1985
1989 if (D1->isParameterPack() != D2->isParameterPack()) {
1990 if (Context.Complain) {
1991 Context.Diag2(D2->getLocation(),
1992 Context.getApplicableDiagnostic(
1993 diag::err_odr_parameter_pack_non_pack))
1994 << D2->isParameterPack();
1995 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
1996 << D1->isParameterPack();
1997 }
1998 return false;
1999 }
2000
2001 // Check types.
2002 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
2003 if (Context.Complain) {
2004 Context.Diag2(D2->getLocation(),
2005 Context.getApplicableDiagnostic(
2006 diag::err_odr_non_type_parameter_type_inconsistent))
2007 << D2->getType() << D1->getType();
2008 Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
2009 << D1->getType();
2010 }
2011 return false;
2012 }
2013
2014 return true;
2015}
2016
2020 if (D1->isParameterPack() != D2->isParameterPack()) {
2021 if (Context.Complain) {
2022 Context.Diag2(D2->getLocation(),
2023 Context.getApplicableDiagnostic(
2024 diag::err_odr_parameter_pack_non_pack))
2025 << D2->isParameterPack();
2026 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2027 << D1->isParameterPack();
2028 }
2029 return false;
2030 }
2031
2032 // Check template parameter lists.
2033 return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
2034 D2->getTemplateParameters());
2035}
2036
2040 return false;
2041 if (!D1->getIdentifier()) // Special name
2042 if (D1->getNameAsString() != D2->getNameAsString())
2043 return false;
2045 D2->getTemplateParameters());
2046}
2047
2050 ClassTemplateDecl *D2) {
2051 // Check template parameters.
2052 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2053 return false;
2054
2055 // Check the templated declaration.
2056 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
2057 D2->getTemplatedDecl());
2058}
2059
2063 // Check template parameters.
2064 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2065 return false;
2066
2067 // Check the templated declaration.
2068 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
2069 D2->getTemplatedDecl()->getType());
2070}
2071
2075 // Check template parameters.
2076 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2077 return false;
2078
2079 // Check the templated declaration.
2080 return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
2081 D2->getTemplatedDecl());
2082}
2083
2085 ConceptDecl *D1,
2086 ConceptDecl *D2) {
2087 // Check template parameters.
2088 if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2))
2089 return false;
2090
2091 // Check the constraint expression.
2092 return IsStructurallyEquivalent(Context, D1->getConstraintExpr(),
2093 D2->getConstraintExpr());
2094}
2095
2097 FriendDecl *D1, FriendDecl *D2) {
2098 if ((D1->getFriendType() && D2->getFriendDecl()) ||
2099 (D1->getFriendDecl() && D2->getFriendType())) {
2100 return false;
2101 }
2102 if (D1->getFriendType() && D2->getFriendType())
2103 return IsStructurallyEquivalent(Context,
2104 D1->getFriendType()->getType(),
2105 D2->getFriendType()->getType());
2106 if (D1->getFriendDecl() && D2->getFriendDecl())
2107 return IsStructurallyEquivalent(Context, D1->getFriendDecl(),
2108 D2->getFriendDecl());
2109 return false;
2110}
2111
2115 return false;
2116
2117 return IsStructurallyEquivalent(Context, D1->getUnderlyingType(),
2118 D2->getUnderlyingType());
2119}
2120
2122 FunctionDecl *D1, FunctionDecl *D2) {
2124 return false;
2125
2126 if (D1->isOverloadedOperator()) {
2127 if (!D2->isOverloadedOperator())
2128 return false;
2130 return false;
2131 }
2132
2133 // FIXME: Consider checking for function attributes as well.
2134 if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType()))
2135 return false;
2136
2137 return true;
2138}
2139
2141 ObjCIvarDecl *D1, ObjCIvarDecl *D2,
2142 QualType Owner2Type) {
2143 if (D1->getAccessControl() != D2->getAccessControl())
2144 return false;
2145
2146 return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1),
2147 cast<FieldDecl>(D2), Owner2Type);
2148}
2149
2151 ObjCIvarDecl *D1, ObjCIvarDecl *D2) {
2152 QualType Owner2Type =
2153 Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface());
2154 return IsStructurallyEquivalent(Context, D1, D2, Owner2Type);
2155}
2156
2158 ObjCMethodDecl *Method1,
2159 ObjCMethodDecl *Method2) {
2160 bool PropertiesEqual =
2161 Method1->isInstanceMethod() == Method2->isInstanceMethod() &&
2162 Method1->isVariadic() == Method2->isVariadic() &&
2163 Method1->isDirectMethod() == Method2->isDirectMethod();
2164 if (!PropertiesEqual)
2165 return false;
2166
2167 // Compare selector slot names.
2168 Selector Selector1 = Method1->getSelector(),
2169 Selector2 = Method2->getSelector();
2170 unsigned NumArgs = Selector1.getNumArgs();
2171 if (NumArgs != Selector2.getNumArgs())
2172 return false;
2173 // Compare all selector slots. For selectors with arguments it means all arg
2174 // slots. And if there are no arguments, compare the first-and-only slot.
2175 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2176 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2178 Selector2.getIdentifierInfoForSlot(I)))
2179 return false;
2180 }
2181
2182 // Compare types.
2183 if (!IsStructurallyEquivalent(Context, Method1->getReturnType(),
2184 Method2->getReturnType()))
2185 return false;
2186 assert(
2187 Method1->param_size() == Method2->param_size() &&
2188 "Same number of arguments should be already enforced in Selector checks");
2190 ParamT1 = Method1->param_type_begin(),
2191 ParamT1End = Method1->param_type_end(),
2192 ParamT2 = Method2->param_type_begin(),
2193 ParamT2End = Method2->param_type_end();
2194 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2195 ++ParamT1, ++ParamT2) {
2196 if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2))
2197 return false;
2198 }
2199
2200 return true;
2201}
2202
2204 ObjCCategoryDecl *D1,
2205 ObjCCategoryDecl *D2) {
2207 return false;
2208
2209 const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(),
2210 *Intf2 = D2->getClassInterface();
2211 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2212 return false;
2213
2214 if (Intf1 &&
2215 !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier()))
2216 return false;
2217
2218 // Compare protocols.
2220 Protocol2End = D2->protocol_end();
2222 Protocol1End = D1->protocol_end();
2223 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2224 if (Protocol2 == Protocol2End)
2225 return false;
2226 if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(),
2227 (*Protocol2)->getIdentifier()))
2228 return false;
2229 }
2230 if (Protocol2 != Protocol2End)
2231 return false;
2232
2233 // Compare ivars.
2234 QualType D2Type =
2235 Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType();
2237 Ivar2End = D2->ivar_end();
2239 Ivar1End = D1->ivar_end();
2240 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2241 if (Ivar2 == Ivar2End)
2242 return false;
2243 if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type))
2244 return false;
2245 }
2246 if (Ivar2 != Ivar2End)
2247 return false;
2248
2249 // Compare methods.
2251 Method2End = D2->meth_end();
2252 for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(),
2253 Method1End = D1->meth_end();
2254 Method1 != Method1End; ++Method1, ++Method2) {
2255 if (Method2 == Method2End)
2256 return false;
2257 if (!IsStructurallyEquivalent(Context, *Method1, *Method2))
2258 return false;
2259 }
2260 if (Method2 != Method2End)
2261 return false;
2262
2263 return true;
2264}
2265
2266/// Determine structural equivalence of two declarations.
2268 Decl *D1, Decl *D2) {
2269 // FIXME: Check for known structural equivalences via a callback of some sort.
2270
2271 D1 = D1->getCanonicalDecl();
2272 D2 = D2->getCanonicalDecl();
2273 std::pair<Decl *, Decl *> P{D1, D2};
2274
2275 // Check whether we already know that these two declarations are not
2276 // structurally equivalent.
2277 if (Context.NonEquivalentDecls.count(P))
2278 return false;
2279
2280 // Check if a check for these declarations is already pending.
2281 // If yes D1 and D2 will be checked later (from DeclsToCheck),
2282 // or these are already checked (and equivalent).
2283 bool Inserted = Context.VisitedDecls.insert(P).second;
2284 if (!Inserted)
2285 return true;
2286
2287 Context.DeclsToCheck.push(P);
2288
2289 return true;
2290}
2291
2293 unsigned DiagID) {
2294 assert(Complain && "Not allowed to complain");
2295 if (LastDiagFromC2)
2297 LastDiagFromC2 = false;
2298 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2299}
2300
2302 unsigned DiagID) {
2303 assert(Complain && "Not allowed to complain");
2304 if (!LastDiagFromC2)
2306 LastDiagFromC2 = true;
2307 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2308}
2309
2310std::optional<unsigned>
2312 ASTContext &Context = Anon->getASTContext();
2313 QualType AnonTy = Context.getRecordType(Anon);
2314
2315 const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
2316 if (!Owner)
2317 return std::nullopt;
2318
2319 unsigned Index = 0;
2320 for (const auto *D : Owner->noload_decls()) {
2321 const auto *F = dyn_cast<FieldDecl>(D);
2322 if (!F)
2323 continue;
2324
2325 if (F->isAnonymousStructOrUnion()) {
2326 if (Context.hasSameType(F->getType(), AnonTy))
2327 break;
2328 ++Index;
2329 continue;
2330 }
2331
2332 // If the field looks like this:
2333 // struct { ... } A;
2334 QualType FieldType = F->getType();
2335 // In case of nested structs.
2336 while (const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2337 FieldType = ElabType->getNamedType();
2338
2339 if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2340 const RecordDecl *RecDecl = RecType->getDecl();
2341 if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
2342 if (Context.hasSameType(FieldType, AnonTy))
2343 break;
2344 ++Index;
2345 continue;
2346 }
2347 }
2348 }
2349
2350 return Index;
2351}
2352
2354 unsigned ErrorDiagnostic) {
2356 return ErrorDiagnostic;
2357
2358 switch (ErrorDiagnostic) {
2359 case diag::err_odr_variable_type_inconsistent:
2360 return diag::warn_odr_variable_type_inconsistent;
2361 case diag::err_odr_variable_multiple_def:
2362 return diag::warn_odr_variable_multiple_def;
2363 case diag::err_odr_function_type_inconsistent:
2364 return diag::warn_odr_function_type_inconsistent;
2365 case diag::err_odr_tag_type_inconsistent:
2366 return diag::warn_odr_tag_type_inconsistent;
2367 case diag::err_odr_field_type_inconsistent:
2368 return diag::warn_odr_field_type_inconsistent;
2369 case diag::err_odr_ivar_type_inconsistent:
2370 return diag::warn_odr_ivar_type_inconsistent;
2371 case diag::err_odr_objc_superclass_inconsistent:
2372 return diag::warn_odr_objc_superclass_inconsistent;
2373 case diag::err_odr_objc_method_result_type_inconsistent:
2374 return diag::warn_odr_objc_method_result_type_inconsistent;
2375 case diag::err_odr_objc_method_num_params_inconsistent:
2376 return diag::warn_odr_objc_method_num_params_inconsistent;
2377 case diag::err_odr_objc_method_param_type_inconsistent:
2378 return diag::warn_odr_objc_method_param_type_inconsistent;
2379 case diag::err_odr_objc_method_variadic_inconsistent:
2380 return diag::warn_odr_objc_method_variadic_inconsistent;
2381 case diag::err_odr_objc_property_type_inconsistent:
2382 return diag::warn_odr_objc_property_type_inconsistent;
2383 case diag::err_odr_objc_property_impl_kind_inconsistent:
2384 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2385 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2386 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2387 case diag::err_odr_different_num_template_parameters:
2388 return diag::warn_odr_different_num_template_parameters;
2389 case diag::err_odr_different_template_parameter_kind:
2390 return diag::warn_odr_different_template_parameter_kind;
2391 case diag::err_odr_parameter_pack_non_pack:
2392 return diag::warn_odr_parameter_pack_non_pack;
2393 case diag::err_odr_non_type_parameter_type_inconsistent:
2394 return diag::warn_odr_non_type_parameter_type_inconsistent;
2395 }
2396 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2397}
2398
2400
2401 // Ensure that the implementation functions (all static functions in this TU)
2402 // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
2403 // because that will wreak havoc the internal state (DeclsToCheck and
2404 // VisitedDecls members) and can cause faulty behaviour.
2405 // In other words: Do not start a graph search from a new node with the
2406 // internal data of another search in progress.
2407 // FIXME: Better encapsulation and separation of internal and public
2408 // functionality.
2409 assert(DeclsToCheck.empty());
2410 assert(VisitedDecls.empty());
2411
2412 if (!::IsStructurallyEquivalent(*this, D1, D2))
2413 return false;
2414
2415 return !Finish();
2416}
2417
2419 assert(DeclsToCheck.empty());
2420 assert(VisitedDecls.empty());
2421 if (!::IsStructurallyEquivalent(*this, T1, T2))
2422 return false;
2423
2424 return !Finish();
2425}
2426
2428 assert(DeclsToCheck.empty());
2429 assert(VisitedDecls.empty());
2430 if (!::IsStructurallyEquivalent(*this, S1, S2))
2431 return false;
2432
2433 return !Finish();
2434}
2435
2436bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2437 // Check for equivalent described template.
2438 TemplateDecl *Template1 = D1->getDescribedTemplate();
2439 TemplateDecl *Template2 = D2->getDescribedTemplate();
2440 if ((Template1 != nullptr) != (Template2 != nullptr))
2441 return false;
2442 if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2))
2443 return false;
2444
2445 // FIXME: Move check for identifier names into this function.
2446
2447 return true;
2448}
2449
2450bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2451 Decl *D1, Decl *D2) {
2452
2453 // Kind mismatch.
2454 if (D1->getKind() != D2->getKind())
2455 return false;
2456
2457 // Cast the Decls to their actual subclass so that the right overload of
2458 // IsStructurallyEquivalent is called.
2459 switch (D1->getKind()) {
2460#define ABSTRACT_DECL(DECL)
2461#define DECL(DERIVED, BASE) \
2462 case Decl::Kind::DERIVED: \
2463 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2464 static_cast<DERIVED##Decl *>(D2));
2465#include "clang/AST/DeclNodes.inc"
2466 }
2467 return true;
2468}
2469
2470bool StructuralEquivalenceContext::Finish() {
2471 while (!DeclsToCheck.empty()) {
2472 // Check the next declaration.
2473 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2474 DeclsToCheck.pop();
2475
2476 Decl *D1 = P.first;
2477 Decl *D2 = P.second;
2478
2479 bool Equivalent =
2480 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2481
2482 if (!Equivalent) {
2483 // Note that these two declarations are not equivalent (and we already
2484 // know about it).
2485 NonEquivalentDecls.insert(P);
2486
2487 return true;
2488 }
2489 }
2490
2491 return false;
2492}
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.
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1109
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.
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.
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:182
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:2574
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2590
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:1590
DiagnosticsEngine & getDiagnostics() const
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
Definition: ASTContext.h:1188
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition: Expr.h:4338
LabelDecl * getLabel() const
Definition: Expr.h:4361
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3514
ArraySizeModifier getSizeModifier() const
Definition: Type.h:3528
Qualifiers getIndexTypeQualifiers() const
Definition: Type.h:3532
QualType getElementType() const
Definition: Type.h:3526
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:6437
AtomicOp getOp() const
Definition: Expr.h:6501
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3840
Expr * getLHS() const
Definition: Expr.h:3889
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2181
Expr * getRHS() const
Definition: Expr.h:3891
Opcode getOpcode() const
Definition: Expr.h:3884
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 static or instance method of a struct/union/class.
Definition: DeclCXX.h:2060
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:2462
bool isVirtual() const
Definition: DeclCXX.h:2115
bool isVolatile() const
Definition: DeclCXX.h:2113
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this method.
Definition: DeclCXX.h:2236
bool isConst() const
Definition: DeclCXX.h:2112
bool isStatic() const
Definition: DeclCXX.cpp:2186
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:186
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:1022
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition: DeclCXX.cpp:1594
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2820
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3011
Decl * getCalleeDecl()
Definition: Expr.h:2984
unsigned getValue() const
Definition: Expr.h:1610
CharacterLiteralKind getKind() const
Definition: Expr.h:1603
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Definition: Expr.h:4558
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:1606
unsigned size() const
Definition: Stmt.h:1651
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents a concrete matrix type with constant number of rows and columns.
Definition: Type.h:4163
unsigned getNumColumns() const
Returns the number of columns in the matrix.
Definition: Type.h:4184
unsigned getNumRows() const
Returns the number of rows in the matrix.
Definition: Type.h:4181
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
Definition: DeclBase.h:2342
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2066
bool isTranslationUnit() const
Definition: DeclBase.h:2142
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Definition: DeclBase.h:2637
bool isInlineNamespace() const
Definition: DeclBase.cpp:1243
bool isFunctionOrMethod() const
Definition: DeclBase.h:2118
Decl::Kind getDeclKind() const
Definition: DeclBase.h:2059
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1345
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1260
ValueDecl * getDecl()
Definition: Expr.h:1328
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:239
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:501
SourceLocation getLocation() const
Definition: DeclBase.h:445
DeclContext * getDeclContext()
Definition: DeclBase.h:454
AccessSpecifier getAccess() const
Definition: DeclBase.h:513
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:968
Kind getKind() const
Definition: DeclBase.h:448
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:3292
NestedNameSpecifier * getQualifier() const
Retrieve the nested-name-specifier that qualifies this declaration.
Definition: ExprCXX.h:3344
DeclarationName getDeclName() const
Retrieve the name that this expression refers to.
Definition: ExprCXX.h:3331
Represents a matrix type where the type and the number of rows and columns is dependent on a template...
Definition: Type.h:4222
Expr * getColumnExpr() const
Definition: Type.h:4235
Expr * getRowExpr() const
Definition: Type.h:4234
Represents a dependent template name that cannot be resolved prior to template instantiation.
Definition: TemplateName.h:488
OverloadedOperatorKind getOperator() const
Return the overloaded operator to which this template name refers.
Definition: TemplateName.h:560
bool isIdentifier() const
Determine whether this template name refers to an identifier.
Definition: TemplateName.h:547
NestedNameSpecifier * getQualifier() const
Return the nested name specifier that qualifies this name.
Definition: TemplateName.h:544
const IdentifierInfo * getIdentifier() const
Returns the identifier to which this template name refers.
Definition: TemplateName.h:550
bool isOverloadedOperator() const
Determine whether this template name refers to an overloaded operator.
Definition: TemplateName.h:557
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1271
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1547
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:896
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3298
llvm::APSInt getInitVal() const
Definition: Decl.h:3318
const Expr * getInitExpr() const
Definition: Decl.h:3316
Represents an enum.
Definition: Decl.h:3868
enumerator_iterator enumerator_begin() const
Definition: Decl.h:4005
EnumDecl * getDefinition() const
Definition: Decl.h:3971
enumerator_iterator enumerator_end() const
Definition: Decl.h:4012
This represents one expression.
Definition: Expr.h:110
QualType getType() const
Definition: Expr.h:142
An expression trait intrinsic.
Definition: ExprCXX.h:2917
ExpressionTrait getTrait() const
Definition: ExprCXX.h:2954
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:3058
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3149
bool isAnonymousStructOrUnion() const
Determines whether this field is a representative for an anonymous struct or union.
Definition: Decl.cpp:4562
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Definition: Decl.h:3162
llvm::APFloat getValue() const
Definition: Expr.h:1647
bool isExact() const
Definition: Expr.h:1680
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:137
TypeSourceInfo * getFriendType() const
If this friend declaration names an (untemplated but possibly dependent) type, return the type; other...
Definition: DeclFriend.h:122
Represents a function declaration or definition.
Definition: Decl.h:1971
bool isDeleted() const
Whether this function has been deleted.
Definition: Decl.h:2503
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2323
bool isDefaulted() const
Whether this function is defaulted.
Definition: Decl.h:2348
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Definition: Decl.h:2843
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition: Decl.cpp:3979
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4652
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition: Type.h:4911
QualType getExceptionType(unsigned i) const
Return the ith exception type, where 0 <= i < getNumExceptions().
Definition: Type.h:4962
unsigned getNumExceptions() const
Return the number of types in the exception specification.
Definition: Type.h:4954
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Definition: Type.h:4969
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:4363
CallingConv getCC() const
Definition: Type.h:4425
bool getNoCfCheck() const
Definition: Type.h:4415
unsigned getRegParm() const
Definition: Type.h:4418
bool getNoCallerSavedRegs() const
Definition: Type.h:4414
bool getHasRegParm() const
Definition: Type.h:4416
bool getProducesResult() const
Definition: Type.h:4412
Represents a C11 generic selection.
Definition: Expr.h:5725
ArrayRef< TypeSourceInfo * > getAssocTypeSourceInfos() const
Definition: Expr.h:6025
GotoStmt - This represents a direct goto.
Definition: Stmt.h:2862
LabelDecl * getLabel() const
Definition: Stmt.h:2875
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:3655
Represents the declaration of a label.
Definition: Decl.h:499
QualType getElementType() const
Returns type of the elements being stored in the matrix.
Definition: Type.h:4141
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3172
DeclAccessPair getFoundDecl() const
Retrieves the declaration found by lookup.
Definition: Expr.h:3259
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
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:292
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.
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2326
ivar_iterator ivar_begin() const
Definition: DeclObjC.h:2441
ivar_iterator ivar_end() const
Definition: DeclObjC.h:2445
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.h:2369
protocol_iterator protocol_end() const
Definition: DeclObjC.h:2408
protocol_iterator protocol_begin() const
Definition: DeclObjC.h:2404
ObjCProtocolList::iterator protocol_iterator
Definition: DeclObjC.h:2397
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:1950
AccessControl getAccessControl() const
Definition: DeclObjC.h:1998
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
Definition: DeclObjC.cpp:1875
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:871
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:2976
NestedNameSpecifier * getQualifier() const
Fetches the nested-name qualifier, if one was given.
Definition: ExprCXX.h:3091
TemplateArgumentLoc const * getTemplateArgs() const
Definition: ExprCXX.h:3129
unsigned getNumTemplateArgs() const
Definition: ExprCXX.h:3135
DeclarationName getName() const
Gets the name looked up.
Definition: ExprCXX.h:3085
A structure for storing the information associated with an overloaded template name.
Definition: TemplateName.h:108
A (possibly-)qualified type.
Definition: Type.h:940
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:1007
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:7395
Represents a struct/union/class.
Definition: Decl.h:4169
field_iterator field_end() const
Definition: Decl.h:4378
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:4360
field_iterator field_begin() const
Definition: Decl.cpp:5071
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5545
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:4727
SourceLocIdentKind getIdentKind() const
Definition: Expr.h:4747
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
Definition: Expr.h:4383
unsigned getTemplateDepth() const
Definition: Expr.h:4412
Stmt - This represents one statement.
Definition: Stmt.h:84
@ NoStmtClass
Definition: Stmt.h:87
child_range children()
Definition: Stmt.cpp:287
StmtClass getStmtClass() const
Definition: Stmt.h:1358
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1773
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
Definition: Expr.h:1858
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Definition: ExprCXX.h:4442
std::optional< unsigned > getPackIndex() const
Definition: ExprCXX.h:4490
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
Definition: ExprCXX.h:4484
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Definition: ExprCXX.h:4488
Represents a reference to a non-type template parameter pack that has been substituted with a non-tem...
Definition: ExprCXX.h:4527
TemplateArgument getArgumentPack() const
Retrieve the template argument pack containing the substituted template arguments.
Definition: ExprCXX.cpp:1730
A structure for storing an already-substituted template template parameter pack.
Definition: TemplateName.h:141
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:156
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3585
bool isBeingDefined() const
Return true if this decl is currently being defined.
Definition: Decl.h:3708
bool isUnion() const
Definition: Decl.h:3791
TagKind getTagKind() const
Definition: Decl.h:3780
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:394
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:413
Represents a C++ template name within the type system.
Definition: TemplateName.h:202
TemplateDecl * getAsTemplateDecl() 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:247
@ OverloadedTemplate
A set of overloaded template declarations.
Definition: TemplateName.h:222
@ Template
A single template declaration.
Definition: TemplateName.h:219
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
Definition: TemplateName.h:234
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
Definition: TemplateName.h:238
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
Definition: TemplateName.h:243
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
Definition: TemplateName.h:230
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
Definition: TemplateName.h:226
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:144
SourceLocation getTemplateLoc() const
Definition: DeclTemplate.h:199
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:7337
A type trait used in the implementation of various C++11 and Library TR1 trait templates.
Definition: ExprCXX.h:2761
ArrayRef< TypeSourceInfo * > getArgs() const
Retrieve the argument types.
Definition: ExprCXX.h:2817
TypeTrait getTrait() const
Determine which type trait this expression uses.
Definition: ExprCXX.h:2798
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8186
TypeClass getTypeClass() const
Definition: Type.h:2300
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3433
QualType getUnderlyingType() const
Definition: Decl.h:3488
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition: Expr.h:2568
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition: Expr.h:2637
UnaryExprOrTypeTrait getKind() const
Definition: Expr.h:2600
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2183
Expr * getSubExpr() const
Definition: Expr.h:2228
Opcode getOpcode() const
Definition: Expr.h:2223
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given unary opcode.
Definition: Expr.cpp:1429
Represents a call to the builtin function __builtin_va_arg.
Definition: Expr.h:4667
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:706
QualType getType() const
Definition: Decl.h:717
Represents a variable declaration or definition.
Definition: Decl.h:918
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition: Decl.cpp:2257
const Expr * getInit() const
Definition: Decl.h:1355
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1155
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)
llvm::DenseSet< std::pair< Decl *, Decl * > > & NonEquivalentDecls
Declaration (from, to) pairs that are known not to be equivalent (which we have already complained ab...
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 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.
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.