652 lines
24 KiB
C++
652 lines
24 KiB
C++
#include "../Utils/leak_detector.h"
|
|
|
|
#include <cstdio>
|
|
#include <map>
|
|
#include <string>
|
|
#include <algorithm>
|
|
|
|
#include "dvm.h"
|
|
#include "verifications.h"
|
|
|
|
#include "../ParallelizationRegions/ParRegions.h"
|
|
#include "../Utils/utils.h"
|
|
#include "../Utils/SgUtils.h"
|
|
#include "../Utils/errors.h"
|
|
|
|
using std::vector;
|
|
using std::map;
|
|
using std::pair;
|
|
using std::string;
|
|
using std::wstring;
|
|
using std::make_pair;
|
|
using std::set;
|
|
|
|
bool EndDoLoopChecker(SgFile *file, vector<Messages> &currMessages)
|
|
{
|
|
int funcNum = file->numberOfFunctions();
|
|
bool checkOK = true;
|
|
|
|
for (int i = 0; i < funcNum; ++i)
|
|
{
|
|
SgStatement *st = file->functions(i);
|
|
SgStatement *lastNode = st->lastNodeOfStmt();
|
|
|
|
while (st != lastNode)
|
|
{
|
|
if (st == NULL)
|
|
{
|
|
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
|
break;
|
|
}
|
|
|
|
if (st->variant() == CONTAINS_STMT)
|
|
break;
|
|
|
|
if (st->variant() == FOR_NODE)
|
|
{
|
|
SgForStmt *currSt = (SgForStmt*)st;
|
|
if (currSt->isEnddoLoop() == 0)
|
|
{
|
|
__spf_print(1, " ERROR: Loop on line %d does not have END DO\n", st->lineNumber());
|
|
currMessages.push_back(Messages(ERROR, st->lineNumber(), R51, L"This loop does not have END DO format", 1018));
|
|
checkOK = false;
|
|
}
|
|
}
|
|
|
|
if (st->variant() == FORALL_NODE || st->variant() == FORALL_STAT ||
|
|
st->variant() == WHERE_BLOCK_STMT || st->variant() == WHERE_NODE)
|
|
{
|
|
__spf_print(1, " ERROR: Loop on line %d does not have END DO\n", st->lineNumber());
|
|
currMessages.push_back(Messages(ERROR, st->lineNumber(), R50, L"This loop does not have END DO format", 1018));
|
|
checkOK = false;
|
|
}
|
|
|
|
if (st->variant() == WHILE_NODE)
|
|
{
|
|
auto last = st->lastNodeOfStmt();
|
|
auto str = string(last->unparse());
|
|
convertToLower(str);
|
|
if (last->variant() != CONTROL_END || str.find("enddo") == string::npos)
|
|
{
|
|
__spf_print(1, " ERROR: Loop on line %d does not have END DO\n", st->lineNumber());
|
|
currMessages.push_back(Messages(ERROR, st->lineNumber(), R50, L"This loop does not have END DO format", 1018));
|
|
checkOK = false;
|
|
}
|
|
}
|
|
|
|
st = st->lexNext();
|
|
}
|
|
}
|
|
return checkOK;
|
|
}
|
|
|
|
bool DvmDirectiveChecker(SgFile *file, map<string, vector<int>> &errors, const int keepDvmDirectives, const int ignoreDvmChecker)
|
|
{
|
|
if (keepDvmDirectives != 0)
|
|
return true;
|
|
|
|
int funcNum = file->numberOfFunctions();
|
|
bool checkOK = true;
|
|
__spf_print(1, " ignoreDvmChecker = %d\n", ignoreDvmChecker);
|
|
|
|
for (int i = 0; i < funcNum; ++i)
|
|
{
|
|
SgStatement *st = file->functions(i);
|
|
SgStatement *lastNode = st->lastNodeOfStmt();
|
|
|
|
for ( ; st != lastNode; st = st->lexNext())
|
|
{
|
|
if (st->variant() == CONTAINS_STMT)
|
|
break;
|
|
|
|
if (isDVM_stat(st) && (st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
|
|
{
|
|
errors[st->fileName()].push_back(st->lineNumber());
|
|
checkOK = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return checkOK;
|
|
}
|
|
|
|
bool EquivalenceChecker(SgFile *file, const string &fileName, const vector<ParallelRegion*> ®ions, map<string, vector<Messages>> &currMessages)
|
|
{
|
|
int funcNum = file->numberOfFunctions();
|
|
bool checkOK = true;
|
|
|
|
for (int i = 0; i < funcNum; ++i)
|
|
{
|
|
SgStatement *st = file->functions(i);
|
|
SgStatement *lastNode = st->lastNodeOfStmt();
|
|
int lastLine = 1;
|
|
|
|
while (st != lastNode)
|
|
{
|
|
lastLine = st->lineNumber();
|
|
if (st == NULL)
|
|
{
|
|
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
|
break;
|
|
}
|
|
|
|
if (st->variant() == EQUI_STAT)
|
|
{
|
|
auto eqList = isSgNestedVarListDeclStmt(st);
|
|
if (eqList == NULL)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
bool needToReport = false;
|
|
bool checkTmp = true;
|
|
//TODO: need to check variables in region
|
|
if (getRegionByLine(regions, st->fileName(), lastLine))
|
|
{
|
|
checkTmp = false;
|
|
needToReport = true;
|
|
}
|
|
else
|
|
needToReport = true;
|
|
|
|
bool onlyVars = true;
|
|
for (int z = 0; z < eqList->numberOfLists(); ++z)
|
|
{
|
|
auto list = eqList->list(z);
|
|
while (list)
|
|
{
|
|
SgSymbol* symb = list->lhs()->symbol();
|
|
checkNull(symb, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
if (isArrayRef(list->lhs()) ||
|
|
symb->type() && symb->type()->variant() == T_ARRAY)
|
|
{
|
|
SgStatement* decl = declaratedInStmt(symb);
|
|
DIST::Array* array = getArrayFromDeclarated(decl, symb->identifier());
|
|
|
|
if (array && !array->IsNotDistribute())
|
|
onlyVars = false;
|
|
}
|
|
list = list->rhs();
|
|
}
|
|
}
|
|
|
|
if (onlyVars)
|
|
{
|
|
needToReport = false;
|
|
checkTmp = true;
|
|
}
|
|
|
|
checkOK &= checkTmp;
|
|
if (needToReport)
|
|
{
|
|
__spf_print(1, "The equivalence operator is not supported yet at line %d of file %s\n", st->lineNumber(), st->fileName());
|
|
currMessages[st->fileName()].push_back(Messages(checkOK ? WARR : ERROR, st->lineNumber(), R70, L"An equivalence operator is not supported yet", 1038));
|
|
}
|
|
}
|
|
|
|
if (st->variant() == PAUSE_NODE)
|
|
{
|
|
checkOK &= false;
|
|
__spf_print(1, "The PAUSE operator is not supported yet at line %d of file %s\n", st->lineNumber(), st->fileName());
|
|
currMessages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), R69, L"An PAUSE operator is deprecated to parallel", 1038));
|
|
}
|
|
st = st->lexNext();
|
|
}
|
|
}
|
|
return checkOK;
|
|
}
|
|
|
|
bool CommonBlockChecker(SgFile *file, const string &fileName, const map<string, CommonBlock*> &commonBlocks, map<string, vector<Messages>> &messages)
|
|
{
|
|
bool checkOK = true;
|
|
|
|
for (auto& block : commonBlocks)
|
|
{
|
|
auto vars = block.second->getVariables();
|
|
|
|
for (int i = 0; i < vars.size(); i++)
|
|
{
|
|
int pos = vars[i]->getPosition();
|
|
varType type = vars[i]->getType();
|
|
|
|
//only this file
|
|
bool needToSkip = true;
|
|
const CommonVariableUse *currUse = NULL;
|
|
for (auto &elem : vars[i]->getAllUse())
|
|
{
|
|
if (elem.getFile() == file)
|
|
{
|
|
needToSkip = false;
|
|
currUse = &elem;
|
|
}
|
|
}
|
|
|
|
if (needToSkip)
|
|
continue;
|
|
|
|
for (int j = i + 1; j < vars.size(); j++)
|
|
{
|
|
bool needToReport = false;
|
|
auto typeMessage = NOTE;
|
|
|
|
if ((vars[j]->getPosition() == pos) &&
|
|
((vars[j]->getType() == ARRAY && type != ARRAY) || (vars[j]->getType() != ARRAY && type == ARRAY)))
|
|
{
|
|
DIST::Array *array = NULL;
|
|
if (vars[j]->getType() == ARRAY)
|
|
array = getArrayFromDeclarated(vars[j]->getDeclarated(), vars[j]->getName());
|
|
else
|
|
array = getArrayFromDeclarated(vars[i]->getDeclarated(), vars[i]->getName());
|
|
|
|
if (array == NULL)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
if (array->IsNotDistribute())
|
|
typeMessage = WARR;
|
|
else
|
|
{
|
|
checkOK = false;
|
|
typeMessage = ERROR;
|
|
}
|
|
needToReport = true;
|
|
}
|
|
else if (vars[j]->getPosition() == pos && vars[j]->getType() != type)
|
|
{
|
|
typeMessage = WARR;
|
|
needToReport = true;
|
|
}
|
|
|
|
if (needToReport)
|
|
{
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"Variables '%s' and '%s' in one storage association (common block '%s') have different types (files - %s:%d and %s:%d)",
|
|
to_wstring(vars[i]->getName()).c_str(), to_wstring(vars[j]->getName()).c_str(), to_wstring(block.first).c_str(),
|
|
to_wstring(vars[i]->getDeclarated()->fileName()).c_str(), vars[i]->getDeclarated()->lineNumber(),
|
|
to_wstring(vars[j]->getDeclarated()->fileName()).c_str(), vars[j]->getDeclarated()->lineNumber());
|
|
|
|
__spf_printToLongBuf(messageR, R71,
|
|
to_wstring(vars[i]->getName()).c_str(), to_wstring(vars[j]->getName()).c_str(), to_wstring(block.first).c_str(),
|
|
to_wstring(vars[i]->getDeclarated()->fileName()).c_str(), vars[i]->getDeclarated()->lineNumber(),
|
|
to_wstring(vars[j]->getDeclarated()->fileName()).c_str(), vars[j]->getDeclarated()->lineNumber());
|
|
|
|
messages[vars[i]->getDeclarated()->fileName()].push_back(Messages(typeMessage, vars[i]->getDeclarated()->lineNumber(), messageR, messageE, 1039));
|
|
messages[vars[j]->getDeclarated()->fileName()].push_back(Messages(typeMessage, vars[j]->getDeclarated()->lineNumber(), messageR, messageE, 1039));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return checkOK;
|
|
}
|
|
|
|
bool FunctionsChecker(SgFile *file, map<string, pair<string, int>> &funcNames, map<string, vector<Messages>> &currMessages)
|
|
{
|
|
int funcNum = file->numberOfFunctions();
|
|
bool checkOK = true;
|
|
|
|
for (int i = 0; i < funcNum; ++i)
|
|
{
|
|
SgStatement *st = file->functions(i);
|
|
SgStatement *lastNode = st->lastNodeOfStmt();
|
|
|
|
if (st->controlParent()->variant() == GLOBAL)
|
|
{
|
|
string funcName = st->symbol()->identifier();
|
|
auto it = funcNames.find(funcName);
|
|
if (it == funcNames.end())
|
|
funcNames[funcName] = make_pair(file->filename(), st->lineNumber());
|
|
else
|
|
{
|
|
__spf_print(1, "the same function name in different places was found: func %s, places %s:%d and %s:%d\n",
|
|
it->first.c_str(), it->second.first.c_str(), it->second.second, file->filename(), st->lineNumber());
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"Function '%s' was declared in more than one place: '%s':%d and '%s':%d",
|
|
to_wstring(funcName).c_str(), to_wstring(it->second.first).c_str(),
|
|
it->second.second, to_wstring(file->filename()).c_str(), st->lineNumber());
|
|
|
|
__spf_printToLongBuf(messageR, R92,
|
|
to_wstring(funcName).c_str(), to_wstring(it->second.first).c_str(),
|
|
it->second.second, to_wstring(file->filename()).c_str(), st->lineNumber());
|
|
|
|
currMessages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1048));
|
|
currMessages[it->second.first].push_back(Messages(ERROR, it->second.second, messageR, messageE, 1048));
|
|
|
|
checkOK = false;
|
|
}
|
|
|
|
if (isIntrinsicFunctionName(funcName.c_str()))
|
|
{
|
|
__spf_print(1, "the same function name in different places was found: func %s, places %s:%d and %s:%d\n",
|
|
funcName.c_str(), file->filename(), st->lineNumber(), "intrinsic", 0);
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"Function '%s' was declared in more than one place: '%s':%d and '%s':%d",
|
|
to_wstring(funcName).c_str(), to_wstring(file->filename()).c_str(), st->lineNumber(), to_wstring("intrinsic").c_str(), 0);
|
|
|
|
__spf_printToLongBuf(messageR, R92,
|
|
to_wstring(funcName).c_str(), to_wstring(file->filename()).c_str(), st->lineNumber(), to_wstring("intrinsic").c_str(), 0);
|
|
|
|
currMessages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1048));
|
|
|
|
checkOK = false;
|
|
}
|
|
}
|
|
}
|
|
return checkOK;
|
|
}
|
|
|
|
void fillFunctionInfo(SgFile* file, map<string, vector<Function>>& funcInfo)
|
|
{
|
|
const int funcNum = file->numberOfFunctions();
|
|
const string fileName = file->filename();
|
|
for (int i = 0; i < funcNum; ++i)
|
|
{
|
|
SgStatement* st = file->functions(i);
|
|
SgStatement* lastNode = st->lastNodeOfStmt();
|
|
|
|
if (st->fileName() != fileName)
|
|
continue;
|
|
|
|
Function newFunc;
|
|
newFunc.name = st->symbol()->identifier();
|
|
newFunc.line = st->lineNumber();
|
|
newFunc.file = file->filename();
|
|
newFunc.point = st;
|
|
if (isSgProgHedrStmt(st) == NULL)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
newFunc.parametersCount = ((SgProgHedrStmt*)st)->numberOfParameters();
|
|
|
|
auto cp = st->controlParent();
|
|
if (cp->variant() == GLOBAL)
|
|
newFunc.type = 1;
|
|
else if (cp->variant() == MODULE_STMT)
|
|
{
|
|
if (string(cp->fileName()) != file->filename())
|
|
continue; // add module functions only once
|
|
newFunc.type = 0;
|
|
newFunc.parentName = cp->symbol()->identifier();
|
|
}
|
|
else
|
|
{
|
|
auto cpcp = cp->controlParent();
|
|
if (cpcp->variant() == GLOBAL)
|
|
{
|
|
newFunc.type = 2;
|
|
newFunc.parentName = cp->symbol()->identifier();
|
|
}
|
|
else
|
|
{
|
|
newFunc.type = 3;
|
|
newFunc.parentName = cp->symbol()->identifier();
|
|
newFunc.globalName = cpcp->symbol()->identifier();
|
|
}
|
|
}
|
|
funcInfo[newFunc.name].push_back(newFunc);
|
|
}
|
|
}
|
|
|
|
//TODO: for the same parameters count
|
|
// add support of optilnal parameters
|
|
static SgSymbol* resolveName(SgFile* file, SgStatement* context, SgExpression* parameters, const vector<Function>& functions, const string& name)
|
|
{
|
|
SgSymbol* corrected = NULL;
|
|
|
|
int parCount = 0;
|
|
while (parameters)
|
|
{
|
|
parCount++;
|
|
parameters = parameters->rhs();
|
|
}
|
|
|
|
auto cp = getFuncStat(context, { MODULE_STMT } );
|
|
auto cpcp = cp->controlParent();
|
|
auto globalP = cpcp->controlParent();
|
|
|
|
const string cpName = cp->symbol()->identifier();
|
|
const string cpcpName = (cpcp->variant() == GLOBAL) ? "" : cpcp->symbol()->identifier();
|
|
const string global = globalP ? ((globalP->variant() != GLOBAL) ? globalP->symbol()->identifier() : "") : "";
|
|
|
|
//try to resolve by parameters count
|
|
vector<Function> firstStep, candidates;
|
|
|
|
for (auto& func : functions)
|
|
if (func.parametersCount == parCount)
|
|
firstStep.push_back(func);
|
|
|
|
if (firstStep.size() != 1)
|
|
{
|
|
for (auto& func : firstStep)
|
|
{
|
|
if (func.type == 3)
|
|
{
|
|
if (func.parentName == cpName && func.globalName == cpcpName ||
|
|
func.parentName == cpcpName && func.globalName == global)
|
|
{
|
|
candidates.push_back(func);
|
|
}
|
|
}
|
|
else if (func.type == 0)
|
|
{
|
|
if (func.parentName == cpcpName)
|
|
candidates.push_back(func);
|
|
}
|
|
else if (func.type == 2)
|
|
{
|
|
if (func.parentName == cpName || func.parentName == cpcpName) // contains
|
|
candidates.push_back(func);
|
|
}
|
|
else
|
|
{
|
|
//TODO:
|
|
candidates.push_back(func);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
candidates = firstStep;
|
|
|
|
if (candidates.size() == 0)
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
//TODO: added candidate filtration by context
|
|
|
|
if (candidates.size() == 1)
|
|
{
|
|
Function target = candidates[0];
|
|
auto itF = target.resolved.find(file);
|
|
|
|
if (itF != target.resolved.end())
|
|
corrected = itF->second;
|
|
else
|
|
{
|
|
if (target.type == 1 || target.type == 2) // global or internal
|
|
{
|
|
if (target.file == file->filename())
|
|
{
|
|
corrected = target.point->symbol();
|
|
target.resolved[file] = corrected;
|
|
}
|
|
/*else //TODO: create needed symbol?
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);*/
|
|
}
|
|
else if (target.type == 0) // module
|
|
{
|
|
if (target.file == file->filename())
|
|
{
|
|
corrected = target.point->symbol();
|
|
target.resolved[file] = corrected;
|
|
}
|
|
else
|
|
;//TODO: find module symbol clone in current file
|
|
}
|
|
}
|
|
}
|
|
else // TODO
|
|
{
|
|
__spf_print(1, "can not resolve of CALL '%s' function, candidates count %d, file %s and line %d\n", name.c_str(), functions.size(), current_file->filename(), context->lineNumber());
|
|
for (auto& func : functions)
|
|
__spf_print(1, " --> from file file %s and line %d, parameter count - %d\n", func.file.c_str(), func.line, func.parametersCount);
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
}
|
|
|
|
return corrected;
|
|
}
|
|
|
|
static void resolveFunctionCalls(SgFile* file, SgStatement* context, SgExpression* ex, const set<string>& toResolve, const map<string, vector<Function>>& funcInfo)
|
|
{
|
|
if (ex)
|
|
{
|
|
if (ex->variant() == FUNC_CALL)
|
|
{
|
|
string name = ex->symbol()->identifier();
|
|
if (toResolve.find(name) != toResolve.end())
|
|
{
|
|
auto newS = resolveName(file, context, ex->lhs(), funcInfo.at(name), name);
|
|
if (newS && ex->symbol()->id() != newS->id())
|
|
ex->setSymbol(*newS);
|
|
}
|
|
}
|
|
|
|
resolveFunctionCalls(file, context, ex->lhs(), toResolve, funcInfo);
|
|
resolveFunctionCalls(file, context, ex->rhs(), toResolve, funcInfo);
|
|
}
|
|
}
|
|
|
|
void resolveFunctionCalls(SgFile* file, const set<string>& toResolve, const map<string, vector<Function>>& funcInfo)
|
|
{
|
|
if (toResolve.size() == 0)
|
|
return;
|
|
|
|
int funcNum = file->numberOfFunctions();
|
|
for (int z = 0; z < funcNum; ++z)
|
|
{
|
|
SgStatement* st = file->functions(z);
|
|
SgStatement* lastNode = st->lastNodeOfStmt();
|
|
|
|
while (st != lastNode)
|
|
{
|
|
if (st->variant() == CONTAINS_STMT)
|
|
break;
|
|
|
|
if (st->variant() == PROC_STAT)
|
|
{
|
|
string name = st->symbol()->identifier();
|
|
if (toResolve.find(name) != toResolve.end())
|
|
{
|
|
auto newS = resolveName(file, st, st->expr(0), funcInfo.at(name), name);
|
|
if (newS && st->symbol()->id() != newS->id())
|
|
st->setSymbol(*newS);
|
|
}
|
|
}
|
|
|
|
for (int z = 0; z < 3; ++z)
|
|
resolveFunctionCalls(file, st, st->expr(z), toResolve, funcInfo);
|
|
st = st->lexNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool OperatorChecker(SgFile* file, map<string, vector<Messages>>& currMessages)
|
|
{
|
|
bool checkOK = true;
|
|
set<int> usedLines;
|
|
|
|
SgStatement* st = file->firstStatement();
|
|
string currF = file->filename();
|
|
|
|
const set<int> cpOnSameLine = { ARITHIF_NODE, LOGIF_NODE, GOTO_NODE , IF_NODE, FORALL_STAT };
|
|
while (st)
|
|
{
|
|
int line = st->lineNumber();
|
|
if (line > 0 && st->variant() == PROG_HEDR && st->symbol()->identifier() == string("_MAIN"))
|
|
; // skip
|
|
else if (line > 0 && st->fileName() == currF)
|
|
{
|
|
int var = st->controlParent()->variant();
|
|
bool cpWasAdded = cpOnSameLine.find(var) != cpOnSameLine.end() && (usedLines.find(line) != usedLines.end());
|
|
|
|
if (usedLines.find(line) != usedLines.end() && !cpWasAdded)
|
|
{
|
|
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"More than one operator found on a line, try to run Code correction pass");
|
|
__spf_printToLongBuf(messageR, R179);
|
|
|
|
currMessages[st->fileName()].push_back(Messages(ERROR, line, messageR, messageE, 1027));
|
|
checkOK = false;
|
|
}
|
|
usedLines.insert(line);
|
|
}
|
|
st = st->lexNext();
|
|
}
|
|
return checkOK;
|
|
}
|
|
|
|
bool checkAndMoveFormatOperators(SgFile* file, vector<Messages>& currMessages, bool withError)
|
|
{
|
|
bool checkOK = true;
|
|
|
|
const int funcNum = file->numberOfFunctions();
|
|
for (int i = 0; i < funcNum; ++i)
|
|
{
|
|
SgStatement* st = file->functions(i);
|
|
SgStatement* lastNode = st->lastNodeOfStmt();
|
|
|
|
vector<SgStatement*> toMove;
|
|
while (st != lastNode)
|
|
{
|
|
if (st == NULL)
|
|
{
|
|
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
|
break;
|
|
}
|
|
|
|
if (st->variant() == CONTAINS_STMT)
|
|
break;
|
|
|
|
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st))
|
|
break;
|
|
|
|
if (st->variant() == FORMAT_STAT)
|
|
{
|
|
if (withError)
|
|
{
|
|
toMove.push_back(st);
|
|
st = st->lexNext();
|
|
}
|
|
else
|
|
{
|
|
SgStatement* needed = st;
|
|
st = st->lexNext();
|
|
toMove.push_back(needed->extractStmt());
|
|
}
|
|
}
|
|
else
|
|
st = st->lexNext();
|
|
}
|
|
|
|
if (toMove.size() > 0)
|
|
{
|
|
if (!withError)
|
|
{
|
|
for (auto& format : toMove)
|
|
lastNode->insertStmtBefore(*format, *lastNode->controlParent());
|
|
}
|
|
else
|
|
{
|
|
for (auto& format : toMove)
|
|
{
|
|
wstring messageE, messageR;
|
|
__spf_printToLongBuf(messageE, L"FORMAT operators cannot be placed in the declaration scope in the SAPFOR, try to run Code correction pass");
|
|
__spf_printToLongBuf(messageR, R183);
|
|
|
|
currMessages.push_back(Messages(ERROR, format->lineNumber(), messageR, messageE, 1060));
|
|
}
|
|
checkOK = false;
|
|
}
|
|
}
|
|
}
|
|
return checkOK;
|
|
}
|