#include #include "AST.h" #include "BadSubfield.h" #include "ClassDecl.h" #include "FieldDecl.h" #include "PrimitiveDecl.h" #include "Subfield.h" //////////////////////////////////////////////////////////////////////// void FieldAccessNode::checkEmbeddedLocals() { assert( !accessedObjectType()->isLocal() ); list< BadSubfield > badFields; type()->decl()->collectEmbeddedLocals( badFields ); if (!badFields.empty()) { error() << "cannot copy " << decl()->errorName() << " across a global reference:" << endl; for (list< BadSubfield >::const_iterator subfield = badFields.begin(); subfield != badFields.end(); ++subfield) subfield->source.message() << "\tsubfield " << subfield->name << " is local" << endl; } } void BroadcastNode::checkEmbeddedLocals() { list< BadSubfield > badFields; const TypeNode &exprType = *expr()->type(); exprType.decl()->collectEmbeddedLocals( badFields ); if (!badFields.empty()) { expr()->error() << "cannot broadcast " << exprType.decl()->errorName() << ':' << endl; for (list< BadSubfield >::const_iterator subfield = badFields.begin(); subfield != badFields.end(); ++subfield) subfield->source.message() << "\tsubfield " << subfield->name << " is local" << endl; } } //////////////////////////////////////////////////////////////////////// void ClassDecl::collectEmbeddedLocals( list< BadSubfield > &collection, const Subfield *parent ) { if (modifiers() & Common::Immutable) foriter (field, environ()->allProperDecls( Field ), EnvironIter) { const FieldDecl &fieldDecl = static_cast< FieldDecl & >( *field ); fieldDecl.collectEmbeddedLocals( collection, parent ); } } void PrimitiveDecl::collectEmbeddedLocals( list< BadSubfield > &, const Subfield * ) { } extern bool immutableClassContains(ClassDecl *outer, ClassDecl *target, bool topmostcall=true); void FieldDecl::collectEmbeddedLocals( list< BadSubfield > &collection, const Subfield *parent ) const { if (!isStatic()) { Subfield me( *this, parent ); if (type()->isLocal()) collection.push_back( me ); else if (type()->isImmutable() && !immutableClassContains((ClassDecl*)type()->decl(), container())) /* need to watch for cycles (PR370) */ type()->decl()->collectEmbeddedLocals( collection, &me ); } } //////////////////////////////////////////////////////////////////////// bool ClassDecl::containsEmbeddedLocals() { if (modifiers() & Common::Immutable) foriter (field, environ()->allProperDecls( Field ), EnvironIter) { const FieldDecl &fieldDecl = static_cast< FieldDecl & >( *field ); if (fieldDecl.containsEmbeddedLocals()) return true; } return false; } bool PrimitiveDecl::containsEmbeddedLocals() { return false; } bool FieldDecl::containsEmbeddedLocals() const { return !isStatic() && (type()->isLocal() || (type()->isImmutable() && !type()->isTitaniumArrayType() /* PR656: prevent inf recursion */ && type()->decl()->containsEmbeddedLocals())); }