DeclBase.cpp revision 67762a35dca6202d2272db02d0b8740728e3aa8f
1//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
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// This file implements the Decl and DeclContext classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/DeclBase.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/Type.h"
21#include "llvm/ADT/DenseMap.h"
22#include <algorithm>
23#include <functional>
24#include <vector>
25using namespace clang;
26
27//===----------------------------------------------------------------------===//
28//  Statistics
29//===----------------------------------------------------------------------===//
30
31#define DECL(Derived, Base) static int n##Derived##s = 0;
32#include "clang/AST/DeclNodes.def"
33
34static bool StatSwitch = false;
35
36// This keeps track of all decl attributes. Since so few decls have attrs, we
37// keep them in a hash map instead of wasting space in the Decl class.
38typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
39
40static DeclAttrMapTy *DeclAttrs = 0;
41
42const char *Decl::getDeclKindName() const {
43  switch (DeclKind) {
44  default: assert(0 && "Declaration not in DeclNodes.def!");
45#define DECL(Derived, Base) case Derived: return #Derived;
46#include "clang/AST/DeclNodes.def"
47  }
48}
49
50const char *DeclContext::getDeclKindName() const {
51  switch (DeclKind) {
52  default: assert(0 && "Declaration context not in DeclNodes.def!");
53#define DECL(Derived, Base) case Decl::Derived: return #Derived;
54#include "clang/AST/DeclNodes.def"
55  }
56}
57
58bool Decl::CollectingStats(bool Enable) {
59  if (Enable)
60    StatSwitch = true;
61  return StatSwitch;
62}
63
64void Decl::PrintStats() {
65  fprintf(stderr, "*** Decl Stats:\n");
66
67  int totalDecls = 0;
68#define DECL(Derived, Base) totalDecls += n##Derived##s;
69#include "clang/AST/DeclNodes.def"
70  fprintf(stderr, "  %d decls total.\n", totalDecls);
71
72  int totalBytes = 0;
73#define DECL(Derived, Base)                                             \
74  if (n##Derived##s > 0) {                                              \
75    totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl));         \
76    fprintf(stderr, "    %d " #Derived " decls, %d each (%d bytes)\n",  \
77            n##Derived##s, (int)sizeof(Derived##Decl),                  \
78            (int)(n##Derived##s * sizeof(Derived##Decl)));              \
79  }
80#include "clang/AST/DeclNodes.def"
81
82  fprintf(stderr, "Total bytes = %d\n", totalBytes);
83}
84
85void Decl::addDeclKind(Kind k) {
86  switch (k) {
87  default: assert(0 && "Declaration not in DeclNodes.def!");
88#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
89#include "clang/AST/DeclNodes.def"
90  }
91}
92
93//===----------------------------------------------------------------------===//
94// Decl Implementation
95//===----------------------------------------------------------------------===//
96
97void Decl::setDeclContext(DeclContext *DC) {
98  if (isOutOfSemaDC())
99    delete getMultipleDC();
100
101  DeclCtx = reinterpret_cast<uintptr_t>(DC);
102}
103
104void Decl::setLexicalDeclContext(DeclContext *DC) {
105  if (DC == getLexicalDeclContext())
106    return;
107
108  if (isInSemaDC()) {
109    MultipleDC *MDC = new MultipleDC();
110    MDC->SemanticDC = getDeclContext();
111    MDC->LexicalDC = DC;
112    DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
113  } else {
114    getMultipleDC()->LexicalDC = DC;
115  }
116}
117
118// Out-of-line virtual method providing a home for Decl.
119Decl::~Decl() {
120  if (isOutOfSemaDC())
121    delete getMultipleDC();
122
123  if (!HasAttrs)
124    return;
125
126  DeclAttrMapTy::iterator it = DeclAttrs->find(this);
127  assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
128
129  // release attributes.
130  delete it->second;
131  invalidateAttrs();
132}
133
134void Decl::addAttr(Attr *NewAttr) {
135  if (!DeclAttrs)
136    DeclAttrs = new DeclAttrMapTy();
137
138  Attr *&ExistingAttr = (*DeclAttrs)[this];
139
140  NewAttr->setNext(ExistingAttr);
141  ExistingAttr = NewAttr;
142
143  HasAttrs = true;
144}
145
146void Decl::invalidateAttrs() {
147  if (!HasAttrs) return;
148
149  HasAttrs = false;
150  (*DeclAttrs)[this] = 0;
151  DeclAttrs->erase(this);
152
153  if (DeclAttrs->empty()) {
154    delete DeclAttrs;
155    DeclAttrs = 0;
156  }
157}
158
159const Attr *Decl::getAttrs() const {
160  if (!HasAttrs)
161    return 0;
162
163  return (*DeclAttrs)[this];
164}
165
166void Decl::swapAttrs(Decl *RHS) {
167  bool HasLHSAttr = this->HasAttrs;
168  bool HasRHSAttr = RHS->HasAttrs;
169
170  // Usually, neither decl has attrs, nothing to do.
171  if (!HasLHSAttr && !HasRHSAttr) return;
172
173  // If 'this' has no attrs, swap the other way.
174  if (!HasLHSAttr)
175    return RHS->swapAttrs(this);
176
177  // Handle the case when both decls have attrs.
178  if (HasRHSAttr) {
179    std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
180    return;
181  }
182
183  // Otherwise, LHS has an attr and RHS doesn't.
184  (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
185  (*DeclAttrs).erase(this);
186  this->HasAttrs = false;
187  RHS->HasAttrs = true;
188}
189
190
191void Decl::Destroy(ASTContext& C) {
192#if 0
193  // FIXME: Once ownership is fully understood, we can enable this code
194  if (DeclContext *DC = dyn_cast<DeclContext>(this))
195    DC->decls_begin()->Destroy(C);
196
197  // Observe the unrolled recursion.  By setting N->NextDeclInScope = 0x0
198  // within the loop, only the Destroy method for the first Decl
199  // will deallocate all of the Decls in a chain.
200
201  Decl* N = NextDeclInScope;
202
203  while (N) {
204    Decl* Tmp = N->NextDeclInScope;
205    N->NextDeclInScope = 0;
206    N->Destroy(C);
207    N = Tmp;
208  }
209
210  this->~Decl();
211  C.Deallocate((void *)this);
212#endif
213}
214
215Decl *Decl::castFromDeclContext (const DeclContext *D) {
216  Decl::Kind DK = D->getDeclKind();
217  switch(DK) {
218#define DECL_CONTEXT(Name) \
219    case Decl::Name:     \
220      return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
221#define DECL_CONTEXT_BASE(Name)
222#include "clang/AST/DeclNodes.def"
223    default:
224#define DECL_CONTEXT_BASE(Name)                                   \
225      if (DK >= Decl::Name##First && DK <= Decl::Name##Last)    \
226        return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
227#include "clang/AST/DeclNodes.def"
228      assert(false && "a decl that inherits DeclContext isn't handled");
229      return 0;
230  }
231}
232
233DeclContext *Decl::castToDeclContext(const Decl *D) {
234  Decl::Kind DK = D->getKind();
235  switch(DK) {
236#define DECL_CONTEXT(Name) \
237    case Decl::Name:     \
238      return static_cast<Name##Decl*>(const_cast<Decl*>(D));
239#define DECL_CONTEXT_BASE(Name)
240#include "clang/AST/DeclNodes.def"
241    default:
242#define DECL_CONTEXT_BASE(Name)                                   \
243      if (DK >= Decl::Name##First && DK <= Decl::Name##Last)    \
244        return static_cast<Name##Decl*>(const_cast<Decl*>(D));
245#include "clang/AST/DeclNodes.def"
246      assert(false && "a decl that inherits DeclContext isn't handled");
247      return 0;
248  }
249}
250
251//===----------------------------------------------------------------------===//
252// DeclContext Implementation
253//===----------------------------------------------------------------------===//
254
255bool DeclContext::classof(const Decl *D) {
256  switch (D->getKind()) {
257#define DECL_CONTEXT(Name) case Decl::Name:
258#define DECL_CONTEXT_BASE(Name)
259#include "clang/AST/DeclNodes.def"
260      return true;
261    default:
262#define DECL_CONTEXT_BASE(Name)                   \
263      if (D->getKind() >= Decl::Name##First &&  \
264          D->getKind() <= Decl::Name##Last)     \
265        return true;
266#include "clang/AST/DeclNodes.def"
267      return false;
268  }
269}
270
271/// StoredDeclsList - This is an array of decls optimized a common case of only
272/// containing one entry.
273struct StoredDeclsList {
274  /// Data - If the integer is 0, then the pointer is a NamedDecl*.  If the
275  /// integer is 1, then it is a VectorTy;
276  llvm::PointerIntPair<void*, 1, bool> Data;
277
278  /// VectorTy - When in vector form, this is what the Data pointer points to.
279  typedef llvm::SmallVector<NamedDecl*, 4> VectorTy;
280public:
281  StoredDeclsList() {}
282  StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
283    if (isVector())
284      Data.setPointer(new VectorTy(getVector()));
285  }
286
287  ~StoredDeclsList() {
288    // If this is a vector-form, free the vector.
289    if (isVector())
290      delete &getVector();
291  }
292
293  bool isVector() const { return Data.getInt() != 0; }
294  bool isInline() const { return Data.getInt() == 0; }
295  bool isNull() const { return Data.getPointer() == 0; }
296
297  void setOnlyValue(NamedDecl *ND) {
298    assert(isInline() && "Not inline");
299    Data.setPointer(ND);
300  }
301
302  /// getLookupResult - Return an array of all the decls that this list
303  /// represents.
304  DeclContext::lookup_result getLookupResult() {
305    // If we have a single inline unit, return it.
306    if (isInline()) {
307      assert(!isNull() && "Empty list isn't allowed");
308
309      // Data is a raw pointer to a NamedDecl*, return it.
310      void *Ptr = &Data;
311      return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
312    }
313
314    // Otherwise, we have a range result.
315    VectorTy &V = getVector();
316    return DeclContext::lookup_result(&V[0], &V[0]+V.size());
317  }
318
319  /// HandleRedeclaration - If this is a redeclaration of an existing decl,
320  /// replace the old one with D and return true.  Otherwise return false.
321  bool HandleRedeclaration(NamedDecl *D) {
322    // Most decls only have one entry in their list, special case it.
323    if (isInline()) {
324      if (!D->declarationReplaces(getInlineValue()))
325        return false;
326      setOnlyValue(D);
327      return true;
328    }
329
330    // Determine if this declaration is actually a redeclaration.
331    VectorTy &Vec = getVector();
332    VectorTy::iterator RDI
333      = std::find_if(Vec.begin(), Vec.end(),
334                     std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
335                                  D));
336    if (RDI == Vec.end())
337      return false;
338    *RDI = D;
339    return true;
340  }
341
342  /// AddSubsequentDecl - This is called on the second and later decl when it is
343  /// not a redeclaration to merge it into the appropriate place in our list.
344  ///
345  void AddSubsequentDecl(NamedDecl *D) {
346    // If this is the second decl added to the list, convert this to vector
347    // form.
348    if (isInline()) {
349      NamedDecl *OldD = getInlineValue();
350      Data.setInt(1);
351      VectorTy *VT = new VectorTy();
352      VT->push_back(OldD);
353      Data.setPointer(VT);
354    }
355
356    VectorTy &Vec = getVector();
357    if (isa<UsingDirectiveDecl>(D) ||
358        D->getIdentifierNamespace() == Decl::IDNS_Tag)
359      Vec.push_back(D);
360    else if (Vec.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
361      NamedDecl *TagD = Vec.back();
362      Vec.back() = D;
363      Vec.push_back(TagD);
364    } else
365      Vec.push_back(D);
366  }
367
368
369private:
370  VectorTy &getVector() const {
371    assert(isVector() && "Not in vector form");
372    return *static_cast<VectorTy*>(Data.getPointer());
373  }
374
375  NamedDecl *getInlineValue() const {
376    assert(isInline() && "Not in inline form");
377    return (NamedDecl*)Data.getPointer();
378  }
379};
380
381
382
383typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
384
385DeclContext::~DeclContext() {
386  unsigned Size = LookupPtr.getInt();
387  if (Size == LookupIsMap)
388    delete static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
389  else
390    delete [] static_cast<NamedDecl**>(LookupPtr.getPointer());
391}
392
393void DeclContext::DestroyDecls(ASTContext &C) {
394  for (decl_iterator D = decls_begin(); D != decls_end(); )
395    (*D++)->Destroy(C);
396}
397
398bool DeclContext::isTransparentContext() const {
399  if (DeclKind == Decl::Enum)
400    return true; // FIXME: Check for C++0x scoped enums
401  else if (DeclKind == Decl::LinkageSpec)
402    return true;
403  else if (DeclKind == Decl::Record || DeclKind == Decl::CXXRecord)
404    return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
405  else if (DeclKind == Decl::Namespace)
406    return false; // FIXME: Check for C++0x inline namespaces
407
408  return false;
409}
410
411DeclContext *DeclContext::getPrimaryContext() {
412  switch (DeclKind) {
413  case Decl::TranslationUnit:
414  case Decl::LinkageSpec:
415  case Decl::Block:
416    // There is only one DeclContext for these entities.
417    return this;
418
419  case Decl::Namespace:
420    // The original namespace is our primary context.
421    return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
422
423  case Decl::ObjCMethod:
424    return this;
425
426  case Decl::ObjCInterface:
427  case Decl::ObjCProtocol:
428  case Decl::ObjCCategory:
429    // FIXME: Can Objective-C interfaces be forward-declared?
430    return this;
431
432  case Decl::ObjCImplementation:
433  case Decl::ObjCCategoryImpl:
434    return this;
435
436  default:
437    if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
438      // If this is a tag type that has a definition or is currently
439      // being defined, that definition is our primary context.
440      if (TagType *TagT
441            = cast_or_null<TagType>(cast<TagDecl>(this)->TypeForDecl))
442        if (TagT->isBeingDefined() ||
443            (TagT->getDecl() && TagT->getDecl()->isDefinition()))
444          return TagT->getDecl();
445      return this;
446    }
447
448    assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
449          "Unknown DeclContext kind");
450    return this;
451  }
452}
453
454DeclContext *DeclContext::getNextContext() {
455  switch (DeclKind) {
456  case Decl::Namespace:
457    // Return the next namespace
458    return static_cast<NamespaceDecl*>(this)->getNextNamespace();
459
460  default:
461    return 0;
462  }
463}
464
465void DeclContext::addDecl(Decl *D) {
466  assert(D->getLexicalDeclContext() == this &&
467         "Decl inserted into wrong lexical context");
468  assert(!D->NextDeclInScope && D != LastDecl &&
469         "Decl already inserted into a DeclContext");
470
471  if (FirstDecl) {
472    LastDecl->NextDeclInScope = D;
473    LastDecl = D;
474  } else {
475    FirstDecl = LastDecl = D;
476  }
477
478  if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
479    ND->getDeclContext()->makeDeclVisibleInContext(ND);
480}
481
482/// buildLookup - Build the lookup data structure with all of the
483/// declarations in DCtx (and any other contexts linked to it or
484/// transparent contexts nested within it).
485void DeclContext::buildLookup(DeclContext *DCtx) {
486  for (; DCtx; DCtx = DCtx->getNextContext()) {
487    for (decl_iterator D = DCtx->decls_begin(), DEnd = DCtx->decls_end();
488         D != DEnd; ++D) {
489      // Insert this declaration into the lookup structure
490      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
491        makeDeclVisibleInContextImpl(ND);
492
493      // If this declaration is itself a transparent declaration context,
494      // add its members (recursively).
495      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
496        if (InnerCtx->isTransparentContext())
497          buildLookup(InnerCtx->getPrimaryContext());
498    }
499  }
500}
501
502DeclContext::lookup_result
503DeclContext::lookup(DeclarationName Name) {
504  DeclContext *PrimaryContext = getPrimaryContext();
505  if (PrimaryContext != this)
506    return PrimaryContext->lookup(Name);
507
508  /// If there is no lookup data structure, build one now by walking
509  /// all of the linked DeclContexts (in declaration order!) and
510  /// inserting their values.
511  if (LookupPtr.getPointer() == 0)
512    buildLookup(this);
513
514  if (isLookupMap()) {
515    StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
516    StoredDeclsMap::iterator Pos = Map->find(Name);
517    if (Pos == Map->end())
518      return lookup_result(0, 0);
519    return Pos->second.getLookupResult();
520  }
521
522  // We have a small array. Look into it.
523  unsigned Size = LookupPtr.getInt();
524  NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
525  for (unsigned Idx = 0; Idx != Size; ++Idx)
526    if (Array[Idx]->getDeclName() == Name) {
527      unsigned Last = Idx + 1;
528      while (Last != Size && Array[Last]->getDeclName() == Name)
529        ++Last;
530      return lookup_result(&Array[Idx], &Array[Last]);
531    }
532
533  return lookup_result(0, 0);
534}
535
536DeclContext::lookup_const_result
537DeclContext::lookup(DeclarationName Name) const {
538  return const_cast<DeclContext*>(this)->lookup(Name);
539}
540
541const DeclContext *DeclContext::getLookupContext() const {
542  const DeclContext *Ctx = this;
543  // Skip through transparent contexts.
544  while (Ctx->isTransparentContext())
545    Ctx = Ctx->getParent();
546  return Ctx;
547}
548
549void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
550  // FIXME: This feels like a hack. Should DeclarationName support
551  // template-ids, or is there a better way to keep specializations
552  // from being visible?
553  if (isa<ClassTemplateSpecializationDecl>(D))
554    return;
555
556  DeclContext *PrimaryContext = getPrimaryContext();
557  if (PrimaryContext != this) {
558    PrimaryContext->makeDeclVisibleInContext(D);
559    return;
560  }
561
562  // If we already have a lookup data structure, perform the insertion
563  // into it. Otherwise, be lazy and don't build that structure until
564  // someone asks for it.
565  if (LookupPtr.getPointer())
566    makeDeclVisibleInContextImpl(D);
567
568  // If we are a transparent context, insert into our parent context,
569  // too. This operation is recursive.
570  if (isTransparentContext())
571    getParent()->makeDeclVisibleInContext(D);
572}
573
574void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
575  // Skip unnamed declarations.
576  if (!D->getDeclName())
577    return;
578
579  // FIXME: This feels like a hack. Should DeclarationName support
580  // template-ids, or is there a better way to keep specializations
581  // from being visible?
582  if (isa<ClassTemplateSpecializationDecl>(D))
583    return;
584
585  bool MayBeRedeclaration = true;
586
587  if (!isLookupMap()) {
588    unsigned Size = LookupPtr.getInt();
589
590    // The lookup data is stored as an array. Search through the array
591    // to find the insertion location.
592    NamedDecl **Array;
593    if (Size == 0) {
594      Array = new NamedDecl*[LookupIsMap - 1];
595      LookupPtr.setPointer(Array);
596    } else {
597      Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
598    }
599
600    // We always keep declarations of the same name next to each other
601    // in the array, so that it is easy to return multiple results
602    // from lookup().
603    unsigned FirstMatch;
604    for (FirstMatch = 0; FirstMatch != Size; ++FirstMatch)
605      if (Array[FirstMatch]->getDeclName() == D->getDeclName())
606        break;
607
608    unsigned InsertPos = FirstMatch;
609    if (FirstMatch != Size) {
610      // We found another declaration with the same name. First
611      // determine whether this is a redeclaration of an existing
612      // declaration in this scope, in which case we will replace the
613      // existing declaration.
614      unsigned LastMatch = FirstMatch;
615      for (; LastMatch != Size; ++LastMatch) {
616        if (Array[LastMatch]->getDeclName() != D->getDeclName())
617          break;
618
619        if (D->declarationReplaces(Array[LastMatch])) {
620          // D is a redeclaration of an existing element in the
621          // array. Replace that element with D.
622          Array[LastMatch] = D;
623          return;
624        }
625      }
626
627      // [FirstMatch, LastMatch) contains the set of declarations that
628      // have the same name as this declaration. Determine where the
629      // declaration D will be inserted into this range.
630      if (D->getKind() == Decl::UsingDirective ||
631          D->getIdentifierNamespace() == Decl::IDNS_Tag)
632        InsertPos = LastMatch;
633      else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
634        InsertPos = LastMatch - 1;
635      else
636        InsertPos = LastMatch;
637    }
638
639    if (Size < LookupIsMap - 1) {
640      // The new declaration will fit in the array. Insert the new
641      // declaration at the position Match in the array.
642      for (unsigned Idx = Size; Idx > InsertPos; --Idx)
643       Array[Idx] = Array[Idx-1];
644
645      Array[InsertPos] = D;
646      LookupPtr.setInt(Size + 1);
647      return;
648    }
649
650    // We've reached capacity in this array. Create a map and copy in
651    // all of the declarations that were stored in the array.
652    StoredDeclsMap *Map = new StoredDeclsMap(16);
653    LookupPtr.setPointer(Map);
654    LookupPtr.setInt(LookupIsMap);
655    for (unsigned Idx = 0; Idx != LookupIsMap - 1; ++Idx)
656      makeDeclVisibleInContextImpl(Array[Idx]);
657    delete [] Array;
658
659    // Fall through to perform insertion into the map.
660    MayBeRedeclaration = false;
661  }
662
663  // Insert this declaration into the map.
664  StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
665  StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
666  if (DeclNameEntries.isNull()) {
667    DeclNameEntries.setOnlyValue(D);
668    return;
669  }
670
671  // If it is possible that this is a redeclaration, check to see if there is
672  // already a decl for which declarationReplaces returns true.  If there is
673  // one, just replace it and return.
674  if (MayBeRedeclaration && DeclNameEntries.HandleRedeclaration(D))
675    return;
676
677  // Put this declaration into the appropriate slot.
678  DeclNameEntries.AddSubsequentDecl(D);
679}
680
681/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
682/// this context.
683DeclContext::udir_iterator_range DeclContext::getUsingDirectives() const {
684  lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
685  return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
686                             reinterpret_cast<udir_iterator>(Result.second));
687}
688
689