Skip to content

Commit 64b7aab

Browse files
Version 1.4.21. Record base classes and member record supported
1 parent b93367e commit 64b7aab

31 files changed

+2282
-78
lines changed

sc_tool/lib/sc_tool/SCToolFrontendAction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ Object* getOuterArray(SCDesign& designDB, Object* memberObj)
112112
return arrayObj;
113113
}
114114

115-
const std::string SCElabASTConsumer::TOOL_VERSION = "1.4.19";
116-
const std::string SCElabASTConsumer::TOOL_DATE = "22 Apr,2022";
115+
const std::string SCElabASTConsumer::TOOL_VERSION = "1.4.21";
116+
const std::string SCElabASTConsumer::TOOL_DATE = "29 Apr,2022";
117117

118118
void SCElabASTConsumer::HandleTranslationUnit(clang::ASTContext &astCtx)
119119
{

sc_tool/lib/sc_tool/cfg/SValue.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,8 @@ class SRecord : public SObject
433433

434434
bool operator == (const SRecord& rhs) const {
435435
if (var) {
436-
return (var == rhs.var && index == rhs.index);
436+
// Compare type to distinguish base classes of record
437+
return (var == rhs.var && type == rhs.type && index == rhs.index);
437438
} else {
438439
return (SObject::operator ==(rhs));
439440
}

sc_tool/lib/sc_tool/cfg/ScState.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ void ScState::putValue(const SValue& lval, const SValue& rval, bool deReference,
449449
tuples.erase(llval);
450450

451451
if (DebugOptions::isEnabled(DebugComponent::doState)) {
452-
cout << "putValue (" << lval.asString() << ", NO_VALUE)" << endl;
452+
cout << "putValue (" << lval << ", NO_VALUE)" << endl;
453453
}
454454

455455
} else {
@@ -473,12 +473,12 @@ void ScState::putValue(const SValue& lval, const SValue& rval, bool deReference,
473473
}
474474
}
475475
if (DebugOptions::isEnabled(DebugComponent::doState)) {
476-
cout << "putValue (" << lval.asString() << ", " << rrval.asString() << ")" << endl;
476+
cout << "putValue (" << lval << ", " << rrval << ")" << endl;
477477
}
478478
}
479479
} else {
480480
if (DebugOptions::isEnabled(DebugComponent::doState)) {
481-
cout << "putValue (" << lval.asString() << ", " << rval.asString() << ")" << endl;
481+
cout << "putValue (" << lval << ", " << rval << ")" << endl;
482482
}
483483
}
484484
}

sc_tool/lib/sc_tool/diag/ScToolDiagnostic.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class ScDiag {
203203
CPP_STRING_BINARY_OPER = 231,
204204
CPP_STATIC_STD_VECTOR = 232,
205205
SYNTH_LITER_OVERFLOW = 233,
206+
SYNTH_RECORD_CTOR_NONEMPTY = 234,
206207

207208
SC_FATAL_ELAB_TYPES_NS = 300,
208209
SC_WARN_ELAB_UNSUPPORTED_TYPE,
@@ -708,6 +709,12 @@ class ScDiag {
708709
{clang::DiagnosticIDs::Error,
709710
"Literal is too big, up to 4096 symbols supported"};
710711

712+
idFormatMap[SYNTH_RECORD_CTOR_NONEMPTY] =
713+
{clang::DiagnosticIDs::Error,
714+
"Base class or member class non-empty constructor not supported"};
715+
716+
717+
711718
// Elaboration
712719
idFormatMap[SC_FATAL_ELAB_TYPES_NS] =
713720
{clang::DiagnosticIDs::Fatal,

sc_tool/lib/sc_tool/expr/ScParseExpr.cpp

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ std::pair<SValue, std::vector<SValue> >
485485
iival = evaluateConstInt(iexpr, ival, checkConst);
486486
initvals.push_back(ival);
487487
}
488+
//cout << "parseValueDecl val " << val << " ival " << ival << endl;
488489

489490
if (isRef) {
490491
// It needs to put reference value into state
@@ -851,8 +852,12 @@ void ScParseExpr::parseExpr(clang::StringLiteral* expr, SValue& val)
851852
// Used for local variables access in left/right parts
852853
void ScParseExpr::parseExpr(clang::DeclRefExpr* expr, SValue& val)
853854
{
854-
using namespace llvm;
855-
auto* decl = expr->getDecl();
855+
ValueDecl* decl = expr->getDecl();
856+
857+
// Parameter variable has @modval parent, local variable has @recval
858+
bool isParamVar = isa<ParmVarDecl>(decl);
859+
SValue recVal = recval ? recval : modval;
860+
//cout << "DeclRefExpr recVal " << recVal << endl;
856861

857862
if (auto* enumConstDecl = dyn_cast<clang::EnumConstantDecl>(decl)) {
858863
// Enum constants are not stored in state, evaluated immediately
@@ -869,40 +874,38 @@ void ScParseExpr::parseExpr(clang::DeclRefExpr* expr, SValue& val)
869874

870875
} else {
871876
// Regular data member
872-
val = SValue(decl, modval);
877+
val = SValue(decl, recVal);
873878
}
874879
} else {
875880
// This happens for function pointer passed as parameter
876881
decl->dumpColor();
877882
SCT_TOOL_ASSERT (false, "Record has not variable declaration");
878883
}
884+
//cout << "Record variable val " << val << endl;
879885

880886
} else
881887
if (!isa<clang::FunctionDecl>(decl->getDeclContext())) {
882888
// Global variable
883889
val = SValue(decl, NO_VALUE);
884-
885-
} else
886-
if (isUserDefinedClass(decl->getType())) {
887-
// Local record value
888-
val = SValue(decl, modval);
889-
//cout << "Local record val " << val << ", modval " << modval << endl;
890+
//cout << "Global variable val " << val << endl;
890891

891892
} else {
892893
// Function local variable
893-
val = SValue(decl, modval);
894+
val = SValue(decl, isParamVar ? modval : recVal);
895+
//cout << "Local variable val " << val << " isParamVar " << isParamVar << endl;
894896
}
895897
}
896898
}
897899

