source: src/Validate/EnumAndPointerDecay.cpp @ 9d5eacb

Last change on this file since 9d5eacb was 85855b0, checked in by JiadaL <j82liang@…>, 5 months ago
  1. Implement enum cast; 2. Change valueE so that opague enum returns quasi_void; 3. change enum hiding interpretation and pass visiting scheme
  • Property mode set to 100644
File size: 4.1 KB
Line 
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//
7// EnumAndPointerDecay.cpp -- Normalizes enumerations and types in functions.
8//
9// Author           : Andrew Beach
10// Created On       : Tue Jun 28 15:50:00 2022
11// Last Modified By : Andrew Beach
12// Last Modified On : Tue Sep 20 16:14:00 2022
13// Update Count     : 1
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"
22#include "SymTab/FixFunction.hpp"
23#include "Validate/NoIdSymbolTable.hpp"
24
25namespace Validate {
26
27namespace {
28
29struct EnumAndPointerDecayCore final : public WithNoIdSymbolTable, public ast::WithCodeLocation {
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
35ast::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 );
42        std::vector<ast::ptr<ast::Decl>> buffer;
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>() ) {
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                                ));
71                        }
72                }
73        }
74        mut->members = buffer;
75        return mut;
76}
77
78template<typename Member>
79void 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
100ast::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
110ast::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
123void 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: //
Note: See TracBrowser for help on using the repository browser.