| [b87a5ed] | 1 | //
 | 
|---|
 | 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
 | 5 | // file "LICENCE" distributed with Cforall.
 | 
|---|
 | 6 | //
 | 
|---|
| [c92bdcc] | 7 | // DeclarationNode.cpp --
 | 
|---|
| [b87a5ed] | 8 | //
 | 
|---|
 | 9 | // Author           : Rodolfo G. Esteves
 | 
|---|
 | 10 | // Created On       : Sat May 16 12:34:05 2015
 | 
|---|
| [b38f6da] | 11 | // Last Modified By : Peter A. Buhr
 | 
|---|
| [4175659] | 12 | // Last Modified On : Mon Dec  2 15:04:12 2024
 | 
|---|
 | 13 | // Update Count     : 1558
 | 
|---|
| [b87a5ed] | 14 | //
 | 
|---|
 | 15 | 
 | 
|---|
| [c92bdcc] | 16 | #include "DeclarationNode.hpp"
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 | #include <cassert>                     // for assert, assertf, strict_dynami...
 | 
|---|
 | 19 | #include <iterator>                    // for back_insert_iterator
 | 
|---|
 | 20 | #include <list>                        // for list
 | 
|---|
 | 21 | #include <memory>                      // for unique_ptr
 | 
|---|
 | 22 | #include <ostream>                     // for operator<<, ostream, basic_ost...
 | 
|---|
 | 23 | #include <string>                      // for string, operator+, allocator, ...
 | 
|---|
 | 24 | 
 | 
|---|
 | 25 | #include "AST/Attribute.hpp"           // for Attribute
 | 
|---|
 | 26 | #include "AST/Copy.hpp"                // for shallowCopy
 | 
|---|
 | 27 | #include "AST/Decl.hpp"                // for Decl
 | 
|---|
 | 28 | #include "AST/Expr.hpp"                // for Expr
 | 
|---|
 | 29 | #include "AST/Print.hpp"               // for print
 | 
|---|
 | 30 | #include "AST/Stmt.hpp"                // for AsmStmt, DirectiveStmt
 | 
|---|
 | 31 | #include "AST/StorageClasses.hpp"      // for Storage::Class
 | 
|---|
 | 32 | #include "AST/Type.hpp"                // for Type
 | 
|---|
 | 33 | #include "Common/CodeLocation.hpp"     // for CodeLocation
 | 
|---|
 | 34 | #include "Common/Iterate.hpp"          // for reverseIterate
 | 
|---|
 | 35 | #include "Common/SemanticError.hpp"    // for SemanticError
 | 
|---|
 | 36 | #include "Common/UniqueName.hpp"       // for UniqueName
 | 
|---|
 | 37 | #include "Common/Utility.hpp"          // for copy, spliceBegin
 | 
|---|
 | 38 | #include "Parser/ExpressionNode.hpp"   // for ExpressionNode
 | 
|---|
 | 39 | #include "Parser/InitializerNode.hpp"  // for InitializerNode
 | 
|---|
 | 40 | #include "Parser/StatementNode.hpp"    // for StatementNode
 | 
|---|
 | 41 | #include "TypeData.hpp"                // for TypeData, TypeData::Aggregate_t
 | 
|---|
 | 42 | #include "TypedefTable.hpp"            // for TypedefTable
 | 
|---|
| [bdd516a] | 43 | 
 | 
|---|
| [de62360d] | 44 | extern TypedefTable typedefTable;
 | 
|---|
 | 45 | 
 | 
|---|
| [51b73452] | 46 | using namespace std;
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | UniqueName DeclarationNode::anonymous( "__anonymous" );
 | 
|---|
 | 49 | 
 | 
|---|
| [bb7422a] | 50 | extern ast::Linkage::Spec linkage;                                              // defined in parser.yy
 | 
|---|
| [51b73452] | 51 | 
 | 
|---|
| [7d05e7e] | 52 | DeclarationNode::DeclarationNode() :
 | 
|---|
| [e07caa2] | 53 |         linkage( ::linkage ) {
 | 
|---|
| [2298f728] | 54 | 
 | 
|---|
| [bb7422a] | 55 |         variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS;
 | 
|---|
| [28307be] | 56 |         variable.assertions = nullptr;
 | 
|---|
| [67cf18c] | 57 |         variable.initializer = nullptr;
 | 
|---|
| [7d05e7e] | 58 | 
 | 
|---|
| [f6e3e34] | 59 |         assert.condition = nullptr;
 | 
|---|
 | 60 |         assert.message = nullptr;
 | 
|---|
| [28307be] | 61 | }
 | 
|---|
 | 62 | 
 | 
|---|
 | 63 | DeclarationNode::~DeclarationNode() {
 | 
|---|
| [4c0b674] | 64 |         delete name;
 | 
|---|
 | 65 | 
 | 
|---|
| [2298f728] | 66 |         delete variable.assertions;
 | 
|---|
| [67cf18c] | 67 |         delete variable.initializer;
 | 
|---|
| [2298f728] | 68 | 
 | 
|---|
| [4a72fef] | 69 |         delete type;
 | 
|---|
| [28307be] | 70 |         delete bitfieldWidth;
 | 
|---|
| [e994912] | 71 | 
 | 
|---|
 | 72 |         delete asmStmt;
 | 
|---|
| [58dd019] | 73 |         // asmName, no delete, passed to next stage
 | 
|---|
| [28307be] | 74 |         delete initializer;
 | 
|---|
| [f6e3e34] | 75 | 
 | 
|---|
 | 76 |         delete assert.condition;
 | 
|---|
 | 77 |         delete assert.message;
 | 
|---|
| [28307be] | 78 | }
 | 
|---|
 | 79 | 
 | 
|---|
| [ba7aa2d] | 80 | DeclarationNode * DeclarationNode::clone() const {
 | 
|---|
 | 81 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [44adf1b] | 82 |         newnode->next = maybeCopy( next );
 | 
|---|
| [2298f728] | 83 |         newnode->name = name ? new string( *name ) : nullptr;
 | 
|---|
| [c0aa336] | 84 | 
 | 
|---|
| [5bf685f] | 85 |         newnode->type = maybeCopy( type );
 | 
|---|
| [679e644] | 86 |         newnode->inLine = inLine;
 | 
|---|
| [a7c90d4] | 87 |         newnode->storageClasses = storageClasses;
 | 
|---|
 | 88 |         newnode->funcSpecs = funcSpecs;
 | 
|---|
| [5bf685f] | 89 |         newnode->bitfieldWidth = maybeCopy( bitfieldWidth );
 | 
|---|
 | 90 |         newnode->enumeratorValue.reset( maybeCopy( enumeratorValue.get() ) );
 | 
|---|
| [b87a5ed] | 91 |         newnode->hasEllipsis = hasEllipsis;
 | 
|---|
 | 92 |         newnode->linkage = linkage;
 | 
|---|
| [bb7422a] | 93 |         newnode->asmName = maybeCopy( asmName );
 | 
|---|
 | 94 |         newnode->attributes = attributes;
 | 
|---|
| [5bf685f] | 95 |         newnode->initializer = maybeCopy( initializer );
 | 
|---|
| [c0aa336] | 96 |         newnode->extension = extension;
 | 
|---|
| [5bf685f] | 97 |         newnode->asmStmt = maybeCopy( asmStmt );
 | 
|---|
| [c0aa336] | 98 |         newnode->error = error;
 | 
|---|
| [3848e0e] | 99 | 
 | 
|---|
| [28307be] | 100 |         newnode->variable.tyClass = variable.tyClass;
 | 
|---|
| [5bf685f] | 101 |         newnode->variable.assertions = maybeCopy( variable.assertions );
 | 
|---|
 | 102 |         newnode->variable.initializer = maybeCopy( variable.initializer );
 | 
|---|
| [3848e0e] | 103 | 
 | 
|---|
| [5bf685f] | 104 |         newnode->assert.condition = maybeCopy( assert.condition );
 | 
|---|
| [bb7422a] | 105 |         newnode->assert.message = maybeCopy( assert.message );
 | 
|---|
| [28307be] | 106 |         return newnode;
 | 
|---|
 | 107 | } // DeclarationNode::clone
 | 
|---|
| [3848e0e] | 108 | 
 | 
|---|
| [f2f512ba] | 109 | void DeclarationNode::print( std::ostream & os, int indent ) const {
 | 
|---|
| [59db689] | 110 |         os << string( indent, ' ' );
 | 
|---|
| [2298f728] | 111 |         if ( name ) {
 | 
|---|
 | 112 |                 os << *name << ": ";
 | 
|---|
| [68cd1ce] | 113 |         } // if
 | 
|---|
| [51b73452] | 114 | 
 | 
|---|
| [bb7422a] | 115 |         if ( linkage != ast::Linkage::Cforall ) {
 | 
|---|
 | 116 |                 os << ast::Linkage::name( linkage ) << " ";
 | 
|---|
| [68cd1ce] | 117 |         } // if
 | 
|---|
| [3848e0e] | 118 | 
 | 
|---|
| [bb7422a] | 119 |         ast::print( os, storageClasses );
 | 
|---|
 | 120 |         ast::print( os, funcSpecs );
 | 
|---|
| [dd020c0] | 121 | 
 | 
|---|
| [b87a5ed] | 122 |         if ( type ) {
 | 
|---|
 | 123 |                 type->print( os, indent );
 | 
|---|
 | 124 |         } else {
 | 
|---|
 | 125 |                 os << "untyped entity ";
 | 
|---|
| [68cd1ce] | 126 |         } // if
 | 
|---|
| [3848e0e] | 127 | 
 | 
|---|
| [b87a5ed] | 128 |         if ( bitfieldWidth ) {
 | 
|---|
| [59db689] | 129 |                 os << endl << string( indent + 2, ' ' ) << "with bitfield width ";
 | 
|---|
| [b87a5ed] | 130 |                 bitfieldWidth->printOneLine( os );
 | 
|---|
| [68cd1ce] | 131 |         } // if
 | 
|---|
| [3848e0e] | 132 | 
 | 
|---|
| [2298f728] | 133 |         if ( initializer ) {
 | 
|---|
| [59db689] | 134 |                 os << endl << string( indent + 2, ' ' ) << "with initializer ";
 | 
|---|
| [b87a5ed] | 135 |                 initializer->printOneLine( os );
 | 
|---|
| [790f251] | 136 |                 if ( ! initializer->get_maybeConstructed() ) {
 | 
|---|
 | 137 |                         os << " constructed with @= ";
 | 
|---|
 | 138 |                 } // if
 | 
|---|
| [68cd1ce] | 139 |         } // if
 | 
|---|
| [3848e0e] | 140 | 
 | 
|---|
| [692c1cc] | 141 |         if ( ! attributes.empty() ) {
 | 
|---|
| [4eb3a7c5] | 142 |                 os << string( indent + 2, ' ' ) << "with attributes" << endl;
 | 
|---|
| [bb7422a] | 143 |                 for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) {
 | 
|---|
| [4eb3a7c5] | 144 |                         os << string( indent + 4, ' ' );
 | 
|---|
 | 145 |                         ast::print( os, attr, indent + 2 );
 | 
|---|
| [692c1cc] | 146 |                 } // for
 | 
|---|
 | 147 |         } // if
 | 
|---|
| [66406f3] | 148 | 
 | 
|---|
| [b87a5ed] | 149 |         os << endl;
 | 
|---|
| [51b73452] | 150 | }
 | 
|---|
 | 151 | 
 | 
|---|
| [f2f512ba] | 152 | void DeclarationNode::printList( std::ostream & os, int indent ) const {
 | 
|---|
| [dc3fbe5] | 153 |         ParseList::printList( os, indent );
 | 
|---|
| [b87a5ed] | 154 |         if ( hasEllipsis ) {
 | 
|---|
 | 155 |                 os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
 | 
|---|
| [68cd1ce] | 156 |         } // if
 | 
|---|
| [51b73452] | 157 | }
 | 
|---|
 | 158 | 
 | 
|---|
| [6cef439] | 159 | DeclarationNode * DeclarationNode::newFromTypeData( TypeData * type ) {
 | 
|---|
 | 160 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
 | 161 |         newnode->type = type;
 | 
|---|
 | 162 |         return newnode;
 | 
|---|
 | 163 | } // DeclarationNode::newFromTypeData
 | 
|---|
 | 164 | 
 | 
|---|
| [bb7422a] | 165 | DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) {
 | 
|---|
| [ba7aa2d] | 166 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [08d5507b] | 167 |         newnode->storageClasses = sc;
 | 
|---|
| [b87a5ed] | 168 |         return newnode;
 | 
|---|
| [dd020c0] | 169 | } // DeclarationNode::newStorageClass
 | 
|---|
| [3848e0e] | 170 | 
 | 
|---|
| [bb7422a] | 171 | DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) {
 | 
|---|
| [ba7aa2d] | 172 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [08d5507b] | 173 |         newnode->funcSpecs = fs;
 | 
|---|
| [c1c1112] | 174 |         return newnode;
 | 
|---|
| [dd020c0] | 175 | } // DeclarationNode::newFuncSpecifier
 | 
|---|
| [c1c1112] | 176 | 
 | 
|---|
| [bb7422a] | 177 | DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
 | 
|---|
| [ba7aa2d] | 178 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 179 |         newnode->type = new TypeData( TypeData::Aggregate );
 | 
|---|
| [8f6f47d7] | 180 |         newnode->type->aggregate.kind = kind;
 | 
|---|
| [692c1cc] | 181 |         newnode->type->aggregate.anon = name == nullptr;
 | 
|---|
 | 182 |         newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
 | 
|---|
| [8f6f47d7] | 183 |         newnode->type->aggregate.actuals = actuals;
 | 
|---|
 | 184 |         newnode->type->aggregate.fields = fields;
 | 
|---|
 | 185 |         newnode->type->aggregate.body = body;
 | 
|---|
| [b87a5ed] | 186 |         return newnode;
 | 
|---|
| [984dce6] | 187 | } // DeclarationNode::newAggregate
 | 
|---|
| [3848e0e] | 188 | 
 | 
|---|
| [99f7f37] | 189 | DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body, bool isCfa, DeclarationNode * base, EnumHiding hiding ) {
 | 
|---|
| [67467a3] | 190 |         DeclarationNode * newnode = newAggregate( ast::AggregateDecl::Enum, name, nullptr, constants, body );
 | 
|---|
| [99f7f37] | 191 |         newnode->type->aggregate.isCfa = isCfa;
 | 
|---|
| [67467a3] | 192 |         newnode->type->aggregate.hiding = hiding;
 | 
|---|
| [057608a] | 193 |         if ( base ) {
 | 
|---|
| [99f7f37] | 194 |                 assert( isCfa );
 | 
|---|
| [057608a] | 195 |                 assert( base->type );
 | 
|---|
| [ed9a1ae] | 196 |                 newnode->type->base = base->type;
 | 
|---|
| [057608a] | 197 |                 base->type = nullptr;
 | 
|---|
 | 198 |                 delete base;
 | 
|---|
| [9e7236f4] | 199 |         } // if
 | 
|---|
 | 200 | 
 | 
|---|
| [b87a5ed] | 201 |         return newnode;
 | 
|---|
| [984dce6] | 202 | } // DeclarationNode::newEnum
 | 
|---|
| [3848e0e] | 203 | 
 | 
|---|
| [a46b69c] | 204 | DeclarationNode * DeclarationNode::newName( const string * name ) {
 | 
|---|
| [ba7aa2d] | 205 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [a46b69c] | 206 |         assert( ! newnode->name );
 | 
|---|
| [2298f728] | 207 |         newnode->name = name;
 | 
|---|
| [a46b69c] | 208 |         return newnode;
 | 
|---|
 | 209 | } // DeclarationNode::newName
 | 
|---|
 | 210 | 
 | 
|---|
| [374cb117] | 211 | DeclarationNode * DeclarationNode::newEnumConstant( const string * name, ExpressionNode * constant ) {
 | 
|---|
| [a46b69c] | 212 |         DeclarationNode * newnode = newName( name );
 | 
|---|
| [4f147cc] | 213 |         newnode->enumeratorValue.reset( constant );
 | 
|---|
| [b87a5ed] | 214 |         return newnode;
 | 
|---|
| [984dce6] | 215 | } // DeclarationNode::newEnumConstant
 | 
|---|
| [3848e0e] | 216 | 
 | 
|---|
| [374cb117] | 217 | DeclarationNode * DeclarationNode::newEnumValueGeneric( const string * name, InitializerNode * init ) {
 | 
|---|
| [057608a] | 218 |         if ( nullptr == init ) {
 | 
|---|
| [b0d9ff7] | 219 |                 return newName( name );
 | 
|---|
| [057608a] | 220 |         } else if ( init->get_expression() ) {
 | 
|---|
 | 221 |                 return newEnumConstant( name, init->get_expression() );
 | 
|---|
 | 222 |         } else {
 | 
|---|
 | 223 |                 DeclarationNode * newnode = newName( name );
 | 
|---|
 | 224 |                 newnode->initializer = init;
 | 
|---|
 | 225 |                 return newnode;
 | 
|---|
| [374cb117] | 226 |         } // if
 | 
|---|
| [9e7236f4] | 227 | } // DeclarationNode::newEnumValueGeneric
 | 
|---|
| [374cb117] | 228 | 
 | 
|---|
| [d9bad51] | 229 | DeclarationNode * DeclarationNode::newEnumInLine( const std::string * name ) {
 | 
|---|
 | 230 |         DeclarationNode * newnode = newName( name );
 | 
|---|
| [1e30df7] | 231 |         newnode->enumInLine = true;
 | 
|---|
 | 232 |         return newnode;
 | 
|---|
 | 233 | }
 | 
|---|
 | 234 | 
 | 
|---|
| [bb7422a] | 235 | DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) {
 | 
|---|
| [a46b69c] | 236 |         DeclarationNode * newnode = newName( name );
 | 
|---|
| [2298f728] | 237 |         newnode->type = nullptr;
 | 
|---|
| [28307be] | 238 |         newnode->variable.tyClass = tc;
 | 
|---|
| [faddbd8] | 239 |         newnode->variable.assertions = nullptr;
 | 
|---|
| [b87a5ed] | 240 |         return newnode;
 | 
|---|
| [984dce6] | 241 | } // DeclarationNode::newTypeParam
 | 
|---|
| [3848e0e] | 242 | 
 | 
|---|
| [fb114fa1] | 243 | DeclarationNode * DeclarationNode::newTrait( const string * name, DeclarationNode * params, DeclarationNode * asserts ) {
 | 
|---|
| [ba7aa2d] | 244 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 245 |         newnode->type = new TypeData( TypeData::Aggregate );
 | 
|---|
| [2298f728] | 246 |         newnode->type->aggregate.name = name;
 | 
|---|
| [bb7422a] | 247 |         newnode->type->aggregate.kind = ast::AggregateDecl::Trait;
 | 
|---|
| [8f6f47d7] | 248 |         newnode->type->aggregate.params = params;
 | 
|---|
 | 249 |         newnode->type->aggregate.fields = asserts;
 | 
|---|
| [b87a5ed] | 250 |         return newnode;
 | 
|---|
| [984dce6] | 251 | } // DeclarationNode::newTrait
 | 
|---|
| [3848e0e] | 252 | 
 | 
|---|
| [fb114fa1] | 253 | DeclarationNode * DeclarationNode::newTraitUse( const string * name, ExpressionNode * params ) {
 | 
|---|
| [ba7aa2d] | 254 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 255 |         newnode->type = new TypeData( TypeData::AggregateInst );
 | 
|---|
| [8f6f47d7] | 256 |         newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate );
 | 
|---|
| [bb7422a] | 257 |         newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait;
 | 
|---|
| [2298f728] | 258 |         newnode->type->aggInst.aggregate->aggregate.name = name;
 | 
|---|
| [8f6f47d7] | 259 |         newnode->type->aggInst.params = params;
 | 
|---|
| [b87a5ed] | 260 |         return newnode;
 | 
|---|
| [984dce6] | 261 | } // DeclarationNode::newTraitUse
 | 
|---|
| [3848e0e] | 262 | 
 | 
|---|
| [25bca42] | 263 | DeclarationNode * DeclarationNode::newTypeDecl( const string * name, DeclarationNode * typeParams ) {
 | 
|---|
| [a46b69c] | 264 |         DeclarationNode * newnode = newName( name );
 | 
|---|
| [b87a5ed] | 265 |         newnode->type = new TypeData( TypeData::Symbolic );
 | 
|---|
| [8f6f47d7] | 266 |         newnode->type->symbolic.isTypedef = false;
 | 
|---|
 | 267 |         newnode->type->symbolic.params = typeParams;
 | 
|---|
| [b87a5ed] | 268 |         return newnode;
 | 
|---|
| [984dce6] | 269 | } // DeclarationNode::newTypeDecl
 | 
|---|
| [3848e0e] | 270 | 
 | 
|---|
| [ce8c12f] | 271 | DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers, OperKinds kind ) {
 | 
|---|
| [ba7aa2d] | 272 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [ce8c12f] | 273 |         newnode->type = new TypeData( kind == OperKinds::PointTo ? TypeData::Pointer : TypeData::Reference );
 | 
|---|
| [71d0eab] | 274 |         if ( kind == OperKinds::And ) {
 | 
|---|
 | 275 |                 // T && is parsed as 'And' operator rather than two references => add a second reference type
 | 
|---|
 | 276 |                 TypeData * td = new TypeData( TypeData::Reference );
 | 
|---|
 | 277 |                 td->base = newnode->type;
 | 
|---|
 | 278 |                 newnode->type = td;
 | 
|---|
 | 279 |         }
 | 
|---|
| [c3396e0] | 280 |         if ( qualifiers ) {
 | 
|---|
 | 281 |                 return newnode->addQualifiers( qualifiers );
 | 
|---|
 | 282 |         } else {
 | 
|---|
 | 283 |                 return newnode;
 | 
|---|
 | 284 |         } // if
 | 
|---|
| [984dce6] | 285 | } // DeclarationNode::newPointer
 | 
|---|
| [3848e0e] | 286 | 
 | 
|---|
| [ba7aa2d] | 287 | DeclarationNode * DeclarationNode::newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic ) {
 | 
|---|
 | 288 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 289 |         newnode->type = new TypeData( TypeData::Array );
 | 
|---|
| [8f6f47d7] | 290 |         newnode->type->array.dimension = size;
 | 
|---|
 | 291 |         newnode->type->array.isStatic = isStatic;
 | 
|---|
| [a3525c4] | 292 |         newnode->type->array.isVarLen = size && !size->isExpressionType<ast::ConstantExpr *>();
 | 
|---|
| [b87a5ed] | 293 |         return newnode->addQualifiers( qualifiers );
 | 
|---|
| [984dce6] | 294 | } // DeclarationNode::newArray
 | 
|---|
| [3848e0e] | 295 | 
 | 
|---|
| [ba7aa2d] | 296 | DeclarationNode * DeclarationNode::newVarArray( DeclarationNode * qualifiers ) {
 | 
|---|
 | 297 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 298 |         newnode->type = new TypeData( TypeData::Array );
 | 
|---|
| [2298f728] | 299 |         newnode->type->array.dimension = nullptr;
 | 
|---|
| [8f6f47d7] | 300 |         newnode->type->array.isStatic = false;
 | 
|---|
 | 301 |         newnode->type->array.isVarLen = true;
 | 
|---|
| [b87a5ed] | 302 |         return newnode->addQualifiers( qualifiers );
 | 
|---|
| [3848e0e] | 303 | }
 | 
|---|
 | 304 | 
 | 
|---|
| [ba7aa2d] | 305 | DeclarationNode * DeclarationNode::newBitfield( ExpressionNode * size ) {
 | 
|---|
 | 306 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 307 |         newnode->bitfieldWidth = size;
 | 
|---|
 | 308 |         return newnode;
 | 
|---|
| [3848e0e] | 309 | }
 | 
|---|
 | 310 | 
 | 
|---|
| [ba7aa2d] | 311 | DeclarationNode * DeclarationNode::newTuple( DeclarationNode * members ) {
 | 
|---|
 | 312 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 313 |         newnode->type = new TypeData( TypeData::Tuple );
 | 
|---|
| [8f6f47d7] | 314 |         newnode->type->tuple = members;
 | 
|---|
| [b87a5ed] | 315 |         return newnode;
 | 
|---|
| [3848e0e] | 316 | }
 | 
|---|
 | 317 | 
 | 
|---|
| [f855545] | 318 | DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr, bool basetypeof ) {
 | 
|---|
| [ba7aa2d] | 319 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [f855545] | 320 |         newnode->type = new TypeData( basetypeof ? TypeData::Basetypeof : TypeData::Typeof );
 | 
|---|
| [8f6f47d7] | 321 |         newnode->type->typeexpr = expr;
 | 
|---|
| [b87a5ed] | 322 |         return newnode;
 | 
|---|
| [3848e0e] | 323 | }
 | 
|---|
 | 324 | 
 | 
|---|
| [a46b69c] | 325 | DeclarationNode * DeclarationNode::newFunction( const string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
 | 
|---|
 | 326 |         DeclarationNode * newnode = newName( name );
 | 
|---|
 | 327 |         newnode->type = new TypeData( TypeData::Function );
 | 
|---|
 | 328 |         newnode->type->function.params = param;
 | 
|---|
 | 329 |         newnode->type->function.body = body;
 | 
|---|
 | 330 | 
 | 
|---|
 | 331 |         if ( ret ) {
 | 
|---|
 | 332 |                 newnode->type->base = ret->type;
 | 
|---|
 | 333 |                 ret->type = nullptr;
 | 
|---|
 | 334 |                 delete ret;
 | 
|---|
 | 335 |         } // if
 | 
|---|
 | 336 | 
 | 
|---|
 | 337 |         return newnode;
 | 
|---|
 | 338 | } // DeclarationNode::newFunction
 | 
|---|
 | 339 | 
 | 
|---|
| [25bca42] | 340 | DeclarationNode * DeclarationNode::newAttribute( const string * name, ExpressionNode * expr ) {
 | 
|---|
| [44a81853] | 341 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
 | 342 |         newnode->type = nullptr;
 | 
|---|
| [bb7422a] | 343 |         std::vector<ast::ptr<ast::Expr>> exprs;
 | 
|---|
| [44a81853] | 344 |         buildList( expr, exprs );
 | 
|---|
| [b38f6da] | 345 |         newnode->attributes.push_back( new ast::Attribute( *name, std::move( exprs ) ) );
 | 
|---|
| [44a81853] | 346 |         delete name;
 | 
|---|
 | 347 |         return newnode;
 | 
|---|
 | 348 | }
 | 
|---|
 | 349 | 
 | 
|---|
| [2d019af] | 350 | DeclarationNode * DeclarationNode::newDirectiveStmt( StatementNode * stmt ) {
 | 
|---|
 | 351 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
 | 352 |         newnode->directiveStmt = stmt;
 | 
|---|
 | 353 |         return newnode;
 | 
|---|
 | 354 | }
 | 
|---|
 | 355 | 
 | 
|---|
| [e994912] | 356 | DeclarationNode * DeclarationNode::newAsmStmt( StatementNode * stmt ) {
 | 
|---|
 | 357 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
 | 358 |         newnode->asmStmt = stmt;
 | 
|---|
 | 359 |         return newnode;
 | 
|---|
 | 360 | }
 | 
|---|
 | 361 | 
 | 
|---|
| [bb7422a] | 362 | DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr * message ) {
 | 
|---|
| [f6e3e34] | 363 |         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
 | 364 |         newnode->assert.condition = condition;
 | 
|---|
 | 365 |         newnode->assert.message = message;
 | 
|---|
 | 366 |         return newnode;
 | 
|---|
 | 367 | }
 | 
|---|
 | 368 | 
 | 
|---|
| [bb7422a] | 369 | static void appendError( string & dst, const string & src ) {
 | 
|---|
| [5b639ee] | 370 |         if ( src.empty() ) return;
 | 
|---|
 | 371 |         if ( dst.empty() ) { dst = src; return; }
 | 
|---|
 | 372 |         dst += ", " + src;
 | 
|---|
 | 373 | } // appendError
 | 
|---|
 | 374 | 
 | 
|---|
| [ba7aa2d] | 375 | void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) {
 | 
|---|
| [bb7422a] | 376 |         const ast::CV::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
 | 
|---|
 | 377 |         const ast::CV::Qualifiers duplicates = qsrc & qdst;
 | 
|---|
 | 378 | 
 | 
|---|
 | 379 |         if ( duplicates.any() ) {
 | 
|---|
 | 380 |                 std::stringstream str;
 | 
|---|
 | 381 |                 str << "duplicate ";
 | 
|---|
 | 382 |                 ast::print( str, duplicates );
 | 
|---|
 | 383 |                 str << "qualifier(s)";
 | 
|---|
 | 384 |                 appendError( error, str.str() );
 | 
|---|
| [a7c90d4] | 385 |         } // for
 | 
|---|
| [c1c1112] | 386 | } // DeclarationNode::checkQualifiers
 | 
|---|
 | 387 | 
 | 
|---|
| [a7c90d4] | 388 | void DeclarationNode::checkSpecifiers( DeclarationNode * src ) {
 | 
|---|
| [bb7422a] | 389 |         ast::Function::Specs fsDups = funcSpecs & src->funcSpecs;
 | 
|---|
 | 390 |         if ( fsDups.any() ) {
 | 
|---|
 | 391 |                 std::stringstream str;
 | 
|---|
 | 392 |                 str << "duplicate ";
 | 
|---|
 | 393 |                 ast::print( str, fsDups );
 | 
|---|
 | 394 |                 str << "function specifier(s)";
 | 
|---|
 | 395 |                 appendError( error, str.str() );
 | 
|---|
| [dd020c0] | 396 |         } // if
 | 
|---|
 | 397 | 
 | 
|---|
| [bb7422a] | 398 |         // Skip if everything is unset.
 | 
|---|
 | 399 |         if ( storageClasses.any() && src->storageClasses.any() ) {
 | 
|---|
 | 400 |                 ast::Storage::Classes dups = storageClasses & src->storageClasses;
 | 
|---|
 | 401 |                 // Check for duplicates.
 | 
|---|
 | 402 |                 if ( dups.any() ) {
 | 
|---|
 | 403 |                         std::stringstream str;
 | 
|---|
 | 404 |                         str << "duplicate ";
 | 
|---|
 | 405 |                         ast::print( str, dups );
 | 
|---|
 | 406 |                         str << "storage class(es)";
 | 
|---|
 | 407 |                         appendError( error, str.str() );
 | 
|---|
 | 408 |                 // Check for conflicts.
 | 
|---|
 | 409 |                 } else if ( !src->storageClasses.is_threadlocal_any() ) {
 | 
|---|
 | 410 |                         std::stringstream str;
 | 
|---|
 | 411 |                         str << "conflicting ";
 | 
|---|
 | 412 |                         ast::print( str, ast::Storage::Classes( 1 << storageClasses.ffs() ) );
 | 
|---|
 | 413 |                         str << "& ";
 | 
|---|
 | 414 |                         ast::print( str, ast::Storage::Classes( 1 << src->storageClasses.ffs() ) );
 | 
|---|
 | 415 |                         str << "storage classes";
 | 
|---|
 | 416 |                         appendError( error, str.str() );
 | 
|---|
 | 417 |                         // FIX to preserve invariant of one basic storage specifier
 | 
|---|
 | 418 |                         src->storageClasses.reset();
 | 
|---|
 | 419 |                 }
 | 
|---|
| [b6424d9] | 420 |         } // if
 | 
|---|
| [dd020c0] | 421 | 
 | 
|---|
| [a7c90d4] | 422 |         appendError( error, src->error );
 | 
|---|
 | 423 | } // DeclarationNode::checkSpecifiers
 | 
|---|
| [b6424d9] | 424 | 
 | 
|---|
| [4eb3a7c5] | 425 | DeclarationNode * DeclarationNode::copySpecifiers( DeclarationNode * q, bool copyattr ) {
 | 
|---|
| [6f95000] | 426 |         funcSpecs |= q->funcSpecs;
 | 
|---|
 | 427 |         storageClasses |= q->storageClasses;
 | 
|---|
| [c0aa336] | 428 | 
 | 
|---|
| [4eb3a7c5] | 429 |         if ( copyattr ) {
 | 
|---|
 | 430 |                 std::vector<ast::ptr<ast::Attribute>> tmp;
 | 
|---|
 | 431 |                 tmp.reserve( q->attributes.size() );
 | 
|---|
 | 432 |                 for ( auto const & attr : q->attributes ) {
 | 
|---|
 | 433 |                         tmp.emplace_back( ast::shallowCopy( attr.get() ) );
 | 
|---|
 | 434 |                 } // for
 | 
|---|
 | 435 |                 spliceBegin( attributes, tmp );
 | 
|---|
 | 436 |         } // if
 | 
|---|
| [bb7422a] | 437 | 
 | 
|---|
| [b6424d9] | 438 |         return this;
 | 
|---|
| [a7c90d4] | 439 | } // DeclarationNode::copySpecifiers
 | 
|---|
| [b6424d9] | 440 | 
 | 
|---|
| [ba7aa2d] | 441 | DeclarationNode * DeclarationNode::addQualifiers( DeclarationNode * q ) {
 | 
|---|
| [af9da5f] | 442 |         if ( ! q ) { return this; }                                                     // empty qualifier
 | 
|---|
| [101e0bd] | 443 | 
 | 
|---|
| [a7c90d4] | 444 |         checkSpecifiers( q );
 | 
|---|
 | 445 |         copySpecifiers( q );
 | 
|---|
| [101e0bd] | 446 | 
 | 
|---|
| [c38ae92] | 447 |         if ( ! q->type ) { delete q; return this; }
 | 
|---|
| [101e0bd] | 448 | 
 | 
|---|
 | 449 |         if ( ! type ) {
 | 
|---|
| [c38ae92] | 450 |                 type = q->type;                                                                 // reuse structure
 | 
|---|
| [1b772749] | 451 |                 q->type = nullptr;
 | 
|---|
 | 452 |                 delete q;
 | 
|---|
| [101e0bd] | 453 |                 return this;
 | 
|---|
 | 454 |         } // if
 | 
|---|
 | 455 | 
 | 
|---|
| [a7c90d4] | 456 |         checkQualifiers( type, q->type );
 | 
|---|
| [1cfe640] | 457 |         type = ::addQualifiers( type, q->type );
 | 
|---|
| [af60383] | 458 |         q->type = nullptr;
 | 
|---|
| [6ef2d81] | 459 | 
 | 
|---|
| [b87a5ed] | 460 |         delete q;
 | 
|---|
 | 461 |         return this;
 | 
|---|
| [101e0bd] | 462 | } // addQualifiers
 | 
|---|
| [3848e0e] | 463 | 
 | 
|---|
| [af60383] | 464 | DeclarationNode * DeclarationNode::addType( DeclarationNode * o, bool copyattr ) {
 | 
|---|
 | 465 |         if ( !o ) return this;
 | 
|---|
 | 466 | 
 | 
|---|
 | 467 |         checkSpecifiers( o );
 | 
|---|
 | 468 |         copySpecifiers( o, copyattr );
 | 
|---|
 | 469 |         if ( o->type ) {
 | 
|---|
| [1cfe640] | 470 |                 type = ::addType( type, o->type, o->attributes );
 | 
|---|
| [af60383] | 471 |                 o->type = nullptr;
 | 
|---|
| [101e0bd] | 472 |         } // if
 | 
|---|
| [af60383] | 473 |         if ( o->bitfieldWidth ) {
 | 
|---|
 | 474 |                 bitfieldWidth = o->bitfieldWidth;
 | 
|---|
| [68cd1ce] | 475 |         } // if
 | 
|---|
| [3848e0e] | 476 | 
 | 
|---|
| [af60383] | 477 |         // there may be typedefs chained onto the type
 | 
|---|
 | 478 |         if ( o->next ) {
 | 
|---|
 | 479 |                 set_last( o->next->clone() );
 | 
|---|
| [68cd1ce] | 480 |         } // if
 | 
|---|
| [66406f3] | 481 | 
 | 
|---|
| [af60383] | 482 |         delete o;
 | 
|---|
| [b87a5ed] | 483 |         return this;
 | 
|---|
| [3848e0e] | 484 | }
 | 
|---|
 | 485 | 
 | 
|---|
| [f135b50] | 486 | DeclarationNode * DeclarationNode::addEnumBase( DeclarationNode * o ) {
 | 
|---|
| [af60383] | 487 |         if ( o && o->type ) {
 | 
|---|
 | 488 |                 type->base = o->type;
 | 
|---|
| [b38f6da] | 489 |         } // if
 | 
|---|
| [f135b50] | 490 |         delete o;
 | 
|---|
 | 491 |         return this;
 | 
|---|
 | 492 | }
 | 
|---|
 | 493 | 
 | 
|---|
| [2583407] | 494 | // This code handles a special issue with the attribute transparent_union.
 | 
|---|
 | 495 | //
 | 
|---|
 | 496 | //    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
 | 
|---|
 | 497 | //
 | 
|---|
 | 498 | // Here the attribute aligned goes with the typedef_name, so variables declared of this type are
 | 
|---|
 | 499 | // aligned.  However, the attribute transparent_union must be moved from the typedef_name to
 | 
|---|
 | 500 | // alias union U.  Currently, this is the only know attribute that must be moved from typedef to
 | 
|---|
 | 501 | // alias.
 | 
|---|
 | 502 | static void moveUnionAttribute( DeclarationNode * decl, DeclarationNode * unionDecl ) {
 | 
|---|
 | 503 |         assert( decl->type->kind == TypeData::Symbolic );
 | 
|---|
 | 504 |         assert( decl->type->symbolic.isTypedef );
 | 
|---|
 | 505 |         assert( unionDecl->type->kind == TypeData::Aggregate );
 | 
|---|
 | 506 | 
 | 
|---|
 | 507 |         if ( unionDecl->type->aggregate.kind != ast::AggregateDecl::Union ) return;
 | 
|---|
 | 508 | 
 | 
|---|
 | 509 |         // Ignore the Aggregate_t::attributes. Why did we add that before the rework?
 | 
|---|
 | 510 |         for ( auto attr = decl->attributes.begin() ; attr != decl->attributes.end() ; ) {
 | 
|---|
 | 511 |                 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
 | 
|---|
 | 512 |                         unionDecl->attributes.emplace_back( attr->release() );
 | 
|---|
 | 513 |                         attr = decl->attributes.erase( attr );
 | 
|---|
 | 514 |                 } else {
 | 
|---|
 | 515 |                         ++attr;
 | 
|---|
 | 516 |                 }
 | 
|---|
 | 517 |         }
 | 
|---|
 | 518 | }
 | 
|---|
 | 519 | 
 | 
|---|
 | 520 | // Helper for addTypedef, handles the case where the typedef wraps an
 | 
|---|
 | 521 | // aggregate declaration (not a type), returns a chain of nodes.
 | 
|---|
 | 522 | static DeclarationNode * addTypedefAggr(
 | 
|---|
 | 523 |                 DeclarationNode * olddecl, TypeData * newtype ) {
 | 
|---|
 | 524 |         TypeData *& oldaggr = olddecl->type->aggInst.aggregate;
 | 
|---|
 | 525 | 
 | 
|---|
 | 526 |         // Handle anonymous aggregates: typedef struct { int i; } foo
 | 
|---|
 | 527 |         // Give the typedefed type a consistent name across translation units.
 | 
|---|
 | 528 |         if ( oldaggr->aggregate.anon ) {
 | 
|---|
 | 529 |                 delete oldaggr->aggregate.name;
 | 
|---|
 | 530 |                 oldaggr->aggregate.name = new string( "__anonymous_" + *olddecl->name );
 | 
|---|
 | 531 |                 oldaggr->aggregate.anon = false;
 | 
|---|
 | 532 |                 oldaggr->qualifiers.reset();
 | 
|---|
 | 533 |         }
 | 
|---|
 | 534 | 
 | 
|---|
 | 535 |         // Replace the wrapped TypeData with a forward declaration.
 | 
|---|
 | 536 |         TypeData * newaggr = new TypeData( TypeData::Aggregate );
 | 
|---|
 | 537 |         newaggr->aggregate.kind = oldaggr->aggregate.kind;
 | 
|---|
 | 538 |         newaggr->aggregate.name = oldaggr->aggregate.name ? new string( *oldaggr->aggregate.name ) : nullptr;
 | 
|---|
 | 539 |         newaggr->aggregate.body = false;
 | 
|---|
 | 540 |         newaggr->aggregate.anon = oldaggr->aggregate.anon;
 | 
|---|
| [99f7f37] | 541 |         newaggr->aggregate.isCfa = oldaggr->aggregate.isCfa;
 | 
|---|
| [67467a3] | 542 |         newaggr->aggregate.hiding = oldaggr->aggregate.hiding;
 | 
|---|
| [2583407] | 543 |         swap( newaggr, oldaggr );
 | 
|---|
 | 544 | 
 | 
|---|
 | 545 |         newtype->base = olddecl->type;
 | 
|---|
 | 546 |         olddecl->type = newtype;
 | 
|---|
 | 547 |         DeclarationNode * newdecl = new DeclarationNode;
 | 
|---|
 | 548 |         newdecl->type = newaggr;
 | 
|---|
 | 549 |         newdecl->next = olddecl;
 | 
|---|
 | 550 | 
 | 
|---|
 | 551 |         moveUnionAttribute( olddecl, newdecl );
 | 
|---|
 | 552 | 
 | 
|---|
 | 553 |         return newdecl;
 | 
|---|
 | 554 | }
 | 
|---|
 | 555 | 
 | 
|---|
| [057608a] | 556 | // Wrap the declaration in a typedef. It actually does that by modifying the
 | 
|---|
 | 557 | // existing declaration, and may split it into two declarations.
 | 
|---|
 | 558 | // This only happens if the wrapped type is actually a declaration of a SUE
 | 
|---|
 | 559 | // type. If it does, the DeclarationNode for the SUE declaration is the node
 | 
|---|
 | 560 | // returned, make sure later transformations are applied to the right node.
 | 
|---|
| [ba7aa2d] | 561 | DeclarationNode * DeclarationNode::addTypedef() {
 | 
|---|
 | 562 |         TypeData * newtype = new TypeData( TypeData::Symbolic );
 | 
|---|
| [2298f728] | 563 |         newtype->symbolic.params = nullptr;
 | 
|---|
| [8f6f47d7] | 564 |         newtype->symbolic.isTypedef = true;
 | 
|---|
| [2298f728] | 565 |         newtype->symbolic.name = name ? new string( *name ) : nullptr;
 | 
|---|
| [2583407] | 566 |         // If this typedef is wrapping an aggregate, separate them out.
 | 
|---|
 | 567 |         if ( TypeData::AggregateInst == type->kind
 | 
|---|
 | 568 |                         && TypeData::Aggregate == type->aggInst.aggregate->kind
 | 
|---|
 | 569 |                         && type->aggInst.aggregate->aggregate.body ) {
 | 
|---|
 | 570 |                 return addTypedefAggr( this, newtype );
 | 
|---|
 | 571 |         // There is no internal declaration, just a type.
 | 
|---|
 | 572 |         } else {
 | 
|---|
 | 573 |                 newtype->base = type;
 | 
|---|
 | 574 |                 type = newtype;
 | 
|---|
 | 575 |                 return this;
 | 
|---|
 | 576 |         }
 | 
|---|
| [3848e0e] | 577 | }
 | 
|---|
 | 578 | 
 | 
|---|
| [ba7aa2d] | 579 | DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) {
 | 
|---|
| [bb7422a] | 580 |         if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
 | 
|---|
| [4a72fef] | 581 |                 extend( variable.assertions, assertions );
 | 
|---|
| [702e826] | 582 |                 return this;
 | 
|---|
| [2298f728] | 583 |         } // if
 | 
|---|
 | 584 | 
 | 
|---|
| [b87a5ed] | 585 |         assert( type );
 | 
|---|
| [4a72fef] | 586 |         assert( TypeData::Symbolic == type->kind );
 | 
|---|
 | 587 |         extend( type->symbolic.assertions, assertions );
 | 
|---|
| [974906e2] | 588 | 
 | 
|---|
| [b87a5ed] | 589 |         return this;
 | 
|---|
| [51b73452] | 590 | }
 | 
|---|
 | 591 | 
 | 
|---|
| [fb114fa1] | 592 | DeclarationNode * DeclarationNode::addName( string * newname ) {
 | 
|---|
| [2298f728] | 593 |         assert( ! name );
 | 
|---|
 | 594 |         name = newname;
 | 
|---|
| [b87a5ed] | 595 |         return this;
 | 
|---|
| [51b73452] | 596 | }
 | 
|---|
 | 597 | 
 | 
|---|
| [c0aa336] | 598 | DeclarationNode * DeclarationNode::addAsmName( DeclarationNode * newname ) {
 | 
|---|
| [58dd019] | 599 |         assert( ! asmName );
 | 
|---|
| [c0aa336] | 600 |         asmName = newname ? newname->asmName : nullptr;
 | 
|---|
 | 601 |         return this->addQualifiers( newname );
 | 
|---|
| [58dd019] | 602 | }
 | 
|---|
 | 603 | 
 | 
|---|
| [ba7aa2d] | 604 | DeclarationNode * DeclarationNode::addBitfield( ExpressionNode * size ) {
 | 
|---|
| [b87a5ed] | 605 |         bitfieldWidth = size;
 | 
|---|
 | 606 |         return this;
 | 
|---|
| [51b73452] | 607 | }
 | 
|---|
 | 608 | 
 | 
|---|
| [ba7aa2d] | 609 | DeclarationNode * DeclarationNode::addVarArgs() {
 | 
|---|
| [b87a5ed] | 610 |         assert( type );
 | 
|---|
 | 611 |         hasEllipsis = true;
 | 
|---|
 | 612 |         return this;
 | 
|---|
| [51b73452] | 613 | }
 | 
|---|
 | 614 | 
 | 
|---|
| [c453ac4] | 615 | DeclarationNode * DeclarationNode::addFunctionBody( StatementNode * body, ExpressionNode * withExprs ) {
 | 
|---|
| [b87a5ed] | 616 |         assert( type );
 | 
|---|
 | 617 |         assert( type->kind == TypeData::Function );
 | 
|---|
| [2298f728] | 618 |         assert( ! type->function.body );
 | 
|---|
| [8f6f47d7] | 619 |         type->function.body = body;
 | 
|---|
| [c453ac4] | 620 |         type->function.withExprs = withExprs;
 | 
|---|
| [b87a5ed] | 621 |         return this;
 | 
|---|
| [51b73452] | 622 | }
 | 
|---|
 | 623 | 
 | 
|---|
| [ba7aa2d] | 624 | DeclarationNode * DeclarationNode::addOldDeclList( DeclarationNode * list ) {
 | 
|---|
| [b87a5ed] | 625 |         assert( type );
 | 
|---|
 | 626 |         assert( type->kind == TypeData::Function );
 | 
|---|
| [2298f728] | 627 |         assert( ! type->function.oldDeclList );
 | 
|---|
| [8f6f47d7] | 628 |         type->function.oldDeclList = list;
 | 
|---|
| [b87a5ed] | 629 |         return this;
 | 
|---|
| [51b73452] | 630 | }
 | 
|---|
 | 631 | 
 | 
|---|
| [c0aa336] | 632 | DeclarationNode * DeclarationNode::setBase( TypeData * newType ) {
 | 
|---|
| [b87a5ed] | 633 |         if ( type ) {
 | 
|---|
| [af60383] | 634 |                 type->setLastBase( newType );
 | 
|---|
| [b87a5ed] | 635 |         } else {
 | 
|---|
 | 636 |                 type = newType;
 | 
|---|
| [68cd1ce] | 637 |         } // if
 | 
|---|
| [c0aa336] | 638 |         return this;
 | 
|---|
| [3848e0e] | 639 | }
 | 
|---|
 | 640 | 
 | 
|---|
| [c0aa336] | 641 | DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) {
 | 
|---|
 | 642 |         if ( a ) {
 | 
|---|
| [bb7422a] | 643 |                 spliceBegin( attributes, a->attributes );
 | 
|---|
| [c0aa336] | 644 |                 a->attributes.clear();
 | 
|---|
 | 645 |         } // if
 | 
|---|
 | 646 |         return this;
 | 
|---|
 | 647 | } // copyAttribute
 | 
|---|
 | 648 | 
 | 
|---|
| [ba7aa2d] | 649 | DeclarationNode * DeclarationNode::addPointer( DeclarationNode * p ) {
 | 
|---|
| [b87a5ed] | 650 |         if ( p ) {
 | 
|---|
| [6926a6d] | 651 |                 assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference );
 | 
|---|
| [c0aa336] | 652 |                 setBase( p->type );
 | 
|---|
| [2298f728] | 653 |                 p->type = nullptr;
 | 
|---|
| [c0aa336] | 654 |                 copyAttribute( p );
 | 
|---|
| [b87a5ed] | 655 |                 delete p;
 | 
|---|
| [68cd1ce] | 656 |         } // if
 | 
|---|
| [b87a5ed] | 657 |         return this;
 | 
|---|
| [3848e0e] | 658 | }
 | 
|---|
 | 659 | 
 | 
|---|
| [ba7aa2d] | 660 | DeclarationNode * DeclarationNode::addArray( DeclarationNode * a ) {
 | 
|---|
| [b87a5ed] | 661 |         if ( a ) {
 | 
|---|
 | 662 |                 assert( a->type->kind == TypeData::Array );
 | 
|---|
| [c0aa336] | 663 |                 setBase( a->type );
 | 
|---|
| [2298f728] | 664 |                 a->type = nullptr;
 | 
|---|
| [c0aa336] | 665 |                 copyAttribute( a );
 | 
|---|
| [b87a5ed] | 666 |                 delete a;
 | 
|---|
| [68cd1ce] | 667 |         } // if
 | 
|---|
| [b87a5ed] | 668 |         return this;
 | 
|---|
| [51b73452] | 669 | }
 | 
|---|
 | 670 | 
 | 
|---|
| [ba7aa2d] | 671 | DeclarationNode * DeclarationNode::addNewPointer( DeclarationNode * p ) {
 | 
|---|
| [4a72fef] | 672 |         if ( !p ) return this;
 | 
|---|
 | 673 |         assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference );
 | 
|---|
 | 674 |         if ( type ) {
 | 
|---|
 | 675 |                 p->type->base = makeNewBase( type );
 | 
|---|
 | 676 |                 type = nullptr;
 | 
|---|
| [68cd1ce] | 677 |         } // if
 | 
|---|
| [4a72fef] | 678 |         delete this;
 | 
|---|
 | 679 |         return p;
 | 
|---|
| [51b73452] | 680 | }
 | 
|---|
 | 681 | 
 | 
|---|
| [ba7aa2d] | 682 | DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) {
 | 
|---|
| [4a72fef] | 683 |         if ( !a ) return this;
 | 
|---|
| [738e304] | 684 |         assert( a->type->kind == TypeData::Array );
 | 
|---|
 | 685 |         if ( type ) {
 | 
|---|
| [af60383] | 686 |                 a->type->setLastBase( makeNewBase( type ) );
 | 
|---|
| [738e304] | 687 |                 type = nullptr;
 | 
|---|
| [68cd1ce] | 688 |         } // if
 | 
|---|
| [738e304] | 689 |         delete this;
 | 
|---|
 | 690 |         return a;
 | 
|---|
| [51b73452] | 691 | }
 | 
|---|
| [3848e0e] | 692 | 
 | 
|---|
| [ba7aa2d] | 693 | DeclarationNode * DeclarationNode::addParamList( DeclarationNode * params ) {
 | 
|---|
 | 694 |         TypeData * ftype = new TypeData( TypeData::Function );
 | 
|---|
| [8f6f47d7] | 695 |         ftype->function.params = params;
 | 
|---|
| [c0aa336] | 696 |         setBase( ftype );
 | 
|---|
| [b87a5ed] | 697 |         return this;
 | 
|---|
| [3848e0e] | 698 | }
 | 
|---|
 | 699 | 
 | 
|---|
| [ba7aa2d] | 700 | static TypeData * addIdListToType( TypeData * type, DeclarationNode * ids ) {
 | 
|---|
| [b87a5ed] | 701 |         if ( type ) {
 | 
|---|
 | 702 |                 if ( type->kind != TypeData::Function ) {
 | 
|---|
 | 703 |                         type->base = addIdListToType( type->base, ids );
 | 
|---|
 | 704 |                 } else {
 | 
|---|
| [8f6f47d7] | 705 |                         type->function.idList = ids;
 | 
|---|
| [68cd1ce] | 706 |                 } // if
 | 
|---|
| [b87a5ed] | 707 |                 return type;
 | 
|---|
| [3848e0e] | 708 |         } else {
 | 
|---|
| [ba7aa2d] | 709 |                 TypeData * newtype = new TypeData( TypeData::Function );
 | 
|---|
| [8f6f47d7] | 710 |                 newtype->function.idList = ids;
 | 
|---|
| [b87a5ed] | 711 |                 return newtype;
 | 
|---|
| [68cd1ce] | 712 |         } // if
 | 
|---|
| [2298f728] | 713 | } // addIdListToType
 | 
|---|
| [974906e2] | 714 | 
 | 
|---|
| [ba7aa2d] | 715 | DeclarationNode * DeclarationNode::addIdList( DeclarationNode * ids ) {
 | 
|---|
| [b87a5ed] | 716 |         type = addIdListToType( type, ids );
 | 
|---|
 | 717 |         return this;
 | 
|---|
| [3848e0e] | 718 | }
 | 
|---|
 | 719 | 
 | 
|---|
| [ba7aa2d] | 720 | DeclarationNode * DeclarationNode::addInitializer( InitializerNode * init ) {
 | 
|---|
| [b87a5ed] | 721 |         initializer = init;
 | 
|---|
 | 722 |         return this;
 | 
|---|
| [3848e0e] | 723 | }
 | 
|---|
 | 724 | 
 | 
|---|
| [67cf18c] | 725 | DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) {
 | 
|---|
| [bb7422a] | 726 |         assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
 | 
|---|
| [67cf18c] | 727 |         variable.initializer = init;
 | 
|---|
 | 728 |         return this;
 | 
|---|
 | 729 | }
 | 
|---|
 | 730 | 
 | 
|---|
| [a46b69c] | 731 | DeclarationNode * DeclarationNode::cloneType( string * name ) {
 | 
|---|
 | 732 |         DeclarationNode * newnode = newName( name );
 | 
|---|
| [5bf685f] | 733 |         newnode->type = maybeCopy( type );
 | 
|---|
| [a7c90d4] | 734 |         newnode->copySpecifiers( this );
 | 
|---|
| [b87a5ed] | 735 |         return newnode;
 | 
|---|
| [3848e0e] | 736 | }
 | 
|---|
 | 737 | 
 | 
|---|
| [4eb3a7c5] | 738 | DeclarationNode * DeclarationNode::cloneBaseType( DeclarationNode * o, bool copyattr ) {
 | 
|---|
| [2298f728] | 739 |         if ( ! o ) return nullptr;
 | 
|---|
| [4eb3a7c5] | 740 |         o->copySpecifiers( this, copyattr );
 | 
|---|
| [2298f728] | 741 |         if ( type ) {
 | 
|---|
| [af60383] | 742 |                 o->type = ::cloneBaseType( type, o->type );
 | 
|---|
| [68cd1ce] | 743 |         } // if
 | 
|---|
| [b87a5ed] | 744 |         return o;
 | 
|---|
| [51b73452] | 745 | }
 | 
|---|
 | 746 | 
 | 
|---|
| [ba7aa2d] | 747 | DeclarationNode * DeclarationNode::extractAggregate() const {
 | 
|---|
| [b87a5ed] | 748 |         if ( type ) {
 | 
|---|
| [ba7aa2d] | 749 |                 TypeData * ret = typeextractAggregate( type );
 | 
|---|
| [b87a5ed] | 750 |                 if ( ret ) {
 | 
|---|
| [ba7aa2d] | 751 |                         DeclarationNode * newnode = new DeclarationNode;
 | 
|---|
| [b87a5ed] | 752 |                         newnode->type = ret;
 | 
|---|
| [4eb3a7c5] | 753 |                         if ( ret->kind == TypeData::Aggregate ) {
 | 
|---|
 | 754 |                                 newnode->attributes.swap( ret->aggregate.attributes );
 | 
|---|
| [4a72fef] | 755 |                         } // if
 | 
|---|
| [b87a5ed] | 756 |                         return newnode;
 | 
|---|
| [843054c2] | 757 |                 } // if
 | 
|---|
 | 758 |         } // if
 | 
|---|
| [2298f728] | 759 |         return nullptr;
 | 
|---|
| [3848e0e] | 760 | }
 | 
|---|
 | 761 | 
 | 
|---|
| [45e753c] | 762 | // Get the non-anonymous name of the instance type of the declaration,
 | 
|---|
 | 763 | // if one exists.
 | 
|---|
 | 764 | static const std::string * getInstTypeOfName( ast::Decl * decl ) {
 | 
|---|
 | 765 |         if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
 | 
|---|
 | 766 |                 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) {
 | 
|---|
 | 767 |                         if ( aggr->name.find("anonymous") == std::string::npos ) {
 | 
|---|
 | 768 |                                 return &aggr->name;
 | 
|---|
 | 769 |                         }
 | 
|---|
 | 770 |                 }
 | 
|---|
 | 771 |         }
 | 
|---|
 | 772 |         return nullptr;
 | 
|---|
 | 773 | }
 | 
|---|
 | 774 | 
 | 
|---|
| [b38f6da] | 775 | void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::Decl>> & outputList ) {
 | 
|---|
| [a16764a6] | 776 |         SemanticErrorException errors;
 | 
|---|
| [bb7422a] | 777 |         std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
 | 
|---|
| [2298f728] | 778 | 
 | 
|---|
| [dc3fbe5] | 779 |         for ( const DeclarationNode * cur = firstNode ; cur ; cur = cur->next ) {
 | 
|---|
| [b87a5ed] | 780 |                 try {
 | 
|---|
| [45e753c] | 781 |                         bool extracted_named = false;
 | 
|---|
| [692c1cc] | 782 | 
 | 
|---|
| [ba7aa2d] | 783 |                         if ( DeclarationNode * extr = cur->extractAggregate() ) {
 | 
|---|
| [78e2fca] | 784 |                                 assert( cur->type );
 | 
|---|
| [692c1cc] | 785 | 
 | 
|---|
| [45e753c] | 786 |                                 if ( ast::Decl * decl = extr->build() ) {
 | 
|---|
| [692c1cc] | 787 |                                         *out++ = decl;
 | 
|---|
| [3d7e53b] | 788 | 
 | 
|---|
 | 789 |                                         // need to remember the cases where a declaration contains an anonymous aggregate definition
 | 
|---|
 | 790 |                                         assert( extr->type );
 | 
|---|
 | 791 |                                         if ( extr->type->kind == TypeData::Aggregate ) {
 | 
|---|
| [692c1cc] | 792 |                                                 // typedef struct { int A } B is the only case?
 | 
|---|
| [4eb3a7c5] | 793 |                                                 extracted_named = ! extr->type->aggregate.anon;
 | 
|---|
| [45e753c] | 794 |                                         } else {
 | 
|---|
 | 795 |                                                 extracted_named = true;
 | 
|---|
| [3d7e53b] | 796 |                                         }
 | 
|---|
| [843054c2] | 797 |                                 } // if
 | 
|---|
| [f39096c] | 798 |                                 delete extr;
 | 
|---|
| [843054c2] | 799 |                         } // if
 | 
|---|
| [2298f728] | 800 | 
 | 
|---|
| [45e753c] | 801 |                         if ( ast::Decl * decl = cur->build() ) {
 | 
|---|
 | 802 |                                 if ( "" == decl->name && !cur->get_inLine() ) {
 | 
|---|
 | 803 |                                         // Don't include anonymous declaration for named aggregates,
 | 
|---|
 | 804 |                                         // but do include them for anonymous aggregates, e.g.:
 | 
|---|
 | 805 |                                         // struct S {
 | 
|---|
 | 806 |                                         //   struct T { int x; }; // no anonymous member
 | 
|---|
 | 807 |                                         //   struct { int y; };   // anonymous member
 | 
|---|
 | 808 |                                         //   struct T;            // anonymous member
 | 
|---|
 | 809 |                                         // };
 | 
|---|
 | 810 |                                         if ( extracted_named ) {
 | 
|---|
 | 811 |                                                 continue;
 | 
|---|
 | 812 |                                         }
 | 
|---|
| [692c1cc] | 813 | 
 | 
|---|
| [45e753c] | 814 |                                         if ( auto name = getInstTypeOfName( decl ) ) {
 | 
|---|
 | 815 |                                                 // Temporary: warn about anonymous member declarations of named types, since
 | 
|---|
 | 816 |                                                 // this conflicts with the syntax for the forward declaration of an anonymous type.
 | 
|---|
 | 817 |                                                 SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() );
 | 
|---|
 | 818 |                                         }
 | 
|---|
| [e07caa2] | 819 |                                 } // if
 | 
|---|
| [45e753c] | 820 |                                 *out++ = decl;
 | 
|---|
| [843054c2] | 821 |                         } // if
 | 
|---|
| [45e753c] | 822 |                 } catch ( SemanticErrorException & e ) {
 | 
|---|
| [b87a5ed] | 823 |                         errors.append( e );
 | 
|---|
| [843054c2] | 824 |                 } // try
 | 
|---|
| [e07caa2] | 825 |         } // for
 | 
|---|
| [2298f728] | 826 | 
 | 
|---|
| [16ba4897] | 827 |         errors.throwIfNonEmpty();
 | 
|---|
| [2298f728] | 828 | } // buildList
 | 
|---|
| [3848e0e] | 829 | 
 | 
|---|
| [3d7e53b] | 830 | // currently only builds assertions, function parameters, and return values
 | 
|---|
| [6611177] | 831 | void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {
 | 
|---|
| [a16764a6] | 832 |         SemanticErrorException errors;
 | 
|---|
| [bb7422a] | 833 |         std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
 | 
|---|
| [43c89a7] | 834 | 
 | 
|---|
| [dc3fbe5] | 835 |         for ( const DeclarationNode * cur = firstNode; cur; cur = cur->next ) {
 | 
|---|
| [b87a5ed] | 836 |                 try {
 | 
|---|
| [bb7422a] | 837 |                         ast::Decl * decl = cur->build();
 | 
|---|
| [45e753c] | 838 |                         assertf( decl, "buildList: build for ast::DeclWithType." );
 | 
|---|
| [bb7422a] | 839 |                         if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
 | 
|---|
| [47498bd] | 840 |                                 dwt->location = cur->location;
 | 
|---|
| [3ca7ef3] | 841 |                                 *out++ = dwt;
 | 
|---|
| [bb7422a] | 842 |                         } else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) {
 | 
|---|
| [3d7e53b] | 843 |                                 // e.g., int foo(struct S) {}
 | 
|---|
| [bb7422a] | 844 |                                 auto inst = new ast::StructInstType( agg->name );
 | 
|---|
 | 845 |                                 auto obj = new ast::ObjectDecl( cur->location, "", inst );
 | 
|---|
 | 846 |                                 obj->linkage = linkage;
 | 
|---|
| [3ca7ef3] | 847 |                                 *out++ = obj;
 | 
|---|
| [47498bd] | 848 |                                 delete agg;
 | 
|---|
| [bb7422a] | 849 |                         } else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) {
 | 
|---|
| [3d7e53b] | 850 |                                 // e.g., int foo(union U) {}
 | 
|---|
| [bb7422a] | 851 |                                 auto inst = new ast::UnionInstType( agg->name );
 | 
|---|
 | 852 |                                 auto obj = new ast::ObjectDecl( cur->location,
 | 
|---|
 | 853 |                                         "", inst, nullptr, ast::Storage::Classes(),
 | 
|---|
 | 854 |                                         linkage );
 | 
|---|
| [3ca7ef3] | 855 |                                 *out++ = obj;
 | 
|---|
| [bb7422a] | 856 |                         } else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) {
 | 
|---|
| [3d7e53b] | 857 |                                 // e.g., int foo(enum E) {}
 | 
|---|
| [bb7422a] | 858 |                                 auto inst = new ast::EnumInstType( agg->name );
 | 
|---|
 | 859 |                                 auto obj = new ast::ObjectDecl( cur->location,
 | 
|---|
 | 860 |                                         "",
 | 
|---|
 | 861 |                                         inst,
 | 
|---|
 | 862 |                                         nullptr,
 | 
|---|
 | 863 |                                         ast::Storage::Classes(),
 | 
|---|
 | 864 |                                         linkage
 | 
|---|
 | 865 |                                 );
 | 
|---|
| [3ca7ef3] | 866 |                                 *out++ = obj;
 | 
|---|
| [45e753c] | 867 |                         } else {
 | 
|---|
 | 868 |                                 assertf( false, "buildList: Could not convert to ast::DeclWithType." );
 | 
|---|
| [843054c2] | 869 |                         } // if
 | 
|---|
| [45e753c] | 870 |                 } catch ( SemanticErrorException & e ) {
 | 
|---|
| [b87a5ed] | 871 |                         errors.append( e );
 | 
|---|
| [843054c2] | 872 |                 } // try
 | 
|---|
| [3a5131ed] | 873 |         } // for
 | 
|---|
 | 874 | 
 | 
|---|
| [16ba4897] | 875 |         errors.throwIfNonEmpty();
 | 
|---|
| [2298f728] | 876 | } // buildList
 | 
|---|
| [3848e0e] | 877 | 
 | 
|---|
| [bb7422a] | 878 | void buildTypeList( const DeclarationNode * firstNode,
 | 
|---|
 | 879 |                 std::vector<ast::ptr<ast::Type>> & outputList ) {
 | 
|---|
| [a16764a6] | 880 |         SemanticErrorException errors;
 | 
|---|
| [bb7422a] | 881 |         std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
 | 
|---|
| [2298f728] | 882 | 
 | 
|---|
| [dc3fbe5] | 883 |         for ( const DeclarationNode * cur = firstNode ; cur ; cur = cur->next ) {
 | 
|---|
| [b87a5ed] | 884 |                 try {
 | 
|---|
| [ba7aa2d] | 885 |                         * out++ = cur->buildType();
 | 
|---|
| [45e753c] | 886 |                 } catch ( SemanticErrorException & e ) {
 | 
|---|
| [b87a5ed] | 887 |                         errors.append( e );
 | 
|---|
| [843054c2] | 888 |                 } // try
 | 
|---|
| [45e753c] | 889 |         } // for
 | 
|---|
| [2298f728] | 890 | 
 | 
|---|
| [16ba4897] | 891 |         errors.throwIfNonEmpty();
 | 
|---|
| [2298f728] | 892 | } // buildTypeList
 | 
|---|
| [51b73452] | 893 | 
 | 
|---|
| [bb7422a] | 894 | ast::Decl * DeclarationNode::build() const {
 | 
|---|
| [a16764a6] | 895 |         if ( ! error.empty() ) SemanticError( this, error + " in declaration of " );
 | 
|---|
| [2298f728] | 896 | 
 | 
|---|
| [e994912] | 897 |         if ( asmStmt ) {
 | 
|---|
| [bb7422a] | 898 |                 auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() );
 | 
|---|
 | 899 |                 return new ast::AsmDecl( stmt->location, stmt );
 | 
|---|
| [e994912] | 900 |         } // if
 | 
|---|
| [2d019af] | 901 |         if ( directiveStmt ) {
 | 
|---|
| [bb7422a] | 902 |                 auto stmt = strict_dynamic_cast<ast::DirectiveStmt *>( directiveStmt->build() );
 | 
|---|
 | 903 |                 return new ast::DirectiveDecl( stmt->location, stmt );
 | 
|---|
| [2d019af] | 904 |         } // if
 | 
|---|
| [e994912] | 905 | 
 | 
|---|
| [bb7422a] | 906 |         if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
 | 
|---|
| [f0ecf9b] | 907 |                 // otype is internally converted to dtype + otype parameters
 | 
|---|
| [bb7422a] | 908 |                 static const ast::TypeDecl::Kind kindMap[] = { ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Ftype, ast::TypeDecl::Ttype, ast::TypeDecl::Dimension };
 | 
|---|
 | 909 |                 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == ast::TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
 | 
|---|
| [8f60f0b] | 910 |                 assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." );
 | 
|---|
| [bb7422a] | 911 |                 ast::TypeDecl * ret = new ast::TypeDecl( location,
 | 
|---|
 | 912 |                         *name,
 | 
|---|
 | 913 |                         ast::Storage::Classes(),
 | 
|---|
 | 914 |                         (ast::Type *)nullptr,
 | 
|---|
 | 915 |                         kindMap[ variable.tyClass ],
 | 
|---|
 | 916 |                         variable.tyClass == ast::TypeDecl::Otype || variable.tyClass == ast::TypeDecl::DStype,
 | 
|---|
 | 917 |                         variable.initializer ? variable.initializer->buildType() : nullptr
 | 
|---|
 | 918 |                 );
 | 
|---|
 | 919 |                 buildList( variable.assertions, ret->assertions );
 | 
|---|
| [2298f728] | 920 |                 return ret;
 | 
|---|
 | 921 |         } // if
 | 
|---|
 | 922 | 
 | 
|---|
| [843054c2] | 923 |         if ( type ) {
 | 
|---|
| [dd020c0] | 924 |                 // Function specifiers can only appear on a function definition/declaration.
 | 
|---|
 | 925 |                 //
 | 
|---|
 | 926 |                 //    inline _Noreturn int f();                 // allowed
 | 
|---|
 | 927 |                 //    inline _Noreturn int g( int i );  // allowed
 | 
|---|
 | 928 |                 //    inline _Noreturn int i;                   // disallowed
 | 
|---|
| [fb04321] | 929 |                 if ( type->kind != TypeData::Function && funcSpecs.any() ) {
 | 
|---|
| [a16764a6] | 930 |                         SemanticError( this, "invalid function specifier for " );
 | 
|---|
| [dd020c0] | 931 |                 } // if
 | 
|---|
| [284da8c] | 932 |                 // Forall qualifier can only appear on a function/aggregate definition/declaration.
 | 
|---|
 | 933 |                 //
 | 
|---|
 | 934 |                 //    forall int f();                                   // allowed
 | 
|---|
 | 935 |                 //    forall int g( int i );                    // allowed
 | 
|---|
 | 936 |                 //    forall int i;                                             // disallowed
 | 
|---|
 | 937 |                 if ( type->kind != TypeData::Function && type->forall ) {
 | 
|---|
 | 938 |                         SemanticError( this, "invalid type qualifier for " );
 | 
|---|
 | 939 |                 } // if
 | 
|---|
| [3ed994e] | 940 |                 bool isDelete = initializer && initializer->get_isDelete();
 | 
|---|
| [bb7422a] | 941 |                 ast::Decl * decl = buildDecl(
 | 
|---|
 | 942 |                         type,
 | 
|---|
 | 943 |                         name ? *name : string( "" ),
 | 
|---|
 | 944 |                         storageClasses,
 | 
|---|
 | 945 |                         maybeBuild( bitfieldWidth ),
 | 
|---|
 | 946 |                         funcSpecs,
 | 
|---|
 | 947 |                         linkage,
 | 
|---|
 | 948 |                         asmName,
 | 
|---|
 | 949 |                         isDelete ? nullptr : maybeBuild( initializer ),
 | 
|---|
 | 950 |                         copy( attributes )
 | 
|---|
| [d1fbc56e] | 951 |                 );
 | 
|---|
 | 952 |                 decl->extension = extension;
 | 
|---|
| [3ed994e] | 953 |                 if ( isDelete ) {
 | 
|---|
| [bb7422a] | 954 |                         auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl );
 | 
|---|
| [3ed994e] | 955 |                         dwt->isDeleted = true;
 | 
|---|
 | 956 |                 }
 | 
|---|
 | 957 |                 return decl;
 | 
|---|
| [843054c2] | 958 |         } // if
 | 
|---|
| [2298f728] | 959 | 
 | 
|---|
| [f6e3e34] | 960 |         if ( assert.condition ) {
 | 
|---|
| [bb7422a] | 961 |                 auto cond = maybeBuild( assert.condition );
 | 
|---|
 | 962 |                 auto msg = strict_dynamic_cast<ast::ConstantExpr *>( maybeCopy( assert.message ) );
 | 
|---|
 | 963 |                 return new ast::StaticAssertDecl( location, cond, msg );
 | 
|---|
| [f6e3e34] | 964 |         }
 | 
|---|
 | 965 | 
 | 
|---|
| [dd020c0] | 966 |         // SUE's cannot have function specifiers, either
 | 
|---|
 | 967 |         //
 | 
|---|
| [79aae15] | 968 |         //    inline _Noreturn struct S { ... };                // disallowed
 | 
|---|
 | 969 |         //    inline _Noreturn enum   E { ... };                // disallowed
 | 
|---|
| [fb04321] | 970 |         if ( funcSpecs.any() ) {
 | 
|---|
| [a16764a6] | 971 |                 SemanticError( this, "invalid function specifier for " );
 | 
|---|
| [843054c2] | 972 |         } // if
 | 
|---|
| [e874605] | 973 |         if ( enumInLine ) {
 | 
|---|
| [bb7422a] | 974 |                 return new ast::InlineMemberDecl( location,
 | 
|---|
 | 975 |                         *name, (ast::Type*)nullptr, storageClasses, linkage );
 | 
|---|
| [e874605] | 976 |         } // if
 | 
|---|
| [dd020c0] | 977 |         assertf( name, "ObjectDecl must a have name\n" );
 | 
|---|
| [bb7422a] | 978 |         auto ret = new ast::ObjectDecl( location,
 | 
|---|
 | 979 |                 *name,
 | 
|---|
 | 980 |                 (ast::Type*)nullptr,
 | 
|---|
 | 981 |                 maybeBuild( initializer ),
 | 
|---|
 | 982 |                 storageClasses,
 | 
|---|
 | 983 |                 linkage,
 | 
|---|
 | 984 |                 maybeBuild( bitfieldWidth )
 | 
|---|
 | 985 |         );
 | 
|---|
 | 986 |         ret->asmName = asmName;
 | 
|---|
 | 987 |         ret->extension = extension;
 | 
|---|
 | 988 |         return ret;
 | 
|---|
| [51b73452] | 989 | }
 | 
|---|
 | 990 | 
 | 
|---|
| [bb7422a] | 991 | ast::Type * DeclarationNode::buildType() const {
 | 
|---|
| [b87a5ed] | 992 |         assert( type );
 | 
|---|
| [974906e2] | 993 | 
 | 
|---|
| [790f251] | 994 |         // Some types are parsed as declarations and, syntactically, can have initializers, which are not support (possibly
 | 
|---|
 | 995 |         // meaningless).
 | 
|---|
 | 996 |         if ( initializer && initializer->get_maybeConstructed() ) { // no @=
 | 
|---|
 | 997 |                 SemanticError( location, "default initialization for parameter %s is unsupport for a function-pointer declaration.",
 | 
|---|
 | 998 |                                            (this->name) ? this->name->c_str() : "anonymous" );
 | 
|---|
| [afb15cf] | 999 |         }
 | 
|---|
 | 1000 | 
 | 
|---|
| [b87a5ed] | 1001 |         switch ( type->kind ) {
 | 
|---|
| [0d0931d] | 1002 |         case TypeData::Aggregate: {
 | 
|---|
| [bb7422a] | 1003 |                 ast::BaseInstType * ret =
 | 
|---|
 | 1004 |                         buildComAggInst( type, copy( attributes ), linkage );
 | 
|---|
 | 1005 |                 buildList( type->aggregate.actuals, ret->params );
 | 
|---|
| [0d0931d] | 1006 |                 return ret;
 | 
|---|
 | 1007 |         }
 | 
|---|
 | 1008 |         case TypeData::Symbolic: {
 | 
|---|
| [bb7422a] | 1009 |                 ast::TypeInstType * ret = new ast::TypeInstType(
 | 
|---|
 | 1010 |                         *type->symbolic.name,
 | 
|---|
 | 1011 |                         // This is just a default, the true value is not known yet.
 | 
|---|
 | 1012 |                         ast::TypeDecl::Dtype,
 | 
|---|
 | 1013 |                         buildQualifiers( type ),
 | 
|---|
 | 1014 |                         copy( attributes ) );
 | 
|---|
 | 1015 |                 buildList( type->symbolic.actuals, ret->params );
 | 
|---|
| [0d0931d] | 1016 |                 return ret;
 | 
|---|
 | 1017 |         }
 | 
|---|
 | 1018 |         default:
 | 
|---|
| [bb7422a] | 1019 |                 ast::Type * simpletypes = typebuild( type );
 | 
|---|
 | 1020 |                 // copy because member is const
 | 
|---|
 | 1021 |                 simpletypes->attributes = attributes;
 | 
|---|
| [c0aa336] | 1022 |                 return simpletypes;
 | 
|---|
| [b87a5ed] | 1023 |         } // switch
 | 
|---|
| [3848e0e] | 1024 | }
 | 
|---|
 | 1025 | 
 | 
|---|
| [b87a5ed] | 1026 | // Local Variables: //
 | 
|---|
 | 1027 | // tab-width: 4 //
 | 
|---|
 | 1028 | // mode: c++ //
 | 
|---|
 | 1029 | // compile-command: "make install" //
 | 
|---|
 | 1030 | // End: //
 | 
|---|