151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//                     The LLVM Compiler Infrastructure
451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This file is distributed under the University of Illinois Open Source
651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// License. See LICENSE.TXT for details.
751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// These tablegen backends emit Clang AST node tables
1151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
1351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
143cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h"
153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include <cctype>
173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include <map>
1851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <set>
193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include <string>
2051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
2151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// ClangASTNodesEmitter - The top-level class emits .inc files containing
233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen///  declarations of Clang statements.
243cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen///
253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass ClangASTNodesEmitter {
273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // A map from a node to each of its derived nodes.
283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  typedef std::multimap<Record*, Record*> ChildMap;
293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  typedef ChildMap::const_iterator ChildIterator;
303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  RecordKeeper &Records;
323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  Record Root;
333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  const std::string &BaseSuffix;
343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // Create a macro-ized version of a name
363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  static std::string macroName(std::string S) {
373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    for (unsigned i = 0; i < S.size(); ++i)
383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      S[i] = std::toupper(S[i]);
393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    return S;
413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // Return the name to be printed in the base field. Normally this is
443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // the record's name plus the base suffix, but if it is the root node and
453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // the suffix is non-empty, it's just the suffix.
463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  std::string baseName(Record &R) {
473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (&R == &Root && !BaseSuffix.empty())
483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      return BaseSuffix;
493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    return R.getName() + BaseSuffix;
513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen                                          Record *Base);
553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen                                const std::string &S)
583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    : Records(R), Root(N, SMLoc(), R), BaseSuffix(S)
593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    {}
603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // run - Output the .inc file contents
623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void run(raw_ostream &OS);
633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
6651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
6751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Statement Node Tables (.inc file) generation.
6851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
6951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
7051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Returns the first and last non-abstract subrecords
7151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Called recursively to ensure that nodes remain contiguous
7251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestd::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
7351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                                           const ChildMap &Tree,
7451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                                           raw_ostream &OS,
7551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                                           Record *Base) {
7651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string BaseName = macroName(Base->getName());
7751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
7851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
7951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
8051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  Record *First = 0, *Last = 0;
8151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // This might be the pseudo-node for Stmt; don't assume it has an Abstract
8251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // bit
8351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
8451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    First = Last = Base;
8551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
8651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (; i != e; ++i) {
8751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = i->second;
8851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool Abstract = R->getValueAsBit("Abstract");
8951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string NodeName = macroName(R->getName());
9051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
9151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#ifndef " << NodeName << "\n";
9251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#  define " << NodeName << "(Type, Base) "
9351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        << BaseName << "(Type, Base)\n";
9451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#endif\n";
9551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
9651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Abstract)
9751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
9851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          << R->getName() << ", " << baseName(*Base) << "))\n";
9951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
10051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << NodeName << "(" << R->getName() << ", "
10151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          << baseName(*Base) << ")\n";
10251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
10351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Tree.find(R) != Tree.end()) {
10451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      const std::pair<Record *, Record *> &Result
10551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        = EmitNode(Tree, OS, R);
10651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (!First && Result.first)
10751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        First = Result.first;
10851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (Result.second)
10951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        Last = Result.second;
11051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
11151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (!Abstract) {
11251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        Last = R;
11351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
11451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (!First)
11551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          First = R;
11651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
11751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
11851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
11951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#undef " << NodeName << "\n\n";
12051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
12151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
12251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (First) {
12351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    assert (Last && "Got a first node but not a last node for a range!");
12451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Base == &Root)
12551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
12651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
12751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << macroName(Root.getName()) << "_RANGE(";
12851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << Base->getName() << ", " << First->getName() << ", "
12951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       << Last->getName() << ")\n\n";
13051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
13151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
13251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return std::make_pair(First, Last);
13351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
13451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
13551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid ClangASTNodesEmitter::run(raw_ostream &OS) {
13651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Write the preamble
13751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
13851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#  define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
13951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n";
14051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
14151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
14251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#  define "
14351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne     << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
14451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
14551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
14651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
14751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#  define LAST_"
14851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne     << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
14951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne     << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
15051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
15151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
15251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit statements
15351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> Stmts
15451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    = Records.getAllDerivedDefinitions(Root.getName());
15551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
15651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ChildMap Tree;
15751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
15851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
15951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = Stmts[i];
16051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
16151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getValue("Base"))
16251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
16351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
16451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Tree.insert(std::make_pair(&Root, R));
16551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
16651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
16751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  EmitNode(Tree, OS, &Root);
16851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
16951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef " << macroName(Root.getName()) << "\n";
17051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
17151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
17251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
17351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
17451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
1763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
1773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen                       const std::string &N, const std::string &S) {
1783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClangASTNodesEmitter(RK, N, S).run(OS);
1793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
1803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits and addendum to a .inc file to enumerate the clang declaration
1823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// contexts.
1833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
18451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // FIXME: Find a .td file format to allow for this to be represented better.
18551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
18651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef DECL_CONTEXT\n";
18751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#  define DECL_CONTEXT(DECL)\n";
18851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n";
18951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
19051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef DECL_CONTEXT_BASE\n";
19151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#  define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
19251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n";
19351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
19451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  typedef std::set<Record*> RecordSet;
19551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  typedef std::vector<Record*> RecordVector;
19651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
19751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordVector DeclContextsVector
19851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    = Records.getAllDerivedDefinitions("DeclContext");
19951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
20051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
20151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
20251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
20351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = *i;
20451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
20551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getValue("Base")) {
20651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Record *B = R->getValueAsDef("Base");
20751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (DeclContexts.find(B) != DeclContexts.end()) {
20851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
20951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        DeclContexts.erase(B);
21051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
21151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
21251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
21351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
21451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // To keep identical order, RecordVector may be used
21551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // instead of RecordSet.
21651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (RecordVector::iterator
21751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         i = DeclContextsVector.begin(), e = DeclContextsVector.end();
21851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       i != e; ++i)
21951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (DeclContexts.find(*i) != DeclContexts.end())
22051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
22151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef DECL_CONTEXT\n";
22351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef DECL_CONTEXT_BASE\n";
22451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
2253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
226