| [1931bb01] | 1 | //
 | 
|---|
 | 2 | // Cforall Version 1.0.0 Copyright (C) 2018 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 | //
 | 
|---|
| [11df881] | 7 | // EnumAndPointerDecay.cpp -- Normalizes enumerations and types in functions.
 | 
|---|
| [1931bb01] | 8 | //
 | 
|---|
 | 9 | // Author           : Andrew Beach
 | 
|---|
 | 10 | // Created On       : Tue Jun 28 15:50:00 2022
 | 
|---|
 | 11 | // Last Modified By : Andrew Beach
 | 
|---|
| [e9e9f56] | 12 | // Last Modified On : Tue Sep 20 16:14:00 2022
 | 
|---|
 | 13 | // Update Count     : 1
 | 
|---|
| [1931bb01] | 14 | //
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | #include "EnumAndPointerDecay.hpp"
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 | #include "AST/CVQualifiers.hpp"
 | 
|---|
 | 19 | #include "AST/Decl.hpp"
 | 
|---|
 | 20 | #include "AST/Pass.hpp"
 | 
|---|
 | 21 | #include "AST/Type.hpp"
 | 
|---|
| [c92bdcc] | 22 | #include "SymTab/FixFunction.hpp"
 | 
|---|
| [e874605] | 23 | #include "Validate/NoIdSymbolTable.hpp"
 | 
|---|
| [1931bb01] | 24 | 
 | 
