@@ -115,83 +115,91 @@ static bool IsStructurallyEquivalent(const DeclarationName Name1,
115
115
116
116
using ContextVector = llvm::SmallVector<const DeclContext *, 4 >;
117
117
118
- static void GetContexts (ContextVector &Contexts, const NamedDecl *ND) {
118
+ static void GetContextsForEquivalenceCheck (ContextVector &Contexts,
119
+ const NamedDecl *ND) {
119
120
const DeclContext *Ctx = ND->getDeclContext ();
120
121
121
122
// For ObjC methods, look through categories and use the interface as context.
122
123
if (auto *MD = dyn_cast<ObjCMethodDecl>(ND))
123
124
if (auto *ID = MD->getClassInterface ())
124
125
Ctx = ID;
125
126
126
- while (Ctx && Ctx->isFunctionOrMethod ())
127
- Ctx = Ctx->getParent ();
128
-
129
127
// Collect named contexts.
128
+ // Function contexts are ignored, this behavior is enough for ASTImporter.
129
+ // FIXME: Add assertion if different (non equivalent) functions are
130
+ // encountered on the paths (except the first)?
130
131
while (Ctx) {
131
- if (isa<NamedDecl>(Ctx))
132
+ if (isa<NamedDecl>(Ctx) && !isa<FunctionDecl>(Ctx) )
132
133
Contexts.push_back (Ctx);
133
134
Ctx = Ctx->getParent ();
134
135
}
135
136
}
136
137
137
- static bool IsEquivalentContext (StructuralEquivalenceContext &Context, const ContextVector &Contexts1, const ContextVector &Contexts2) {
138
+ static bool IsEquivalentDeclContext (StructuralEquivalenceContext &Context,
139
+ const DeclContext *DC1,
140
+ const DeclContext *DC2) {
141
+ if (const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
142
+ const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
143
+ if (!Spec2)
144
+ return false ;
145
+ if (!IsStructurallyEquivalent (Spec1->getDeclName (), Spec2->getDeclName ()))
146
+ return false ;
147
+ if (!IsStructurallyEquivalent (Context, Spec1->getTemplateArgs (),
148
+ Spec2->getTemplateArgs ()))
149
+ return false ;
150
+ } else if (const auto *ND1 = dyn_cast<NamespaceDecl>(DC1)) {
151
+ const auto *ND2 = dyn_cast<NamespaceDecl>(DC2);
152
+ if (!ND2)
153
+ return false ;
154
+ if (ND1->isAnonymousNamespace () != ND2->isAnonymousNamespace ())
155
+ return false ;
156
+ if (ND1->isInline () != ND2->isInline ())
157
+ return false ;
158
+ if (ND1->isAnonymousNamespace () || ND1->isInlineNamespace ())
159
+ return true ;
160
+ if (!IsStructurallyEquivalent (ND1->getDeclName (), ND2->getDeclName ()))
161
+ return false ;
162
+ } else if (const auto *RD1 = dyn_cast<RecordDecl>(DC1)) {
163
+ const auto *RD2 = dyn_cast<RecordDecl>(DC2);
164
+ if (!RD2)
165
+ return false ;
166
+ if (!IsStructurallyEquivalent (RD1->getDeclName (), RD2->getDeclName ()))
167
+ return false ;
168
+ } else if (const auto *ED1 = dyn_cast<EnumDecl>(DC1)) {
169
+ const auto *ED2 = dyn_cast<EnumDecl>(DC2);
170
+ if (!ED2)
171
+ return false ;
172
+ if (ED1->isScoped () != ED2->isScoped ())
173
+ return false ;
174
+ } else if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
175
+ const auto *ND2 = cast<NamedDecl>(DC2);
176
+ if (!IsStructurallyEquivalent (ND1->getDeclName (), ND2->getDeclName ()))
177
+ return false ;
178
+ } else
179
+ llvm_unreachable (" Context should be NamedDecl." );
180
+
181
+ return true ;
182
+ }
183
+
184
+ // / This function checks for equivalent "context" (scope) of an entity.
185
+ // / This should check if the scope of two names is equivalent.
186
+ // / Functions are excluded from this scope check because there is no use case
187
+ // / when entities from different functions are compared.
188
+ static bool IsEquivalentContext (StructuralEquivalenceContext &Context,
189
+ const NamedDecl *ND1, const NamedDecl *ND2) {
190
+ ContextVector Contexts1, Contexts2;
191
+ GetContextsForEquivalenceCheck (Contexts1, ND1);
192
+ GetContextsForEquivalenceCheck (Contexts2, ND2);
193
+
138
194
auto DC2I = Contexts2.begin ();
139
195
for (const DeclContext *DC1 : Contexts1) {
140
196
if (DC2I == Contexts2.end ())
141
197
return false ;
142
198
const DeclContext *DC2 = *DC2I;
143
199
++DC2I;
144
200
145
- if (const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
146
- const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
147
- if (!Spec2)
148
- return false ;
149
- if (!IsStructurallyEquivalent (Spec1->getDeclName (), Spec2->getDeclName ()))
150
- return false ;
151
- if (!IsStructurallyEquivalent (Context, Spec1->getTemplateArgs (), Spec2->getTemplateArgs ()))
152
- return false ;
153
- } else if (const auto *ND1 = dyn_cast<NamespaceDecl>(DC1)) {
154
- const auto *ND2 = dyn_cast<NamespaceDecl>(DC2);
155
- if (!ND2)
156
- return false ;
157
- if (ND1->isAnonymousNamespace () != ND2->isAnonymousNamespace ())
158
- return false ;
159
- if (ND1->isInline () != ND2->isInline ())
160
- return false ;
161
- if (ND1->isAnonymousNamespace () || ND1->isInlineNamespace ())
162
- continue ;
163
- if (!IsStructurallyEquivalent (ND1->getDeclName (), ND2->getDeclName ()))
164
- return false ;
165
- } else if (const auto *RD1 = dyn_cast<RecordDecl>(DC1)) {
166
- const auto *RD2 = dyn_cast<RecordDecl>(DC2);
167
- if (!RD2)
168
- return false ;
169
- if (!IsStructurallyEquivalent (RD1->getDeclName (), RD2->getDeclName ()))
170
- return false ;
171
- } else if (const auto *FD1 = dyn_cast<FunctionDecl>(DC1)) {
172
- const auto *FD2 = dyn_cast<FunctionDecl>(DC2);
173
- if (!FD2)
174
- return false ;
175
- if (!IsStructurallyEquivalent (Context, const_cast <FunctionDecl *>(FD1), const_cast <FunctionDecl *>(FD2)))
176
- return false ;
177
- /* } else if (const auto *ED = dyn_cast<EnumDecl>(DC)) {
178
- // C++ [dcl.enum]p10: Each enum-name and each unscoped
179
- // enumerator is declared in the scope that immediately contains
180
- // the enum-specifier. Each scoped enumerator is declared in the
181
- // scope of the enumeration.
182
- // For the case of unscoped enumerator, do not include in the qualified
183
- // name any information about its enum enclosing scope, as its visibility
184
- // is global.
185
- if (ED->isScoped())
186
- OS << *ED;
187
- else
188
- continue;*/
189
- } else if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
190
- const auto *ND2 = cast<NamedDecl>(DC2);
191
- if (!IsStructurallyEquivalent (ND1->getDeclName (), ND2->getDeclName ()))
192
- return false ;
193
- } else
194
- llvm_unreachable (" Context should be NamedDecl." );
201
+ if (!IsEquivalentDeclContext (Context, DC1, DC2))
202
+ return false ;
195
203
}
196
204
197
205
if (DC2I != Contexts2.end ())
@@ -1789,10 +1797,7 @@ bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
1789
1797
auto *ND2 = dyn_cast<NamedDecl>(D2);
1790
1798
if (!ND2)
1791
1799
return false ;
1792
- ContextVector Contexts1, Contexts2;
1793
- GetContexts (Contexts1, ND1);
1794
- GetContexts (Contexts2, ND2);
1795
- if (!IsEquivalentContext (*this , Contexts1, Contexts2))
1800
+ if (!IsEquivalentContext (*this , ND1, ND2))
1796
1801
return false ;
1797
1802
}
1798
1803
0 commit comments