source: src/ResolvExpr/ResolveTypeof.cc @ fc1a3e2

Last change on this file since fc1a3e2 was 7a780ad, checked in by Andrew Beach <ajbeach@…>, 2 months ago

Moved ast::BasicType::Kind to ast::BasicKind? in its own hearder. This is more consistent with other utility enums (although we still use this as a enum class) and reduces what some files need to include. Also did a upgrade in a comment with MAX_INTEGER_TYPE, it is now part of the enum.

  • Property mode set to 100644
File size: 6.0 KB
Line 
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//
7// ResolveTypeof.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 12:12:20 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Mar 16 16:09:00 2022
13// Update Count     : 4
14//
15
16#include "ResolveTypeof.h"
17
18#include <cassert>  // for assert
19
20#include "AST/CVQualifiers.hpp"
21#include "AST/Node.hpp"
22#include "AST/Pass.hpp"
23#include "AST/TranslationUnit.hpp"
24#include "AST/Type.hpp"
25#include "AST/TypeEnvironment.hpp"
26#include "Common/utility.h"       // for copy
27#include "InitTweak/InitTweak.h"  // for isConstExpr
28#include "RenameVars.h"
29#include "Resolver.h"  // for resolveInVoidContext
30#include "SymTab/Mangler.h"
31
32namespace ResolvExpr {
33
34namespace {
35
36struct ResolveTypeof : public ast::WithShortCircuiting {
37        const ResolveContext & context;
38
39        ResolveTypeof( const ResolveContext & context ) : context( context ) {}
40
41        void previsit( const ast::TypeofType * ) { visit_children = false; }
42
43        const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
44                // pass on null expression
45                if ( ! typeofType->expr ) return typeofType;
46
47                ast::ptr< ast::Type > newType;
48                if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) {
49                        // typeof wrapping type
50                        newType = tyExpr->type;
51                } else {
52                        // typeof wrapping expression
53                        ast::TypeEnvironment dummy;
54                        ast::ptr< ast::Expr > newExpr =
55                                resolveInVoidContext( typeofType->expr, context, dummy );
56                        assert( newExpr->result && ! newExpr->result->isVoid() );
57                        newType = newExpr->result;
58                }
59
60                // clear qualifiers for base, combine with typeoftype quals regardless
61                if ( typeofType->kind == ast::TypeofType::Basetypeof ) {
62                        // replace basetypeof(<enum>) by int
63                        if ( newType.as< ast::EnumInstType >() ) {
64                                newType = new ast::BasicType(
65                                        ast::BasicKind::SignedInt, newType->qualifiers, copy(newType->attributes) );
66                        }
67                        reset_qualifiers(
68                                newType,
69                                ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
70                } else {
71                        add_qualifiers( newType, typeofType->qualifiers );
72                }
73
74                return newType.release();
75        }
76};
77
78} // anonymous namespace
79
80const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
81        ast::Pass< ResolveTypeof > mutator( context );
82        return type->accept( mutator );
83}
84
85struct FixArrayDimension {
86        const ResolveContext & context;
87        FixArrayDimension(const ResolveContext & context) : context( context ) {}
88
89        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
90                if (!arrayType->dimension) return arrayType;
91                auto mutType = mutate(arrayType);
92                auto globalSizeType = context.global.sizeType;
93                ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType( ast::BasicKind::LongUnsignedInt );
94                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context );
95
96                if (InitTweak::isConstExpr(mutType->dimension)) {
97                        mutType->isVarLen = ast::LengthFlag::FixedLen;
98                }
99                else {
100                        mutType->isVarLen = ast::LengthFlag::VariableLen;
101                }
102                return mutType;
103        }
104};
105
106const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) {
107        ast::Pass<FixArrayDimension> visitor(context);
108        return type->accept(visitor);
109}
110
111const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) {
112        if ( decl->isTypeFixed ) {
113                return decl;
114        }
115
116        auto mutDecl = mutate(decl);
117        fixObjectInit(decl, context);
118        {
119                auto resolvedType = resolveTypeof(decl->type, context);
120                resolvedType = fixArrayType(resolvedType, context);
121                mutDecl->type = resolvedType;
122        }
123
124        // Do not mangle unnamed variables.
125        if ( !mutDecl->name.empty() ) {
126                mutDecl->mangleName = Mangle::mangle(mutDecl);
127        }
128
129        mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
130        mutDecl->isTypeFixed = true;
131        return mutDecl;
132}
133
134const ast::ObjectDecl *fixObjectInit(
135                const ast::ObjectDecl *decl, const ResolveContext &context) {
136        if ( decl->isTypeFixed ) {
137                return decl;
138        }
139
140        if ( auto listInit = decl->init.as<ast::ListInit>() ) {
141                for ( size_t k = 0; k < listInit->designations.size(); k++ ) {
142                        const ast::Designation *des = listInit->designations[k].get();
143                        // Desination here
144                        ast::Designation * newDesignation = new ast::Designation(des->location);
145                        std::deque<ast::ptr<ast::Expr>> newDesignators;
146
147                        for ( ast::ptr<ast::Expr> designator : des->designators ) {
148                                // Stupid flag variable for development, to be removed
149                                if ( const ast::NameExpr * designatorName = designator.as<ast::NameExpr>() ) {
150                                        auto candidates = context.symtab.lookupId(designatorName->name);
151                                        // Does not work for the overloading case currently
152                                        // assert( candidates.size() == 1 );
153                                        if ( candidates.size() != 1 ) return decl;
154                                        auto candidate = candidates.at(0);
155                                        if ( const ast::EnumInstType * enumInst = dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type())) {
156                                                // determine that is an enumInst, swap it with its const value
157                                                assert( candidates.size() == 1 );
158                                                const ast::EnumDecl * baseEnum = enumInst->base;
159                                                // Need to iterate over all enum value to find the initializer to swap
160                                                for ( size_t m = 0; m < baseEnum->members.size(); ++m ) {
161                                                        const ast::ObjectDecl * mem = baseEnum->members.at(m).as<const ast::ObjectDecl>();
162                                                        if ( baseEnum->members.at(m)->name == designatorName->name ) {
163                                                                assert( mem );
164                                                                newDesignators.push_back( ast::ConstantExpr::from_int(designator->location, m) );
165                                                                break;
166                                                        }
167                                                }
168                                        } else {
169                                                newDesignators.push_back( des->designators.at(0) );
170                                        }
171                                } else {
172                                        newDesignators.push_back( des->designators.at(0) );
173                                }
174                        }
175                        newDesignation->designators = newDesignators;
176                        listInit = ast::mutate_field_index(listInit, &ast::ListInit::designations, k, newDesignation);
177                }
178        }
179        return decl;
180}
181
182} // namespace ResolvExpr
183
184// Local Variables: //
185// tab-width: 4 //
186// mode: c++ //
187// compile-command: "make install" //
188// End: //
Note: See TracBrowser for help on using the repository browser.