898900
void ScParseExpr::parseExpr(clang::MemberExpr* expr, SValue& val)
899901
{
902+
//cout << "ScParseExpr::MemberExpr # " << hex << expr << dec << endl;
903+
900904
// Get record from variable/dynamic object
901905
SCT_TOOL_ASSERT (expr->getBase(), "In parseExpr for MemberExpr no base found");
902906
SValue tval = evalSubExpr(expr->getBase());
903907
SValue ttval = getRecordFromState(tval, ArrayUnkwnMode::amArrayUnknown);
904908

905-
//cout << "ScParseExpr::MemberExpr # " << hex << expr << dec << endl;
906909
//cout << "ScParseExpr::MemberExpr tval = " << tval << ", base->getType() = "
907910
// << expr->getBase()->getType().getAsString() << endl;
908911
//cout << "final ttval = " << ttval << endl;
@@ -945,13 +948,11 @@ void ScParseExpr::parseExpr(clang::MemberExpr* expr, SValue& val)
945948
}
946949
}
947950

948-
//cout << " tval = " << tval << ", val = " << val
949-
// << ", expr->getType() = " << expr->getType().getAsString() << endl;
951+
//cout << " tval = " << tval << ", val = " << val << endl;
950952
}
951953

952954
void ScParseExpr::parseExpr(clang::CXXThisExpr* expr, SValue& thisPtrVal)
953955
{
954-
using namespace std;
955956
//cout << "parse CXXThisExpr, recval " << recval << ", modval " << modval << endl;
956957

957958
thisPtrVal = SValue(expr->getType()); // pointer
@@ -962,8 +963,8 @@ void ScParseExpr::parseExpr(clang::CXXThisExpr* expr, SValue& thisPtrVal)
962963
//cout << " level " << level << ", thisPtrVal " << thisPtrVal << endl;
963964
}
964965