|---|
 | 25 | namespace Validate {
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | namespace {
 | 
|---|
 | 28 | 
 | 
|---|
| [e874605] | 29 | struct EnumAndPointerDecayCore final : public WithNoIdSymbolTable, public ast::WithCodeLocation {
 | 
|---|
| [1931bb01] | 30 |         ast::EnumDecl const * previsit( ast::EnumDecl const * decl );
 | 
|---|
 | 31 |         ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl );
 | 
|---|
 | 32 |         ast::FunctionType const * previsit( ast::FunctionType const * type );
 | 
|---|
 | 33 | };
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | ast::EnumDecl const * EnumAndPointerDecayCore::previsit(
 | 
|---|
 | 36 |                 ast::EnumDecl const * decl ) {
 | 
|---|
 | 37 |         if ( decl->members.empty() ) {
 | 
|---|
 | 38 |                 return decl;
 | 
|---|
 | 39 |         }
 | 
|---|
 | 40 |         // Set the type of each member of the enumeration to be EnumContant.
 | 
|---|
 | 41 |         auto mut = ast::mutate( decl );
 | 
|---|
| [e874605] | 42 |         std::vector<ast::ptr<ast::Decl>> buffer;
 | 
|---|
| [19a8c40] | 43 |         for ( auto member : decl->members ) {
 | 
|---|
 | 44 |                 if ( ast::ObjectDecl const * object = member.as<ast::ObjectDecl>() ) {
 | 
|---|
 | 45 |                         buffer.push_back( ast::mutate_field( object,
 | 
|---|
 | 46 |                                 &ast::ObjectDecl::type,
 | 
|---|
 | 47 |                                 new ast::EnumInstType( decl, ast::CV::Const ) ) );
 | 
|---|
 | 48 |                 } else if ( auto value = member.as<ast::InlineMemberDecl>() ) {
 | 
|---|
| [85855b0] | 49 |                         auto targetEnum = symtab.lookupEnum( value->name );
 | 
|---|
 | 50 |                         // assert( targetEnum );
 | 
|---|
 | 51 |                         if (!targetEnum) {
 | 
|---|
 | 52 |                                 SemanticError(value, "Only another enum is allowed for enum inline syntax ");
 | 
|---|
 | 53 |                         }
 | 
|---|
 | 54 |                         const ast::EnumInstType * instType = new ast::EnumInstType(targetEnum);
 | 
|---|
 | 55 |                         mut->inlinedDecl.push_back( std::move(instType) );
 | 
|---|
 | 56 |                         for ( auto enumMember : targetEnum->members ) {
 | 
|---|
 | 57 |                                 auto enumObject = enumMember.strict_as<ast::ObjectDecl>();
 | 
|---|
 | 58 |                                 buffer.push_back(new ast::ObjectDecl(
 | 
|---|
 | 59 |                                         // Get the location from the "inline" declaration.
 | 
|---|
 | 60 |                                         value->location,
 | 
|---|
 | 61 |                                         enumObject->name,
 | 
|---|
 | 62 |                                         // Construct a new EnumInstType as the type.
 | 
|---|
 | 63 |                                         new ast::EnumInstType( decl, ast::CV::Const ),
 | 
|---|
 | 64 |                                         enumObject->init,
 | 
|---|
 | 65 |                                         enumObject->storage,
 | 
|---|
 | 66 |                                         enumObject->linkage,
 | 
|---|
 | 67 |                                         enumObject->bitfieldWidth,
 | 
|---|
 | 68 |                                         {},
 | 
|---|
 | 69 |                                         enumObject->funcSpec
 | 
|---|
 | 70 |                                 ));
 | 
|---|
| [e874605] | 71 |                         }
 | 
|---|
 | 72 |                 }
 | 
|---|
| [1931bb01] | 73 |         }
 | 
|---|
| [e874605] | 74 |         mut->members = buffer;
 | 
|---|
| [1931bb01] | 75 |         return mut;
 | 
|---|
 | 76 | }
 | 
|---|
 | 77 | 
 | 
|---|
 | 78 | template<typename Member>
 | 
|---|
 | 79 | void fixFunctionList( CodeLocation const & location, bool isVarArgs,
 | 
|---|
 | 80 |                 std::vector<ast::ptr<Member>> & list ) {
 | 
|---|
 | 81 |         bool hasVoid = false;
 | 
|---|
 | 82 |         for ( ast::ptr<Member> & member : list ) {
 | 
|---|
 | 83 |                 member = SymTab::fixFunction( member, hasVoid );
 | 
|---|
 | 84 |         }
 | 
|---|
 | 85 | 
 | 
|---|
 | 86 |         // The remaining code only applies if void is present.
 | 
|---|
 | 87 |         if ( !hasVoid ) {
 | 
|---|
 | 88 |                 return;
 | 
|---|
 | 89 |         }
 | 
|---|
 | 90 | 
 | 
|---|
 | 91 |         // So there is a void, which is only valid if it is the only argument.
 | 
|---|
 | 92 |         if ( 1 < list.size() || isVarArgs ) {
 | 
|---|
 | 93 |                 SemanticError( location, "invalid type void in function type " );
 | 
|---|
 | 94 |         }
 | 
|---|
 | 95 | 
 | 
|---|
 | 96 |         // If a single "void" thing in the list to remove it.
 | 
|---|
 | 97 |         list.clear();
 | 
|---|
 | 98 | }
 | 
|---|
 | 99 | 
 | 
|---|
 | 100 | ast::FunctionDecl const * EnumAndPointerDecayCore::previsit(
 | 
|---|
 | 101 |                 ast::FunctionDecl const * decl ) {
 | 
|---|
 | 102 |         auto mut = ast::mutate( decl );
 | 
|---|
 | 103 |         ast::ArgumentFlag isVarArgs = mut->type->isVarArgs;
 | 
|---|
 | 104 |         // It seems fixFunction (via fixFunctionList) does the pointer decay part.
 | 
|---|
 | 105 |         fixFunctionList( mut->location, isVarArgs, mut->params );
 | 
|---|
 | 106 |         fixFunctionList( mut->location, false, mut->returns );
 | 
|---|
 | 107 |         return mut;
 | 
|---|
 | 108 | }
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 | ast::FunctionType const * EnumAndPointerDecayCore::previsit(
 | 
|---|
 | 111 |                 ast::FunctionType const * type ) {
 | 
|---|
 | 112 |         assert( location );
 | 
|---|
 | 113 |         auto mut = ast::mutate( type );
 | 
|---|
 | 114 |         ast::ArgumentFlag isVarArgs = mut->isVarArgs;
 | 
|---|
 | 115 |         // It seems fixFunction (via fixFunctionList) does the pointer decay part.
 | 
|---|
 | 116 |         fixFunctionList( *location, isVarArgs, mut->params );
 | 
|---|
 | 117 |         fixFunctionList( *location, false, mut->returns );
 | 
|---|
 | 118 |         return mut;
 | 
|---|
 | 119 | }
 | 
|---|
 | 120 | 
 | 
|---|
 | 121 | } // namespace
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 | void decayEnumsAndPointers( ast::TranslationUnit & translationUnit ) {
 | 
|---|
 | 124 |         ast::Pass<EnumAndPointerDecayCore>::run( translationUnit );
 | 
|---|
 | 125 | }
 | 
|---|
 | 126 | 
 | 
|---|
 | 127 | } // namespace Validate
 | 
|---|
 | 128 | 
 | 
|---|
 | 129 | // Local Variables: //
 | 
|---|
 | 130 | // tab-width: 4 //
 | 
|---|
 | 131 | // mode: c++ //
 | 
|---|
 | 132 | // compile-command: "make install" //
 | 
|---|
 | 133 | // End: //
 | 
|---|