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