AnalysisManager.h revision 4fed22cdd8bb7d98127853ebb3f42be66bf2ce59
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//== AnalysisManager.h - Path sensitive analysis data manager ------*- C++ -*-//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file defines the AnalysisManager class that manages the data and policy
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for path sensitive analysis.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef LLVM_CLANG_GR_ANALYSISMANAGER_H
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LLVM_CLANG_GR_ANALYSISMANAGER_H
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Analysis/AnalysisContext.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace clang {
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace idx {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Indexer;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class TranslationUnit;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ento {
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  class CheckerManager;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AnalysisManager : public BugReporterData {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnalysisContextManager AnaCtxMgr;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LocationContextManager LocCtxMgr;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASTContext &Ctx;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Diagnostic &Diags;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const LangOptions &LangInfo;
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  llvm::OwningPtr<PathDiagnosticClient> PD;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Configurable components creators.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StoreManagerCreator CreateStoreMgr;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConstraintManagerCreator CreateConstraintMgr;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckerManager *CheckerMgr;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// \brief Provide function definitions in other translation units. This is
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NULL if we don't have multiple translation units. AnalysisManager does
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// not own the Indexer.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  idx::Indexer *Idxer;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The maximum number of exploded nodes the analyzer will generate.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned MaxNodes;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The maximum number of times the analyzer visit a block.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned MaxVisit;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool VisualizeEGDot;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool VisualizeEGUbi;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool PurgeDead;
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  /// EargerlyAssume - A flag indicating how the engine should handle
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //   expressions such as: 'x = (y != 0)'.  When this flag is true then
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the subexpression 'y != 0' will be eagerly assumed to be true or false,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   thus evaluating it to the integers 0 or 1 respectively.  The upside
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  //   is that this can increase analysis precision until we have a better way
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  //   to lazily evaluate such logic.  The downside is that it eagerly
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   bifurcates paths.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool EagerlyAssume;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TrimGraph;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool InlineCall;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool EagerlyTrimEGraph;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnalysisManager(ASTContext &ctx, Diagnostic &diags,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const LangOptions &lang, PathDiagnosticClient *pd,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  StoreManagerCreator storemgr,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ConstraintManagerCreator constraintmgr,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  CheckerManager *checkerMgr,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  idx::Indexer *idxer,
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  unsigned maxnodes, unsigned maxvisit,
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  bool inlinecall, bool useUnoptimizedCFG,
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  bool addImplicitDtors, bool addInitializers,
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  bool eagerlyTrimEGraph);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~AnalysisManager() { FlushDiagnostics(); }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearContexts() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LocCtxMgr.clear();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AnaCtxMgr.clear();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AnalysisContextManager& getAnalysisContextManager() {
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return AnaCtxMgr;
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  StoreManagerCreator getStoreManagerCreator() {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateStoreMgr;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConstraintManagerCreator getConstraintManagerCreator() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateConstraintMgr;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckerManager *getCheckerManager() const { return CheckerMgr; }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  idx::Indexer *getIndexer() const { return Idxer; }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ASTContext &getASTContext() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Ctx;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual SourceManager &getSourceManager() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return getASTContext().getSourceManager();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Diagnostic &getDiagnostic() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Diags;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const LangOptions &getLangOptions() const {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LangInfo;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PathDiagnosticClient *getPathDiagnosticClient() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PD.get();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FlushDiagnostics() {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (PD.get())
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PD->FlushDiagnostics();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned getMaxNodes() const { return MaxNodes; }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned getMaxVisit() const { return MaxVisit; }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldVisualize() const {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return VisualizeEGDot || VisualizeEGUbi;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldEagerlyTrimExplodedGraph() const { return EagerlyTrimEGraph; }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldTrimGraph() const { return TrimGraph; }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldPurgeDead() const { return PurgeDead; }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldEagerlyAssume() const { return EagerlyAssume; }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shouldInlineCall() const { return InlineCall; }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool hasIndexer() const { return Idxer != 0; }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFG *getCFG(Decl const *D) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AnaCtxMgr.getContext(D)->getCFG();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LiveVariables *getLiveVariables(Decl const *D) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AnaCtxMgr.getContext(D)->getLiveVariables();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParentMap &getParentMap(Decl const *D) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AnaCtxMgr.getContext(D)->getParentMap();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnalysisContext *getAnalysisContext(const Decl *D) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AnaCtxMgr.getContext(D);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AnaCtxMgr.getContext(D, TU);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         LocationContext const *Parent,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const Stmt *S,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const CFGBlock *Blk, unsigned Idx) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the top level stack frame.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const StackFrameContext *getStackFrame(Decl const *D,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         idx::TranslationUnit *TU) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a stack frame with parent.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StackFrameContext const *getStackFrame(const Decl *D,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         LocationContext const *Parent,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const Stmt *S,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const CFGBlock *Blk, unsigned Idx) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Blk,Idx);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end GR namespace
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end clang namespace
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)