965-
// Create record/module object value and parse its field declarations
966-
// Used for arrays of record elements
966+
// Create record/module object value and parse its field declarations,
967+
// no constructor function call. Used for arrays of record elements
967968
SValue ScParseExpr::createRecValue(const clang::CXXRecordDecl* recDecl,
968969
const SValue& parent, const SValue& var,
969970
bool parseFields, size_t index)
@@ -982,7 +983,7 @@ SValue ScParseExpr::createRecValue(const clang::CXXRecordDecl* recDecl,
982983
// Record value
983984
SValue currec = SValue(QualType(recDecl->getTypeForDecl(), 0),
984985
bases, parent, var, index);
985-
986+
986987
// Current module in @recval required for field initialization
987988
SValue lastRecval(recval); recval = currec;
988989

@@ -1047,30 +1048,32 @@ SValue ScParseExpr::createRecordCopy(CXXConstructExpr* expr,
10471048
SValue ScParseExpr::parseRecordCtor(CXXConstructExpr* expr, SValue parent,
10481049
SValue currecvar, bool analyzeRecordCtor)
10491050
{
1050-
//cout << "parseRecordCtor for var " << currecvar << endl;
1051+
//cout << "parseRecordCtor for currecvar " << currecvar << " parent " << parent << endl;
1052+
1053+
// Prepare constructor parameters before base constructors and
1054+
// initialization list because they can be used there,
1055+
// parameters declared in previous module
1056+
prepareCallParams(expr, modval, expr->getConstructor());
10511057

10521058
// Base classes constructors
1059+
std::vector<SValue> bases;
10531060
for (auto init : expr->getConstructor()->inits()) {
10541061
if (init->isBaseInitializer()) {
1055-
1062+
auto baseInit = removeExprCleanups(init->getInit());
1063+
auto baseExpr = dyn_cast<CXXConstructExpr>(baseInit);
1064+
SCT_TOOL_ASSERT (baseExpr, "No base class constructor found");
10561065
// Parse base constructor
1057-
if (auto baseExpr = dyn_cast<CXXConstructExpr>(init->getInit())) {
1058-
parseRecordCtor(baseExpr, currecvar, parent, false);
1059-
}
1066+
SValue bval = parseRecordCtor(baseExpr, parent, currecvar, false);
1067+
bases.push_back(bval);
10601068
}
10611069
}
10621070

10631071
// Create value for this record and put it into record variable,
10641072
// required to have variable for record in state, replaced in parseValueDecl
1065-
SValue currec = createRecValue(expr->getBestDynamicClassType(),
1066-
parent, currecvar, false);
1073+
SValue currec = SValue(expr->getType(), bases, parent, currecvar, 0);
10671074
state->putValue(currecvar, currec);
10681075
//cout << "currecvar " << currecvar << ", currec " << currec << endl;
10691076

1070-
// Prepare constructor parameters before initialization list because
1071-
// they can be used there, parameters declared in previous module
1072-
prepareCallParams(expr, modval, expr->getConstructor());
1073-
10741077
// Current module in @recval required for field initialization
10751078
SValue lastRecval(recval); recval = currec;
10761079

@@ -1139,9 +1142,19 @@ SValue ScParseExpr::parseRecordCtor(CXXConstructExpr* expr, SValue parent,
11391142
// Restore current module before parse constructor call
11401143
recval = lastRecval;
11411144

1142-
// Activate call constructor body as function, parameters already prepared
11431145
if (analyzeRecordCtor) {
1146+
// Activate call constructor body as function, parameters already prepared
11441147
prepareCallContext(expr, modval, currec, expr->getConstructor(), NO_VALUE);
1148+
1149+
} else {
1150+
// Check constructor is empty
1151+
auto ctorDecl = expr->getConstructor();
1152+
if (auto ctorStmt = dyn_cast<CompoundStmt>(ctorDecl->getBody())) {
1153+
if (!ctorStmt->body_empty()) {
1154+
ScDiag::reportScDiag(ctorStmt->getBeginLoc(),
1155+
ScDiag::SYNTH_RECORD_CTOR_NONEMPTY);
1156+
}
1157+
}
11451158
}
11461159

11471160
state->fillDerivedClasses(currec);
@@ -1185,45 +1198,39 @@ void ScParseExpr::parseExpr(clang::ImplicitCastExpr *expr, SValue& rval, SValue
11851198
}
11861199
}
11871200

1188-
// !!! Use getRecordFromState -- need to ensure it really required
11891201
// Get record from variable/dynamic object
1190-
bool isVariable = !tval.isRecord();
1191-
if (isVariable) {
1192-
SValue ttval;
1193-
state->getValue(tval, ttval, false);
1194-
tval = ttval;
1195-
}
1202+
SValue ttval = getRecordFromState(tval, ArrayUnkwnMode::amFirstElement);
11961203

1197-
if (tval.isRecord()) {
1204+
if (ttval.isRecord()) {
11981205
// CXX class type cast
11991206
if (!isUserDefinedClass(castType)) {
12001207
SCT_TOOL_ASSERT (false, "Derived cast type is not class");
12011208
}
12021209

12031210
// Get base class of @tval with @castType type
1204-
SValue bval = getBaseClass(tval, castType);
1205-
//cout << "Base class " << bval.asString() << endl;
1211+
SValue bval = getBaseClass(ttval, castType);
1212+
//cout << " base class " << bval << " for tval " << ttval << endl;
12061213

1207-
// Add variable for base record object
1208-
if (isVariable) {
1214+
// Add variable for base record object, required for passing record
1215+
// as reference to base class
1216+
if (tval.isVariable()) {
12091217
SValue bbval(castType);
12101218
state->putValue(bbval, bval);
12111219
state->setValueLevel(bbval, level+1);
1212-
12131220
bval = bbval;
1214-
//cout << "Variable to base class bval = " << bval.asString() << endl;
1221+
//cout << " variable to base class bval = " << bval << endl;
12151222
}
12161223

12171224
// Create pointer to base record object
12181225
if (isPtr || isPortIf) {
12191226
val = SValue(exprType);
12201227
state->putValue(val, bval);
12211228
state->setValueLevel(val, level+1);
1222-
//cout << "Pointer to base class variable val = " << val.asString() << endl;
1229+
//cout << " pointer to base class variable val = " << val << endl;
12231230
} else {
12241231
val = bval;
12251232
}
1226-
//cout << "Return val " << val.asString() << endl;
1233+
//cout << " return val " << val << endl;
12271234

12281235
} else {
12291236
// Do nothing, it can be SC data type cast

sc_tool/lib/sc_tool/expr/ScParseExpr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ class ScParseExpr {
132132
SValue getRecordFromState(const SValue& val,
133133
ArrayUnkwnMode returnUnknown = ArrayUnkwnMode::amNoValue);
134134

135-
/// Create record/module object value, not module/class variable
135+
/// Create record/module object value and parse its field declarations,
136+
/// no constructor function call. Used for arrays of record elements
136137
/// \param var -- local variable/member owns this record
137138
/// \param index -- local element number in single/multi dimensional array
138139
SValue createRecValue(const clang::CXXRecordDecl* recDecl,

sc_tool/lib/sc_tool/expr/ScParseExprValue.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,8 @@ void ScParseExprValue::parseExpr(CXXConstructExpr* expr, SValue& val)
700700
if (isCopyCtor) {
701701
// Copy constructor to pass record parameter by value
702702
if (!expr->getArg(0)) {
703-
SCT_TOOL_ASSERT (false, "No argument in copy constructor");
703+
SCT_INTERNAL_ERROR (expr->getBeginLoc(),
704+
"No argument in copy constructor");
704705
}
705706

706707
SValue rval = evalSubExpr(expr->getArg(0));
@@ -720,8 +721,10 @@ void ScParseExprValue::parseExpr(CXXConstructExpr* expr, SValue& val)
720721
} else {
721722
// Get normal record to create copy
722723
state->getValue(rval, rrec);
723-
SCT_TOOL_ASSERT (rrec.isRecord(),
724-
"Incorrect value type for copy constructor");
724+
if (!rrec.isRecord()) {
725+
SCT_INTERNAL_ERROR (expr->getBeginLoc(),
726+
"Incorrect value type for copy constructor");
727+
}
725728

726729
// Create record copy to avoid sharing the same record value
727730
// No set level as record is returned

sc_tool/lib/sc_tool/utils/CheckCppInheritance.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
#include "sc_tool/utils/CheckCppInheritance.h"
13+
#include "sc_tool/utils/ScTypeTraits.h"
1314
#include "clang/AST/DeclTemplate.h"
1415

1516
namespace sc {
@@ -101,21 +102,24 @@ pair<SValue, FunctionDecl*> getVirtualFunc(const SValue& tval,
101102

102103
// Find given class type in class hierarchy of @tval
103104
// \return base class value or NO_VALUE
104-
SValue getBaseClass(const SValue& tval, const QualType& baseType)
105+
SValue getBaseClass(const SValue& tval, QualType baseType)
105106
{
106107
SCT_TOOL_ASSERT (tval.isRecord(), "No record in getBaseClass()");
107108

108109
// Check if @tval has required type itself
109-
if (tval.getRecord().getType().getTypePtr() == baseType.getTypePtr()) {
110+
auto thisType = getPureType(tval.getRecord().getType());
111+
baseType = getPureType(baseType);
112+
if (thisType == baseType) {
110113
return tval;
111114
}
112115

113-
for (const auto& b : tval.getRecord().bases) {
114-
if (b.getRecord().getType().getTypePtr() == baseType.getTypePtr()) {
115-
return b;
116+
for (const auto& bval : tval.getRecord().bases) {
117+
thisType = getPureType(bval.getRecord().getType());
118+
if (thisType == baseType) {
119+
return bval;
116120
}
117121

118-
SValue res = getBaseClass(b, baseType);
122+
SValue res = getBaseClass(bval, baseType);
119123
if (res != NO_VALUE) {
120124
return res;
121125
}
@@ -162,7 +166,8 @@ void correctParentBaseClass(SValue& val)
162166
}
163167

164168
// Get direct base classes for module type
165-
std::vector<clang::Type*> getModuleBases(const clang::CXXRecordDecl* decl)
169+
// Not used
170+
/*std::vector<clang::Type*> getModuleBases(const clang::CXXRecordDecl* decl)
166171
{
167172
std::vector<clang::Type*> bases;
168173
for (auto&& b: decl->bases()) {
@@ -183,6 +188,6 @@ std::vector<clang::Type*> getModuleBases(const clang::CXXRecordDecl* decl)
183188
}
184189
}
185190
return bases;
186-
}
191+
}*/
187192

188193
}

0 commit comments

Comments
 (0)