"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "projects/CodeThorn/src/NormalizationCxx.C" between
rose-0.11.53.0.tar.gz and rose-0.11.54.0.tar.gz

About: ROSE is a compiler infrastructure to build source-to-source program transformation and analysis tools for large-scale C, C++, UPC, Fortran, OpenMP, Java, Python and PHP applications.

NormalizationCxx.C  (rose-0.11.53.0):NormalizationCxx.C  (rose-0.11.54.0)
skipping to change at line 121 skipping to change at line 121
/// returns the only SgInitializedName object of a variable declaration /// returns the only SgInitializedName object of a variable declaration
SgInitializedName& onlyName(const SgVariableDeclaration& n) SgInitializedName& onlyName(const SgVariableDeclaration& n)
{ {
const SgInitializedNamePtrList& lst = n.get_variables(); const SgInitializedNamePtrList& lst = n.get_variables();
ROSE_ASSERT(lst.size() == 1 && lst[0]); ROSE_ASSERT(lst.size() == 1 && lst[0]);
return *lst[0]; return *lst[0];
} }
SgBasicBlock&
getBody(const SgFunctionDeclaration& n)
{
return SG_DEREF(SG_DEREF(n.get_definition()).get_body());
}
SgType&
getReturnType(const SgFunctionDeclaration& n)
{
return SG_DEREF(SG_DEREF(n.get_type()).get_return_type());
}
void copyElements(const SgBasicBlock& src, SgBasicBlock& tgt)
{
for (const SgStatement* orig : src.get_statements())
{
SgStatement* copy = si::deepCopy(orig);
tgt.append_statement(copy);
}
}
// //
// transformation wrappers // transformation wrappers
// borrowed from XPlacer // borrowed from XPlacer
struct BaseTransform struct BaseTransform
{ {
virtual ~BaseTransform() = default; virtual ~BaseTransform() = default;
BaseTransform() = default; BaseTransform() = default;
virtual void execute(CxxTransformStats& stat) = 0; virtual void execute(CxxTransformStats& stat) = 0;
skipping to change at line 300 skipping to change at line 322
Memoizer<Fn> memoizer(Fn fn) Memoizer<Fn> memoizer(Fn fn)
{ {
return Memoizer<Fn>(fn); return Memoizer<Fn>(fn);
} }
// end memoization wrapper // end memoization wrapper
// //
// convenience functions + functors // convenience functions + functors
SgBasicBlock& getCtorBody(SgMemberFunctionDeclaration& n) SgBasicBlock& getCtorBody(const SgMemberFunctionDeclaration& n)
{ {
SgFunctionDefinition& def = SG_DEREF(n.get_definition()); SgFunctionDefinition& def = SG_DEREF(n.get_definition());
return SG_DEREF(def.get_body()); return SG_DEREF(def.get_body());
} }
SgClassDefinition& getClassDef(SgDeclarationStatement& n) SgClassDefinition& getClassDef(const SgDeclarationStatement& n)
{ {
SgDeclarationStatement& defdcl = SG_DEREF(n.get_definingDeclaration()); SgDeclarationStatement* defdcl = n.get_definingDeclaration();
SgClassDeclaration& clsdef = SG_ASSERT_TYPE(SgClassDeclaration, defdcl); SgClassDeclaration& clsdef = SG_DEREF(isSgClassDeclaration(defdcl));
return SG_DEREF(clsdef.get_definition()); return SG_DEREF(clsdef.get_definition());
} }
SgClassDefinition& getClassDef(SgMemberFunctionDeclaration& n) SgClassDefinition& getClassDef(const SgMemberFunctionDeclaration& n)
{ {
return getClassDef(SG_DEREF(n.get_associatedClassDeclaration())); return getClassDef(SG_DEREF(n.get_associatedClassDeclaration()));
} }
SgClassDefinition* getClassDefOpt(SgClassType& n) SgClassDefinition* getClassDefOpt(const SgClassType& n)
{ {
SgDeclarationStatement& dcl = SG_DEREF( n.get_declaration() ); SgDeclarationStatement& dcl = SG_DEREF( n.get_declaration() );
SgDeclarationStatement* defdcl = dcl.get_definingDeclaration(); SgDeclarationStatement* defdcl = dcl.get_definingDeclaration();
logWarn() << dcl.get_mangled_name() << std::endl; logWarn() << dcl.get_mangled_name() << std::endl;
return defdcl ? SG_ASSERT_TYPE(SgClassDeclaration, *defdcl).get_definition() return defdcl ? SG_ASSERT_TYPE(SgClassDeclaration, *defdcl).get_definition()
: nullptr : nullptr
; ;
} }
skipping to change at line 382 skipping to change at line 404
return sg::dispatch(TriviallyDestructible(), ty); return sg::dispatch(TriviallyDestructible(), ty);
} }
SgMemberFunctionDeclaration* SgMemberFunctionDeclaration*
isDtor(SgMemberFunctionDeclaration& n) isDtor(SgMemberFunctionDeclaration& n)
{ {
return n.get_specialFunctionModifier().isDestructor()? &n : nullptr; return n.get_specialFunctionModifier().isDestructor()? &n : nullptr;
} }
SgMemberFunctionDeclaration* SgMemberFunctionDeclaration*
isCtor(SgMemberFunctionDeclaration& n)
{
return n.get_specialFunctionModifier().isConstructor()? &n : nullptr;
}
SgMemberFunctionDeclaration*
isCtorDtor(SgMemberFunctionDeclaration& n)
{
SgMemberFunctionDeclaration* res = nullptr;
(res = isCtor(n)) || (res = isDtor(n));
return res;
}
SgMemberFunctionDeclaration*
isDtor(SgNode& n) isDtor(SgNode& n)
{ {
SgMemberFunctionDeclaration* dcl = isSgMemberFunctionDeclaration(&n); SgMemberFunctionDeclaration* dcl = isSgMemberFunctionDeclaration(&n);
return dcl ? isDtor(*dcl) : dcl; return dcl ? isDtor(*dcl) : dcl;
} }
/* /*
SgMemberFunctionDeclaration* SgMemberFunctionDeclaration*
isDtorBlock(SgBasicBlock& n) isDtorBlock(SgBasicBlock& n)
skipping to change at line 565 skipping to change at line 602
ConstructorInitializerListError(const std::string& what, SgInitializedName* ini) ConstructorInitializerListError(const std::string& what, SgInitializedName* ini)
: base(what), initname(ini) : base(what), initname(ini)
{} {}
SgInitializedName* initname; SgInitializedName* initname;
}; };
struct SameClassDef struct SameClassDef
{ {
explicit explicit
SameClassDef(SgBaseClass& base) SameClassDef(const SgClassDefinition& base)
: classdef(getClassDef(SG_DEREF(base.get_base_class()))) : classdef(base)
{} {}
bool operator()(SgInitializedName* cand) bool operator()(SgInitializedName* cand)
{ {
if (ERROR_TOLERANT && !(cand && cand->get_initializer())) if (ERROR_TOLERANT && !(cand && cand->get_initializer()))
{ {
throw ConstructorInitializerListError("unusual constructor list element" , cand); throw ConstructorInitializerListError("unusual constructor list element" , cand);
} }
ROSE_ASSERT(cand && cand->get_initializer()); ROSE_ASSERT(cand && cand->get_initializer());
skipping to change at line 590 skipping to change at line 627
// -> ignore // -> ignore
// \todo once we see a member variable initialization, the base class was not found, // \todo once we see a member variable initialization, the base class was not found,
// and the iteration can be aborted. // and the iteration can be aborted.
if (!ctorini) return false; if (!ctorini) return false;
SgMemberFunctionDeclaration& mfn = SG_DEREF( ctorini->get_declaration() ); SgMemberFunctionDeclaration& mfn = SG_DEREF( ctorini->get_declaration() );
return &getClassDef(mfn) == &classdef; return &getClassDef(mfn) == &classdef;
} }
SgClassDefinition& classdef; private:
const SgClassDefinition& classdef;
}; };
SgInitializer* // finds the initializer for a specific base class in the constructor initiali
getBaseInitializer(SgBaseClass& base, SgCtorInitializerList& ctorini) zer list
// returns nullptr if the class is default initialized.
// \{
SgConstructorInitializer*
getBaseInitializer(const SgClassDefinition& clsdef, SgCtorInitializerList& cto
rini)
{ {
SgInitializedNamePtrList& lst = ctorini.get_ctors(); SgInitializedNamePtrList& lst = ctorini.get_ctors();
SgInitializedNamePtrList::const_iterator pos = std::find_if(lst.begin(), lst .end(), SameClassDef(base)); SgInitializedNamePtrList::const_iterator pos = std::find_if(lst.begin(), lst .end(), SameClassDef{clsdef});
return (pos != lst.end()) ? (*pos)->get_initializer() : nullptr; return (pos != lst.end()) ? isSgConstructorInitializer((*pos)->get_initializ er()) : nullptr;
} }
SgConstructorInitializer*
getBaseInitializer(const SgClassDeclaration& clsdcl, SgCtorInitializerList& ct
orini)
{
return getBaseInitializer(getClassDef(clsdcl), ctorini);
}
SgConstructorInitializer*
getBaseInitializer(const SgBaseClass& base, SgCtorInitializerList& ctorini)
{
return getBaseInitializer(SG_DEREF(base.get_base_class()), ctorini);
}
// \}
SgArrayType* isArrayType(SgType* t) SgArrayType* isArrayType(SgType* t)
{ {
if (SgArrayType* arrty = isSgArrayType(t)) if (SgArrayType* arrty = isSgArrayType(t))
return arrty; return arrty;
if (SgTypedefType* tdty = isSgTypedefType(t)) if (SgTypedefType* tdty = isSgTypedefType(t))
return isArrayType(tdty->get_base_type()); return isArrayType(tdty->get_base_type());
if (SgModifierType* modty = isSgModifierType(t)) if (SgModifierType* modty = isSgModifierType(t))
return isArrayType(modty->get_base_type()); return isArrayType(modty->get_base_type());
skipping to change at line 1029 skipping to change at line 1083
} }
SgMemberFunctionDeclaration& SgMemberFunctionDeclaration&
mkCtorDtorDef(SgClassDefinition& clsdef, SgMemberFunctionDeclaration& nondef, bool ctor) mkCtorDtorDef(SgClassDefinition& clsdef, SgMemberFunctionDeclaration& nondef, bool ctor)
{ {
typedef SgTemplateInstantiationMemberFunctionDecl TemplateMemberFunction; typedef SgTemplateInstantiationMemberFunctionDecl TemplateMemberFunction;
ROSE_ASSERT(nondef.get_definingDeclaration() == nullptr); ROSE_ASSERT(nondef.get_definingDeclaration() == nullptr);
SgName nm = nondef.get_name(); SgName nm = nondef.get_name();
SgType& ty = SG_DEREF(nondef.get_orig_return_type()); SgType& ty = getReturnType(nondef);
SgFunctionParameterList& lst = SG_DEREF(sb::buildFunctionParameterList( )); SgFunctionParameterList& lst = SG_DEREF(sb::buildFunctionParameterList( ));
TemplateMemberFunction* tmpl = isSgTemplateInstantiationMemberFunctionD ecl(&nondef); TemplateMemberFunction* tmpl = isSgTemplateInstantiationMemberFunctionD ecl(&nondef);
SgMemberFunctionDeclaration* pdcl = sb::buildDefiningMemberFunctionDeclarati on( nm, SgMemberFunctionDeclaration* pdcl = sb::buildDefiningMemberFunctionDeclarati on( nm,
&ty, &ty,
&lst, &lst,
&clsdef, &clsdef,
nullptr /* decorator list */, nullptr /* decorator list */,
tmpl != nullptr /* build template instance */, tmpl != nullptr /* build template instance */,
0, 0,
&nondef, &nondef,
skipping to change at line 1124 skipping to change at line 1178
logInfo() << "link to default ctor" << std::endl; logInfo() << "link to default ctor" << std::endl;
// args is temporary // args is temporary
//~ SgExprListExp emptyargs; //~ SgExprListExp emptyargs;
ExprListGuard emptyargs{ sb::buildExprListExp() }; ExprListGuard emptyargs{ sb::buildExprListExp() };
SgClassDefinition& clsdef = getClassDef(SG_DEREF(clsty->get_declaration())); SgClassDefinition& clsdef = getClassDef(SG_DEREF(clsty->get_declaration()));
return &obtainGeneratableCtor( clsdef, *emptyargs ); return &obtainGeneratableCtor( clsdef, *emptyargs );
} }
struct BaseCtorCallTransformer /*
concept EmptyTransformer
{ {
BaseCtorCallTransformer(SgBasicBlock& where, SgBaseClass& what, SgInitiali EmptyTransformer(EmptyTransformer&&) = default;
zer* how) EmptyTransformer& operator=(EmptyTransformer&&) = default;
: blk(where), baseclass(what), ini(isSgConstructorInitializer(how))
{ EmptyTransformer() = delete;
// if how != nullptr then ini != nullptr EmptyTransformer(const EmptyTransformer&) = delete;
ROSE_ASSERT((!how) || ini); EmptyTransformer& operator=(const EmptyTransformer&&) = delete;
}
SgThisExp& mkThisExp(SgClassDeclaration& cls) const void execute(CxxTransformStats&);
};
*/
struct CtorCallCreator
{
CtorCallCreator(SgClassDefinition& clz, SgClassDeclaration& basecls, SgCon
structorInitializer* how)
: cls(clz), bsedcl(basecls), ini(how)
{}
/// returns static_cast<Base*>(this)
SgExpression& mkThisExpForBase(SgClassDeclaration& base) const
{ {
SgSymbol& sym = SG_DEREF( cls.search_for_symbol_from_symbol_table() ); SgClassDeclaration& clsdcl = SG_DEREF(cls.get_declaration());
SgSymbol& clssym = SG_DEREF(clsdcl.search_for_symbol_from_symb
ol_table());
SgThisExp& thisop = SG_DEREF(sb::buildThisExp(&clssym));
SgType& bseptr = SG_DEREF(sb::buildPointerType(base.get_type
()));
return SG_DEREF( sb::buildThisExp(&sym) ); return SG_DEREF(sb::buildCastExp(&thisop, &bseptr, SgCastExp::e_static_c ast));
} }
SgStatement& mkDefaultInitializer(SgClassDeclaration& clazz) const SgStatement& mkDefaultInitializer(SgClassDeclaration& clazz) const
{ {
SgExprListExp& args = SG_DEREF( sb::buildExprListExp() ); SgExprListExp& args = SG_DEREF( sb::buildExprListExp() );
SgMemberFunctionDeclaration& ctor = obtainGeneratableCtor(getClassDef(c lazz), args); SgMemberFunctionDeclaration& ctor = obtainGeneratableCtor(getClassDef(c lazz), args);
SgExpression& self = mkThisExp(clazz); SgExpression& self = mkThisExpForBase(clazz);
return createMemberCall(self, ctor, args, false /* non-virtual call */); return createMemberCall(self, ctor, args, false /* non-virtual call */);
} }
SgStatement& mkCtorCall() const SgStatement& mkCtorCall() const
{ {
SgClassDeclaration& clazz = SG_DEREF( baseclass.get_base_class() ); return ini ? createMemberCallFromConstructorInitializer(mkThisExpForBase
(bsedcl), *ini)
: mkDefaultInitializer(bsedcl);
}
if (!ini) return mkDefaultInitializer(clazz); private:
SgClassDefinition& cls;
SgClassDeclaration& bsedcl;
SgConstructorInitializer* ini;
};
SgExpression& self = mkThisExp(clazz); struct BaseCtorCallTransformer : CtorCallCreator
{
using base = CtorCallCreator;
return createMemberCallFromConstructorInitializer(self, *ini); BaseCtorCallTransformer(SgClassDefinition& clz, SgBasicBlock& where, SgBas
} eClass& baseclass, SgConstructorInitializer* how)
: base(clz, SG_DEREF(baseclass.get_base_class()), how), blk(where)
{}
void execute(CxxTransformStats&) void execute(CxxTransformStats&)
{ {
newStmt = &mkCtorCall(); newStmt = &base::mkCtorCall();
blk.prepend_statement(newStmt); blk.prepend_statement(newStmt);
} }
private: private:
SgBasicBlock& blk; SgBasicBlock& blk;
SgBaseClass& baseclass;
SgConstructorInitializer* ini;
SgStatement* newStmt = nullptr; SgStatement* newStmt = nullptr;
}; };
SgFunctionSymbol& SgFunctionSymbol&
get_symbol(SgFunctionDeclaration& fundecl) get_symbol(SgFunctionDeclaration& fundecl)
{ {
SgSymbol& symbl = SG_DEREF( fundecl.search_for_symbol_from_symbol_table() ); SgSymbol& symbl = SG_DEREF( fundecl.search_for_symbol_from_symbol_table() );
return SG_ASSERT_TYPE(SgFunctionSymbol, symbl); return SG_ASSERT_TYPE(SgFunctionSymbol, symbl);
skipping to change at line 1214 skipping to change at line 1290
blk.append_statement(newStmt); blk.append_statement(newStmt);
} }
private: private:
SgBasicBlock& blk; SgBasicBlock& blk;
SgBaseClass& baseclass; SgBaseClass& baseclass;
SgExprStatement* newStmt = nullptr; SgExprStatement* newStmt = nullptr;
}; };
#if 0
struct DtorCallCreator : sg::DispatchHandler<SgStatement*>
{
using base = sg::DispatchHandler<SgStatement*>;
explicit
DtorCallCreator(SgExpression& expr)
: base(), elem(expr)
{}
void descend(SgNode* n) { res = sg::dispatch(*this, n); }
SgForStatement&
createLoopOverArray(SgArrayType& arrty)
{
return ::createLoopOverArray<DtorCallCreator>(arrty);
}
void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
void handle(SgModifierType& n) { descend(n.get_base_type()); }
void handle(SgTypedefType& n) { descend(n.get_base_type()); }
void handle(SgPointerType& n) { descend(n.get_base_type()); }
void handle(SgClassType& n)
{
SgClassDefinition& clsdef = SG_DEREF( getClassDefOpt(n) );
SgExprListExp& args = SG_DEREF( sb::buildExprListExp()
);
SgMemberFunctionDeclaration& dtorDcl = obtainGeneratableDtor(clsdef, ar
gs);
res = &createMemberCall(elem, dtorDcl, args, false /* non-virtual call (
full type is known) */);
}
void handle(SgArrayType& n)
{
res = &createLoopOverArray(n);
}
private:
SgExpression& elem;
};
#endif
/// compares two /// compares two
bool sameObject(const SgNode* lhs, const SgNode* rhs) bool sameObject(const SgNode* lhs, const SgNode* rhs)
{ {
return dynamic_cast<const void*>(lhs) == dynamic_cast<const void*>(rhs); return dynamic_cast<const void*>(lhs) == dynamic_cast<const void*>(rhs);
} }
bool isNormalizedSageNode(const SgLocatedNode& n) bool isNormalizedSageNode(const SgLocatedNode& n)
{ {
static const std::string TRANSFORM = "transformation" ; static const std::string TRANSFORM = "transformation" ;
skipping to change at line 1515 skipping to change at line 1548
/// if \ref n is a SgBasicBlock, posInScope is needed to /// if \ref n is a SgBasicBlock, posInScope is needed to
/// destruct variables that have been allocated before posIn Scope. /// destruct variables that have been allocated before posIn Scope.
/// \param blk the block where the destructors need to be inserted /// \param blk the block where the destructors need to be inserted
/// \param pos insert position in blk /// \param pos insert position in blk
/// \param transf any new destruction will be added to the sequence of /// \param transf any new destruction will be added to the sequence of
/// transformations. /// transformations.
void recordScopedDestructors( SgScopeStatement& n, void recordScopedDestructors( SgScopeStatement& n,
SgStatement& posInScope, SgStatement& posInScope,
SgBasicBlock& blk, SgBasicBlock& blk,
SgStatement& pos, SgStatement& pos,
std::vector<AnyTransform>& transf transformation_container& transf
) )
{ {
SgInitializedNamePtrList vars = variableList(n, posInScope); SgInitializedNamePtrList vars = variableList(n, posInScope);
for (SgInitializedName* var : adapt::reverse(vars)) for (SgInitializedName* var : adapt::reverse(vars))
{ {
ROSE_ASSERT(var); ROSE_ASSERT(var);
if (!TriviallyDestructible::check(var->get_type())) if (!TriviallyDestructible::check(var->get_type()))
{ {
skipping to change at line 1550 skipping to change at line 1583
: pos(&where), blk(&block), limit(&outerLimit) : pos(&where), blk(&block), limit(&outerLimit)
{} {}
void execute(CxxTransformStats& stat) void execute(CxxTransformStats& stat)
{ {
logTrace() << "create block dtor: " << typeid(blk).name() logTrace() << "create block dtor: " << typeid(blk).name()
<< " to: " << typeid(limit).name() << " to: " << typeid(limit).name()
<< " // " << SrcLoc(*blk) << " // " << SrcLoc(*blk)
<< std::endl; << std::endl;
std::vector<AnyTransform> transf; transformation_container transf;
SgStatement* prev = pos; SgStatement* prev = pos;
for (SgScopeStatement* curr = blk; curr != limit; curr = si::getEnclosin gScope(curr)) for (SgScopeStatement* curr = blk; curr != limit; curr = si::getEnclosin gScope(curr))
{ {
recordScopedDestructors(SG_DEREF(curr), *prev, *blk, *pos, transf); recordScopedDestructors(SG_DEREF(curr), *prev, *blk, *pos, transf);
prev = curr; prev = curr;
} }
stat.cnt += transf.size(); stat.cnt += transf.size();
skipping to change at line 1881 skipping to change at line 1914
/*SgVariableSymbol* sym =*/ si::appendArg(fn.get_parameterList(), parm); /*SgVariableSymbol* sym =*/ si::appendArg(fn.get_parameterList(), parm);
fnty.set_return_type(sb::buildVoidType()); fnty.set_return_type(sb::buildVoidType());
} }
private: private:
SgFunctionDeclaration& fn; SgFunctionDeclaration& fn;
SgType& ty; SgType& ty;
}; };
struct FullCtorDtorTransformer
{
using VirtualBaseContainer = ClassData::VirtualBaseOrderContainer;
FullCtorDtorTransformer(SgMemberFunctionDeclaration& n, const VirtualBaseC
ontainer& vbases)
: ctordtor(n), virtualBases(vbases)
{}
FullCtorDtorTransformer(FullCtorDtorTransformer&& orig) = default;
~FullCtorDtorTransformer() = default;
FullCtorDtorTransformer& operator=(FullCtorDtorTransformer&&) = delete;
FullCtorDtorTransformer(const FullCtorDtorTransformer&) = delete;
FullCtorDtorTransformer& operator=(const FullCtorDtorTransformer&) = delet
e;
void execute(CxxTransformStats&)
{
using StmtInserter = void (SgBasicBlock::*)(SgStatement*);
std::string fullName = ctordtor.get_name();
fullName += 'v';
SgClassDefinition& clsdef = getClassDef(ctordtor);
SgMemberFunctionDeclaration* fulldclNondef = sb::buildNondefiningMemberF
unctionDeclaration(
fullName,
&getReturnType(
ctordtor),
si::deepCopy(ct
ordtor.get_parameterList()),
&clsdef,
nullptr /*decor
atorList*/,
0 /*functionCon
stVolatileFlags*/,
false /*buildTe
mplateInstantiation*/,
nullptr /*templ
ateArgumentsList*/
);
ROSE_ASSERT(fulldclNondef);
clsdef.append_member(fulldclNondef);
// create full ctor/dtor
SgMemberFunctionDeclaration& fulldcl = mkCtorDtorDef(clsdef, *fulldclNon
def, !isDtor(ctordtor));
// rename dtor/ctor
fulldcl.set_name(fullName);
SgBasicBlock& funbdy = getBody(fulldcl);
// copy the body
copyElements(getBody(fulldcl), funbdy);
SgCtorInitializerList& ctorlst = SG_DEREF(ctordtor.get_CtorInitia
lizerList());
StmtInserter inserter = isCtor(ctordtor) ? &SgBasicBlock
::append_statement
: &SgBasicBlock
::prepend_statement;
// add virtual base class constructor calls to constructor body
//~ for (const SgClassDefinition* bsecls : adapt::reverse(virtualBases))
for (int i = virtualBases.size(); i != 0; --i)
{
const SgClassDefinition* bsecls = virtualBases.at(i-1);
ROSE_ASSERT(bsecls);
// create: static_cast<Base*>(this)->Base(args as needed);
SgConstructorInitializer* ini = getBaseInitializer(*bsecls, ctorlst);
CtorCallCreator callCreator{clsdef, SG_DEREF(bsecls->get_dec
laration()), ini};
SgStatement& call = callCreator.mkCtorCall();
(funbdy.*inserter)(&call);
}
// add new constructor to class
newDtorCtor = &fulldcl;
clsdef.append_member(newDtorCtor);
}
private:
SgMemberFunctionDeclaration& ctordtor;
const VirtualBaseContainer& virtualBases;
SgMemberFunctionDeclaration* newDtorCtor = nullptr;
};
struct FullCtorDtorCallTransformer
{
explicit
FullCtorDtorCallTransformer(SgMemberFunctionRefExp& n)
: ctorDtorRef(n)
{}
SgMemberFunctionDeclaration&
findFullCtorDtor(SgMemberFunctionDeclaration& ctorDtor)
{
return ctorDtor; // \todo
}
void execute(CxxTransformStats&)
{
// find newly generated full constructor
SgMemberFunctionDeclaration& ctorDtor = SG_DEREF(ctorDtorRef.getAssociat
edMemberFunctionDeclaration());
SgMemberFunctionDeclaration& fullCtorDtor = findFullCtorDtor(ctorDtor);
SgSymbol* fullSym = fullCtorDtor.search_for_symbol_fr
om_symbol_table();
newCtorDtorRef = sb::buildMemberFunctionRefExp(isSgMemberFunctionSymbol(
fullSym), false /*nonvirtual*/, false /*w/o qualifier*/);
si::replaceExpression(&ctorDtorRef, newCtorDtorRef, true /* no delete */
);
}
private:
SgMemberFunctionRefExp& ctorDtorRef;
SgMemberFunctionRefExp* newCtorDtorRef = nullptr;
};
// //
// memoized functors // memoized functors
SgInitializedNamePtrList SgInitializedNamePtrList
extractNonStaticMemberVars(const SgClassDefinition* cls) extractNonStaticMemberVars(const SgClassDefinition* cls)
{ {
SgInitializedNamePtrList res; SgInitializedNamePtrList res;
for (SgDeclarationStatement* cand : cls->get_members()) for (SgDeclarationStatement* cand : cls->get_members())
{ {
skipping to change at line 1938 skipping to change at line 2081
ROSE_ASSERT(cand); ROSE_ASSERT(cand);
if (isVirtualBase(*cand)) if (isVirtualBase(*cand))
res.push_back(cand); res.push_back(cand);
} }
return res; return res;
} }
); );
struct GlobalClassAnalysis
{
static
const ClassAnalysis& get()
{
return SG_DEREF(globalClassAnalysis);
}
static
void init(SgProject* prj)
{
if (globalClassAnalysis)
return;
globalClassAnalysis = new ClassAnalysis(ct::analyzeClasses(prj));
}
static
void clear()
{
delete globalClassAnalysis;
}
private:
static ClassAnalysis* globalClassAnalysis;
};
ClassAnalysis* GlobalClassAnalysis::globalClassAnalysis = nullptr;
void clearMemoized() void clearMemoized()
{ {
logInfo() << getDirectNonVirtualBases << " getDirectNonVirtualBases - cache\ n" logInfo() << getDirectNonVirtualBases << " getDirectNonVirtualBases - cache\ n"
<< getAllVirtualBases << " getAllVirtualBases - cache\n" << getAllVirtualBases << " getAllVirtualBases - cache\n"
<< getMemberVars << " getMemberVars - cache\n" << getMemberVars << " getMemberVars - cache\n"
<< std::endl; << std::endl;
getDirectNonVirtualBases.clear(); getDirectNonVirtualBases.clear();
getAllVirtualBases.clear(); getAllVirtualBases.clear();
getMemberVars.clear(); getMemberVars.clear();
GlobalClassAnalysis::clear();
} }
// end memoized functors // end memoized functors
void normalizeCtorDef(SgMemberFunctionDeclaration& fun, transformation_contain er& cont) void normalizeCtorDef(SgMemberFunctionDeclaration& fun, transformation_contain er& cont)
{ {
if (!fun.get_definition()) return; if (!fun.get_definition()) return;
SgBasicBlock& blk = getCtorBody(fun); SgBasicBlock& blk = getCtorBody(fun);
SgClassDefinition& cls = getClassDef(fun); SgClassDefinition& cls = getClassDef(fun);
skipping to change at line 1977 skipping to change at line 2151
cont.emplace_back(MemberVariableCtorTransformer{blk, *var, ini}); cont.emplace_back(MemberVariableCtorTransformer{blk, *var, ini});
} }
// explicitly construct all direct non-virtual bases; // explicitly construct all direct non-virtual bases;
// execute the transformations in reverse order // execute the transformations in reverse order
// (the last transformation appears first in code) // (the last transformation appears first in code)
for (SgBaseClass* base : adapt::reverse(getDirectNonVirtualBases(&cls))) for (SgBaseClass* base : adapt::reverse(getDirectNonVirtualBases(&cls)))
{ {
try try
{ {
SgInitializer* ini = getBaseInitializer(*base, lst); SgConstructorInitializer* ini = getBaseInitializer(*base, lst);
cont.emplace_back(BaseCtorCallTransformer{blk, *base, ini}); cont.emplace_back(BaseCtorCallTransformer{cls, blk, *base, ini});
} }
catch (const ConstructorInitializerListError& err) catch (const ConstructorInitializerListError& err)
{ {
logError() << "Constructor Initializer List Error in: " << fun.get_name( ) << std::endl; logError() << "Constructor Initializer List Error in: " << fun.get_name( ) << std::endl;
if (err.initname == nullptr) if (err.initname == nullptr)
logError() << "An SgInitializedName element is NULL" << std::endl; logError() << "An SgInitializedName element is NULL" << std::endl;
else if (err.initname->get_initializer() == nullptr) else if (err.initname->get_initializer() == nullptr)
logError() << "An SgInitializedName element " << err.initname->get_nam e() << " has a NULL initializer: " logError() << "An SgInitializedName element " << err.initname->get_nam e() << " has a NULL initializer: "
<< err.initname->unparseToString() << err.initname->unparseToString()
<< std::endl; << std::endl;
else else
logError() << "Unknown condition" << std::endl; logError() << "Unknown condition" << std::endl;
logError() << "Skipping generation of one base class initializer!" << st d::endl; logError() << "Skipping generation of one base class initializer!" << st d::endl;
} }
} }
// log errors for unhandled virtual base classes // log errors for unhandled virtual base classes
if (getAllVirtualBases(&cls).size()) // virtual base class initialization is normalized elsewhere
{
logError() << "virtual base class normalization in constructor NOT YET IMP
LEMENTED: " << fun.get_name()
<< std::endl;
throw std::logic_error("virtual base class normalization in constructor NO
T YET IMPLEMENTED");
}
// the initializer list is emptied.
// while it is not part of the ICFG, its nodes would be seen by
// the normalization.
cont.emplace_back(CtorInitListTransformer{lst});
} }
void normalizeDtorDef(SgMemberFunctionDeclaration& fun, transformation_contain er& cont) void normalizeDtorDef(SgMemberFunctionDeclaration& fun, transformation_contain er& cont)
{ {
if (!fun.get_definition()) return; if (!fun.get_definition()) return;
SgBasicBlock& blk = getCtorBody(fun); SgBasicBlock& blk = getCtorBody(fun);
SgClassDefinition& cls = getClassDef(fun); SgClassDefinition& cls = getClassDef(fun);
// recordScopedDestructors(blk, blk, blk, cont); // recordScopedDestructors(blk, blk, blk, cont);
skipping to change at line 2143 skipping to change at line 2306
} }
/// adds constructors and destructors as needed and normalizes these functions /// adds constructors and destructors as needed and normalizes these functions
struct CxxCtorDtorGenerator : GeneratorBase struct CxxCtorDtorGenerator : GeneratorBase
{ {
using GeneratorBase::GeneratorBase; using GeneratorBase::GeneratorBase;
using GeneratorBase::handle; using GeneratorBase::handle;
void handle(SgNode& n); void handle(SgNode& n);
void handle(SgCtorInitializerList&) { /* skip */ }
void handle(SgConstructorInitializer& n) void handle(SgConstructorInitializer& n)
{ {
SgMemberFunctionDeclaration* ctor = n.get_declaration(); SgMemberFunctionDeclaration* ctor = n.get_declaration();
// do nothing if there is // do nothing if there is
// - no declaration // - no declaration
// - or has a definition // - or has a definition
if (!ctor || !needsCompilerGeneration(*ctor)) if (!ctor || !needsCompilerGeneration(*ctor))
{ {
SgClassDeclaration* cls = n.get_class_decl(); SgClassDeclaration* cls = n.get_class_decl();
skipping to change at line 2214 skipping to change at line 2379
}; };
void CxxCtorDtorGenerator::handle(SgNode& n) void CxxCtorDtorGenerator::handle(SgNode& n)
{ {
descend(*this, n); descend(*this, n);
} }
/// passes over object initialization /// passes over object initialization
/// breaks up an object declaration into allocation and initialization /// breaks up an object declaration into allocation and initialization
/// transformations if A is a non-trivial user defined type: /// transformations if A is a non-trivial user defined type:
/// A a = A(x, y, z); => A a; a->A(x, y, z); /// A a = A(x, y, z); => A a; a.A(x, y, z);
/// A* a = new A(1); => A* a = new A; a->A(1); /// A* a = new A(1); => A* a = new A; a->A(1);
/// a = new A(1); => a = new A; a->A(1); /// a = new A(1); => a = new A; a->A(1);
/// a = new (p) A(1); => a = p; a->A(1); /// a = new (p) A(1); => a = p; a->A(1);
/// delete a; => a->~A(); delete a; /// delete a; => a->~A(); delete a;
/// \todo array versions /// \todo array versions
struct CxxAllocInitSplitGenerator : GeneratorBase struct CxxAllocInitSplitGenerator : GeneratorBase
{ {
using GeneratorBase::GeneratorBase; using GeneratorBase::GeneratorBase;
using GeneratorBase::handle; using GeneratorBase::handle;
void descend(SgNode& n); void descend(SgNode& n);
void handle(SgNode& n) { descend(n); } void handle(SgNode& n) { descend(n); }
void handle(SgCtorInitializerList&) { /* skip */ }
void handle(SgInitializedName& n) void handle(SgInitializedName& n)
{ {
if (SgConstructorInitializer* init = constructorInitializer(n.get_initia lizer())) if (SgConstructorInitializer* init = constructorInitializer(n.get_initia lizer()))
record(InitSplitTransformer{n, *init}); record(InitSplitTransformer{n, *init});
varsym = isSgVariableSymbol(n.search_for_symbol_from_symbol_table()); varsym = isSgVariableSymbol(n.search_for_symbol_from_symbol_table());
// \note varsym can be null in case this is a forward function declarati on // \note varsym can be null in case this is a forward function declarati on
descend(n); descend(n);
} }
skipping to change at line 2280 skipping to change at line 2447
private: private:
SgVariableSymbol* varsym = nullptr; SgVariableSymbol* varsym = nullptr;
}; };
void CxxAllocInitSplitGenerator::descend(SgNode& n) void CxxAllocInitSplitGenerator::descend(SgNode& n)
{ {
::ct::descend(*this, n); ::ct::descend(*this, n);
} }
/// finds all allocation and deallocations (static and dynamic)
/// and replaces the constructors with constructors that also initialize
/// virtual base classes.
/// e.g.,
/// struct A : virtual B { A() {} }; A a; a.A();
/// =>
/// struct A : virtual B { A() {} Av() { this->B(); } }; A a; a.Av();
/// \details
/// Av is the full constructor that initializes both virtual and non-virtual
base classes. It needs
/// to be called whenever an element of A is allocated. Similarly, ~Av is th
e full destructor.
/// The "normal" constructors A and destructor ~A are only called from a der
ived type of A.
struct CxxVirtualBaseCtorDtorGenerator : GeneratorBase
{
using NewCtorDtorList = std::unordered_set<const SgMemberFunctionDeclarati
on*>;
CxxVirtualBaseCtorDtorGenerator( GeneratorBase::container& transf,
GeneratorBase::node_set& visited
)
: GeneratorBase(transf, visited), classes(&GlobalClassAnalysis::get()), ne
wCtorDtorList()
{}
using GeneratorBase::handle;
void descend(SgNode& n);
void handle(SgNode& n) { descend(n); }
void handle(SgCtorInitializerList&) { /* skip */ }
void handle(SgMemberFunctionRefExp& n)
{
using VirtualBaseContainer = ClassData::VirtualBaseOrderContainer;
SgMemberFunctionDeclaration& memdcl = SG_DEREF(n.getAssociatedMemberFu
nctionDeclaration());
SgMemberFunctionDeclaration* ctordtor = isCtorDtor(memdcl);
if (!ctordtor) return;
ClassKeyType classkey = &getClassDef(memdcl);
const ClassData& classdesc = classes->at(classkey);
const VirtualBaseContainer& virtualBases = classdesc.virtualBaseClassOrd
er();
// no transformation if there is no virtual base class
if (virtualBases.empty()) return;
// generate the new ctor dtor impl.
if (!alreadyProcessed(newCtorDtorList, ctordtor))
{
record(FullCtorDtorTransformer{memdcl, virtualBases});
}
// replace the reference to the ctor with a reference to the full ctor.
// unless this is a base class construction/destruction
record(FullCtorDtorCallTransformer{n});
}
private:
const ClassAnalysis* classes;
NewCtorDtorList newCtorDtorList;
};
void CxxVirtualBaseCtorDtorGenerator::descend(SgNode& n)
{
::ct::descend(*this, n);
}
SgType* optimizedReturnType(SgType& ty) SgType* optimizedReturnType(SgType& ty)
{ {
SgClassType* clsTy = isSgClassType(ty.stripType(STRIP_MODIFIER_ALIAS)); SgClassType* clsTy = isSgClassType(ty.stripType(STRIP_MODIFIER_ALIAS));
return (clsTy && !si::IsTrivial(clsTy)) ? &ty : nullptr; return (clsTy && !si::IsTrivial(clsTy)) ? &ty : nullptr;
} }
SgType* optimizedFunctionReturnType(SgFunctionType& ty) SgType* optimizedFunctionReturnType(SgFunctionType& ty)
{ {
return optimizedReturnType(SG_DEREF(ty.get_return_type())); return optimizedReturnType(SG_DEREF(ty.get_return_type()));
skipping to change at line 2316 skipping to change at line 2549
{ {
CxxRVOGenerator cpy(*this); CxxRVOGenerator cpy(*this);
cpy.rvoFunc = ctx; cpy.rvoFunc = ctx;
::ct::descend(cpy, n); ::ct::descend(cpy, n);
} }
void handle(SgNode& n) { descend(n); } void handle(SgNode& n) { descend(n); }
void handle(SgCtorInitializerList&) { /* skip */ }
void handle(SgReturnStmt& n) void handle(SgReturnStmt& n)
{ {
if (rvoFunc && !isSgNullExpression(n.get_expression())) if (rvoFunc && !isSgNullExpression(n.get_expression()))
{ {
//~ if (!isSgConstructorInitializer(n.get_expression())) //~ if (!isSgConstructorInitializer(n.get_expression()))
//~ std::cerr << ">> " << n.unparseToString() //~ std::cerr << ">> " << n.unparseToString()
//~ << "\n@" << sg::ancestor<SgFunctionDeclaration>(n).unp arseToString() //~ << "\n@" << sg::ancestor<SgFunctionDeclaration>(n).unp arseToString()
//~ << std::endl; //~ << std::endl;
ROSE_ASSERT(isSgConstructorInitializer(n.get_expression())); ROSE_ASSERT(isSgConstructorInitializer(n.get_expression()));
skipping to change at line 2390 skipping to change at line 2625
void loop(SgScopeStatement& n); void loop(SgScopeStatement& n);
// records a scope sequence for destructor generation // records a scope sequence for destructor generation
void recordScopeDestructors(SgStatement& n, SgBasicBlock& start, SgScopeSt atement& limit); void recordScopeDestructors(SgStatement& n, SgBasicBlock& start, SgScopeSt atement& limit);
// recursive tree traversal // recursive tree traversal
void descend(SgNode& n); void descend(SgNode& n);
void handle(SgNode& n) { descend(n); } void handle(SgNode& n) { descend(n); }
void handle(SgCtorInitializerList&) { /* skip */ }
void handle(SgWhileStmt& n) { loop(n); } void handle(SgWhileStmt& n) { loop(n); }
void handle(SgDoWhileStmt& n) { loop(n); } void handle(SgDoWhileStmt& n) { loop(n); }
void handle(SgForStatement& n) { loop(n); } void handle(SgForStatement& n) { loop(n); }
void handle(SgSwitchStatement& n) void handle(SgSwitchStatement& n)
{ {
breakScope = &n; breakScope = &n;
descend(n); descend(n);
} }
skipping to change at line 2519 skipping to change at line 2756
void CxxNormalizationCheck::reportNode(SgStatement& n, SgLocatedNode& offender ) void CxxNormalizationCheck::reportNode(SgStatement& n, SgLocatedNode& offender )
{ {
std::cerr << "wanted: " << n.unparseToString() std::cerr << "wanted: " << n.unparseToString()
<< " <" << typeid(offender).name() << ">" << " <" << typeid(offender).name() << ">"
<< " parent = " << typeid(*n.get_parent()).name() << " parent = " << typeid(*n.get_parent()).name()
<< "\n@" << SrcLoc(offender) << " / " << SrcLoc(*isSgLocatedNode(n .get_parent())) << "\n@" << SrcLoc(offender) << " / " << SrcLoc(*isSgLocatedNode(n .get_parent()))
<< std::endl; << std::endl;
} }
struct CxxCleanCtorInitlistGenerator : GeneratorBase
{
using GeneratorBase::GeneratorBase;
using GeneratorBase::handle;
// recursive tree traversal
void descend(SgNode& n);
void handle(SgNode& n) { descend(n); }
void handle(SgCtorInitializerList&) { /* skip */ }
void handle(SgMemberFunctionDeclaration& n)
{
if (SgCtorInitializerList* lst = n.get_CtorInitializerList())
record(CtorInitListTransformer{*lst});
}
};
void CxxCleanCtorInitlistGenerator::descend(SgNode& n)
{
::ct::descend(*this, n);
}
template <class Transformer> template <class Transformer>
GeneratorBase::container GeneratorBase::container
computeTransform(SgNode* root, CxxTransformStats& stats) computeTransform(SgNode* root, CxxTransformStats& stats)
{ {
GeneratorBase::container transformations; GeneratorBase::container transformations;
GeneratorBase::node_set nodes; GeneratorBase::node_set nodes;
sg::dispatch(Transformer{transformations, nodes}, root); sg::dispatch(Transformer{transformations, nodes}, root);
stats.cnt += transformations.size(); stats.cnt += transformations.size();
return transformations; return transformations;
} }
using CxxTransformGenerator = std::function<std::vector<AnyTransform>(SgNode*, CxxTransformStats&)>; using CxxTransformGenerator = std::function<transformation_container(SgNode*, CxxTransformStats&)>;
void normalize(CxxTransformGenerator gen, SgNode* root, CxxTransformStats& sta ts) void normalize(CxxTransformGenerator gen, SgNode* root, CxxTransformStats& sta ts)
{ {
for (AnyTransform& tf : gen(root, stats)) for (AnyTransform& tf : gen(root, stats))
tf.execute(stats); tf.execute(stats);
} }
template <class Transformer> template <class Transformer>
void normalize(SgNode* root, std::string msg) void normalize(SgNode* root, std::string msg)
{ {
skipping to change at line 2565 skipping to change at line 2826
} // anonymous namespace } // anonymous namespace
// //
// externally visible function // externally visible function
void normalizeCxx1(Normalization& norm, SgNode* root) void normalizeCxx1(Normalization& norm, SgNode* root)
{ {
logInfo() << "Starting C++ normalization. (Phase 1/2)" << std::endl; logInfo() << "Starting C++ normalization. (Phase 1/2)" << std::endl;
logTrace() << "Not normalizing templates.." << std::endl; logTrace() << "Not normalizing templates.." << std::endl;
GlobalClassAnalysis::init(isSgProject(root));
//~ normalize<CxxCtorDtorGenerator>(root, "terrific C++ ctor/dtor normalizat ions..."); //~ normalize<CxxCtorDtorGenerator>(root, "terrific C++ ctor/dtor normalizat ions...");
logInfo() << "Finished C++ normalization. (Phase 1/2)" << std::endl; logInfo() << "Finished C++ normalization. (Phase 1/2)" << std::endl;
} }
void normalizeCxx2(Normalization& norm, SgNode* root) void normalizeCxx2(Normalization& norm, SgNode* root)
{ {
logInfo() << "Starting C++ normalization. (Phase 2/2)" << std::endl; logInfo() << "Starting C++ normalization. (Phase 2/2)" << std::endl;
logTrace() << "Not normalizing templates.." << std::endl; logTrace() << "Not normalizing templates.." << std::endl;
normalize<CxxCtorDtorGenerator> (root, "awesome C++ ctor/dtor normal // create ctor/dtor if needed and not available
izations..."); normalize<CxxCtorDtorGenerator> (root, "awesome C++ ctor/dtor norm
normalize<CxxAllocInitSplitGenerator> (root, "brilliant C++ alloc/init spl alizations...");
its...");
normalize<CxxRVOGenerator> (root, "crucial C++ return value opt // splits allocation and initialization
imizations..."); normalize<CxxAllocInitSplitGenerator> (root, "brilliant C++ alloc/init s
normalize<CxxObjectDestructionGenerator>(root, "delightful C++ object destru plits...");
ction insertion...");
normalize<CxxNormalizationCheck> (root, "checking AST for unwanted no // return value optimization
des..."); normalize<CxxRVOGenerator> (root, "crucial C++ return value o
ptimizations...");
// inserts object destruction into blocks
normalize<CxxObjectDestructionGenerator> (root, "delightful C++ object dest
ruction insertion...");
// inserts calls to virtual base class constructor and destructor
// generates full constructors (those that initialize the virtual bases) a
nd destructors if needed
// replaces references to constructors
normalize<CxxVirtualBaseCtorDtorGenerator>(root, "extraordinary C++ ctor/dto
r w/ virtual base class normalizations...");
// last pass that removes AST nodes from the initializer list. They have bee
n moved into the appropriate
// destructors, and now they are removed so that any subsequent traversal wi
ll not see them.
normalize<CxxCleanCtorInitlistGenerator> (root, "fantastic C++ ctor initial
izer list normalizations...");
// check if any unwanted nodes remain in the AST
normalize<CxxNormalizationCheck> (root, "checking AST for unwanted
nodes...");
clearMemoized(); clearMemoized();
logInfo() << "Finished C++ normalization. (Phase 2/2)" << std::endl; logInfo() << "Finished C++ normalization. (Phase 2/2)" << std::endl;
} }
bool cppCreatesTemporaryObject(const SgExpression* n, bool withCplusplus) bool cppCreatesTemporaryObject(const SgExpression* n, bool withCplusplus)
{ {
if (!withCplusplus) return false; if (!withCplusplus) return false;
ASSERT_not_null(n); ASSERT_not_null(n);
 End of changes. 45 change blocks. 
110 lines changed or deleted 423 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)