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