More flexible DNA template support

This commit is contained in:
Jack Andersen 2018-07-15 21:42:14 -10:00
parent 9a7bee95c4
commit 24666aebdd
4 changed files with 78 additions and 255 deletions

View File

@ -226,10 +226,10 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
return propIdExpr; return propIdExpr;
} }
static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr, int64_t endianVal) static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& endianExpr)
{ {
return "<Op, "s + (endianVal ? "Endian::Big" : "Endian::Little") + ">({" + propIdExpr + "}, " + fieldName + ", s)"; return "<Op, "s + endianExpr + ">({" + propIdExpr + "}, " + fieldName + ", s)";
} }
static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr)
@ -238,9 +238,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
return "<Op>({" + propIdExpr + "}, " + fieldName + ", s)"; return "<Op>({" + propIdExpr + "}, " + fieldName + ", s)";
} }
static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr, int64_t endianVal) static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr, const std::string& endianExpr)
{ {
return "<Op, "s + (endianVal ? "Endian::Big" : "Endian::Little") + ">({" + propIdExpr + "}, " + fieldName + ", " + sizeExpr + ", s)"; return "<Op, "s + endianExpr + ">({" + propIdExpr + "}, " + fieldName + ", " + sizeExpr + ", s)";
} }
static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr) static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr)
@ -456,7 +456,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (!tsDecl->getName().compare("Value")) if (!tsDecl->getName().compare("Value"))
{ {
llvm::APSInt endian(64, -1); llvm::APSInt endian(64, -1);
const clang::Expr* endianExpr = nullptr; std::string endianExprStr;
bool defaultEndian = true; bool defaultEndian = true;
if (classParms->size() >= 2) if (classParms->size() >= 2)
{ {
@ -464,15 +464,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm)
{ {
const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm;
const clang::Expr* defArg = nttParm->getDefaultArgument(); llvm::raw_string_ostream strStream(endianExprStr);
endianExpr = defArg; nttParm->print(strStream, context.getPrintingPolicy());
if (!defArg->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true));
continue;
}
} }
} }
@ -481,36 +474,12 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr();
endianExpr = expr; llvm::raw_string_ostream strStream(endianExprStr);
expr->printPretty(strStream, nullptr, context.getPrintingPolicy());
defaultEndian = false; defaultEndian = false;
if (!expr->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
continue;
}
} }
} }
int64_t endianVal = endian.getSExtValue();
if (endianVal != 0 && endianVal != 1)
{
if (endianExpr)
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true));
}
else
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
}
continue;
}
std::string ioOp; std::string ioOp;
bool isDNAType = false; bool isDNAType = false;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
@ -520,7 +489,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (defaultEndian) if (defaultEndian)
ioOp = GetOpString(fieldName, propIdExpr); ioOp = GetOpString(fieldName, propIdExpr);
else else
ioOp = GetOpString(fieldName, propIdExpr, endianVal); ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
} }
} }
@ -537,7 +506,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
else if (!tsDecl->getName().compare("Vector")) else if (!tsDecl->getName().compare("Vector"))
{ {
llvm::APSInt endian(64, -1); llvm::APSInt endian(64, -1);
const clang::Expr* endianExpr = nullptr; std::string endianExprStr;
bool defaultEndian = true; bool defaultEndian = true;
if (classParms->size() >= 3) if (classParms->size() >= 3)
{ {
@ -545,21 +514,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm)
{ {
const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm;
const clang::Expr* defArg = nttParm->getDefaultArgument(); llvm::raw_string_ostream strStream(endianExprStr);
endianExpr = defArg; nttParm->print(strStream, context.getPrintingPolicy());
if (!defArg->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true));
continue;
}
} }
} }
std::string sizeExpr; std::string sizeExpr;
size_t idx = 0; size_t idx = 0;
bool bad = false;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
@ -588,46 +549,19 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
} }
} }
} }
llvm::raw_string_ostream strStream(sizeExpr); llvm::raw_string_ostream strStream2(sizeExpr);
argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy());
} }
} }
else if (idx == 2) else if (idx == 2)
{ {
defaultEndian = false; defaultEndian = false;
endianExpr = expr; llvm::raw_string_ostream strStream(endianExprStr);
if (!expr->isIntegerConstantExpr(endian, context)) expr->printPretty(strStream, nullptr, context.getPrintingPolicy());
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
bad = true;
break;
}
} }
} }
++idx; ++idx;
} }
if (bad)
continue;
int64_t endianVal = endian.getSExtValue();
if (endianVal != 0 && endianVal != 1)
{
if (endianExpr)
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true));
}
else
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
}
continue;
}
clang::QualType templateType; clang::QualType templateType;
std::string ioOp; std::string ioOp;
@ -640,7 +574,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (defaultEndian) if (defaultEndian)
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr);
else else
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianVal); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr);
} }
} }
@ -741,7 +675,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
else if (!tsDecl->getName().compare("WString")) else if (!tsDecl->getName().compare("WString"))
{ {
llvm::APSInt endian(64, -1); llvm::APSInt endian(64, -1);
const clang::Expr* endianExpr = nullptr; std::string endianExprStr;
bool defaultEndian = true; bool defaultEndian = true;
if (classParms->size() >= 2) if (classParms->size() >= 2)
{ {
@ -749,21 +683,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm)
{ {
const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm;
const clang::Expr* defArg = nttParm->getDefaultArgument(); llvm::raw_string_ostream strStream(endianExprStr);
endianExpr = defArg; nttParm->print(strStream, context.getPrintingPolicy());
if (!defArg->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true));
continue;
}
} }
} }
std::string sizeExprStr; std::string sizeExprStr;
size_t idx = 0; size_t idx = 0;
bool bad = false;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
@ -779,8 +705,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
const clang::Expr* argExpr = uExpr->getArgumentExpr(); const clang::Expr* argExpr = uExpr->getArgumentExpr();
while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass)
argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr();
llvm::raw_string_ostream strStream(sizeExprStr); llvm::raw_string_ostream strStream2(sizeExprStr);
argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy());
} }
else if (expr->isIntegerConstantExpr(sizeLiteral, context)) else if (expr->isIntegerConstantExpr(sizeLiteral, context))
{ {
@ -790,39 +716,12 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
else if (idx == 1) else if (idx == 1)
{ {
defaultEndian = false; defaultEndian = false;
endianExpr = expr; llvm::raw_string_ostream strStream(endianExprStr);
if (!expr->isIntegerConstantExpr(endian, context)) expr->printPretty(strStream, nullptr, context.getPrintingPolicy());
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
bad = true;
break;
}
} }
} }
++idx; ++idx;
} }
if (bad)
continue;
int64_t endianVal = endian.getSExtValue();
if (endianVal != 0 && endianVal != 1)
{
if (endianExpr)
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true));
}
else
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
}
continue;
}
std::string ioOp; std::string ioOp;
if (!sizeExprStr.empty()) if (!sizeExprStr.empty())
@ -830,14 +729,14 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (defaultEndian) if (defaultEndian)
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
else else
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianVal); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr);
} }
else else
{ {
if (defaultEndian) if (defaultEndian)
ioOp = GetOpString(fieldName, propIdExpr); ioOp = GetOpString(fieldName, propIdExpr);
else else
ioOp = GetOpString(fieldName, propIdExpr, endianVal); ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
} }
outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false);
@ -943,6 +842,16 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
outputNodes.emplace_back(NodeType::DoAlign, fieldName, "<Op>("s + align.toString(10, true) + ", s)", false); outputNodes.emplace_back(NodeType::DoAlign, fieldName, "<Op>("s + align.toString(10, true) + ", s)", false);
} }
} }
else
{
const clang::NamedDecl* nd = tsDecl->getTemplatedDecl();
if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null<clang::CXXRecordDecl>(nd))
{
std::string baseDNA;
if (isDNARecord(rd, baseDNA))
outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false);
}
}
} }
else if (regType->getTypeClass() == clang::Type::Record) else if (regType->getTypeClass() == clang::Type::Record)
@ -1025,7 +934,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (!tsDecl->getName().compare("Value")) if (!tsDecl->getName().compare("Value"))
{ {
llvm::APSInt endian(64, -1); llvm::APSInt endian(64, -1);
const clang::Expr* endianExpr = nullptr; std::string endianExprStr;
bool defaultEndian = true; bool defaultEndian = true;
if (classParms->size() >= 2) if (classParms->size() >= 2)
{ {
@ -1033,15 +942,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm)
{ {
const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm;
const clang::Expr* defArg = nttParm->getDefaultArgument(); llvm::raw_string_ostream strStream(endianExprStr);
endianExpr = defArg; nttParm->print(strStream, context.getPrintingPolicy());
if (!defArg->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true));
continue;
}
} }
} }
@ -1050,36 +952,12 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
{ {
const clang::Expr* expr = arg.getAsExpr(); const clang::Expr* expr = arg.getAsExpr();
endianExpr = expr; llvm::raw_string_ostream strStream(endianExprStr);
expr->printPretty(strStream, nullptr, context.getPrintingPolicy());
defaultEndian = false; defaultEndian = false;
if (!expr->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
continue;
}
} }
} }
int64_t endianVal = endian.getSExtValue();
if (endianVal != 0 && endianVal != 1)
{
if (endianExpr)
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true));
}
else
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
}
continue;
}
std::string ioOp; std::string ioOp;
bool isDNAType = false; bool isDNAType = false;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
@ -1089,7 +967,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (defaultEndian) if (defaultEndian)
ioOp = GetOpString(fieldName, propIdExpr); ioOp = GetOpString(fieldName, propIdExpr);
else else
ioOp = GetOpString(fieldName, propIdExpr, endianVal); ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
} }
} }
@ -1109,7 +987,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
else if (!tsDecl->getName().compare("Vector")) else if (!tsDecl->getName().compare("Vector"))
{ {
llvm::APSInt endian(64, -1); llvm::APSInt endian(64, -1);
const clang::Expr* endianExpr = nullptr; std::string endianExprStr;
bool defaultEndian = true; bool defaultEndian = true;
if (classParms->size() >= 3) if (classParms->size() >= 3)
{ {
@ -1117,21 +995,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm)
{ {
const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm;
const clang::Expr* defArg = nttParm->getDefaultArgument(); llvm::raw_string_ostream strStream(endianExprStr);
endianExpr = defArg; nttParm->print(strStream, context.getPrintingPolicy());
if (!defArg->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true));
continue;
}
} }
} }
std::string sizeExpr; std::string sizeExpr;
size_t idx = 0; size_t idx = 0;
bool bad = false;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
@ -1146,46 +1016,19 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
const clang::Expr* argExpr = uExpr->getArgumentExpr(); const clang::Expr* argExpr = uExpr->getArgumentExpr();
while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass)
argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr();
llvm::raw_string_ostream strStream(sizeExpr); llvm::raw_string_ostream strStream2(sizeExpr);
argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy());
} }
} }
else if (idx == 2) else if (idx == 2)
{ {
endianExpr = expr; llvm::raw_string_ostream strStream(endianExprStr);
expr->printPretty(strStream, nullptr, context.getPrintingPolicy());
defaultEndian = false; defaultEndian = false;
if (!expr->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
bad = true;
break;
}
} }
} }
++idx; ++idx;
} }
if (bad)
continue;
int64_t endianVal = endian.getSExtValue();
if (endianVal != 0 && endianVal != 1)
{
if (endianExpr)
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true));
}
else
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
}
continue;
}
clang::QualType templateType; clang::QualType templateType;
std::string ioOp; std::string ioOp;
@ -1198,7 +1041,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (defaultEndian) if (defaultEndian)
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr);
else else
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianVal); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr);
} }
} }
@ -1305,7 +1148,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
else if (!tsDecl->getName().compare("WString")) else if (!tsDecl->getName().compare("WString"))
{ {
llvm::APSInt endian(64, -1); llvm::APSInt endian(64, -1);
const clang::Expr* endianExpr = nullptr; std::string endianExprStr;
bool defaultEndian = true; bool defaultEndian = true;
if (classParms->size() >= 2) if (classParms->size() >= 2)
{ {
@ -1313,21 +1156,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm)
{ {
const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm;
const clang::Expr* defArg = nttParm->getDefaultArgument(); llvm::raw_string_ostream strStream(endianExprStr);
endianExpr = defArg; nttParm->print(strStream, context.getPrintingPolicy());
if (!defArg->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true));
continue;
}
} }
} }
std::string sizeExprStr; std::string sizeExprStr;
size_t idx = 0; size_t idx = 0;
bool bad = false;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
{ {
if (arg.getKind() == clang::TemplateArgument::Expression) if (arg.getKind() == clang::TemplateArgument::Expression)
@ -1343,8 +1178,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
const clang::Expr* argExpr = uExpr->getArgumentExpr(); const clang::Expr* argExpr = uExpr->getArgumentExpr();
while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass)
argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr();
llvm::raw_string_ostream strStream(sizeExprStr); llvm::raw_string_ostream strStream2(sizeExprStr);
argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy());
} }
else if (expr->isIntegerConstantExpr(sizeLiteral, context)) else if (expr->isIntegerConstantExpr(sizeLiteral, context))
{ {
@ -1353,40 +1188,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
} }
else if (idx == 1) else if (idx == 1)
{ {
endianExpr = expr; llvm::raw_string_ostream strStream(endianExprStr);
expr->printPretty(strStream, nullptr, context.getPrintingPolicy());
defaultEndian = false; defaultEndian = false;
if (!expr->isIntegerConstantExpr(endian, context))
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
bad = true;
break;
}
} }
} }
++idx; ++idx;
} }
if (bad)
continue;
int64_t endianVal = endian.getSExtValue();
if (endianVal != 0 && endianVal != 1)
{
if (endianExpr)
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true));
}
else
{
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError);
diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'");
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
}
continue;
}
std::string ioOp; std::string ioOp;
if (!sizeExprStr.empty()) if (!sizeExprStr.empty())
@ -1394,20 +1202,34 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (defaultEndian) if (defaultEndian)
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
else else
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianVal); ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr);
} }
else else
{ {
if (defaultEndian) if (defaultEndian)
ioOp = GetOpString(fieldName, propIdExpr); ioOp = GetOpString(fieldName, propIdExpr);
else else
ioOp = GetOpString(fieldName, propIdExpr, endianVal); ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
} }
fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n"
<< " Do" << ioOp << ";\n" << " Do" << ioOp << ";\n"
<< " return true;\n"; << " return true;\n";
} }
else
{
const clang::NamedDecl* nd = tsDecl->getTemplatedDecl();
if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null<clang::CXXRecordDecl>(nd))
{
std::string baseDNA;
if (isDNARecord(rd, baseDNA))
{
fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n"
<< " Do" << GetOpString(fieldName, propIdExpr) << ";\n"
<< " return true;\n";
}
}
}
} }
else if (regType->getTypeClass() == clang::Type::Record) else if (regType->getTypeClass() == clang::Type::Record)
@ -1462,7 +1284,7 @@ public:
bool isPropDNA = false; bool isPropDNA = false;
for (const clang::Decl* d : decl->decls()) for (const clang::Decl* d : decl->decls())
if (const clang::FunctionTemplateDecl* m = clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(d)) if (const clang::FunctionTemplateDecl* m = clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(d))
if (!m->getName().compare(llvm::StringLiteral("Lookup"))) if (m->getDeclName().isIdentifier() && !m->getName().compare(llvm::StringLiteral("Lookup")))
{ {
isPropDNA = true; isPropDNA = true;
break; break;

View File

@ -207,7 +207,7 @@ std::string& rtrim(std::string& s);
// trim from both ends // trim from both ends
std::string& trim(std::string& s); std::string& trim(std::string& s);
atUint64 fileSize(std::string_view filename); atUint64 fileSize(std::string_view filename);
#ifdef _MSC_VER #ifdef _WIN32
atUint64 fileSize(std::wstring_view filename); atUint64 fileSize(std::wstring_view filename);
#endif #endif

View File

@ -41,6 +41,7 @@ public:
RecordRAII() = default; RecordRAII() = default;
public: public:
operator bool() const { return m_r != nullptr; } operator bool() const { return m_r != nullptr; }
void leave() { if (m_r) {m_r->_leaveSubRecord(); m_r = nullptr;} }
~RecordRAII() { if (m_r) m_r->_leaveSubRecord(); } ~RecordRAII() { if (m_r) m_r->_leaveSubRecord(); }
}; };
friend class RecordRAII; friend class RecordRAII;

View File

@ -169,7 +169,7 @@ atUint64 fileSize(std::string_view filename)
return st.st_size; return st.st_size;
} }
#ifdef _MSC_VER #ifdef _WIN32
atUint64 fileSize(std::wstring_view filename) atUint64 fileSize(std::wstring_view filename)
{ {
atStat64_t st; atStat64_t st;