// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // DeclarationNode.cc -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 12:34:05 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Wed Sep 14 23:13:28 2016 // Update Count : 502 // #include #include #include #include #include #include "TypeData.h" #include "SynTree/Declaration.h" #include "SynTree/Expression.h" #include "TypedefTable.h" extern TypedefTable typedefTable; using namespace std; // These must remain in the same order as the corresponding DeclarationNode enumerations. const char *DeclarationNode::storageName[] = { "extern", "static", "auto", "register", "inline", "fortran", "_Noreturn", "_Thread_local", "NoStorageClass" }; const char *DeclarationNode::qualifierName[] = { "const", "restrict", "volatile", "lvalue", "_Atomic", "NoQualifier" }; const char *DeclarationNode::basicTypeName[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "NoBasicType" }; const char *DeclarationNode::complexTypeName[] = { "_Complex", "_Imaginary", "NoComplexType" }; const char *DeclarationNode::signednessName[] = { "signed", "unsigned", "NoSignedness" }; const char *DeclarationNode::lengthName[] = { "short", "long", "long long", "NoLength" }; const char *DeclarationNode::aggregateName[] = { "struct", "union", "context" }; const char *DeclarationNode::typeClassName[] = { "otype", "dtype", "ftype" }; const char *DeclarationNode::builtinTypeName[] = { "__builtin_va_list" }; UniqueName DeclarationNode::anonymous( "__anonymous" ); extern LinkageSpec::Spec linkage; // defined in parser.yy DeclarationNode::DeclarationNode() : type( 0 ), storageClass( NoStorageClass ), isInline( false ), isNoreturn( false ), bitfieldWidth( 0 ), initializer( 0 ), hasEllipsis( false ), linkage( ::linkage ), extension( false ) { variable.tyClass = DeclarationNode::Otype; variable.assertions = nullptr; attr.expr = nullptr; attr.type = nullptr; } DeclarationNode::~DeclarationNode() { delete attr.expr; delete attr.type; delete type; delete bitfieldWidth; delete initializer; } DeclarationNode *DeclarationNode::clone() const { DeclarationNode *newnode = new DeclarationNode; newnode->type = maybeClone( type ); newnode->name = name; newnode->storageClass = storageClass; newnode->isInline = isInline; newnode->isNoreturn = isNoreturn; newnode->bitfieldWidth = maybeClone( bitfieldWidth ); newnode->hasEllipsis = hasEllipsis; newnode->initializer = maybeClone( initializer ); newnode->set_next( maybeClone( get_next() ) ); newnode->linkage = linkage; newnode->variable.assertions = maybeClone( variable.assertions ); newnode->variable.name = variable.name; newnode->variable.tyClass = variable.tyClass; newnode->attr.expr = maybeClone( attr.expr ); newnode->attr.type = maybeClone( attr.type ); return newnode; } // DeclarationNode::clone bool DeclarationNode::get_hasEllipsis() const { return hasEllipsis; } void DeclarationNode::print( std::ostream &os, int indent ) const { os << string( indent, ' ' ); if ( name == "" ) { os << "unnamed: "; } else { os << name << ": "; } // if if ( linkage != LinkageSpec::Cforall ) { os << LinkageSpec::toString( linkage ) << " "; } // if if ( storageClass != NoStorageClass ) os << DeclarationNode::storageName[storageClass] << ' '; if ( isInline ) os << DeclarationNode::storageName[Inline] << ' '; if ( isNoreturn ) os << DeclarationNode::storageName[Noreturn] << ' '; if ( type ) { type->print( os, indent ); } else { os << "untyped entity "; } // if if ( bitfieldWidth ) { os << endl << string( indent + 2, ' ' ) << "with bitfield width "; bitfieldWidth->printOneLine( os ); } // if if ( initializer != 0 ) { os << endl << string( indent + 2, ' ' ) << "with initializer "; initializer->printOneLine( os ); os << " maybe constructed? " << initializer->get_maybeConstructed(); } // if os << endl; } void DeclarationNode::printList( std::ostream &os, int indent ) const { ParseNode::printList( os, indent ); if ( hasEllipsis ) { os << string( indent, ' ' ) << "and a variable number of other arguments" << endl; } // if } DeclarationNode *DeclarationNode::newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param, StatementNode *body, bool newStyle ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); newnode->type = new TypeData( TypeData::Function ); newnode->type->function.params = param; newnode->type->function.newStyle = newStyle; newnode->type->function.body = body; typedefTable.addToEnclosingScope( newnode->name, TypedefTable::ID ); if ( body ) { newnode->type->function.hasBody = true; } // if if ( ret ) { newnode->type->base = ret->type; ret->type = 0; delete ret; } // if return newnode; } // DeclarationNode::newFunction DeclarationNode * DeclarationNode::newQualifier( Qualifier q ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData(); newnode->type->qualifiers[ q ] = 1; return newnode; } // DeclarationNode::newQualifier DeclarationNode * DeclarationNode::newForall( DeclarationNode *forall ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Unknown ); newnode->type->forall = forall; return newnode; } // DeclarationNode::newForall DeclarationNode * DeclarationNode::newStorageClass( DeclarationNode::StorageClass sc ) { DeclarationNode *newnode = new DeclarationNode; //switch (sc) { // case Inline: newnode->isInline = true; break; // case Noreturn: newnode->isNoreturn = true; break; // default: newnode->storageClass = sc; break; //} newnode->storageClass = sc; return newnode; } // DeclarationNode::newStorageClass DeclarationNode * DeclarationNode::newBasicType( BasicType bt ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Basic ); newnode->type->basictype = bt; return newnode; } // DeclarationNode::newBasicType DeclarationNode * DeclarationNode::newComplexType( ComplexType ct ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Basic ); newnode->type->complextype = ct; return newnode; } // DeclarationNode::newComplexType DeclarationNode * DeclarationNode::newSignedNess( Signedness sn ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Basic ); newnode->type->signedness = sn; return newnode; } // DeclarationNode::newSignedNess DeclarationNode * DeclarationNode::newLength( Length lnth ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Basic ); newnode->type->length = lnth; return newnode; } // DeclarationNode::newLength DeclarationNode * DeclarationNode::newFromTypedef( std::string *name ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::SymbolicInst ); newnode->type->symbolic.name = assign_strptr( name ); newnode->type->symbolic.isTypedef = true; newnode->type->symbolic.params = 0; return newnode; } // DeclarationNode::newFromTypedef DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const std::string *name, ExpressionNode *actuals, DeclarationNode *fields, bool body ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Aggregate ); newnode->type->aggregate.kind = kind; newnode->type->aggregate.name = assign_strptr( name ); if ( newnode->type->aggregate.name == "" ) { // anonymous aggregate ? newnode->type->aggregate.name = anonymous.newName(); } // if newnode->type->aggregate.actuals = actuals; newnode->type->aggregate.fields = fields; newnode->type->aggregate.body = body; return newnode; } // DeclarationNode::newAggregate DeclarationNode *DeclarationNode::newEnum( std::string *name, DeclarationNode *constants ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); newnode->type = new TypeData( TypeData::Enum ); newnode->type->enumeration.name = newnode->name; if ( newnode->type->enumeration.name == "" ) { // anonymous enumeration ? newnode->type->enumeration.name = DeclarationNode::anonymous.newName(); } // if newnode->type->enumeration.constants = constants; return newnode; } // DeclarationNode::newEnum DeclarationNode *DeclarationNode::newEnumConstant( std::string *name, ExpressionNode *constant ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); newnode->enumeratorValue.reset( constant ); typedefTable.addToEnclosingScope( newnode->name, TypedefTable::ID ); return newnode; } // DeclarationNode::newEnumConstant DeclarationNode *DeclarationNode::newName( std::string *name ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); return newnode; } // DeclarationNode::newName DeclarationNode *DeclarationNode::newFromTypeGen( std::string *name, ExpressionNode *params ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::SymbolicInst ); newnode->type->symbolic.name = assign_strptr( name ); newnode->type->symbolic.isTypedef = false; newnode->type->symbolic.actuals = params; return newnode; } // DeclarationNode::newFromTypeGen DeclarationNode *DeclarationNode::newTypeParam( TypeClass tc, std::string *name ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); newnode->type = new TypeData( TypeData::Variable ); newnode->variable.tyClass = tc; newnode->variable.name = newnode->name; return newnode; } // DeclarationNode::newTypeParam DeclarationNode *DeclarationNode::newTrait( std::string *name, DeclarationNode *params, DeclarationNode *asserts ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Aggregate ); newnode->type->aggregate.kind = Trait; newnode->type->aggregate.params = params; newnode->type->aggregate.fields = asserts; newnode->type->aggregate.name = assign_strptr( name ); return newnode; } // DeclarationNode::newTrait DeclarationNode *DeclarationNode::newTraitUse( std::string *name, ExpressionNode *params ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::AggregateInst ); newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate ); newnode->type->aggInst.aggregate->aggregate.kind = Trait; newnode->type->aggInst.aggregate->aggregate.name = assign_strptr( name ); newnode->type->aggInst.params = params; return newnode; } // DeclarationNode::newTraitUse DeclarationNode *DeclarationNode::newTypeDecl( std::string *name, DeclarationNode *typeParams ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); newnode->type = new TypeData( TypeData::Symbolic ); newnode->type->symbolic.isTypedef = false; newnode->type->symbolic.params = typeParams; newnode->type->symbolic.name = newnode->name; return newnode; } // DeclarationNode::newTypeDecl DeclarationNode *DeclarationNode::newPointer( DeclarationNode *qualifiers ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Pointer ); return newnode->addQualifiers( qualifiers ); } // DeclarationNode::newPointer DeclarationNode *DeclarationNode::newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Array ); newnode->type->array.dimension = size; newnode->type->array.isStatic = isStatic; if ( newnode->type->array.dimension == 0 || newnode->type->array.dimension->isExpressionType() ) { newnode->type->array.isVarLen = false; } else { newnode->type->array.isVarLen = true; } // if return newnode->addQualifiers( qualifiers ); } // DeclarationNode::newArray DeclarationNode *DeclarationNode::newVarArray( DeclarationNode *qualifiers ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Array ); newnode->type->array.dimension = 0; newnode->type->array.isStatic = false; newnode->type->array.isVarLen = true; return newnode->addQualifiers( qualifiers ); } DeclarationNode *DeclarationNode::newBitfield( ExpressionNode *size ) { DeclarationNode *newnode = new DeclarationNode; newnode->bitfieldWidth = size; return newnode; } DeclarationNode *DeclarationNode::newTuple( DeclarationNode *members ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Tuple ); newnode->type->tuple = members; return newnode; } DeclarationNode *DeclarationNode::newTypeof( ExpressionNode *expr ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Typeof ); newnode->type->typeexpr = expr; return newnode; } DeclarationNode * DeclarationNode::newBuiltinType( BuiltinType bt ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Builtin ); newnode->builtin = bt; return newnode; } // DeclarationNode::newBuiltinType DeclarationNode *DeclarationNode::newAttr( std::string *name, ExpressionNode *expr ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Attr ); newnode->attr.name = assign_strptr( name ); newnode->attr.expr = expr; return newnode; } DeclarationNode *DeclarationNode::newAttr( std::string *name, DeclarationNode *type ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Attr ); newnode->attr.name = assign_strptr( name ); newnode->attr.type = type; return newnode; } void appendError( string & dst, const string & src ) { if ( src.empty() ) return; if ( dst.empty() ) { dst = src; return; } dst += ", " + src; } // appendError void DeclarationNode::checkQualifiers( const TypeData *src, const TypeData *dst ) { TypeData::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization if ( (qsrc & qdst).any() ) { // common qualifier ? for ( int i = 0; i < NoQualifier; i += 1 ) { // find common qualifiers if ( qsrc[i] && qdst[i] ) { appendError( error, string( "duplicate " ) + DeclarationNode::qualifierName[i] ); } // if } // for } // if } // DeclarationNode::checkQualifiers void DeclarationNode::checkStorageClasses( DeclarationNode *q ) { if ( storageClass != NoStorageClass && q->storageClass != NoStorageClass ) { if ( storageClass == q->storageClass ) { // duplicate qualifier appendError( error, string( "duplicate " ) + storageName[ storageClass ] ); } else { // only one storage class appendError( error, string( "conflicting " ) + storageName[ storageClass ] + " & " + storageName[ q->storageClass ] ); q->storageClass = storageClass; // FIX ERROR, prevent assertions from triggering } // if } // if appendError( error, q->error ); } // DeclarationNode::copyStorageClasses DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) { isInline = isInline || q->isInline; isNoreturn = isNoreturn || q->isNoreturn; // do not overwrite an existing value with NoStorageClass if ( q->storageClass != NoStorageClass ) { assert( storageClass == NoStorageClass || storageClass == q->storageClass ); storageClass = q->storageClass; } // if return this; } // DeclarationNode::copyStorageClasses static void addQualifiersToType( TypeData *&src, TypeData *dst ) { if ( src->forall && dst->kind == TypeData::Function ) { if ( dst->forall ) { dst->forall->appendList( src->forall ); } else { dst->forall = src->forall; } // if src->forall = 0; } // if if ( dst->base ) { addQualifiersToType( src, dst->base ); } else if ( dst->kind == TypeData::Function ) { dst->base = src; src = 0; } else { dst->qualifiers |= src->qualifiers; } // if } // addQualifiersToType DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) { if ( ! q ) return this; checkStorageClasses( q ); copyStorageClasses( q ); if ( ! q->type ) { delete q; return this; } if ( ! type ) { // type = new TypeData; type = q->type; return this; } // if checkQualifiers( q->type, type ); addQualifiersToType( q->type, type ); if ( q->type->forall ) { if ( type->forall ) { type->forall->appendList( q->type->forall ); } else { if ( type->kind == TypeData::Aggregate ) { type->aggregate.params = q->type->forall; // change implicit typedef from TYPEDEFname to TYPEGENname typedefTable.changeKind( type->aggregate.name, TypedefTable::TG ); } else { type->forall = q->type->forall; } // if } // if q->type->forall = 0; } // if delete q; return this; } // addQualifiers static void addTypeToType( TypeData *&src, TypeData *&dst ) { if ( src->forall && dst->kind == TypeData::Function ) { if ( dst->forall ) { dst->forall->appendList( src->forall ); } else { dst->forall = src->forall; } // if src->forall = 0; } // if if ( dst->base ) { addTypeToType( src, dst->base ); } else { switch ( dst->kind ) { case TypeData::Unknown: src->qualifiers |= dst->qualifiers; dst = src; src = 0; break; case TypeData::Basic: dst->qualifiers |= src->qualifiers; if ( src->kind != TypeData::Unknown ) { assert( src->kind == TypeData::Basic ); if ( dst->basictype == DeclarationNode::NoBasicType ) { dst->basictype = src->basictype; } else if ( src->basictype != DeclarationNode::NoBasicType ) throw SemanticError( std::string( "conflicting type specifier " ) + DeclarationNode::basicTypeName[ src->basictype ] + " in type: ", src ); if ( dst->complextype == DeclarationNode::NoComplexType ) { dst->complextype = src->complextype; } else if ( src->complextype != DeclarationNode::NoComplexType ) throw SemanticError( std::string( "conflicting type specifier " ) + DeclarationNode::complexTypeName[ src->complextype ] + " in type: ", src ); if ( dst->signedness == DeclarationNode::NoSignedness ) { dst->signedness = src->signedness; } else if ( src->signedness != DeclarationNode::NoSignedness ) throw SemanticError( std::string( "conflicting type specifier " ) + DeclarationNode::signednessName[ src->signedness ] + " in type: ", src ); if ( dst->length == DeclarationNode::NoLength ) { dst->length = src->length; } else if ( dst->length == DeclarationNode::Long && src->length == DeclarationNode::Long ) { dst->length = DeclarationNode::LongLong; } else if ( src->length != DeclarationNode::NoLength ) throw SemanticError( std::string( "conflicting type specifier " ) + DeclarationNode::lengthName[ src->length ] + " in type: ", src ); } // if break; default: switch ( src->kind ) { case TypeData::Aggregate: case TypeData::Enum: dst->base = new TypeData( TypeData::AggregateInst ); dst->base->aggInst.aggregate = src; if ( src->kind == TypeData::Aggregate ) { dst->base->aggInst.params = maybeClone( src->aggregate.actuals ); } // if dst->base->qualifiers |= src->qualifiers; src = 0; break; default: if ( dst->forall ) { dst->forall->appendList( src->forall ); } else { dst->forall = src->forall; } // if src->forall = 0; dst->base = src; src = 0; } // switch } // switch } // if } DeclarationNode *DeclarationNode::addType( DeclarationNode *o ) { if ( o ) { checkStorageClasses( o ); copyStorageClasses( o ); if ( o->type ) { if ( ! type ) { if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) { type = new TypeData( TypeData::AggregateInst ); type->aggInst.aggregate = o->type; if ( o->type->kind == TypeData::Aggregate ) { type->aggInst.params = maybeClone( o->type->aggregate.actuals ); } // if type->qualifiers |= o->type->qualifiers; } else { type = o->type; } // if o->type = 0; } else { addTypeToType( o->type, type ); } // if } // if if ( o->bitfieldWidth ) { bitfieldWidth = o->bitfieldWidth; } // if // there may be typedefs chained onto the type if ( o->get_next() ) { set_last( o->get_next()->clone() ); } // if } // if delete o; return this; } DeclarationNode *DeclarationNode::addTypedef() { TypeData *newtype = new TypeData( TypeData::Symbolic ); newtype->symbolic.params = 0; newtype->symbolic.isTypedef = true; newtype->symbolic.name = name; newtype->base = type; type = newtype; return this; } DeclarationNode *DeclarationNode::addAssertions( DeclarationNode *assertions ) { assert( type ); switch ( type->kind ) { case TypeData::Symbolic: if ( type->symbolic.assertions ) { type->symbolic.assertions->appendList( assertions ); } else { type->symbolic.assertions = assertions; } // if break; case TypeData::Variable: if ( variable.assertions ) { variable.assertions->appendList( assertions ); } else { variable.assertions = assertions; } // if break; default: assert( false ); } // switch return this; } DeclarationNode *DeclarationNode::addName( std::string *newname ) { name = assign_strptr( newname ); return this; } DeclarationNode *DeclarationNode::addBitfield( ExpressionNode *size ) { bitfieldWidth = size; return this; } DeclarationNode *DeclarationNode::addVarArgs() { assert( type ); hasEllipsis = true; return this; } DeclarationNode *DeclarationNode::addFunctionBody( StatementNode *body ) { assert( type ); assert( type->kind == TypeData::Function ); assert( type->function.body == 0 ); type->function.body = body; type->function.hasBody = true; return this; } DeclarationNode *DeclarationNode::addOldDeclList( DeclarationNode *list ) { assert( type ); assert( type->kind == TypeData::Function ); assert( type->function.oldDeclList == 0 ); type->function.oldDeclList = list; return this; } static void setBase( TypeData *&type, TypeData *newType ) { if ( type ) { TypeData *prevBase = type; TypeData *curBase = type->base; while ( curBase != 0 ) { prevBase = curBase; curBase = curBase->base; } // while prevBase->base = newType; } else { type = newType; } // if } DeclarationNode *DeclarationNode::addPointer( DeclarationNode *p ) { if ( p ) { assert( p->type->kind == TypeData::Pointer ); setBase( type, p->type ); p->type = 0; delete p; } // if return this; } DeclarationNode *DeclarationNode::addArray( DeclarationNode *a ) { if ( a ) { assert( a->type->kind == TypeData::Array ); setBase( type, a->type ); a->type = 0; delete a; } // if return this; } DeclarationNode *DeclarationNode::addNewPointer( DeclarationNode *p ) { if ( p ) { assert( p->type->kind == TypeData::Pointer ); if ( type ) { switch ( type->kind ) { case TypeData::Aggregate: case TypeData::Enum: p->type->base = new TypeData( TypeData::AggregateInst ); p->type->base->aggInst.aggregate = type; if ( type->kind == TypeData::Aggregate ) { p->type->base->aggInst.params = maybeClone( type->aggregate.actuals ); } // if p->type->base->qualifiers |= type->qualifiers; break; default: p->type->base = type; } // switch type = 0; } // if delete this; return p; } else { return this; } // if } static TypeData *findLast( TypeData *a ) { assert( a ); TypeData *cur = a; while ( cur->base ) { cur = cur->base; } // while return cur; } DeclarationNode *DeclarationNode::addNewArray( DeclarationNode *a ) { if ( a ) { assert( a->type->kind == TypeData::Array ); TypeData *lastArray = findLast( a->type ); if ( type ) { switch ( type->kind ) { case TypeData::Aggregate: case TypeData::Enum: lastArray->base = new TypeData( TypeData::AggregateInst ); lastArray->base->aggInst.aggregate = type; if ( type->kind == TypeData::Aggregate ) { lastArray->base->aggInst.params = maybeClone( type->aggregate.actuals ); } // if lastArray->base->qualifiers |= type->qualifiers; break; default: lastArray->base = type; } // switch type = 0; } // if delete this; return a; } else { return this; } // if } DeclarationNode *DeclarationNode::addParamList( DeclarationNode *params ) { TypeData *ftype = new TypeData( TypeData::Function ); ftype->function.params = params; setBase( type, ftype ); return this; } static TypeData *addIdListToType( TypeData *type, DeclarationNode *ids ) { if ( type ) { if ( type->kind != TypeData::Function ) { type->base = addIdListToType( type->base, ids ); } else { type->function.idList = ids; } // if return type; } else { TypeData *newtype = new TypeData( TypeData::Function ); newtype->function.idList = ids; return newtype; } // if } DeclarationNode *DeclarationNode::addIdList( DeclarationNode *ids ) { type = addIdListToType( type, ids ); return this; } DeclarationNode *DeclarationNode::addInitializer( InitializerNode *init ) { //assert initializer = init; return this; } DeclarationNode *DeclarationNode::cloneBaseType( string *newName ) { DeclarationNode *newnode = new DeclarationNode; TypeData *srcType = type; while ( srcType->base ) { srcType = srcType->base; } // while newnode->type = maybeClone( srcType ); if ( newnode->type->kind == TypeData::AggregateInst ) { // don't duplicate members if ( newnode->type->aggInst.aggregate->kind == TypeData::Enum ) { delete newnode->type->aggInst.aggregate->enumeration.constants; newnode->type->aggInst.aggregate->enumeration.constants = 0; } else { assert( newnode->type->aggInst.aggregate->kind == TypeData::Aggregate ); delete newnode->type->aggInst.aggregate->aggregate.fields; newnode->type->aggInst.aggregate->aggregate.fields = 0; } // if } // if newnode->type->forall = maybeClone( type->forall ); assert( storageClass == NoStorageClass ); newnode->copyStorageClasses( this ); newnode->name = assign_strptr( newName ); return newnode; } DeclarationNode *DeclarationNode::cloneBaseType( DeclarationNode *o ) { if ( o ) { o->copyStorageClasses( this ); if ( type ) { TypeData *srcType = type; while ( srcType->base ) { srcType = srcType->base; } // while TypeData *newType = srcType->clone(); if ( newType->kind == TypeData::AggregateInst ) { // don't duplicate members if ( newType->aggInst.aggregate->kind == TypeData::Enum ) { delete newType->aggInst.aggregate->enumeration.constants; newType->aggInst.aggregate->enumeration.constants = 0; } else { assert( newType->aggInst.aggregate->kind == TypeData::Aggregate ); delete newType->aggInst.aggregate->aggregate.fields; newType->aggInst.aggregate->aggregate.fields = 0; } // if } // if newType->forall = maybeClone( type->forall ); if ( ! o->type ) { o->type = newType; } else { addTypeToType( newType, o->type ); delete newType; } // if } // if } // if return o; } DeclarationNode *DeclarationNode::cloneType( string *newName ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = maybeClone( type ); assert( storageClass == NoStorageClass ); newnode->copyStorageClasses( this ); newnode->name = assign_strptr( newName ); return newnode; } DeclarationNode *DeclarationNode::cloneType( DeclarationNode *o ) { if ( o ) { assert( storageClass == NoStorageClass ); o->copyStorageClasses( this ); if ( type ) { TypeData *newType = type->clone(); if ( ! o->type ) { o->type = newType; } else { addTypeToType( newType, o->type ); delete newType; } // if } // if } // if delete o; return o; } DeclarationNode *DeclarationNode::extractAggregate() const { if ( type ) { TypeData *ret = typeextractAggregate( type ); if ( ret ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = ret; return newnode; } // if } // if return 0; } void buildList( const DeclarationNode *firstNode, std::list< Declaration * > &outputList ) { SemanticError errors; std::back_insert_iterator< std::list< Declaration * > > out( outputList ); const DeclarationNode *cur = firstNode; while ( cur ) { try { if ( DeclarationNode *extr = cur->extractAggregate() ) { // handle the case where a structure declaration is contained within an object or type declaration Declaration *decl = extr->build(); if ( decl ) { *out++ = decl; } // if delete extr; } // if Declaration *decl = cur->build(); if ( decl ) { *out++ = decl; } // if } catch( SemanticError &e ) { errors.append( e ); } // try cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); } // while if ( ! errors.isEmpty() ) { throw errors; } // if } void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType * > &outputList ) { SemanticError errors; std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList ); const DeclarationNode *cur = firstNode; while ( cur ) { try { Declaration *decl = cur->build(); if ( decl ) { if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { *out++ = dwt; } else if ( StructDecl *agg = dynamic_cast< StructDecl * >( decl ) ) { StructInstType *inst = new StructInstType( Type::Qualifiers(), agg->get_name() ); *out++ = new ObjectDecl( "", DeclarationNode::NoStorageClass, linkage, 0, inst, 0 ); delete agg; } else if ( UnionDecl *agg = dynamic_cast< UnionDecl * >( decl ) ) { UnionInstType *inst = new UnionInstType( Type::Qualifiers(), agg->get_name() ); *out++ = new ObjectDecl( "", DeclarationNode::NoStorageClass, linkage, 0, inst, 0 ); } // if } // if } catch( SemanticError &e ) { errors.append( e ); } // try cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); } // while if ( ! errors.isEmpty() ) { throw errors; } // if } void buildTypeList( const DeclarationNode *firstNode, std::list< Type * > &outputList ) { SemanticError errors; std::back_insert_iterator< std::list< Type * > > out( outputList ); const DeclarationNode *cur = firstNode; while ( cur ) { try { *out++ = cur->buildType(); } catch( SemanticError &e ) { errors.append( e ); } // try cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); } // while if ( ! errors.isEmpty() ) { throw errors; } // if } Declaration *DeclarationNode::build() const { if ( ! error.empty() ) throw SemanticError( error + " in declaration of ", this ); if ( type ) { if ( type->kind == TypeData::Variable ) { static const TypeDecl::Kind kindMap[] = { TypeDecl::Any, TypeDecl::Ftype, TypeDecl::Dtype }; TypeDecl * ret = new TypeDecl( variable.name, DeclarationNode::NoStorageClass, 0, kindMap[ variable.tyClass ] ); buildList( variable.assertions, ret->get_assertions() ); return ret; } else { return buildDecl( type, name, storageClass, maybeBuild< Expression >( bitfieldWidth ), isInline, isNoreturn, linkage, maybeBuild< Initializer >(initializer) )->set_extension( extension ); } // if } // if if ( ! isInline && ! isNoreturn ) { return (new ObjectDecl( name, storageClass, linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) ))->set_extension( extension ); } // if throw SemanticError( "invalid function specifier ", this ); } Type *DeclarationNode::buildType() const { assert( type ); switch ( type->kind ) { case TypeData::Enum: return new EnumInstType( buildQualifiers( type ), type->enumeration.name ); case TypeData::Aggregate: { ReferenceToType *ret; switch ( type->aggregate.kind ) { case DeclarationNode::Struct: ret = new StructInstType( buildQualifiers( type ), type->aggregate.name ); break; case DeclarationNode::Union: ret = new UnionInstType( buildQualifiers( type ), type->aggregate.name ); break; case DeclarationNode::Trait: ret = new TraitInstType( buildQualifiers( type ), type->aggregate.name ); break; default: assert( false ); } // switch buildList( type->aggregate.actuals, ret->get_parameters() ); return ret; } case TypeData::Symbolic: { TypeInstType *ret = new TypeInstType( buildQualifiers( type ), type->symbolic.name, false ); buildList( type->symbolic.actuals, ret->get_parameters() ); return ret; } case TypeData::Attr: { assert( type->kind == TypeData::Attr ); // assert( type->attr ); AttrType * ret; if ( attr.expr ) { ret = new AttrType( buildQualifiers( type ), attr.name, attr.expr->build() ); } else { assert( attr.type ); ret = new AttrType( buildQualifiers( type ), attr.name, attr.type->buildType() ); } // if return ret; } default: return typebuild( type ); } // switch } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //