Changeset 6e1e2d0 for src/Parser/DeclarationNode.cc
- Timestamp:
- May 1, 2023, 4:19:09 PM (14 months ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- c083c3d
- Parents:
- a50fdfb (diff), 985b624 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/DeclarationNode.cc
ra50fdfb r6e1e2d0 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Apr 4 10:28:00 202313 // Update Count : 139 212 // Last Modified On : Thr Apr 20 11:46:00 2023 13 // Update Count : 1393 14 14 // 15 16 #include "DeclarationNode.h" 15 17 16 18 #include <cassert> // for assert, assertf, strict_dynamic_cast … … 34 36 #include "Common/UniqueName.h" // for UniqueName 35 37 #include "Common/utility.h" // for maybeClone 36 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 38 #include "Parser/ExpressionNode.h" // for ExpressionNode 39 #include "Parser/InitializerNode.h"// for InitializerNode 40 #include "Parser/StatementNode.h" // for StatementNode 37 41 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 38 42 #include "TypedefTable.h" // for TypedefTable … … 999 1003 } 1000 1004 1001 void buildList( const DeclarationNode * firstNode, 1005 // If a typedef wraps an anonymous declaration, name the inner declaration 1006 // so it has a consistent name across translation units. 1007 static void nameTypedefedDecl( 1008 DeclarationNode * innerDecl, 1009 const DeclarationNode * outerDecl ) { 1010 TypeData * outer = outerDecl->type; 1011 assert( outer ); 1012 // First make sure this is a typedef: 1013 if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) { 1014 return; 1015 } 1016 TypeData * inner = innerDecl->type; 1017 assert( inner ); 1018 // Always clear any CVs associated with the aggregate: 1019 inner->qualifiers.reset(); 1020 // Handle anonymous aggregates: typedef struct { int i; } foo 1021 if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) { 1022 delete inner->aggregate.name; 1023 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1024 inner->aggregate.anon = false; 1025 assert( outer->base ); 1026 delete outer->base->aggInst.aggregate->aggregate.name; 1027 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1028 outer->base->aggInst.aggregate->aggregate.anon = false; 1029 outer->base->aggInst.aggregate->qualifiers.reset(); 1030 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1031 } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) { 1032 delete inner->enumeration.name; 1033 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1034 inner->enumeration.anon = false; 1035 assert( outer->base ); 1036 delete outer->base->aggInst.aggregate->enumeration.name; 1037 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1038 outer->base->aggInst.aggregate->enumeration.anon = false; 1039 // No qualifiers.reset() here. 1040 } 1041 } 1042 1043 // This code handles a special issue with the attribute transparent_union. 1044 // 1045 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1046 // 1047 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1048 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1049 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1050 // alias. 1051 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) { 1052 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1053 // Is the typedef alias a union aggregate? 1054 if ( nullptr == unionDecl ) return; 1055 1056 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1057 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1058 auto instType = ast::mutate( unionInstType ); 1059 // Remove all transparent_union attributes from typedef and move to alias union. 1060 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { 1061 assert( *attr ); 1062 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1063 unionDecl->attributes.emplace_back( attr->release() ); 1064 attr = instType->attributes.erase( attr ); 1065 } else { 1066 attr++; 1067 } 1068 } 1069 typedefDecl->base = instType; 1070 } 1071 } 1072 } 1073 1074 // Get the non-anonymous name of the instance type of the declaration, 1075 // if one exists. 1076 static const std::string * getInstTypeOfName( ast::Decl * decl ) { 1077 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1078 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1079 if ( aggr->name.find("anonymous") == std::string::npos ) { 1080 return &aggr->name; 1081 } 1082 } 1083 } 1084 return nullptr; 1085 } 1086 1087 void buildList( DeclarationNode * firstNode, 1002 1088 std::vector<ast::ptr<ast::Decl>> & outputList ) { 1003 1089 SemanticErrorException errors; 1004 1090 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); 1005 1091 1006 for ( const DeclarationNode * cur = firstNode ; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1092 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1007 1093 try { 1008 bool extracted = false, anon= false;1009 ast:: AggregateDecl * unionDecl = nullptr;1094 bool extracted_named = false; 1095 ast::UnionDecl * unionDecl = nullptr; 1010 1096 1011 1097 if ( DeclarationNode * extr = cur->extractAggregate() ) { 1012 // Handle the case where a SUE declaration is contained within an object or type declaration.1013 1014 1098 assert( cur->type ); 1015 // Replace anonymous SUE name with typedef name to prevent anonymous naming problems across translation units. 1016 if ( cur->type->kind == TypeData::Symbolic && cur->type->symbolic.isTypedef ) { 1017 assert( extr->type ); 1018 // Handle anonymous aggregates: typedef struct { int i; } foo 1019 extr->type->qualifiers.reset(); // clear any CVs associated with the aggregate 1020 if ( extr->type->kind == TypeData::Aggregate && extr->type->aggregate.anon ) { 1021 delete extr->type->aggregate.name; 1022 extr->type->aggregate.name = new string( "__anonymous_" + *cur->name ); 1023 extr->type->aggregate.anon = false; 1024 assert( cur->type->base ); 1025 if ( cur->type->base ) { 1026 delete cur->type->base->aggInst.aggregate->aggregate.name; 1027 cur->type->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *cur->name ); 1028 cur->type->base->aggInst.aggregate->aggregate.anon = false; 1029 cur->type->base->aggInst.aggregate->qualifiers.reset(); 1030 } // if 1031 } // if 1032 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1033 if ( extr->type->kind == TypeData::Enum && extr->type->enumeration.anon ) { 1034 delete extr->type->enumeration.name; 1035 extr->type->enumeration.name = new string( "__anonymous_" + *cur->name ); 1036 extr->type->enumeration.anon = false; 1037 assert( cur->type->base ); 1038 if ( cur->type->base ) { 1039 delete cur->type->base->aggInst.aggregate->enumeration.name; 1040 cur->type->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *cur->name ); 1041 cur->type->base->aggInst.aggregate->enumeration.anon = false; 1042 } // if 1043 } // if 1044 } // if 1045 1046 ast::Decl * decl = extr->build(); 1047 if ( decl ) { 1099 nameTypedefedDecl( extr, cur ); 1100 1101 if ( ast::Decl * decl = extr->build() ) { 1048 1102 // Remember the declaration if it is a union aggregate ? 1049 1103 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); 1050 1104 1051 decl->location = cur->location;1052 1105 *out++ = decl; 1053 1106 1054 1107 // need to remember the cases where a declaration contains an anonymous aggregate definition 1055 extracted = true;1056 1108 assert( extr->type ); 1057 1109 if ( extr->type->kind == TypeData::Aggregate ) { 1058 1110 // typedef struct { int A } B is the only case? 1059 anon =extr->type->aggregate.anon;1111 extracted_named = !extr->type->aggregate.anon; 1060 1112 } else if ( extr->type->kind == TypeData::Enum ) { 1061 1113 // typedef enum { A } B is the only case? 1062 anon = extr->type->enumeration.anon; 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1063 1117 } 1064 1118 } // if … … 1066 1120 } // if 1067 1121 1068 ast::Decl * decl = cur->build(); 1069 if ( decl ) { 1070 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1071 if ( unionDecl ) { // is the typedef alias a union aggregate ? 1072 // This code handles a special issue with the attribute transparent_union. 1073 // 1074 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1075 // 1076 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1077 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1078 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1079 // alias. 1080 1081 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1082 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1083 auto instType = ast::mutate( unionInstType ); 1084 // Remove all transparent_union attributes from typedef and move to alias union. 1085 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { // forward order 1086 assert( *attr ); 1087 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1088 unionDecl->attributes.emplace_back( attr->release() ); 1089 attr = instType->attributes.erase( attr ); 1090 } else { 1091 attr++; 1092 } // if 1093 } // for 1094 typedefDecl->base = instType; 1095 } // if 1096 } // if 1122 if ( ast::Decl * decl = cur->build() ) { 1123 moveUnionAttribute( decl, unionDecl ); 1124 1125 if ( "" == decl->name && !cur->get_inLine() ) { 1126 // Don't include anonymous declaration for named aggregates, 1127 // but do include them for anonymous aggregates, e.g.: 1128 // struct S { 1129 // struct T { int x; }; // no anonymous member 1130 // struct { int y; }; // anonymous member 1131 // struct T; // anonymous member 1132 // }; 1133 if ( extracted_named ) { 1134 continue; 1135 } 1136 1137 if ( auto name = getInstTypeOfName( decl ) ) { 1138 // Temporary: warn about anonymous member declarations of named types, since 1139 // this conflicts with the syntax for the forward declaration of an anonymous type. 1140 SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() ); 1141 } 1097 1142 } // if 1098 1099 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.: 1100 // struct S { 1101 // struct T { int x; }; // no anonymous member 1102 // struct { int y; }; // anonymous member 1103 // struct T; // anonymous member 1104 // }; 1105 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) { 1106 if ( decl->name == "" ) { 1107 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1108 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1109 if ( aggr->name.find("anonymous") == std::string::npos ) { 1110 if ( ! cur->get_inLine() ) { 1111 // temporary: warn about anonymous member declarations of named types, since 1112 // this conflicts with the syntax for the forward declaration of an anonymous type 1113 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() ); 1114 } // if 1115 } // if 1116 } // if 1117 } // if 1118 } // if 1119 decl->location = cur->location; 1120 *out++ = decl; 1121 } // if 1143 *out++ = decl; 1122 1144 } // if 1123 } catch ( SemanticErrorException & e ) {1145 } catch ( SemanticErrorException & e ) { 1124 1146 errors.append( e ); 1125 1147 } // try … … 1132 1154 1133 1155 // currently only builds assertions, function parameters, and return values 1134 void buildList( constDeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) { 1135 1157 SemanticErrorException errors; 1136 1158 std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList ); 1137 1159 1138 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1160 for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) { 1139 1161 try { 1140 1162 ast::Decl * decl = cur->build(); 1141 assert ( decl);1163 assertf( decl, "buildList: build for ast::DeclWithType." ); 1142 1164 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1143 1165 dwt->location = cur->location; … … 1168 1190 ); 1169 1191 *out++ = obj; 1192 } else { 1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." ); 1170 1194 } // if 1171 } catch ( SemanticErrorException & e ) {1195 } catch ( SemanticErrorException & e ) { 1172 1196 errors.append( e ); 1173 1197 } // try … … 1183 1207 SemanticErrorException errors; 1184 1208 std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList ); 1185 const DeclarationNode * cur = firstNode; 1186 1187 while ( cur ) { 1209 1210 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1188 1211 try { 1189 1212 * out++ = cur->buildType(); 1190 } catch ( SemanticErrorException & e ) {1213 } catch ( SemanticErrorException & e ) { 1191 1214 errors.append( e ); 1192 1215 } // try 1193 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1194 } // while 1216 } // for 1195 1217 1196 1218 if ( ! errors.isEmpty() ) {
Note: See TracChangeset
for help on using the changeset viewer.