source: src/ResolvExpr/CurrentObject.cc@ 09a767e

Last change on this file since 09a767e was 8f557161, checked in by Michael Brooks <mlbrooks@…>, 2 years ago

Clarify and fix accuracy in eval public API, on reporting "unable to evaluate."

While the eval internals always used the flag pair valid and cfavalid almost correctly, the public interface exposed the outcome as a single flag, and the various interpretations of this flag were a mess.

Old cfacc treated sizeof(whatever) in some contexts as "known to be zero," which is wrong.
The generally correct answer, which new cfacc now uses is, "unknown now, but GCC will see it as a fine constant."
New tests/eval.cfa captures this fact: is runnable and would fail on old cfacc; it passes with new cfacc.

  • Property mode set to 100644
File size: 39.8 KB
RevLine 
[e4d829b]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// CurrentObject.h --
8//
9// Author : Rob Schluntz
10// Created On : Tue Jun 13 15:28:32 2017
[485393c]11// Last Modified By : Andrew Beach
[ea2759b]12// Last Modified On : Mon Apr 10 9:40:00 2023
13// Update Count : 18
[e4d829b]14//
15
[ea6332d]16#include <stddef.h> // for size_t
17#include <cassert> // for assertf, assert, safe_dynamic_...
[60aaa51d]18#include <deque>
[ea6332d]19#include <iostream> // for ostream, operator<<, basic_ost...
20#include <stack> // for stack
21#include <string> // for string, operator<<, allocator
[e4d829b]22
[8e1467d]23#include "AST/Copy.hpp" // for shallowCopy
[2b59f55]24#include "AST/Expr.hpp" // for InitAlternative
[60aaa51d]25#include "AST/GenericSubstitution.hpp" // for genericSubstitution
[2b59f55]26#include "AST/Init.hpp" // for Designation
27#include "AST/Node.hpp" // for readonly
[8f06277]28#include "AST/Print.hpp" // for readonly
[60aaa51d]29#include "AST/Type.hpp"
[8f06277]30#include "Common/Eval.h" // for eval
[ea6332d]31#include "Common/Indenter.h" // for Indenter, operator<<
32#include "Common/SemanticError.h" // for SemanticError
33#include "Common/utility.h" // for toString
[e4d829b]34#include "CurrentObject.h"
[ea6332d]35#include "SynTree/Constant.h" // for Constant
36#include "SynTree/Declaration.h" // for ObjectDecl, Declaration, Struc...
37#include "SynTree/Expression.h" // for InitAlternative, VariableExpr
38#include "SynTree/Initializer.h" // for Designation, operator<<
39#include "SynTree/Type.h" // for Type, StructInstType, UnionIns...
40#include "SynTree/TypeSubstitution.h" // for TypeSubstitution
[e4d829b]41
42#if 0
43#define PRINT(x) x
44#else
45#define PRINT(x)
46#endif
47
48namespace ResolvExpr {
[62423350]49 template< typename AggrInst >
50 TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
51 assert( inst );
52 assert( inst->get_baseParameters() );
53 std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
54 std::list< Expression * > typeSubs = inst->get_parameters();
55 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
56 return subs;
57 }
58
59 TypeSubstitution makeGenericSubstitution( Type * type ) {
60 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
61 return makeGenericSubstitution( inst );
62 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
63 return makeGenericSubstitution( inst );
64 } else {
65 return TypeSubstitution();
66 }
67 }
68
[e4d829b]69 class MemberIterator {
70 public:
71 virtual ~MemberIterator() {}
72
[84e8423]73 /// walks the current object using the given designators as a guide
[e4d829b]74 virtual void setPosition( std::list< Expression * > & designators ) = 0;
[84e8423]75
[1df492a]76 /// retrieve the list of possible Type/Designation pairs for the current position in the currect object
[e4d829b]77 virtual std::list<InitAlternative> operator*() const = 0;
[84e8423]78
79 /// true if the iterator is not currently at the end
[e4d829b]80 virtual operator bool() const = 0;
[84e8423]81
82 /// moves the iterator by one member in the current object
[e4d829b]83 virtual MemberIterator & bigStep() = 0;
[84e8423]84
85 /// moves the iterator by one member in the current subobject
[e4d829b]86 virtual MemberIterator & smallStep() = 0;
[84e8423]87
88 /// the type of the current object
[e4d829b]89 virtual Type * getType() = 0;
[84e8423]90
91 /// the type of the current subobject
[e4d829b]92 virtual Type * getNext() = 0;
93
[84e8423]94 /// printing for debug
[e4d829b]95 virtual void print( std::ostream & out, Indenter indent ) const = 0;
96
[84e8423]97 /// helper for operator*; aggregates must add designator to each init alternative, but
98 /// adding designators in operator* creates duplicates.
[e4d829b]99 virtual std::list<InitAlternative> first() const = 0; // should be protected
100 };
101
102 std::ostream & operator<<(std::ostream & out, const MemberIterator & it) {
103 Indenter indenter;
104 it.print( out, indenter );
105 return out;
106 }
107
108 /// create a new MemberIterator that traverses a type correctly
109 MemberIterator * createMemberIterator( Type * type );
110
111 /// iterates "other" types, e.g. basic types, pointer types, etc. which do not change at list initializer entry
112 class SimpleIterator : public MemberIterator {
113 public:
114 SimpleIterator( Type * type ) : type( type ) {}
115
116 virtual void setPosition( std::list< Expression * > & designators ) {
117 assertf( designators.empty(), "simple iterator given non-empty designator..." ); // xxx - might be semantic error
118 }
119
120 virtual std::list<InitAlternative> operator*() const { return first(); }
121 virtual operator bool() const { return type; }
122
123 // big step is the same as small step
124 virtual MemberIterator & bigStep() { return smallStep(); }
125 virtual MemberIterator & smallStep() {
126 type = nullptr; // type is nullified on increment since SimpleIterators do not have members
127 return *this;
128 }
129
[9ff56e7]130 virtual void print( std::ostream & out, __attribute__((unused)) Indenter indent ) const {
[e4d829b]131 out << "SimpleIterator(" << type << ")";
132 }
133
134 virtual Type * getType() { return type; }
135 virtual Type * getNext() { return type; }
136
137 protected:
138 virtual std::list<InitAlternative> first() const {
139 if ( type ) return std::list<InitAlternative>{ { type->clone(), new Designation( {} ) } };
140 else return std::list<InitAlternative>{};
141 }
142 private:
143 Type * type = nullptr;
144 };
145
146 class ArrayIterator : public MemberIterator {
147 public:
148 ArrayIterator( ArrayType * at ) : array( at ) {
149 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
[f072892]150 base = at->base;
[e4d829b]151 memberIter = createMemberIterator( base );
[f072892]152 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
153 setSize( at->dimension );
[e4d829b]154 }
155
156 ~ArrayIterator() {
157 delete memberIter;
158 }
159
160 private:
[f37d9e7]161 void setSize( Expression * expr ) {
162 auto res = eval( expr );
[ba4a1d8]163 if (res.second) {
164 size = res.first;
[e4d829b]165 } else {
[ba4a1d8]166 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
[e4d829b]167 }
168 }
169
170 public:
171 void setPosition( Expression * expr ) {
172 // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
[f37d9e7]173 auto arg = eval( expr );
174 index = arg.first;
175 return;
176
177 // if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
178 // try {
179 // index = constExpr->intValue();
180 // } catch( SemanticErrorException & ) {
181 // SemanticError( expr, "Constant expression of non-integral type in array designator: " );
182 // }
183 // } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
184 // setPosition( castExpr->get_arg() );
185 // } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
186 // EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
187 // assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
188 // long long int value;
189 // if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
190 // index = value;
191 // }
192 // } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
193 // index = 0; // xxx - get actual sizeof/alignof value?
194 // } else {
195 // assertf( false, "4 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
196 // }
[e4d829b]197 }
198
199 virtual void setPosition( std::list< Expression * > & designators ) {
200 if ( ! designators.empty() ) {
201 setPosition( designators.front() );
202 designators.pop_front();
203 memberIter->setPosition( designators );
204 }
205 }
206
207 virtual std::list<InitAlternative> operator*() const {
208 return first();
209 }
210
[4b97770]211 virtual operator bool() const { return index < size; }
[e4d829b]212
213 virtual MemberIterator & bigStep() {
214 PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
215 ++index;
216 delete memberIter;
[4b97770]217 if ( index < size ) memberIter = createMemberIterator( base );
[e4d829b]218 else memberIter = nullptr;
219 return *this;
220 }
221
222 virtual MemberIterator & smallStep() {
223 PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
224 if ( memberIter ) {
225 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
226 memberIter->smallStep();
227 if ( *memberIter ) {
228 PRINT( std::cerr << "has valid member iter" << std::endl; )
229 return *this;
230 }
231 }
232 return bigStep();
233 }
234
235 virtual Type * getType() { return array; }
236 virtual Type * getNext() { return base; }
237
238 virtual std::list<InitAlternative> first() const {
239 PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
240 if ( memberIter && *memberIter ) {
241 std::list<InitAlternative> ret = memberIter->first();
242 for ( InitAlternative & alt : ret ) {
243 alt.designation->get_designators().push_front( new ConstantExpr( Constant::from_ulong( index ) ) );
244 }
245 return ret;
246 }
247 return std::list<InitAlternative>();
248 }
249
250 virtual void print( std::ostream & out, Indenter indent ) const {
251 out << "ArrayIterator(Array of " << base << ")";
252 if ( memberIter ) {
253 Indenter childIndent = indent+1;
254 out << std::endl << childIndent;
255 memberIter->print( out, childIndent );
256 }
257 }
258
259 private:
260 ArrayType * array = nullptr;
261 Type * base = nullptr;
262 size_t index = 0;
263 size_t size = 0;
264 MemberIterator * memberIter = nullptr;
265 };
266
267 class AggregateIterator : public MemberIterator {
268 public:
[62423350]269 typedef std::list<Declaration *> MemberList;
270 typedef MemberList::const_iterator iterator;
271 std::string kind = ""; // for debug
272 std::string name;
273 Type * inst = nullptr;
274 const MemberList & members;
[e4d829b]275 iterator curMember;
[62423350]276 bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning
[e4d829b]277 Type * curType = nullptr;
278 MemberIterator * memberIter = nullptr;
[62423350]279 mutable TypeSubstitution sub;
[e4d829b]280
[62423350]281 AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) {
[c6747a1]282 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
[e4d829b]283 init();
284 }
285
286 virtual ~AggregateIterator() {
287 delete memberIter;
288 }
289
290 bool init() {
[62423350]291 PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
292 if ( curMember != members.end() ) {
[e4d829b]293 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) {
294 PRINT( std::cerr << "incremented to field: " << field << std::endl; )
295 curType = field->get_type();
296 memberIter = createMemberIterator( curType );
297 return true;
298 }
299 }
300 return false;
301 }
302
303 virtual std::list<InitAlternative> operator*() const {
304 if (memberIter && *memberIter) {
305 std::list<InitAlternative> ret = memberIter->first();
[62423350]306 PRINT( std::cerr << "sub: " << sub << std::endl; )
[e4d829b]307 for ( InitAlternative & alt : ret ) {
308 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
[e3e16bc]309 alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
[62423350]310 // need to substitute for generic types, so that casts are to concrete types
311 PRINT( std::cerr << " type is: " << alt.type; )
312 sub.apply( alt.type ); // also apply to designation??
313 PRINT( std::cerr << " ==> " << alt.type << std::endl; )
[e4d829b]314 }
315 return ret;
316 }
317 return std::list<InitAlternative>();
318 }
319
320 virtual void setPosition( std::list< Expression * > & designators ) {
321 if ( ! designators.empty() ) {
322 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) {
[62423350]323 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
[e4d829b]324 if ( *curMember == varExpr->get_var() ) {
325 designators.pop_front();
326 delete memberIter;
327 memberIter = createMemberIterator( varExpr->get_result() );
328 curType = varExpr->get_result();
[62423350]329 atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin??
[e4d829b]330 memberIter->setPosition( designators );
331 return;
332 } // if
333 } // for
[62423350]334 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
[e4d829b]335 } else {
[f37d9e7]336 assertf( false, "3 bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() );
[e4d829b]337 } // if
338 } // if
339 }
340
341 virtual MemberIterator & smallStep() {
342 PRINT( std::cerr << "smallStep in " << kind << std::endl; )
343 atbegin = false;
344 if ( memberIter ) {
345 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
346 memberIter->smallStep();
347 if ( *memberIter ) {
348 PRINT( std::cerr << "success!" << std::endl; )
349 return *this;
350 }
351 }
352 return bigStep();
353 }
354
355 virtual Type * getType() { return inst; }
356 virtual Type * getNext() {
357 if ( memberIter && *memberIter ) return memberIter->getType(); // xxx - ??? recursive call???
358 return nullptr;
359 }
360
361 virtual std::list<InitAlternative> first() const {
362 std::list<InitAlternative> ret;
363 PRINT( std::cerr << "first " << kind << std::endl; )
364 if ( memberIter && *memberIter ) { // might not need *memberIter??
365 PRINT( std::cerr << "adding children" << std::endl; )
366 ret = memberIter->first();
367 for ( InitAlternative & alt : ret ) {
368 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
[e3e16bc]369 alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
[e4d829b]370 }
371 }
[84e8423]372 if ( atbegin ) {
[e4d829b]373 // xxx - what about case of empty struct??
374 // only add self if at the very beginning of the structure
375 PRINT( std::cerr << "adding self" << std::endl; )
376 ret.push_front( { inst->clone(), new Designation( {} ) } );
377 }
378 return ret;
379 }
380
381 virtual void print( std::ostream & out, Indenter indent ) const {
[62423350]382 out << kind << "(" << name << ")";
[e4d829b]383 if ( memberIter ) {
384 Indenter childIndent = indent+1;
385 out << std::endl << childIndent;
386 memberIter->print( out, childIndent );
387 }
388 }
389 };
390
391 class UnionIterator : public AggregateIterator {
392 public:
[62423350]393 UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {}
[e4d829b]394
395 virtual operator bool() const { return (memberIter && *memberIter); }
396 virtual MemberIterator & bigStep() {
397 // unions only initialize one member
398 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
399 atbegin = false;
400 delete memberIter;
401 memberIter = nullptr;
402 curType = nullptr;
[62423350]403 curMember = members.end();
[e4d829b]404 return *this;
405 }
406 };
407
408 class StructIterator : public AggregateIterator {
409 public:
[62423350]410 StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {}
411
412 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
413
414 virtual MemberIterator & bigStep() {
415 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
416 atbegin = false;
417 delete memberIter;
418 memberIter = nullptr;
419 curType = nullptr;
420 for ( ; curMember != members.end(); ) {
421 ++curMember;
422 if ( init() ) {
423 return *this;
424 }
425 }
426 return *this;
427 }
428 };
429
430 class TupleIterator : public AggregateIterator {
431 public:
432 TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {}
[e4d829b]433
[62423350]434 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
[e4d829b]435
436 virtual MemberIterator & bigStep() {
437 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
438 atbegin = false;
439 delete memberIter;
440 memberIter = nullptr;
441 curType = nullptr;
[62423350]442 for ( ; curMember != members.end(); ) {
[e4d829b]443 ++curMember;
444 if ( init() ) {
445 return *this;
446 }
447 }
448 return *this;
449 }
450 };
451
452 MemberIterator * createMemberIterator( Type * type ) {
453 if ( ReferenceToType * aggr = dynamic_cast< ReferenceToType * >( type ) ) {
454 if ( StructInstType * sit = dynamic_cast< StructInstType * >( aggr ) ) {
455 return new StructIterator( sit );
456 } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( aggr ) ) {
457 return new UnionIterator( uit );
458 } else {
[78754d7]459 assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
[62423350]460 return new SimpleIterator( type );
[e4d829b]461 }
462 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
463 return new ArrayIterator( at );
[62423350]464 } else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
465 return new TupleIterator( tt );
[e4d829b]466 } else {
467 return new SimpleIterator( type );
468 }
469 }
470
471 CurrentObject::CurrentObject() {}
472 CurrentObject::CurrentObject( Type * type ) {
473 objStack.push( new SimpleIterator( type ) );
474 }
475
476
477 void CurrentObject::setNext( Designation * designation ) {
478 assertf( ! objStack.empty(), "obj stack empty in setNext" );
479 PRINT( std::cerr << "____setNext" << designation << std::endl; )
480 objStack.top()->setPosition( designation->get_designators() );
481 }
482
483 Designation * CurrentObject::findNext( Designation * designation ) {
484 typedef std::list< Expression * > DesignatorChain;
485 PRINT( std::cerr << "___findNext" << std::endl; )
486 // find all the d's
487 std::list<DesignatorChain> desigAlts{ { } }, newDesigAlts;
488 std::list<Type *> curTypes { (objStack.top())->getType() }, newTypes;
489 for ( Expression * expr : designation->get_designators() ) {
490 PRINT( std::cerr << "____untyped: " << expr << std::endl; )
491 std::list<DesignatorChain>::iterator dit = desigAlts.begin();
492 if ( NameExpr * nexpr = dynamic_cast<NameExpr *>(expr) ) {
493 for ( Type * t : curTypes ) {
494 assert( dit != desigAlts.end() );
495 DesignatorChain & d = *dit;
496 PRINT( std::cerr << "____actual: " << t << std::endl; )
497 ReferenceToType * refType = dynamic_cast<ReferenceToType *>(t);
498 std::list<Declaration *> members;
499 if ( refType ) {
500 refType->lookup( nexpr->get_name(), members ); // concatenate identical field name
501 // xxx - need to also include anonymous members in this somehow...
502 for ( Declaration * mem: members ) {
503 if ( ObjectDecl * field = dynamic_cast<ObjectDecl *>(mem) ) {
504 PRINT( std::cerr << "____alt: " << field->get_type() << std::endl; )
505 DesignatorChain newD = d;
506 newD.push_back( new VariableExpr( field ) );
507 newDesigAlts.push_back( newD );
508 newTypes.push_back( field->get_type() );
509 } // if
510 } // for
511 } // if
512 ++dit;
513 } // for
514 } else {
515 for ( Type * t : curTypes ) {
516 assert( dit != desigAlts.end() );
517 DesignatorChain & d = *dit;
518 if ( ArrayType * at = dynamic_cast< ArrayType * > ( t ) ) {
519 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
520 d.push_back( expr );
521 newDesigAlts.push_back( d );
522 newTypes.push_back( at->get_base() );
523 }
524 ++dit;
525 } // for
526 } // if
527 desigAlts = newDesigAlts;
528 newDesigAlts.clear();
529 curTypes = newTypes;
530 newTypes.clear();
[56e49b0]531 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
[e4d829b]532 } // for
533 if ( desigAlts.size() > 1 ) {
[a16764a6]534 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
[e4d829b]535 } else if ( desigAlts.size() == 0 ) {
[a16764a6]536 SemanticError( designation, "No reasonable alternatives for designation: " );
[e4d829b]537 }
538 DesignatorChain & d = desigAlts.back();
539 PRINT( for ( Expression * expr : d ) {
540 std::cerr << "____desig: " << expr << std::endl;
541 } ) // for
542 assertf( ! curTypes.empty(), "empty designator chosen");
543
544 // set new designators
545 assertf( ! objStack.empty(), "empty object stack when setting designation" );
546 Designation * actualDesignation = new Designation( d );
547 objStack.top()->setPosition( d ); // destroys d
548 return actualDesignation;
549 }
550
551 void CurrentObject::increment() {
552 PRINT( std::cerr << "____increment" << std::endl; )
553 if ( ! objStack.empty() ) {
554 PRINT( std::cerr << *objStack.top() << std::endl; )
555 objStack.top()->smallStep();
556 }
557 }
558
559 void CurrentObject::enterListInit() {
560 PRINT( std::cerr << "____entering list init" << std::endl; )
561 assertf( ! objStack.empty(), "empty obj stack entering list init" );
562 Type * type = objStack.top()->getNext();
563 if ( type ) {
564 objStack.push( createMemberIterator( type ) );
565 } else {
566 assertf( false, "not sure about this case..." );
567 }
568 }
569
570 void CurrentObject::exitListInit() {
571 PRINT( std::cerr << "____exiting list init" << std::endl; )
572 assertf( ! objStack.empty(), "objstack empty" );
573 delete objStack.top();
574 objStack.pop();
575 if ( ! objStack.empty() ) {
576 PRINT( std::cerr << *objStack.top() << std::endl; )
577 objStack.top()->bigStep();
578 }
579 }
580
581 std::list< InitAlternative > CurrentObject::getOptions() {
582 PRINT( std::cerr << "____getting current options" << std::endl; )
583 assertf( ! objStack.empty(), "objstack empty in getOptions" );
584 return **objStack.top();
585 }
[62423350]586
587 Type * CurrentObject::getCurrentType() {
588 PRINT( std::cerr << "____getting current type" << std::endl; )
589 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
590 return objStack.top()->getNext();
591 }
[e4d829b]592} // namespace ResolvExpr
593
[b7d92b96]594namespace ast {
[485393c]595 /// Iterates members of a type by initializer.
596 class MemberIterator {
597 public:
598 virtual ~MemberIterator() {}
599
600 /// Internal set position based on iterator ranges.
601 virtual void setPosition(
602 std::deque< ptr< Expr > >::const_iterator it,
603 std::deque< ptr< Expr > >::const_iterator end ) = 0;
604
605 /// Walks the current object using the given designators as a guide.
606 void setPosition( const std::deque< ptr< Expr > > & designators ) {
607 setPosition( designators.begin(), designators.end() );
608 }
609
610 /// Retrieve the list of possible (Type,Designation) pairs for the
611 /// current position in the current object.
612 virtual std::deque< InitAlternative > operator* () const = 0;
613
614 /// True if the iterator is not currently at the end.
615 virtual operator bool() const = 0;
616
617 /// Moves the iterator by one member in the current object.
618 virtual MemberIterator & bigStep() = 0;
619
620 /// Moves the iterator by one member in the current subobject.
621 virtual MemberIterator & smallStep() = 0;
622
623 /// The type of the current object.
624 virtual const Type * getType() = 0;
625
626 /// The type of the current subobject.
627 virtual const Type * getNext() = 0;
628
629 /// Helper for operator*; aggregates must add designator to each init
630 /// alternative, but adding designators in operator* creates duplicates.
631 virtual std::deque< InitAlternative > first() const = 0;
632 };
633
[60aaa51d]634 /// create a new MemberIterator that traverses a type correctly
635 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
[b7d92b96]636
637 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
638 class SimpleIterator final : public MemberIterator {
[2b59f55]639 CodeLocation location;
[954c954]640 const Type * type = nullptr;
[b7d92b96]641 public:
[2b59f55]642 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
643
[2890212]644 void setPosition(
645 std::deque< ptr< Expr > >::const_iterator begin,
[60aaa51d]646 std::deque< ptr< Expr > >::const_iterator end
647 ) override {
648 if ( begin != end ) {
649 SemanticError( location, "Un-designated initializer given non-empty designator" );
650 }
651 }
[2b59f55]652
[60aaa51d]653 std::deque< InitAlternative > operator* () const override { return first(); }
654
655 operator bool() const override { return type; }
656
657 SimpleIterator & bigStep() override { return smallStep(); }
658 SimpleIterator & smallStep() override {
659 type = nullptr; // empty on increment because no members
660 return *this;
661 }
662
663 const Type * getType() override { return type; }
664
665 const Type * getNext() override { return type; }
666
667 std::deque< InitAlternative > first() const override {
[2b59f55]668 if ( type ) return { InitAlternative{ type, new Designation{ location } } };
669 return {};
670 }
[b7d92b96]671 };
672
[699a97d]673 /// Iterates over an indexed type:
674 class IndexIterator : public MemberIterator {
675 protected:
[60aaa51d]676 CodeLocation location;
677 size_t index = 0;
678 size_t size = 0;
[699a97d]679 std::unique_ptr<MemberIterator> memberIter;
[60aaa51d]680 public:
[699a97d]681 IndexIterator( const CodeLocation & loc, size_t size ) :
682 location( loc ), size( size )
683 {}
[60aaa51d]684
685 void setPosition( const Expr * expr ) {
[2890212]686 // need to permit integer-constant-expressions, including: integer constants,
687 // enumeration constants, character constants, sizeof expressions, alignof expressions,
[60aaa51d]688 // cast expressions
[f37d9e7]689
690 auto arg = eval( expr );
[8f557161]691 assertf( arg.hasKnownValue, "Non-evaluable expression made it to IndexIterator" );
692 index = arg.knownValue;
[f37d9e7]693
694 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
695 // try {
696 // index = constExpr->intValue();
697 // } catch ( SemanticErrorException & ) {
698 // SemanticError( expr, "Constant expression of non-integral type in array designator: " );
699 // }
700 // } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
701 // setPosition( castExpr->arg );
702 // } else if ( dynamic_cast< const SizeofExpr * >( expr ) || dynamic_cast< const AlignofExpr * >( expr ) ) {
703 // index = 0;
704 // } else {
705 // assertf( false, "2 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
706 // }
[60aaa51d]707 }
708
[2890212]709 void setPosition(
[485393c]710 std::deque<ast::ptr<ast::Expr>>::const_iterator begin,
711 std::deque<ast::ptr<ast::Expr>>::const_iterator end
[60aaa51d]712 ) override {
713 if ( begin == end ) return;
714
715 setPosition( *begin );
716 memberIter->setPosition( ++begin, end );
717 }
718
719 std::deque< InitAlternative > operator* () const override { return first(); }
720
721 operator bool() const override { return index < size; }
[699a97d]722 };
723
724 /// Iterates over the members of array types:
725 class ArrayIterator final : public IndexIterator {
726 const ArrayType * array = nullptr;
727 const Type * base = nullptr;
728
729 size_t getSize( const Expr * expr ) {
730 auto res = eval( expr );
[8f557161]731 if ( !res.hasKnownValue ) {
[699a97d]732 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
733 }
[8f557161]734 return res.knownValue;
[699a97d]735 }
736
737 public:
738 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) :
739 IndexIterator( loc, getSize( at->dimension) ),
740 array( at ), base( at->base ) {
741 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
742 memberIter.reset( createMemberIterator( loc, base ) );
743 if ( at->isVarLen ) {
744 SemanticError( location, at, "VLA initialization does not support @=: " );
745 }
746 }
[60aaa51d]747
748 ArrayIterator & bigStep() override {
749 PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
750 ++index;
751 memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
752 return *this;
753 }
754
755 ArrayIterator & smallStep() override {
756 PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
757 if ( memberIter ) {
758 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
759 memberIter->smallStep();
760 if ( *memberIter ) {
761 PRINT( std::cerr << "has valid member iter" << std::endl; )
762 return *this;
763 }
764 }
765 return bigStep();
766 }
767
768 const Type * getType() override { return array; }
769
770 const Type * getNext() override { return base; }
771
772 std::deque< InitAlternative > first() const override {
773 PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
774 if ( memberIter && *memberIter ) {
775 std::deque< InitAlternative > ret = memberIter->first();
776 for ( InitAlternative & alt : ret ) {
[f37d9e7]777 alt.designation.get_and_mutate()->designators.emplace_front( ConstantExpr::from_ulong( location, index ) );
[60aaa51d]778 }
779 return ret;
780 }
781 return {};
782 }
783 };
784
785 class AggregateIterator : public MemberIterator {
786 protected:
787 using MemberList = std::vector< ptr< Decl > >;
788
789 CodeLocation location;
790 std::string kind; // for debug
791 std::string name;
792 const Type * inst;
793 const MemberList & members;
794 MemberList::const_iterator curMember;
795 bool atbegin = true; // false at first {small,big}Step
796 const Type * curType = nullptr;
797 std::unique_ptr< MemberIterator > memberIter = nullptr;
798 TypeSubstitution sub;
799
800 bool init() {
801 PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
802 if ( curMember != members.end() ) {
803 if ( auto field = curMember->as< ObjectDecl >() ) {
804 PRINT( std::cerr << "incremented to field: " << field << std::endl; )
805 curType = field->get_type();
806 memberIter.reset( createMemberIterator( location, curType ) );
807 return true;
808 }
809 }
810 return false;
811 }
812
[2890212]813 AggregateIterator(
814 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
[60aaa51d]815 const MemberList & ms )
[2890212]816 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
[60aaa51d]817 sub( genericSubstitution( i ) ) {
818 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
819 init();
820 }
821
822 public:
[2890212]823 void setPosition(
824 std::deque< ptr< Expr > >::const_iterator begin,
[60aaa51d]825 std::deque< ptr< Expr > >::const_iterator end
826 ) final {
827 if ( begin == end ) return;
828
829 if ( auto varExpr = begin->as< VariableExpr >() ) {
830 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
831 if ( *curMember != varExpr->var ) continue;
832
833 ++begin;
834
835 memberIter.reset( createMemberIterator( location, varExpr->result ) );
836 curType = varExpr->result;
837 atbegin = curMember == members.begin() && begin == end;
838 memberIter->setPosition( begin, end );
839 return;
840 }
[f37d9e7]841 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
[60aaa51d]842 } else {
[f37d9e7]843 assertf( false, "1 bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
[60aaa51d]844 }
845 }
846
847 std::deque< InitAlternative > operator* () const final {
848 if ( memberIter && *memberIter ) {
849 std::deque< InitAlternative > ret = memberIter->first();
850 PRINT( std::cerr << "sub: " << sub << std::endl; )
851 for ( InitAlternative & alt : ret ) {
852 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
853 alt.designation.get_and_mutate()->designators.emplace_front(
854 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
855 // need to substitute for generic types so that casts are to concrete types
[8e1467d]856 alt.type = shallowCopy(alt.type.get());
[60aaa51d]857 PRINT( std::cerr << " type is: " << alt.type; )
858 sub.apply( alt.type ); // also apply to designation??
859 PRINT( std::cerr << " ==> " << alt.type << std::endl; )
860 }
861 return ret;
862 }
863 return {};
864 }
865
866 AggregateIterator & smallStep() final {
867 PRINT( std::cerr << "smallStep in " << kind << std::endl; )
868 atbegin = false;
869 if ( memberIter ) {
870 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
871 memberIter->smallStep();
872 if ( *memberIter ) {
873 PRINT( std::cerr << "success!" << std::endl; )
874 return *this;
875 }
876 }
877 return bigStep();
878 }
879
880 AggregateIterator & bigStep() override = 0;
881
882 const Type * getType() final { return inst; }
883
884 const Type * getNext() final {
[699a97d]885 bool hasMember = memberIter && *memberIter;
886 return hasMember ? memberIter->getType() : nullptr;
[60aaa51d]887 }
888
889 std::deque< InitAlternative > first() const final {
890 std::deque< InitAlternative > ret;
891 PRINT( std::cerr << "first " << kind << std::endl; )
892 if ( memberIter && *memberIter ) {
893 PRINT( std::cerr << "adding children" << std::endl; )
894 ret = memberIter->first();
895 for ( InitAlternative & alt : ret ) {
896 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
[2890212]897 alt.designation.get_and_mutate()->designators.emplace_front(
[60aaa51d]898 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
899 }
900 }
901 if ( atbegin ) {
902 // only add self if at the very beginning of the structure
903 PRINT( std::cerr << "adding self" << std::endl; )
904 ret.emplace_front( inst, new Designation{ location } );
905 }
906 return ret;
907 }
908 };
909
910 class StructIterator final : public AggregateIterator {
911 public:
912 StructIterator( const CodeLocation & loc, const StructInstType * inst )
913 : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
914
915 operator bool() const override {
916 return curMember != members.end() || (memberIter && *memberIter);
917 }
918
919 StructIterator & bigStep() override {
920 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
921 atbegin = false;
922 memberIter = nullptr;
923 curType = nullptr;
924 while ( curMember != members.end() ) {
925 ++curMember;
926 if ( init() ) return *this;
927 }
928 return *this;
929 }
930 };
931
932 class UnionIterator final : public AggregateIterator {
933 public:
934 UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
935 : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
936
937 operator bool() const override { return memberIter && *memberIter; }
938
939 UnionIterator & bigStep() override {
940 // unions only initialize one member
941 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
942 atbegin = false;
943 memberIter = nullptr;
944 curType = nullptr;
945 curMember = members.end();
946 return *this;
947 }
948 };
949
[ea2759b]950 /// Iterates across the positions in a tuple:
[699a97d]951 class TupleIterator final : public IndexIterator {
[ea2759b]952 ast::TupleType const * const tuple;
953
954 const ast::Type * typeAtIndex() const {
955 assert( index < size );
956 return tuple->types[ index ].get();
[fac05b3]957 }
958
[60aaa51d]959 public:
[ea2759b]960 TupleIterator( const CodeLocation & loc, const TupleType * type )
[699a97d]961 : IndexIterator( loc, type->size() ), tuple( type ) {
[ea2759b]962 PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; )
[699a97d]963 memberIter.reset( createMemberIterator( loc, typeAtIndex() ) );
[60aaa51d]964 }
965
966 TupleIterator & bigStep() override {
[ea2759b]967 ++index;
[699a97d]968 memberIter.reset( index < size ?
[ea2759b]969 createMemberIterator( location, typeAtIndex() ) : nullptr );
[60aaa51d]970 return *this;
971 }
[ea2759b]972
973 TupleIterator & smallStep() override {
[699a97d]974 if ( memberIter ) {
975 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
976 memberIter->smallStep();
977 if ( !memberIter ) {
[ea2759b]978 PRINT( std::cerr << "has valid member iter" << std::endl; )
979 return *this;
980 }
981 }
982 return bigStep();
983 }
984
985 const ast::Type * getType() override {
986 return tuple;
987 }
988
989 const ast::Type * getNext() override {
[699a97d]990 bool hasMember = memberIter && *memberIter;
991 return hasMember ? memberIter->getType() : nullptr;
[ea2759b]992 }
993
994 std::deque< InitAlternative > first() const override {
995 PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; )
[699a97d]996 if ( memberIter && *memberIter ) {
997 std::deque< InitAlternative > ret = memberIter->first();
[ea2759b]998 for ( InitAlternative & alt : ret ) {
999 alt.designation.get_and_mutate()->designators.emplace_front(
1000 ConstantExpr::from_ulong( location, index ) );
1001 }
1002 return ret;
1003 }
1004 return {};
1005 }
[60aaa51d]1006 };
1007
1008 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
[98e8b3b]1009 if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
[60aaa51d]1010 if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
[de57af9]1011 assert( sit->base );
[60aaa51d]1012 return new StructIterator{ loc, sit };
1013 } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
[de57af9]1014 assert( uit->base );
[60aaa51d]1015 return new UnionIterator{ loc, uit };
1016 } else {
[2890212]1017 assertf(
1018 dynamic_cast< const EnumInstType * >( type )
1019 || dynamic_cast< const TypeInstType * >( type ),
[98e8b3b]1020 "Encountered unhandled BaseInstType in createMemberIterator: %s",
[60aaa51d]1021 toString( type ).c_str() );
1022 return new SimpleIterator{ loc, type };
1023 }
1024 } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
1025 return new ArrayIterator{ loc, at };
1026 } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
1027 return new TupleIterator{ loc, tt };
1028 } else {
1029 return new SimpleIterator{ loc, type };
1030 }
1031 }
1032
[2b59f55]1033 CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
1034 objStack.emplace_back( new SimpleIterator{ loc, type } );
[b7d92b96]1035 }
1036
[2d11663]1037 const Designation * CurrentObject::findNext( const Designation * designation ) {
1038 using DesignatorChain = std::deque< ptr< Expr > >;
1039 PRINT( std::cerr << "___findNext" << std::endl; )
[2890212]1040
[2d11663]1041 // find all the d's
1042 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
1043 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
1044 for ( const Expr * expr : designation->designators ) {
1045 PRINT( std::cerr << "____untyped: " << expr << std::endl; )
1046 auto dit = desigAlts.begin();
1047 if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) {
1048 for ( const Type * t : curTypes ) {
1049 assert( dit != desigAlts.end() );
1050
1051 DesignatorChain & d = *dit;
1052 PRINT( std::cerr << "____actual: " << t << std::endl; )
[98e8b3b]1053 if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
[2d11663]1054 // concatenate identical field names
1055 for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
1056 if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
1057 PRINT( std::cerr << "____alt: " << field->type << std::endl; )
1058 DesignatorChain d2 = d;
1059 d2.emplace_back( new VariableExpr{ expr->location, field } );
1060 newDesigAlts.emplace_back( std::move( d2 ) );
1061 newTypes.emplace_back( field->type );
1062 }
1063 }
1064 }
1065
1066 ++dit;
1067 }
1068 } else {
1069 for ( const Type * t : curTypes ) {
1070 assert( dit != desigAlts.end() );
1071
1072 DesignatorChain & d = *dit;
1073 if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
1074 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
1075 d.emplace_back( expr );
1076 newDesigAlts.emplace_back( d );
1077 newTypes.emplace_back( at->base );
1078 }
1079 }
1080 }
1081
1082 // reset queue
1083 desigAlts = std::move( newDesigAlts );
1084 newDesigAlts.clear();
1085 curTypes = std::move( newTypes );
1086 newTypes.clear();
1087 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
1088 }
1089
1090 if ( desigAlts.size() > 1 ) {
1091 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
1092 } else if ( desigAlts.empty() ) {
1093 SemanticError( designation, "No reasonable alternatives for designation: " );
1094 }
1095
1096 DesignatorChain & d = desigAlts.back();
1097 PRINT( for ( Expression * expr : d ) {
1098 std::cerr << "____desig: " << expr << std::endl;
1099 } ) // for
1100 assertf( ! curTypes.empty(), "empty designator chosen");
1101
1102 // set new designators
1103 assertf( ! objStack.empty(), "empty object stack when setting designation" );
[2890212]1104 Designation * actualDesignation =
[2d11663]1105 new Designation{ designation->location, DesignatorChain{d} };
1106 objStack.back()->setPosition( d ); // destroys d
1107 return actualDesignation;
1108 }
1109
1110 void CurrentObject::setNext( const Designation * designation ) {
[60aaa51d]1111 PRINT( std::cerr << "____setNext" << designation << std::endl; )
1112 assertf( ! objStack.empty(), "obj stack empty in setNext" );
1113 objStack.back()->setPosition( designation->designators );
1114 }
1115
1116 void CurrentObject::increment() {
1117 PRINT( std::cerr << "____increment" << std::endl; )
1118 if ( objStack.empty() ) return;
1119 PRINT( std::cerr << *objStack.back() << std::endl; )
1120 objStack.back()->smallStep();
1121 }
1122
1123 void CurrentObject::enterListInit( const CodeLocation & loc ) {
1124 PRINT( std::cerr << "____entering list init" << std::endl; )
1125 assertf( ! objStack.empty(), "empty obj stack entering list init" );
1126 const ast::Type * type = objStack.back()->getNext();
1127 assert( type );
1128 objStack.emplace_back( createMemberIterator( loc, type ) );
1129 }
1130
1131 void CurrentObject::exitListInit() {
1132 PRINT( std::cerr << "____exiting list init" << std::endl; )
1133 assertf( ! objStack.empty(), "objstack empty" );
1134 objStack.pop_back();
1135 if ( ! objStack.empty() ) {
1136 PRINT( std::cerr << *objStack.back() << std::endl; )
1137 objStack.back()->bigStep();
1138 }
1139 }
1140
1141 std::deque< InitAlternative > CurrentObject::getOptions() {
[2b59f55]1142 PRINT( std::cerr << "____getting current options" << std::endl; )
1143 assertf( ! objStack.empty(), "objstack empty in getOptions" );
1144 return **objStack.back();
1145 }
[60aaa51d]1146
1147 const Type * CurrentObject::getCurrentType() {
1148 PRINT( std::cerr << "____getting current type" << std::endl; )
1149 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
1150 return objStack.back()->getNext();
1151 }
[b7d92b96]1152}
1153
[e4d829b]1154// Local Variables: //
1155// tab-width: 4 //
1156// mode: c++ //
1157// compile-command: "make install" //
1158// End: //
Note: See TracBrowser for help on using the repository browser.