CheckerContext.h revision 0e89061a399bae32f0eca5b85658ad66a58c504d
16bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
26bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
36bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
46bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
56bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
66bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// License. See LICENSE.TXT for details.
76bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
86bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
96bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
106bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//  This file defines CheckerContext that provides contextual info for
116bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// path-sensitive checkers.
126bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
136bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
146bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
156bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
166bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
176bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
186bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#include "clang/Analysis/Support/SaveAndRestore.h"
196bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
206bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
216bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisnamespace clang {
226bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
236bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisnamespace ento {
246bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
256bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisclass CheckerContext {
266bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNodeSet &Dst;
276bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  StmtNodeBuilder &B;
286bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExprEngine &Eng;
296bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *Pred;
306bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SaveAndRestore<bool> OldSink;
316bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  const void *checkerTag;
326bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SaveAndRestore<ProgramPoint::Kind> OldPointKind;
336bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SaveOr OldHasGen;
346bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  const GRState *ST;
356bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  const Stmt *statement;
366bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  const unsigned size;
376bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidispublic:
386bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  bool *respondsToCallback;
396bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidispublic:
406bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
416bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                 ExprEngine &eng, ExplodedNode *pred,
426bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                 const void *tag, ProgramPoint::Kind K,
436bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                 bool *respondsToCB = 0,
446bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                 const Stmt *stmt = 0, const GRState *st = 0)
456bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    : Dst(dst), B(builder), Eng(eng), Pred(pred),
466bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      OldSink(B.BuildSinks),
476bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      checkerTag(tag),
486bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      OldPointKind(B.PointKind, K),
496bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      OldHasGen(B.hasGeneratedNode),
506bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      ST(st), statement(stmt), size(Dst.size()),
516bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      respondsToCallback(respondsToCB) {}
526bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
536bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ~CheckerContext();
546bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
556bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExprEngine &getEngine() {
566bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng;
576bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
586bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
596bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  AnalysisManager &getAnalysisManager() {
606bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getAnalysisManager();
616bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
626bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
636bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ConstraintManager &getConstraintManager() {
646bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getConstraintManager();
656bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
666bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
676bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  StoreManager &getStoreManager() {
686bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getStoreManager();
696bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
706bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
716bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNodeSet &getNodeSet() { return Dst; }
726bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  StmtNodeBuilder &getNodeBuilder() { return B; }
736bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *&getPredecessor() { return Pred; }
740e89061a399bae32f0eca5b85658ad66a58c504dAnna Zaks  const GRState *getState() { return ST ? ST : Pred->getState(); }
758be5b3aced37e1c7728741c60d47011f11649a58Argyrios Kyrtzidis  const Stmt *getStmt() const { return statement; }
766bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
776bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ASTContext &getASTContext() {
786bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getContext();
796bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
806bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
816bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  BugReporter &getBugReporter() {
826bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getBugReporter();
836bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
846bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
856bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SourceManager &getSourceManager() {
866bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return getBugReporter().getSourceManager();
876bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
886bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
896bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SValBuilder &getSValBuilder() {
906bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getSValBuilder();
916bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
926bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
933f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks  SymbolManager &getSymbolManager() {
943f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks    return getSValBuilder().getSymbolManager();
953f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks  }
963f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks
976bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNode(bool autoTransition = true) {
986bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    assert(statement && "Only transitions with statements currently supported");
996bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    ExplodedNode *N = generateNodeImpl(statement, getState(), false,
1006bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                                       checkerTag);
1016bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (N && autoTransition)
1026bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      Dst.Add(N);
1036bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return N;
1046bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1056bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1066bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
1076bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                             bool autoTransition = true, const void *tag = 0) {
1086bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    assert(state);
1096bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    ExplodedNode *N = generateNodeImpl(stmt, state, false,
1106bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                                       tag ? tag : checkerTag);
1116bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (N && autoTransition)
1126bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      addTransition(N);
1136bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return N;
1146bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1156bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1166bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
1176bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                             bool autoTransition = true) {
1186bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis   assert(statement && "Only transitions with statements currently supported");
1196bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
1206bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (N && autoTransition)
1216bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      addTransition(N);
1226bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return N;
1236bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1246bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1256bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
1266bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                             const void *tag = 0) {
1276bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    assert(statement && "Only transitions with statements currently supported");
1286bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    ExplodedNode *N = generateNodeImpl(statement, state, false,
1296bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                                       tag ? tag : checkerTag);
1306bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (N && autoTransition)
1316bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      addTransition(N);
1326bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return N;
1336bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1346bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1356bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
1366bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return generateNodeImpl(stmt, state ? state : getState(), true,
1376bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                            checkerTag);
1386bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1396bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1406bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateSink(const GRState *state = 0) {
1416bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    assert(statement && "Only transitions with statements currently supported");
1426bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return generateNodeImpl(statement, state ? state : getState(), true,
1436bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                            checkerTag);
1446bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1456bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1466bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  void addTransition(ExplodedNode *node) {
1476bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    Dst.Add(node);
1486bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1496bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1506bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  void addTransition(const GRState *state, const void *tag = 0) {
1516bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    assert(state);
1526bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    // If the 'state' is not new, we need to check if the cached state 'ST'
1536bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    // is new.
1540e89061a399bae32f0eca5b85658ad66a58c504dAnna Zaks    if (state != getState() || (ST && ST != Pred->getState()))
1556bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      // state is new or equals to ST.
1566bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      generateNode(state, true, tag);
1576bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    else
1586bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      Dst.Add(Pred);
1596bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1606bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1616bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  void EmitReport(BugReport *R) {
1626bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    Eng.getBugReporter().EmitReport(R);
1636bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1646bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1656bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  AnalysisContext *getCurrentAnalysisContext() const {
1666bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Pred->getLocationContext()->getAnalysisContext();
1676bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1686bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1696bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisprivate:
1706bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
1716bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                             bool markAsSink, const void *tag) {
1726bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
1736bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (markAsSink && node)
1746bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      node->markAsSink();
1756bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return node;
1766bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1776bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1786bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
1796bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                                 ExplodedNode *pred, bool markAsSink) {
1806bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis   ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
1816bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (markAsSink && node)
1826bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      node->markAsSink();
1836bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return node;
1846bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1856bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis};
1866bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1876bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis} // end GR namespace
1886bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1896bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis} // end clang namespace
1906bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1916bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#endif
192