2024-03-23 10:51:41 +03:00
|
|
|
#include "../Utils/leak_detector.h"
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <map>
|
|
|
|
|
|
2023-12-11 21:41:31 +03:00
|
|
|
#include "Utils/SgUtils.h"
|
|
|
|
|
#include "set_implicit_none.h"
|
|
|
|
|
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::map;
|
2024-03-16 15:31:06 +03:00
|
|
|
using std::set;
|
2024-03-23 11:17:46 +03:00
|
|
|
using std::string;
|
2023-12-11 21:41:31 +03:00
|
|
|
|
2024-03-23 10:51:41 +03:00
|
|
|
static const char commonIntLetters[6] = { 'i', 'j', 'k', 'm', 'n', 'l' };
|
2024-03-12 10:42:22 +03:00
|
|
|
|
2024-03-22 09:19:14 +03:00
|
|
|
static void InitTypes(map<char, SgType*>& types)
|
2024-03-14 15:45:03 +03:00
|
|
|
{
|
2024-03-23 11:24:29 +03:00
|
|
|
for (char letter = 'a'; letter <= 'z'; letter++)
|
|
|
|
|
types[letter] = 0;
|
2024-03-21 21:05:14 +03:00
|
|
|
}
|
|
|
|
|
|
2024-03-22 09:19:14 +03:00
|
|
|
static void FillCommonTypes(map<char, SgType*>& types)
|
2024-03-21 21:05:14 +03:00
|
|
|
{
|
2024-03-23 11:24:29 +03:00
|
|
|
for (char letter : commonIntLetters)
|
|
|
|
|
if (types[letter] == 0)
|
|
|
|
|
types[letter] = new SgType(T_INT);
|
2024-03-21 21:05:14 +03:00
|
|
|
|
2024-03-23 11:24:29 +03:00
|
|
|
for (auto letter : types)
|
|
|
|
|
if (letter.second == NULL)
|
|
|
|
|
types[letter.first] = new SgType(T_FLOAT);
|
2024-03-21 21:05:14 +03:00
|
|
|
}
|
|
|
|
|
|
2024-06-10 09:16:15 +03:00
|
|
|
static bool isByUse(SgSymbol* s, SgStatement* checkScope)
|
|
|
|
|
{
|
|
|
|
|
auto scope = s->scope();
|
|
|
|
|
auto isByUse_s = IS_BY_USE(s);
|
|
|
|
|
|
|
|
|
|
if (!isByUse_s && scope == checkScope)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 17:54:18 +03:00
|
|
|
static void FindAllVars(SgExpression* expr, set<SgSymbol*>& allVars, set<SgSymbol*>& allVarsConst, SgStatement* scope)
|
2024-03-21 21:05:14 +03:00
|
|
|
{
|
2024-03-23 11:24:29 +03:00
|
|
|
if (expr == NULL)
|
|
|
|
|
return;
|
2024-03-21 21:05:14 +03:00
|
|
|
|
2024-04-18 21:36:40 +03:00
|
|
|
const int var = expr->variant();
|
2024-05-12 13:37:42 +03:00
|
|
|
if (var == VAR_REF || var == ARRAY_REF || var == FUNC_CALL)
|
2024-05-13 10:37:59 +03:00
|
|
|
{
|
2024-07-20 13:03:27 +03:00
|
|
|
auto s = expr->symbol();
|
|
|
|
|
const string ident(s->identifier());
|
2025-02-13 16:37:24 +03:00
|
|
|
const int s_var = s->variant();
|
|
|
|
|
|
2024-05-25 17:41:28 +03:00
|
|
|
if (var == FUNC_CALL /*(s->attributes() & EXTERNAL_BIT)*/)
|
2024-05-14 12:53:31 +03:00
|
|
|
{
|
2024-07-20 13:03:27 +03:00
|
|
|
if (!IS_BY_USE(s) && ident.find("::") == string::npos /* && s->scope() == scope*/)
|
2024-05-14 12:53:31 +03:00
|
|
|
allVars.insert(s);
|
|
|
|
|
}
|
2025-02-13 16:37:24 +03:00
|
|
|
else if (s_var != CONSTRUCT_NAME ||
|
|
|
|
|
s_var == VARIABLE_NAME)
|
2024-05-15 17:54:18 +03:00
|
|
|
{
|
2024-07-20 13:03:27 +03:00
|
|
|
if (!IS_BY_USE(s) && ident.find("::") == string::npos && s->scope() == scope)
|
2024-05-15 17:54:18 +03:00
|
|
|
allVars.insert(s);
|
|
|
|
|
}
|
2024-05-13 10:37:59 +03:00
|
|
|
}
|
|
|
|
|
else if (var == CONST_REF)
|
2024-06-10 09:16:15 +03:00
|
|
|
{
|
|
|
|
|
auto s = expr->symbol();
|
|
|
|
|
if (!isByUse(s, scope))
|
|
|
|
|
allVarsConst.insert(s);
|
|
|
|
|
}
|
2024-03-21 21:05:14 +03:00
|
|
|
|
2024-05-15 17:54:18 +03:00
|
|
|
FindAllVars(expr->lhs(), allVars, allVarsConst, scope);
|
|
|
|
|
FindAllVars(expr->rhs(), allVars, allVarsConst, scope);
|
2024-03-21 21:05:14 +03:00
|
|
|
}
|
|
|
|
|
|
2024-03-23 10:51:41 +03:00
|
|
|
static char getValue(SgExpression* ex)
|
2024-03-21 21:05:14 +03:00
|
|
|
{
|
2024-03-23 11:24:29 +03:00
|
|
|
char charVal = 0;
|
|
|
|
|
if (ex && ex->variant() == CHAR_VAL)
|
|
|
|
|
charVal = isSgValueExp(ex)->charValue();
|
|
|
|
|
return charVal;
|
2024-03-23 10:51:41 +03:00
|
|
|
}
|
2024-03-21 21:05:14 +03:00
|
|
|
|
2024-03-23 10:51:41 +03:00
|
|
|
static void AddLettersToMap(SgExpression* expr, SgType* type, map<char, SgType*>& types)
|
|
|
|
|
{
|
2024-03-23 11:24:29 +03:00
|
|
|
while (expr)
|
|
|
|
|
{
|
|
|
|
|
if (expr->variant() != EXPR_LIST)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgExpression* val = expr->lhs();
|
|
|
|
|
if (val->variant() == DDOT)
|
|
|
|
|
{
|
|
|
|
|
char leftVal = getValue(val->lhs());
|
|
|
|
|
char rightVal = getValue(val->rhs());
|
|
|
|
|
|
|
|
|
|
if (leftVal == 0 || rightVal == 0)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (char letter = leftVal; letter <= rightVal; letter++)
|
|
|
|
|
types[letter] = type;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char charVal = getValue(val);
|
|
|
|
|
if (charVal == 0)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
types[charVal] = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expr = expr->rhs();
|
|
|
|
|
}
|
2024-03-13 23:38:42 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-15 17:54:18 +03:00
|
|
|
static vector<SgSymbol*> getVars(const set<string>& functionSymbs, set<SgSymbol*>& toRename,
|
2024-06-10 09:16:15 +03:00
|
|
|
const set<SgSymbol*>& allVars, const map<char, SgType*>& types,
|
|
|
|
|
SgStatement* scope)
|
2024-04-18 21:36:40 +03:00
|
|
|
{
|
|
|
|
|
vector<SgSymbol*> varsWithoutDecl;
|
|
|
|
|
map<string, SgSymbol*> vars;
|
|
|
|
|
for (auto& var : allVars)
|
|
|
|
|
{
|
|
|
|
|
if (vars.find(var->identifier()) != vars.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
vars[var->identifier()] = var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& var : allVars)
|
|
|
|
|
{
|
2024-05-15 17:54:18 +03:00
|
|
|
if (functionSymbs.count(var->identifier()))
|
2024-04-18 21:36:40 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
vector<SgStatement*> allDecls;
|
2024-06-10 09:16:15 +03:00
|
|
|
declaratedInStmt(var, &allDecls, false, (var->variant() == FUNCTION_NAME) ? scope : NULL);
|
2024-04-18 21:36:40 +03:00
|
|
|
|
|
|
|
|
bool hasTypeDecls = false;
|
|
|
|
|
for (auto& decl : allDecls)
|
|
|
|
|
{
|
|
|
|
|
const int var = decl->variant();
|
|
|
|
|
if (var == VAR_DECL || var == VAR_DECL_90 || var == STRUCT_DECL)
|
|
|
|
|
hasTypeDecls = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasTypeDecls)
|
|
|
|
|
{
|
|
|
|
|
const char c = var->identifier()[0];
|
|
|
|
|
auto it = types.find(c);
|
|
|
|
|
if (it != types.end())
|
|
|
|
|
{
|
|
|
|
|
var->setType(it->second);
|
|
|
|
|
|
|
|
|
|
auto s = it->second->symbol();
|
|
|
|
|
if (s)
|
|
|
|
|
{
|
|
|
|
|
auto itS = vars.find(s->identifier());
|
|
|
|
|
if (itS != vars.end())
|
|
|
|
|
toRename.insert(itS->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
varsWithoutDecl.push_back(var);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return varsWithoutDecl;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-19 21:10:43 +03:00
|
|
|
static map<char, SgType*> FunctionImplicitCheck(SgStatement* function, const map<SgStatement*, map<char, SgType*>>& typesByFunctions,
|
|
|
|
|
vector<int>& dvmDirErrorsLines)
|
2024-03-14 15:45:03 +03:00
|
|
|
{
|
2024-04-18 21:36:40 +03:00
|
|
|
set<SgSymbol*> allVars, allVarsConst;
|
2024-03-23 11:24:29 +03:00
|
|
|
map<char, SgType*> types;
|
2024-04-18 21:36:40 +03:00
|
|
|
vector<SgSymbol*> varsWithoutDecl, varsWithoutDeclConst;
|
|
|
|
|
set<SgSymbol*> toRename;
|
2024-03-23 11:24:29 +03:00
|
|
|
|
|
|
|
|
InitTypes(types);
|
|
|
|
|
FillCommonTypes(types);
|
|
|
|
|
|
|
|
|
|
auto cp = function->controlParent();
|
|
|
|
|
if (isSgProgHedrStmt(cp))
|
|
|
|
|
if (typesByFunctions.find(cp) != typesByFunctions.end())
|
|
|
|
|
for (auto& parentType : typesByFunctions.at(cp))
|
|
|
|
|
types[parentType.first] = parentType.second;
|
|
|
|
|
|
|
|
|
|
auto hasImplicitNone = false;
|
|
|
|
|
auto endOfFunc = function->lastNodeOfStmt();
|
|
|
|
|
for (auto st = function; st != endOfFunc; st = st->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == IMPL_DECL)
|
|
|
|
|
{
|
|
|
|
|
SgImplicitStmt* implicitStatement = isSgImplicitStmt(st);
|
|
|
|
|
if (implicitStatement != NULL)
|
|
|
|
|
{
|
|
|
|
|
const int numberOfTypes = implicitStatement->numberOfImplicitTypes();
|
|
|
|
|
|
|
|
|
|
if (numberOfTypes > 0)
|
|
|
|
|
{
|
|
|
|
|
for (int j = 0; j < numberOfTypes; ++j)
|
|
|
|
|
{
|
|
|
|
|
SgType* type = implicitStatement->implicitType(j);
|
|
|
|
|
SgExpression* lettersExpression = implicitStatement->implicitRangeList(j);
|
|
|
|
|
|
|
|
|
|
AddLettersToMap(lettersExpression, type, types);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
hasImplicitNone = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (st->variant() == CONTAINS_STMT || isSgExecutableStatement(st) != NULL)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-05-12 13:37:42 +03:00
|
|
|
|
2024-07-20 13:03:27 +03:00
|
|
|
set<int> skip = { EXTERN_STAT, PRIVATE_STMT, PUBLIC_STMT };
|
2024-03-23 11:24:29 +03:00
|
|
|
|
2024-05-14 12:53:31 +03:00
|
|
|
set<SgSymbol*> allDataSymbols;
|
|
|
|
|
for (auto s = function->symbol()->next(); s; s = s->next())
|
2024-05-15 17:54:18 +03:00
|
|
|
if ((s->attributes() & DATA_BIT) && s->scope() == function)
|
2024-05-14 12:53:31 +03:00
|
|
|
allDataSymbols.insert(s);
|
|
|
|
|
|
2024-05-15 17:54:18 +03:00
|
|
|
set<string> functionSymbs = { function->symbol()->identifier() };
|
|
|
|
|
if (isSgFuncHedrStmt(function))
|
|
|
|
|
{
|
|
|
|
|
SgFuncHedrStmt* hedr = isSgFuncHedrStmt(function);
|
|
|
|
|
if (hedr->resultName())
|
|
|
|
|
functionSymbs.insert(hedr->resultName()->identifier());
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-25 17:41:28 +03:00
|
|
|
auto prog = isSgProgHedrStmt(function);
|
|
|
|
|
if (prog)
|
|
|
|
|
{
|
|
|
|
|
for (int z = 0; z < prog->numberOfInternalSubroutinesDefined(); ++z)
|
|
|
|
|
functionSymbs.insert(prog->internalSubroutine(z)->symbol()->identifier());
|
|
|
|
|
for (int z = 0; z < prog->numberOfInternalFunctionsDefined(); ++z)
|
|
|
|
|
functionSymbs.insert(prog->internalFunction(z)->symbol()->identifier());
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-13 10:37:59 +03:00
|
|
|
for (auto st = function->lexNext(); st != endOfFunc && st->variant() != CONTAINS_STMT; st = st->lexNext())
|
2024-05-12 13:37:42 +03:00
|
|
|
{
|
|
|
|
|
if (skip.count(st->variant()))
|
|
|
|
|
continue;
|
|
|
|
|
|
2024-07-19 21:10:43 +03:00
|
|
|
if (isDVM_stat(st))
|
|
|
|
|
dvmDirErrorsLines.push_back(st->lineNumber());
|
|
|
|
|
|
2024-05-15 17:54:18 +03:00
|
|
|
if (isDVM_stat(st) || isSPF_stat(st))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (st->variant() == INTERFACE_STMT)
|
|
|
|
|
{
|
|
|
|
|
st = st->lastNodeOfStmt();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-14 12:53:31 +03:00
|
|
|
if (st->variant() == DATA_DECL)
|
|
|
|
|
{
|
|
|
|
|
const string str = st->expr(0)->thellnd->entry.string_val;
|
|
|
|
|
|
|
|
|
|
for (auto& data : allDataSymbols)
|
|
|
|
|
{
|
|
|
|
|
if (str.find(data->identifier()) != string::npos)
|
|
|
|
|
allVars.insert(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-23 11:24:29 +03:00
|
|
|
for (int i = 0; i < 3; ++i)
|
2024-05-15 17:54:18 +03:00
|
|
|
FindAllVars(st->expr(i), allVars, allVarsConst, function);
|
2024-03-23 11:24:29 +03:00
|
|
|
|
2024-05-12 13:37:42 +03:00
|
|
|
if (st->variant() == FOR_NODE)
|
2024-06-10 09:16:15 +03:00
|
|
|
if (!isByUse(isSgForStmt(st)->doName(), function))
|
|
|
|
|
allVars.insert(isSgForStmt(st)->doName());
|
2024-05-12 13:37:42 +03:00
|
|
|
}
|
2024-05-14 12:53:31 +03:00
|
|
|
|
2024-05-13 10:37:59 +03:00
|
|
|
//add parameters
|
|
|
|
|
if (prog)
|
|
|
|
|
{
|
|
|
|
|
for (int z = 0; z < prog->numberOfParameters(); ++z)
|
|
|
|
|
{
|
|
|
|
|
auto s = prog->parameter(z);
|
|
|
|
|
if ((s->attributes() & EXTERNAL_BIT) == 0)
|
|
|
|
|
allVars.insert(s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-10 09:16:15 +03:00
|
|
|
varsWithoutDecl = getVars(functionSymbs, toRename, allVars, types, function);
|
|
|
|
|
varsWithoutDeclConst = getVars(functionSymbs, toRename, allVarsConst, types, NULL);
|
2024-04-18 21:36:40 +03:00
|
|
|
|
2024-03-23 11:24:29 +03:00
|
|
|
if (!hasImplicitNone)
|
|
|
|
|
{
|
2024-05-14 12:53:31 +03:00
|
|
|
vector<SgStatement*> macro;
|
|
|
|
|
|
2024-03-23 11:24:29 +03:00
|
|
|
for (auto st = function->lexNext();
|
|
|
|
|
st != endOfFunc && st->variant() != CONTAINS_STMT && isSgExecutableStatement(st) == NULL;
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == IMPL_DECL)
|
|
|
|
|
{
|
|
|
|
|
auto tmpStatement = st;
|
|
|
|
|
st = st->lexNext();
|
|
|
|
|
tmpStatement->deleteStmt();
|
|
|
|
|
}
|
2024-05-14 12:53:31 +03:00
|
|
|
else if (st->variant() == STMTFN_STAT)
|
|
|
|
|
{
|
|
|
|
|
auto stat = st;
|
|
|
|
|
st = st->lexNext();
|
|
|
|
|
macro.push_back(stat->extractStmt());
|
|
|
|
|
}
|
2024-03-23 11:24:29 +03:00
|
|
|
else
|
|
|
|
|
st = st->lexNext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto implNone = new SgStatement(IMPL_DECL);
|
|
|
|
|
implNone->setlineNumber(function->lineNumber());
|
|
|
|
|
implNone->setFileName(function->fileName());
|
|
|
|
|
|
2024-04-18 21:36:40 +03:00
|
|
|
SgStatement* insertPlace = function;
|
|
|
|
|
while (insertPlace->lexNext()->variant() == USE_STMT)
|
|
|
|
|
insertPlace = insertPlace->lexNext();
|
|
|
|
|
|
|
|
|
|
insertPlace->insertStmtAfter(*implNone, *function);
|
|
|
|
|
insertPlace = insertPlace->lexNext();
|
|
|
|
|
|
2024-05-12 13:37:42 +03:00
|
|
|
if (function->variant() == FUNC_HEDR)
|
|
|
|
|
{
|
2024-05-15 17:54:18 +03:00
|
|
|
SgFuncHedrStmt* hedr = isSgFuncHedrStmt(function);
|
|
|
|
|
|
2024-05-12 13:37:42 +03:00
|
|
|
auto type_op = function->expr(1);
|
|
|
|
|
if (type_op == NULL)
|
2024-05-15 17:54:18 +03:00
|
|
|
{
|
|
|
|
|
if (hedr->resultName())
|
|
|
|
|
varsWithoutDecl.push_back(hedr->resultName());
|
|
|
|
|
else
|
|
|
|
|
varsWithoutDecl.push_back(function->symbol());
|
|
|
|
|
}
|
2024-05-12 13:37:42 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-18 21:36:40 +03:00
|
|
|
makeDeclaration(varsWithoutDecl, function);
|
|
|
|
|
|
|
|
|
|
auto declList = makeDeclaration(varsWithoutDeclConst, NULL);
|
|
|
|
|
for (auto& decl : declList)
|
|
|
|
|
insertPlace->insertStmtAfter(*decl, *function);
|
2024-05-14 12:53:31 +03:00
|
|
|
|
|
|
|
|
if (macro.size())
|
|
|
|
|
{
|
|
|
|
|
while (!isSgExecutableStatement(insertPlace) && insertPlace != NULL)
|
|
|
|
|
insertPlace = insertPlace->lexNext();
|
|
|
|
|
|
|
|
|
|
if (insertPlace == NULL)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto& elem : macro)
|
|
|
|
|
insertPlace->insertStmtBefore(*elem, *function);
|
|
|
|
|
}
|
2024-03-23 11:24:29 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-18 21:36:40 +03:00
|
|
|
for (auto& s : toRename)
|
|
|
|
|
s->changeName(TestAndCorrectName((string(s->identifier()) + "_").c_str()));
|
2024-05-12 13:37:42 +03:00
|
|
|
|
2024-03-23 11:24:29 +03:00
|
|
|
return types;
|
2024-03-16 15:31:06 +03:00
|
|
|
}
|
|
|
|
|
|
2024-07-19 21:10:43 +03:00
|
|
|
void implicitCheck(SgFile* file, vector<int>& dvmDirErrorsLines)
|
2024-03-16 15:31:06 +03:00
|
|
|
{
|
2024-03-23 11:24:29 +03:00
|
|
|
map<SgStatement*, map<char, SgType*>> typesByFunctions;
|
2024-03-16 15:31:06 +03:00
|
|
|
|
2024-05-15 17:54:18 +03:00
|
|
|
vector<SgStatement*> modulesAndFunctions;
|
|
|
|
|
getModulesAndFunctions(file, modulesAndFunctions);
|
2024-07-31 17:01:21 +03:00
|
|
|
const string currFile = file->filename();
|
2024-05-15 17:54:18 +03:00
|
|
|
|
|
|
|
|
for (int func = 0; func < modulesAndFunctions.size(); ++func)
|
2024-03-23 11:24:29 +03:00
|
|
|
{
|
2024-05-15 17:54:18 +03:00
|
|
|
SgStatement* function = modulesAndFunctions[func];
|
2024-07-31 17:01:21 +03:00
|
|
|
if (function->fileName() != currFile)
|
|
|
|
|
continue;
|
2024-07-19 21:10:43 +03:00
|
|
|
typesByFunctions[function] = FunctionImplicitCheck(function, typesByFunctions, dvmDirErrorsLines);
|
2024-03-23 11:24:29 +03:00
|
|
|
}
|
2024-03-16 15:31:06 +03:00
|
|
|
|
2024-03-23 11:24:29 +03:00
|
|
|
typesByFunctions.clear();
|
2024-03-23 10:51:41 +03:00
|
|
|
}
|