Changeset 45e753c
- Timestamp:
- Apr 20, 2023, 11:58:06 AM (19 months ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- 699a97d
- Parents:
- 028e512
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/DeclarationNode.cc
r028e512 r45e753c 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 15 … … 1003 1003 } 1004 1004 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 1005 1087 void buildList( DeclarationNode * firstNode, 1006 1088 std::vector<ast::ptr<ast::Decl>> & outputList ) { … … 1008 1090 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); 1009 1091 1010 for ( const DeclarationNode * cur = firstNode ; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1092 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1011 1093 try { 1012 bool extracted = false, anon= false;1013 ast:: AggregateDecl * unionDecl = nullptr;1094 bool extracted_named = false; 1095 ast::UnionDecl * unionDecl = nullptr; 1014 1096 1015 1097 if ( DeclarationNode * extr = cur->extractAggregate() ) { 1016 // Handle the case where a SUE declaration is contained within an object or type declaration.1017 1018 1098 assert( cur->type ); 1019 // Replace anonymous SUE name with typedef name to prevent anonymous naming problems across translation units. 1020 if ( cur->type->kind == TypeData::Symbolic && cur->type->symbolic.isTypedef ) { 1021 assert( extr->type ); 1022 // Handle anonymous aggregates: typedef struct { int i; } foo 1023 extr->type->qualifiers.reset(); // clear any CVs associated with the aggregate 1024 if ( extr->type->kind == TypeData::Aggregate && extr->type->aggregate.anon ) { 1025 delete extr->type->aggregate.name; 1026 extr->type->aggregate.name = new string( "__anonymous_" + *cur->name ); 1027 extr->type->aggregate.anon = false; 1028 assert( cur->type->base ); 1029 if ( cur->type->base ) { 1030 delete cur->type->base->aggInst.aggregate->aggregate.name; 1031 cur->type->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *cur->name ); 1032 cur->type->base->aggInst.aggregate->aggregate.anon = false; 1033 cur->type->base->aggInst.aggregate->qualifiers.reset(); 1034 } // if 1035 } // if 1036 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1037 if ( extr->type->kind == TypeData::Enum && extr->type->enumeration.anon ) { 1038 delete extr->type->enumeration.name; 1039 extr->type->enumeration.name = new string( "__anonymous_" + *cur->name ); 1040 extr->type->enumeration.anon = false; 1041 assert( cur->type->base ); 1042 if ( cur->type->base ) { 1043 delete cur->type->base->aggInst.aggregate->enumeration.name; 1044 cur->type->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *cur->name ); 1045 cur->type->base->aggInst.aggregate->enumeration.anon = false; 1046 } // if 1047 } // if 1048 } // if 1049 1050 ast::Decl * decl = extr->build(); 1051 if ( decl ) { 1099 nameTypedefedDecl( extr, cur ); 1100 1101 if ( ast::Decl * decl = extr->build() ) { 1052 1102 // Remember the declaration if it is a union aggregate ? 1053 1103 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); … … 1056 1106 1057 1107 // need to remember the cases where a declaration contains an anonymous aggregate definition 1058 extracted = true;1059 1108 assert( extr->type ); 1060 1109 if ( extr->type->kind == TypeData::Aggregate ) { 1061 1110 // typedef struct { int A } B is the only case? 1062 anon =extr->type->aggregate.anon;1111 extracted_named = !extr->type->aggregate.anon; 1063 1112 } else if ( extr->type->kind == TypeData::Enum ) { 1064 1113 // typedef enum { A } B is the only case? 1065 anon = extr->type->enumeration.anon; 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1066 1117 } 1067 1118 } // if … … 1069 1120 } // if 1070 1121 1071 ast::Decl * decl = cur->build(); 1072 if ( decl ) { 1073 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1074 if ( unionDecl ) { // is the typedef alias a union aggregate ? 1075 // This code handles a special issue with the attribute transparent_union. 1076 // 1077 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1078 // 1079 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1080 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1081 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1082 // alias. 1083 1084 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1085 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1086 auto instType = ast::mutate( unionInstType ); 1087 // Remove all transparent_union attributes from typedef and move to alias union. 1088 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { // forward order 1089 assert( *attr ); 1090 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1091 unionDecl->attributes.emplace_back( attr->release() ); 1092 attr = instType->attributes.erase( attr ); 1093 } else { 1094 attr++; 1095 } // if 1096 } // for 1097 typedefDecl->base = instType; 1098 } // if 1099 } // 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 } 1100 1142 } // if 1101 1102 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.: 1103 // struct S { 1104 // struct T { int x; }; // no anonymous member 1105 // struct { int y; }; // anonymous member 1106 // struct T; // anonymous member 1107 // }; 1108 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) { 1109 if ( decl->name == "" ) { 1110 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1111 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1112 if ( aggr->name.find("anonymous") == std::string::npos ) { 1113 if ( ! cur->get_inLine() ) { 1114 // temporary: warn about anonymous member declarations of named types, since 1115 // this conflicts with the syntax for the forward declaration of an anonymous type 1116 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() ); 1117 } // if 1118 } // if 1119 } // if 1120 } // if 1121 } // if 1122 *out++ = decl; 1123 } // if 1143 *out++ = decl; 1124 1144 } // if 1125 } catch ( SemanticErrorException & e ) {1145 } catch ( SemanticErrorException & e ) { 1126 1146 errors.append( e ); 1127 1147 } // try … … 1138 1158 std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList ); 1139 1159 1140 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1160 for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) { 1141 1161 try { 1142 1162 ast::Decl * decl = cur->build(); 1143 assert ( decl);1163 assertf( decl, "buildList: build for ast::DeclWithType." ); 1144 1164 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1145 1165 dwt->location = cur->location; … … 1170 1190 ); 1171 1191 *out++ = obj; 1192 } else { 1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." ); 1172 1194 } // if 1173 } catch ( SemanticErrorException & e ) {1195 } catch ( SemanticErrorException & e ) { 1174 1196 errors.append( e ); 1175 1197 } // try … … 1185 1207 SemanticErrorException errors; 1186 1208 std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList ); 1187 const DeclarationNode * cur = firstNode; 1188 1189 while ( cur ) { 1209 1210 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1190 1211 try { 1191 1212 * out++ = cur->buildType(); 1192 } catch ( SemanticErrorException & e ) {1213 } catch ( SemanticErrorException & e ) { 1193 1214 errors.append( e ); 1194 1215 } // try 1195 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1196 } // while 1216 } // for 1197 1217 1198 1218 if ( ! errors.isEmpty() ) {
Note: See TracChangeset
for help on using the changeset viewer.