source: src/ResolvExpr/ResolveTypeof.cc@ f2898df

Last change on this file since f2898df was 2908f08, checked in by Andrew Beach <ajbeach@…>, 22 months ago

Most of ResolvExpr was written before the new style standard. Some files updated, focus on headers.

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