blob: a18d8c6f8b7ee66434b498f44ccc0f2684056930 [file] [log] [blame]
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +00001//===- IndexingContext.h - Higher level API functions ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Index_Internal.h"
11#include "CXCursor.h"
12
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +000013#include "clang/AST/DeclObjC.h"
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +000014#include "clang/AST/DeclGroup.h"
Argyrios Kyrtzidisc6b4a502011-11-16 02:34:59 +000015#include "llvm/ADT/DenseSet.h"
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +000016
17namespace clang {
18 class FileEntry;
19 class ObjCPropertyDecl;
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +000020 class ObjCClassDecl;
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +000021
22namespace cxindex {
23 class IndexingContext;
24
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +000025struct DeclInfo : public CXIdxDeclInfo {
26 CXIdxEntityInfo CXEntInfo;
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +000027 enum DInfoKind {
28 Info_Decl,
29
30 Info_ObjCContainer,
31 Info_ObjCInterface,
32 Info_ObjCProtocol,
33 Info_ObjCCategory
34 };
35
36 DInfoKind Kind;
37
38 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
39 : Kind(Info_Decl) {
40 this->isRedeclaration = isRedeclaration;
41 this->isDefinition = isDefinition;
42 this->isContainer = isContainer;
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +000043 attributes = 0;
44 numAttributes = 0;
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +000045 }
46 DeclInfo(DInfoKind K,
47 bool isRedeclaration, bool isDefinition, bool isContainer)
48 : Kind(K) {
49 this->isRedeclaration = isRedeclaration;
50 this->isDefinition = isDefinition;
51 this->isContainer = isContainer;
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +000052 attributes = 0;
53 numAttributes = 0;
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +000054 }
55
56 static bool classof(const DeclInfo *) { return true; }
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +000057};
58
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +000059struct ObjCContainerDeclInfo : public DeclInfo {
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +000060 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +000061
62 ObjCContainerDeclInfo(bool isForwardRef,
63 bool isRedeclaration,
64 bool isImplementation)
65 : DeclInfo(Info_ObjCContainer, isRedeclaration,
66 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
67 init(isForwardRef, isImplementation);
68 }
69 ObjCContainerDeclInfo(DInfoKind K,
70 bool isForwardRef,
71 bool isRedeclaration,
72 bool isImplementation)
73 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
74 /*isContainer=*/!isForwardRef) {
75 init(isForwardRef, isImplementation);
76 }
77
78 static bool classof(const DeclInfo *D) {
79 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
80 }
81 static bool classof(const ObjCContainerDeclInfo *D) { return true; }
82
83private:
84 void init(bool isForwardRef, bool isImplementation) {
85 if (isForwardRef)
86 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
87 else if (isImplementation)
88 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
89 else
90 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
91 }
92};
93
94struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
95 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
96 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
97
98 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
99 : ObjCContainerDeclInfo(Info_ObjCInterface,
100 /*isForwardRef=*/false,
101 /*isRedeclaration=*/D->isInitiallyForwardDecl(),
102 /*isImplementation=*/false) { }
103
104 static bool classof(const DeclInfo *D) {
105 return D->Kind == Info_ObjCInterface;
106 }
107 static bool classof(const ObjCInterfaceDeclInfo *D) { return true; }
108};
109
110struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
111 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
112
113 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
114 : ObjCContainerDeclInfo(Info_ObjCProtocol,
115 /*isForwardRef=*/false,
116 /*isRedeclaration=*/D->isInitiallyForwardDecl(),
117 /*isImplementation=*/false) { }
118
119 static bool classof(const DeclInfo *D) {
120 return D->Kind == Info_ObjCProtocol;
121 }
122 static bool classof(const ObjCProtocolDeclInfo *D) { return true; }
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000123};
124
125struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +0000126 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +0000127
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +0000128 explicit ObjCCategoryDeclInfo(bool isImplementation)
129 : ObjCContainerDeclInfo(Info_ObjCCategory,
130 /*isForwardRef=*/false,
131 /*isRedeclaration=*/isImplementation,
132 /*isImplementation=*/isImplementation) { }
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +0000133
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +0000134 static bool classof(const DeclInfo *D) {
135 return D->Kind == Info_ObjCCategory;
136 }
137 static bool classof(const ObjCCategoryDeclInfo *D) { return true; }
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000138};
139
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000140struct AttrInfo : public CXIdxAttrInfo {
141 const Attr *A;
142
143 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
144 kind = Kind;
145 cursor = C;
146 loc = Loc;
147 this->A = A;
148 }
149
150 static bool classof(const AttrInfo *) { return true; }
151};
152
153struct IBOutletCollectionInfo : public AttrInfo {
154 CXIdxEntityInfo CXClassInfo;
155 CXIdxIBOutletCollectionAttrInfo IBCollInfo;
156
157 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
158 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
159 assert(C.kind == CXCursor_IBOutletCollectionAttr);
160 }
161
162 static bool classof(const AttrInfo *A) {
163 return A->kind == CXIdxAttr_IBOutletCollection;
164 }
165 static bool classof(const IBOutletCollectionInfo *D) { return true; }
166};
167
Argyrios Kyrtzidisc6b4a502011-11-16 02:34:59 +0000168struct RefFileOccurence {
169 const FileEntry *File;
170 const Decl *Dcl;
171
172 RefFileOccurence(const FileEntry *File, const Decl *Dcl)
173 : File(File), Dcl(Dcl) { }
174};
175
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000176class IndexingContext {
177 ASTContext *Ctx;
178 CXClientData ClientData;
179 IndexerCallbacks &CB;
180 unsigned IndexOptions;
181 CXTranslationUnit CXTU;
182
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000183 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000184 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer> ContainerMapTy;
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000185 FileMapTy FileMap;
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000186 ContainerMapTy ContainerMap;
187
Argyrios Kyrtzidisc6b4a502011-11-16 02:34:59 +0000188 llvm::DenseSet<RefFileOccurence> RefFileOccurences;
189
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000190 SmallVector<DeclGroupRef, 8> TUDeclsInObjCContainer;
191
192 llvm::SmallString<256> StrScratch;
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000193 unsigned StrAdapterCount;
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000194
195 class StrAdapter {
196 llvm::SmallString<256> &Scratch;
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000197 IndexingContext &IdxCtx;
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000198
199 public:
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000200 StrAdapter(IndexingContext &indexCtx)
201 : Scratch(indexCtx.StrScratch), IdxCtx(indexCtx) {
202 ++IdxCtx.StrAdapterCount;
203 }
204
205 ~StrAdapter() {
206 --IdxCtx.StrAdapterCount;
207 if (IdxCtx.StrAdapterCount == 0)
208 Scratch.clear();
209 }
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000210
211 const char *toCStr(StringRef Str);
212
213 unsigned getCurSize() const { return Scratch.size(); }
214
215 const char *getCStr(unsigned CharIndex) {
216 Scratch.push_back('\0');
217 return Scratch.data() + CharIndex;
218 }
219
220 SmallVectorImpl<char> &getBuffer() { return Scratch; }
221 };
222
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +0000223 struct ObjCProtocolListInfo {
224 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
225 SmallVector<CXIdxEntityInfo, 4> ProtEntities;
226 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
227
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000228 CXIdxObjCProtocolRefListInfo getListInfo() const {
Argyrios Kyrtzidisc71d5542011-11-14 22:39:19 +0000229 CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
230 (unsigned)Prots.size() };
231 return Info;
232 }
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +0000233
234 ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
235 IndexingContext &IdxCtx,
236 IndexingContext::StrAdapter &SA);
237 };
238
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000239 struct AttrListInfo {
240 SmallVector<AttrInfo, 2> Attrs;
241 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
242 SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
243
244 const CXIdxAttrInfo *const *getAttrs() const {
245 return CXAttrs.data();
246 }
247 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
248
249 AttrListInfo(const Decl *D,
250 IndexingContext &IdxCtx,
251 IndexingContext::StrAdapter &SA);
252};
253
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000254public:
255 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
256 unsigned indexOptions, CXTranslationUnit cxTU)
257 : Ctx(0), ClientData(clientData), CB(indexCallbacks),
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000258 IndexOptions(indexOptions), CXTU(cxTU), StrAdapterCount(0) { }
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000259
260 ASTContext &getASTContext() const { return *Ctx; }
261
262 void setASTContext(ASTContext &ctx);
263
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000264 bool suppressRefs() const {
265 return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
Argyrios Kyrtzidisc6b4a502011-11-16 02:34:59 +0000266 }
267
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000268 bool shouldAbort();
269
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000270 void enteredMainFile(const FileEntry *File);
271
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000272 void ppIncludedFile(SourceLocation hashLoc,
273 StringRef filename, const FileEntry *File,
274 bool isImport, bool isAngled);
275
Argyrios Kyrtzidis6ec43ad2011-11-12 02:16:30 +0000276 void startedTranslationUnit();
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000277
278 void indexDecl(const Decl *D);
279
280 void indexTagDecl(const TagDecl *D);
281
282 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
283 const DeclContext *DC = 0);
284
285 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
286 const DeclContext *DC);
287
288 void indexDeclContext(const DeclContext *DC);
289
290 void indexBody(const Stmt *S, const DeclContext *DC);
291
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000292 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000293
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000294 bool handleFunction(const FunctionDecl *FD);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000295
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000296 bool handleVar(const VarDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000297
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000298 bool handleField(const FieldDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000299
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000300 bool handleEnumerator(const EnumConstantDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000301
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000302 bool handleTagDecl(const TagDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000303
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000304 bool handleTypedef(const TypedefDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000305
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000306 bool handleObjCClass(const ObjCClassDecl *D);
307 bool handleObjCInterface(const ObjCInterfaceDecl *D);
308 bool handleObjCImplementation(const ObjCImplementationDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000309
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000310 bool handleObjCForwardProtocol(const ObjCProtocolDecl *D,
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000311 SourceLocation Loc,
312 bool isRedeclaration);
313
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000314 bool handleObjCProtocol(const ObjCProtocolDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000315
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000316 bool handleObjCCategory(const ObjCCategoryDecl *D);
317 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000318
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000319 bool handleObjCMethod(const ObjCMethodDecl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000320
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000321 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
322 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000323
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000324 bool handleObjCProperty(const ObjCPropertyDecl *D);
325
326 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
327 const NamedDecl *Parent,
328 const DeclContext *DC,
329 const Expr *E = 0,
330 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
331
332 bool handleReference(const NamedDecl *D, SourceLocation Loc,
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000333 const NamedDecl *Parent,
334 const DeclContext *DC,
Argyrios Kyrtzidisaca19be2011-10-18 15:50:50 +0000335 const Expr *E = 0,
336 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000337
338 bool isNotFromSourceFile(SourceLocation Loc) const;
339
Argyrios Kyrtzidis21ee5702011-11-15 06:20:16 +0000340 void indexTopLevelDecl(Decl *D);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000341 void indexTUDeclsInObjCContainer();
342 void indexDeclGroupRef(DeclGroupRef DG);
343
344 void addTUDeclInObjCContainer(DeclGroupRef DG) {
345 TUDeclsInObjCContainer.push_back(DG);
346 }
347
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000348 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000349 unsigned *line, unsigned *column, unsigned *offset);
350
351private:
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000352 bool handleDecl(const NamedDecl *D,
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000353 SourceLocation Loc, CXCursor Cursor,
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000354 DeclInfo &DInfo);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000355
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000356 bool handleObjCContainer(const ObjCContainerDecl *D,
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000357 SourceLocation Loc, CXCursor Cursor,
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000358 ObjCContainerDeclInfo &ContDInfo);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000359
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000360 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
361
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000362 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
363
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000364 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
365
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000366 CXIdxClientContainer getIndexContainer(const NamedDecl *D) const {
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000367 return getIndexContainerForDC(D->getDeclContext());
368 }
369
370 const DeclContext *getScopedContext(const DeclContext *DC) const;
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000371 CXIdxClientContainer getIndexContainerForDC(const DeclContext *DC) const;
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000372
Argyrios Kyrtzidisdd93c592011-11-11 00:23:36 +0000373 CXIdxClientFile getIndexFile(const FileEntry *File);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000374
375 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
376
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000377 void getEntityInfo(const NamedDecl *D,
378 CXIdxEntityInfo &EntityInfo,
379 StrAdapter &SA);
380
Argyrios Kyrtzidisb395c632011-11-18 00:26:51 +0000381 CXCursor getCursor(const Decl *D) {
382 return cxcursor::MakeCXCursor(const_cast<Decl*>(D), CXTU);
Argyrios Kyrtzidis4e7064f2011-10-17 19:48:19 +0000383 }
384
385 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
386};
387
388}} // end clang::cxindex
Argyrios Kyrtzidisc6b4a502011-11-16 02:34:59 +0000389
390namespace llvm {
391 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
392 /// DenseSets.
393 template <>
394 struct DenseMapInfo<clang::cxindex::RefFileOccurence> {
395 static inline clang::cxindex::RefFileOccurence getEmptyKey() {
396 return clang::cxindex::RefFileOccurence(0, 0);
397 }
398
399 static inline clang::cxindex::RefFileOccurence getTombstoneKey() {
400 return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0,
401 (const clang::Decl *)~0);
402 }
403
404 static unsigned getHashValue(clang::cxindex::RefFileOccurence S) {
405 llvm::FoldingSetNodeID ID;
406 ID.AddPointer(S.File);
407 ID.AddPointer(S.Dcl);
408 return ID.ComputeHash();
409 }
410
411 static bool isEqual(clang::cxindex::RefFileOccurence LHS,
412 clang::cxindex::RefFileOccurence RHS) {
413 return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl;
414 }
415 };
416}