source: src/Validate/ForallPointerDecay.cpp@ 11ab0b4a

Last change on this file since 11ab0b4a was 14c0f7b, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Added invariant to check that referenced declarations are in scope. This one took a while, I don't remember why forall pointer decay is involved.

  • Property mode set to 100644
File size: 7.3 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// ForallPointerDecay.cpp --
8//
9// Author : Andrew Beach
10// Created On : Tue Dec 7 16:15:00 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Sat Apr 23 13:10:00 2022
13// Update Count : 1
14//
15
16#include "ForallPointerDecay.hpp"
17
18#include "AST/Copy.hpp"
19#include "AST/Decl.hpp"
20#include "AST/DeclReplacer.hpp"
21#include "AST/Pass.hpp"
22#include "CodeGen/OperatorTable.h"
23#include "Common/CodeLocation.h"
24#include "Common/ToString.hpp"
25#include "Common/utility.h"
26#include "SymTab/FixFunction.h"
27
28namespace Validate {
29
30namespace {
31
32// Create a function type only using information on the FunctionDecl.
33ast::FunctionType * makeFuncType( const ast::FunctionDecl * decl ) {
34 auto type = new ast::FunctionType( decl->type->isVarArgs );
35 for ( auto & param : decl->params ) {
36 type->params.emplace_back( param->get_type() );
37 }
38 for ( auto & ret : decl->returns ) {
39 type->returns.emplace_back( ret->get_type() );
40 }
41 for ( auto & type_param : decl->type_params ) {
42 type->forall.emplace_back(
43 new ast::TypeInstType( type_param ) );
44 }
45 for ( auto & assertion : decl->assertions ) {
46 type->assertions.emplace_back( new ast::VariableExpr(
47 assertion->location, assertion ) );
48 }
49 return type;
50}
51
52ast::FunctionDecl * updateAssertions( ast::FunctionDecl * decl ) {
53 auto type = ast::mutate( decl->type.get() );
54 type->assertions.clear();
55 type->assertions.reserve( decl->assertions.size() );
56 for ( auto & assertion : decl->assertions ) {
57 type->assertions.emplace_back(
58 new ast::VariableExpr( decl->location, assertion ) );
59 }
60 decl->type = type;
61 return decl;
62}
63
64// Component Passes:
65/// Expand assertions from a trait instance,
66/// performing appropriate type variable substitutions.
67struct TraitExpander final {
68 using AssertionList = std::vector<ast::ptr<ast::DeclWithType>>;
69
70 static AssertionList expandTrait( const ast::TraitInstType * inst ) {
71 assertf( inst->base, "Trait instance not linked to base trait: %s",
72 toCString( inst ) );
73 AssertionList assertions;
74 // Substitute trait decl parameters for instance parameters.
75 ast::TypeSubstitution sub( inst->base->params, inst->params );
76 for ( const ast::ptr<ast::Decl> & decl : inst->base->members ) {
77 ast::ptr<ast::DeclWithType> copy =
78 ast::deepCopy( decl.strict_as<ast::DeclWithType>() );
79
80 int count = sub.apply( copy );
81 (void)count;
82
83 // Update the type (type substution does not seem to cover it).
84 if ( auto func = copy.as<ast::FunctionDecl>() ) {
85 auto mut = ast::mutate( func );
86 mut->type = makeFuncType( func );
87 copy = mut;
88 }
89 assertions.push_back( copy );
90 }
91 return assertions;
92 }
93
94 static AssertionList expandAssertions( const AssertionList & old ) {
95 AssertionList assertions;
96 for ( const ast::ptr<ast::DeclWithType> & decl : old ) {
97 if ( auto traitInst = dynamic_cast<const ast::TraitInstType *>(
98 decl->get_type() ) ) {
99 auto moreAsserts = expandTrait( traitInst );
100 splice( assertions, moreAsserts );
101 } else {
102 assertions.push_back( decl );
103 }
104 }
105 return assertions;
106 }
107
108 using TypeDeclVec = std::vector<ast::ptr<ast::TypeDecl>>;
109
110 static TypeDeclVec expandTypeDecls( const TypeDeclVec & old ) {
111 TypeDeclVec typeDecls;
112 typeDecls.reserve( old.size() );
113 for ( const ast::TypeDecl * typeDecl : old ) {
114 typeDecls.push_back( ast::mutate_field( typeDecl,
115 &ast::TypeDecl::assertions,
116 expandAssertions( typeDecl->assertions ) ) );
117 }
118 return typeDecls;
119 }
120
121 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl ) {
122 if ( decl->assertions.empty() ) {
123 return decl;
124 }
125 auto mut = ast::mutate( decl );
126 mut->assertions = expandAssertions( decl->assertions );
127 // Update the assertion list on the type as well.
128 return updateAssertions( mut );
129 }
130
131 const ast::StructDecl * previsit( const ast::StructDecl * decl ) {
132 if ( decl->params.empty() ) {
133 return decl;
134 }
135 return ast::mutate_field( decl, &ast::StructDecl::params,
136 expandTypeDecls( decl->params ) );
137 }
138
139 const ast::UnionDecl * previsit( const ast::UnionDecl * decl ) {
140 if ( decl->params.empty() ) {
141 return decl;
142 }
143 return ast::mutate_field( decl, &ast::UnionDecl::params,
144 expandTypeDecls( decl->params ) );
145 }
146};
147
148std::vector<ast::ptr<ast::DeclWithType>> fixAssertionList(
149 const ast::ParseNode * node,
150 const std::vector<ast::ptr<ast::DeclWithType>> & assertions ) {
151 std::vector<ast::ptr<ast::DeclWithType>> ret;
152 ret.reserve( assertions.size() );
153 for ( const auto & assn : assertions ) {
154 bool isVoid = false;
155 ret.push_back( SymTab::fixFunction( assn, isVoid ) );
156 if ( isVoid ) {
157 SemanticError( node->location, node,
158 "invalid type void in assertion of function " );
159 }
160 }
161 return ret;
162}
163
164std::vector<ast::ptr<ast::TypeDecl>> fixTypeDeclList(
165 const ast::ParseNode * node,
166 const std::vector<ast::ptr<ast::TypeDecl>> & type_params ) {
167 std::vector<ast::ptr<ast::TypeDecl>> ret;
168 ret.reserve( type_params.size() );
169 for ( const ast::TypeDecl * type_param : type_params ) {
170 auto mutParam = ast::mutate( type_param );
171 mutParam->assertions = fixAssertionList( node, mutParam->assertions );
172 ret.push_back( mutParam );
173 }
174 return ret;
175}
176
177struct AssertionFunctionFixer final {
178 const ast::FunctionDecl * previsit( const ast::FunctionDecl * decl ) {
179 if ( decl->assertions.empty() ) {
180 return decl;
181 }
182 return ast::mutate_field( decl, &ast::FunctionDecl::assertions,
183 fixAssertionList( decl, decl->assertions ) );
184 }
185
186 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl ) {
187 if ( decl->assertions.empty() ) {
188 return decl;
189 }
190 return updateAssertions( mutate( decl ) );
191 }
192
193 const ast::StructDecl * previsit( const ast::StructDecl * decl ) {
194 if ( decl->params.empty() ) {
195 return decl;
196 }
197 return ast::mutate_field( decl, &ast::StructDecl::params,
198 fixTypeDeclList( decl, decl->params ) );
199 }
200
201 const ast::UnionDecl * previsit( const ast::UnionDecl * decl ) {
202 if ( decl->params.empty() ) {
203 return decl;
204 }
205 return ast::mutate_field( decl, &ast::UnionDecl::params,
206 fixTypeDeclList( decl, decl->params ) );
207 }
208};
209
210struct OperatorChecker final {
211 void previsit( const ast::ObjectDecl * obj ) {
212 if ( !CodeGen::isOperator( obj->name ) ) return;
213 auto type = obj->type->stripDeclarator();
214 if ( dynamic_cast< const ast::FunctionType * >( type ) ) return;
215 SemanticError( obj->location,
216 toCString( "operator ", obj->name.c_str(),
217 " is not a function or function pointer." ) );
218 }
219};
220
221struct UniqueFixCore final {
222 const ast::DeclWithType * postvisit( const ast::DeclWithType * decl ) {
223 if ( decl->uniqueId ) {
224 return decl;
225 } else {
226 auto mut = ast::mutate( decl );
227 mut->fixUniqueId();
228 return mut;
229 }
230 }
231};
232
233} // namespace
234
235void decayForallPointers( ast::TranslationUnit & transUnit ) {
236 ast::Pass<TraitExpander>::run( transUnit );
237 ast::Pass<AssertionFunctionFixer>::run( transUnit );
238 ast::Pass<OperatorChecker>::run( transUnit );
239}
240
241void fixUniqueIds( ast::TranslationUnit & transUnit ) {
242 ast::Pass<UniqueFixCore>::run( transUnit );
243}
244
245std::vector<ast::ptr<ast::DeclWithType>> expandAssertions(
246 std::vector<ast::ptr<ast::DeclWithType>> const & old ) {
247 return TraitExpander::expandAssertions( old );
248}
249
250} // namespace Validate
251
252// Local Variables: //
253// tab-width: 4 //
254// mode: c++ //
255// compile-command: "make install" //
256// End: //
Note: See TracBrowser for help on using the repository browser.