// // 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 : Fri Jul 3 12:35:02 2015 // Update Count : 108 // #include #include #include #include #include #include "TypeData.h" #include "SynTree/Declaration.h" #include "SynTree/Expression.h" #include "Parser.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", "" }; const char *DeclarationNode::qualifierName[] = { "const", "restrict", "volatile", "lvalue", "_Atomic" }; const char *DeclarationNode::basicTypeName[] = { "char", "int", "float", "double", "void", "_Bool", "_Complex", "_Imaginary" }; const char *DeclarationNode::modifierName[] = { "signed", "unsigned", "short", "long" }; const char *DeclarationNode::aggregateName[] = { "struct", "union", "context" }; const char *DeclarationNode::typeClassName[] = { "type", "dtype", "ftype" }; UniqueName DeclarationNode::anonymous( "__anonymous" ); extern LinkageSpec::Type linkage; /* defined in cfa.y */ DeclarationNode *DeclarationNode::clone() const { DeclarationNode *newnode = new DeclarationNode; newnode->type = maybeClone( type ); newnode->name = name; newnode->storageClasses = storageClasses; newnode->bitfieldWidth = maybeClone( bitfieldWidth ); newnode->hasEllipsis = hasEllipsis; newnode->initializer = initializer; newnode->next = maybeClone( next ); newnode->linkage = linkage; return newnode; } DeclarationNode::DeclarationNode() : type( 0 ), bitfieldWidth( 0 ), initializer( 0 ), hasEllipsis( false ), linkage( ::linkage ) { } DeclarationNode::~DeclarationNode() { delete type; delete bitfieldWidth; delete initializer; } 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 printEnums( storageClasses.begin(), storageClasses.end(), DeclarationNode::storageName, os ); 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 ); } // 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; if ( body ) { newnode->type->function->hasBody = true; } // if if ( ret ) { newnode->type->base = ret->type; ret->type = 0; delete ret; } // if return newnode; } DeclarationNode *DeclarationNode::newQualifier( Qualifier q ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData(); newnode->type->qualifiers.push_back( q ); return newnode; } DeclarationNode *DeclarationNode::newStorageClass( DeclarationNode::StorageClass sc ) { DeclarationNode *newnode = new DeclarationNode; newnode->storageClasses.push_back( sc ); return newnode; } DeclarationNode *DeclarationNode::newBasicType( BasicType bt ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Basic ); newnode->type->basic->typeSpec.push_back( bt ); return newnode; } DeclarationNode *DeclarationNode::newModifier( Modifier mod ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Basic ); newnode->type->basic->modifiers.push_back( mod ); return newnode; } DeclarationNode *DeclarationNode::newForall( DeclarationNode *forall ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Unknown ); newnode->type->forall = forall; return newnode; } 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 *DeclarationNode::newAggregate( Aggregate kind, const std::string *name, ExpressionNode *actuals, DeclarationNode *fields ) { 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 = DeclarationNode::anonymous.newName(); } else { // SKULLDUGGERY: generate a typedef for the aggregate name so that the aggregate does not have to be qualified // by "struct" typedefTable.addToEnclosingScope( newnode->type->aggregate->name, TypedefTable::TD ); DeclarationNode *typedf = new DeclarationNode; typedf->name = newnode->type->aggregate->name; newnode->appendList( typedf->addType( newnode->clone() )->addTypedef() ); } // if newnode->type->aggregate->actuals = actuals; newnode->type->aggregate->fields = fields; return newnode; } 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(); } else { // SKULLDUGGERY: generate a typedef for the enumeration name so that the enumeration does not have to be // qualified by "enum" typedefTable.addToEnclosingScope( newnode->type->enumeration->name, TypedefTable::TD ); DeclarationNode *typedf = new DeclarationNode; typedf->name = newnode->type->enumeration->name; newnode->appendList( typedf->addType( newnode->clone() )->addTypedef() ); } // if newnode->type->enumeration->constants = constants; return newnode; } DeclarationNode *DeclarationNode::newEnumConstant( std::string *name, ExpressionNode *constant ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); // do something with the constant return newnode; } DeclarationNode *DeclarationNode::newName( std::string *name ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); return newnode; } 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 *DeclarationNode::newTypeParam( TypeClass tc, std::string *name ) { DeclarationNode *newnode = new DeclarationNode; newnode->name = assign_strptr( name ); newnode->type = new TypeData( TypeData::Variable ); newnode->type->variable->tyClass = tc; newnode->type->variable->name = newnode->name; return newnode; } DeclarationNode *DeclarationNode::newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Aggregate ); newnode->type->aggregate->kind = Context; newnode->type->aggregate->params = params; newnode->type->aggregate->fields = asserts; newnode->type->aggregate->name = assign_strptr( name ); return newnode; } DeclarationNode *DeclarationNode::newContextUse( 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 = Context; newnode->type->aggInst->aggregate->aggregate->name = assign_strptr( name ); newnode->type->aggInst->params = params; return newnode; } 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 *DeclarationNode::newPointer( DeclarationNode *qualifiers ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Pointer ); return newnode->addQualifiers( qualifiers ); } 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; newnode->type->array->isVarLen = false; return newnode->addQualifiers( qualifiers ); } 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 = members; return newnode; } DeclarationNode *DeclarationNode::newTypeof( ExpressionNode *expr ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Typeof ); newnode->type->typeexpr->expr = expr; return newnode; } DeclarationNode *DeclarationNode::newAttr( std::string *name, ExpressionNode *expr ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Attr ); newnode->type->attr->name = assign_strptr( name ); newnode->type->attr->expr = expr; return newnode; } DeclarationNode *DeclarationNode::newAttr( std::string *name, DeclarationNode *type ) { DeclarationNode *newnode = new DeclarationNode; newnode->type = new TypeData( TypeData::Attr ); newnode->type->attr->name = assign_strptr( name ); newnode->type->attr->type = type; return newnode; } static void addQualifiersToType( TypeData *&src, TypeData *dst ) { if ( src && 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.splice( dst->qualifiers.end(), src->qualifiers ); } // if } // if } DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) { if ( q ) { storageClasses.splice( storageClasses.end(), q->storageClasses ); if ( q->type ) { if ( ! type ) { type = new TypeData; } // if addQualifiersToType( q->type, type ); if ( q->type && 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 } // if } // if delete q; return this; } DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) { storageClasses = q->storageClasses; return this; } static void addTypeToType( TypeData *&src, TypeData *&dst ) { if ( src && 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.splice( src->qualifiers.end(), dst->qualifiers ); dst = src; src = 0; break; case TypeData::Basic: dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers ); if ( src->kind != TypeData::Unknown ) { assert( src->kind == TypeData::Basic ); dst->basic->modifiers.splice( dst->basic->modifiers.end(), src->basic->modifiers ); dst->basic->typeSpec.splice( dst->basic->typeSpec.end(), src->basic->typeSpec ); } // 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.splice( dst->base->qualifiers.end(), 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 } // if } DeclarationNode *DeclarationNode::addType( DeclarationNode *o ) { if ( o ) { storageClasses.splice( storageClasses.end(), o->storageClasses ); 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.splice( type->qualifiers.end(), 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 } // 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 ( type->variable->assertions ) { type->variable->assertions->appendList( assertions ); } else { type->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.splice( p->type->base->qualifiers.end(), 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.splice( lastArray->base->qualifiers.end(), 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 ); newnode->storageClasses = storageClasses; newnode->name = assign_strptr( newName ); return newnode; } DeclarationNode *DeclarationNode::cloneBaseType( DeclarationNode *o ) { if ( o ) { o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() ); 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 ); newnode->storageClasses = storageClasses; newnode->name = assign_strptr( newName ); return newnode; } DeclarationNode *DeclarationNode::cloneType( DeclarationNode *o ) { if ( o ) { o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() ); if ( type ) { TypeData *newType = type->clone(); if ( ! o->type ) { o->type = newType; } else { addTypeToType( newType, o->type ); delete newType; } // if } // if } // if return o; } DeclarationNode *DeclarationNode::appendList( DeclarationNode *node ) { if ( node != 0 ) { set_link( node ); } // if return this; } DeclarationNode *DeclarationNode::extractAggregate() const { if ( type ) { TypeData *ret = type->extractAggregate(); 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 } // if Declaration *decl = cur->build(); if ( decl ) { *out++ = decl; } // if } catch( SemanticError &e ) { errors.append( e ); } // try cur = dynamic_cast< DeclarationNode *>( cur->get_link() ); } // 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 { /// 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; /// } /// } 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_link() ); } // 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_link() ); } // while if ( ! errors.isEmpty() ) { throw errors; } // if } Declaration *DeclarationNode::build() const { if ( type ) { Declaration *newDecl = type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildFuncSpecifier( Inline ), buildFuncSpecifier( Noreturn ), linkage, maybeBuild< Initializer >(initializer) ); return newDecl; } // if if ( ! buildFuncSpecifier( Inline ) && ! buildFuncSpecifier( Noreturn ) ) { return new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) ); } // if throw SemanticError( "invalid function specifier in declaration of ", this ); } Type *DeclarationNode::buildType() const { assert( type ); switch ( type->kind ) { case TypeData::Enum: return new EnumInstType( type->buildQualifiers(), type->enumeration->name ); case TypeData::Aggregate: { ReferenceToType *ret; switch ( type->aggregate->kind ) { case DeclarationNode::Struct: ret = new StructInstType( type->buildQualifiers(), type->aggregate->name ); break; case DeclarationNode::Union: ret = new UnionInstType( type->buildQualifiers(), type->aggregate->name ); break; case DeclarationNode::Context: ret = new ContextInstType( type->buildQualifiers(), type->aggregate->name ); break; default: assert( false ); } // switch buildList( type->aggregate->actuals, ret->get_parameters() ); return ret; } case TypeData::Symbolic: { TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name, false ); buildList( type->symbolic->actuals, ret->get_parameters() ); return ret; } default: return type->build(); } // switch } DeclarationNode::StorageClass DeclarationNode::buildStorageClass() const { DeclarationNode::StorageClass ret = DeclarationNode::NoStorageClass; for ( std::list< DeclarationNode::StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) { if ( *i == DeclarationNode::Inline || *i == DeclarationNode::Noreturn ) continue; // ignore function specifiers if ( ret != DeclarationNode::NoStorageClass ) { // already have a valid storage class ? throw SemanticError( "invalid combination of storage classes in declaration of ", this ); } // if ret = *i; } // for return ret; } bool DeclarationNode::buildFuncSpecifier( DeclarationNode::StorageClass key ) const { std::list< DeclarationNode::StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), key ); if ( first == storageClasses.end() ) return false; // not found first = std::find( ++first, storageClasses.end(), key ); // found if ( first == storageClasses.end() ) return true; // not found again throw SemanticError( "duplicate function specifier in declaration of ", this ); } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //