source: src/InitTweak/InitTweak.cc @ 83a071f9

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 83a071f9 was 175ad32b, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Fix construction of multi-dimensional arrays by removing address-of from index increment

  • Property mode set to 100644
File size: 21.7 KB
Line 
1#include <algorithm>
2#include "InitTweak.h"
3#include "SynTree/Visitor.h"
4#include "SynTree/Statement.h"
5#include "SynTree/Initializer.h"
6#include "SynTree/Expression.h"
7#include "SynTree/Attribute.h"
8#include "GenPoly/GenPoly.h"
9#include "ResolvExpr/typeops.h"
10
11namespace InitTweak {
12        namespace {
13                class HasDesignations : public Visitor {
14                public:
15                        bool hasDesignations = false;
16                        virtual void visit( Designation * des ) {
17                                if ( ! des->get_designators().empty() ) hasDesignations = true;
18                                else Visitor::visit( des );
19                        }
20                };
21
22                class InitDepthChecker : public Visitor {
23                public:
24                        bool depthOkay = true;
25                        Type * type;
26                        int curDepth = 0, maxDepth = 0;
27                        InitDepthChecker( Type * type ) : type( type ) {
28                                Type * t = type;
29                                while ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) {
30                                        maxDepth++;
31                                        t = at->get_base();
32                                }
33                                maxDepth++;
34                        }
35                        virtual void visit( ListInit * listInit ) {
36                                curDepth++;
37                                if ( curDepth > maxDepth ) depthOkay = false;
38                                Visitor::visit( listInit );
39                                curDepth--;
40                        }
41                };
42
43                class InitFlattener : public Visitor {
44                        public:
45                        virtual void visit( SingleInit * singleInit );
46                        virtual void visit( ListInit * listInit );
47                        std::list< Expression * > argList;
48                };
49
50                void InitFlattener::visit( SingleInit * singleInit ) {
51                        argList.push_back( singleInit->get_value()->clone() );
52                }
53
54                void InitFlattener::visit( ListInit * listInit ) {
55                        // flatten nested list inits
56                        std::list<Initializer*>::iterator it = listInit->begin();
57                        for ( ; it != listInit->end(); ++it ) {
58                                (*it)->accept( *this );
59                        }
60                }
61        }
62
63        std::list< Expression * > makeInitList( Initializer * init ) {
64                InitFlattener flattener;
65                maybeAccept( init, flattener );
66                return flattener.argList;
67        }
68
69        bool isDesignated( Initializer * init ) {
70                HasDesignations finder;
71                maybeAccept( init, finder );
72                return finder.hasDesignations;
73        }
74
75        bool checkInitDepth( ObjectDecl * objDecl ) {
76                InitDepthChecker checker( objDecl->get_type() );
77                maybeAccept( objDecl->get_init(), checker );
78                return checker.depthOkay;
79        }
80
81        class InitExpander::ExpanderImpl {
82        public:
83                virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
84                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
85        };
86
87        class InitImpl : public InitExpander::ExpanderImpl {
88        public:
89                InitImpl( Initializer * init ) : init( init ) {}
90
91                virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
92                        // this is wrong, but just a placeholder for now
93                        // if ( ! flattened ) flatten( indices );
94                        // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
95                        return makeInitList( init );
96                }
97
98                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
99        private:
100                Initializer * init;
101        };
102
103        class ExprImpl : public InitExpander::ExpanderImpl {
104        public:
105                ExprImpl( Expression * expr ) : arg( expr ) {}
106
107                ~ExprImpl() { delete arg; }
108
109                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
110                        std::list< Expression * > ret;
111                        Expression * expr = maybeClone( arg );
112                        if ( expr ) {
113                                for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
114                                        // go through indices and layer on subscript exprs ?[?]
115                                        ++it;
116                                        UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
117                                        subscriptExpr->get_args().push_back( expr );
118                                        subscriptExpr->get_args().push_back( (*it)->clone() );
119                                        expr = subscriptExpr;
120                                }
121                                ret.push_back( expr );
122                        }
123                        return ret;
124                }
125
126                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
127        private:
128                Expression * arg;
129        };
130
131        InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
132
133        InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
134
135        std::list< Expression * > InitExpander::operator*() {
136                return cur;
137        }
138
139        InitExpander & InitExpander::operator++() {
140                cur = expander->next( indices );
141                return *this;
142        }
143
144        // use array indices list to build switch statement
145        void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
146                indices.push_back( index );
147                indices.push_back( dimension );
148        }
149
150        void InitExpander::clearArrayIndices() {
151                deleteAll( indices );
152                indices.clear();
153        }
154
155        namespace {
156                /// given index i, dimension d, initializer init, and callExpr f, generates
157                ///   if (i < d) f(..., init)
158                ///   ++i;
159                /// so that only elements within the range of the array are constructed
160                template< typename OutIterator >
161                void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
162                        UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
163                        cond->get_args().push_back( index->clone() );
164                        cond->get_args().push_back( dimension->clone() );
165
166                        std::list< Expression * > args = makeInitList( init );
167                        callExpr->get_args().splice( callExpr->get_args().end(), args );
168
169                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
170
171                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
172                        increment->get_args().push_back( index->clone() );
173                        *out++ = new ExprStmt( noLabels, increment );
174                }
175
176                template< typename OutIterator >
177                void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
178                        if ( idx == idxEnd ) return;
179                        Expression * index = *idx++;
180                        assert( idx != idxEnd );
181                        Expression * dimension = *idx++;
182
183                        // xxx - may want to eventually issue a warning here if we can detect
184                        // that the number of elements exceeds to dimension of the array
185                        if ( idx == idxEnd ) {
186                                if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
187                                        for ( Initializer * init : *listInit ) {
188                                                buildCallExpr( callExpr->clone(), index, dimension, init, out );
189                                        }
190                                } else {
191                                        buildCallExpr( callExpr->clone(), index, dimension, init, out );
192                                }
193                        } else {
194                                std::list< Statement * > branches;
195
196                                unsigned long cond = 0;
197                                ListInit * listInit = dynamic_cast< ListInit * >( init );
198                                if ( ! listInit ) {
199                                        // xxx - this shouldn't be an error, but need a way to
200                                        // terminate without creating output, so should catch this error
201                                        throw SemanticError( "unbalanced list initializers" );
202                                }
203
204                                static UniqueName targetLabel( "L__autogen__" );
205                                Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
206                                for ( Initializer * init : *listInit ) {
207                                        Expression * condition;
208                                        // check for designations
209                                        // if ( init-> ) {
210                                                condition = new ConstantExpr( Constant::from_ulong( cond ) );
211                                                ++cond;
212                                        // } else {
213                                        //      condition = // ... take designation
214                                        //      cond = // ... take designation+1
215                                        // }
216                                        std::list< Statement * > stmts;
217                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
218                                        stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
219                                        CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
220                                        branches.push_back( caseStmt );
221                                }
222                                *out++ = new SwitchStmt( noLabels, index->clone(), branches );
223                                *out++ = new NullStmt( std::list<Label>{ switchLabel } );
224                        }
225                }
226        }
227
228        // if array came with an initializer list: initialize each element
229        // may have more initializers than elements in the array - need to check at each index that
230        // we haven't exceeded size.
231        // may have fewer initializers than elements in the array - need to default construct
232        // remaining elements.
233        // To accomplish this, generate switch statement, consuming all of expander's elements
234        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
235                if ( ! init ) return NULL;
236                CompoundStmt * block = new CompoundStmt( noLabels );
237                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
238                if ( block->get_kids().empty() ) {
239                        delete block;
240                        return NULL;
241                } else {
242                        init = NULL; // init was consumed in creating the list init
243                        return block;
244                }
245        }
246
247        Statement * ExprImpl::buildListInit( __attribute((unused)) UntypedExpr * dst, __attribute((unused)) std::list< Expression * > & indices ) {
248                return NULL;
249        }
250
251        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
252                return expander->buildListInit( dst, indices );
253        }
254
255        bool tryConstruct( ObjectDecl * objDecl ) {
256                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
257                        (objDecl->get_init() == NULL ||
258                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ))
259                        && ! objDecl->get_storageClasses().is_extern;
260        }
261
262        class CallFinder : public Visitor {
263        public:
264                typedef Visitor Parent;
265                CallFinder( const std::list< std::string > & names ) : names( names ) {}
266
267                virtual void visit( ApplicationExpr * appExpr ) {
268                        handleCallExpr( appExpr );
269                }
270
271                virtual void visit( UntypedExpr * untypedExpr ) {
272                        handleCallExpr( untypedExpr );
273                }
274
275                std::list< Expression * > * matches;
276        private:
277                const std::list< std::string > names;
278
279                template< typename CallExpr >
280                void handleCallExpr( CallExpr * expr ) {
281                        Parent::visit( expr );
282                        std::string fname = getFunctionName( expr );
283                        if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
284                                matches->push_back( expr );
285                        }
286                }
287        };
288
289        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
290                static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
291                finder.matches = &matches;
292                maybeAccept( stmt, finder );
293        }
294
295        Expression * getCtorDtorCall( Statement * stmt ) {
296                std::list< Expression * > matches;
297                collectCtorDtorCalls( stmt, matches );
298                assert( matches.size() <= 1 );
299                return matches.size() == 1 ? matches.front() : NULL;
300        }
301
302        namespace {
303                DeclarationWithType * getCalledFunction( Expression * expr );
304
305                template<typename CallExpr>
306                DeclarationWithType * handleDerefCalledFunction( CallExpr * expr ) {
307                        // (*f)(x) => should get "f"
308                        std::string name = getFunctionName( expr );
309                        assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
310                        assertf( ! expr->get_args().empty(), "Can't get called function from dereference with no arguments" );
311                        return getCalledFunction( expr->get_args().front() );
312                }
313
314                DeclarationWithType * getCalledFunction( Expression * expr ) {
315                        assert( expr );
316                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
317                                return varExpr->get_var();
318                        } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
319                                return memberExpr->get_member();
320                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
321                                return getCalledFunction( castExpr->get_arg() );
322                        } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
323                                return handleDerefCalledFunction( untypedExpr );
324                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
325                                return handleDerefCalledFunction( appExpr );
326                        } else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
327                                return getCalledFunction( addrExpr->get_arg() );
328                        }
329                        return nullptr;
330                }
331        }
332
333        DeclarationWithType * getFunction( Expression * expr ) {
334                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
335                        return getCalledFunction( appExpr->get_function() );
336                } else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * > ( expr ) ) {
337                        return getCalledFunction( untyped->get_function() );
338                }
339                assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
340        }
341
342        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
343                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
344                if ( ! appExpr ) return NULL;
345                DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
346                assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
347                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
348                // will call all member dtors, and some members may have a user defined dtor.
349                return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
350        }
351
352        namespace {
353                template <typename Predicate>
354                bool allofCtorDtor( Statement * stmt, const Predicate & pred ) {
355                        std::list< Expression * > callExprs;
356                        collectCtorDtorCalls( stmt, callExprs );
357                        // if ( callExprs.empty() ) return false; // xxx - do I still need this check?
358                        return std::all_of( callExprs.begin(), callExprs.end(), pred);
359                }
360        }
361
362        bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
363                return allofCtorDtor( stmt, []( Expression * callExpr ){
364                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
365                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() );
366                                assert( funcType );
367                                return funcType->get_parameters().size() == 1;
368                        }
369                        return false;
370                });
371        }
372
373        bool isIntrinsicCallStmt( Statement * stmt ) {
374                return allofCtorDtor( stmt, []( Expression * callExpr ) {
375                        return isIntrinsicCallExpr( callExpr );
376                });
377        }
378
379        namespace {
380                template<typename CallExpr>
381                Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
382                        if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() );
383                        for ( Expression *& arg : callExpr->get_args() ) {
384                                if ( pos == 0 ) return arg;
385                                pos--;
386                        }
387                        assert( false );
388                }
389        }
390
391        Expression *& getCallArg( Expression * callExpr, unsigned int pos ) {
392                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
393                        return callArg( appExpr, pos );
394                } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
395                        return callArg( untypedExpr, pos );
396                } else if ( TupleAssignExpr * tupleExpr = dynamic_cast< TupleAssignExpr * > ( callExpr ) ) {
397                        std::list< Statement * > & stmts = tupleExpr->get_stmtExpr()->get_statements()->get_kids();
398                        assertf( ! stmts.empty(), "TupleAssignExpr somehow has no statements." );
399                        ExprStmt * stmt = safe_dynamic_cast< ExprStmt * >( stmts.back() );
400                        TupleExpr * tuple = safe_dynamic_cast< TupleExpr * >( stmt->get_expr() );
401                        assertf( ! tuple->get_exprs().empty(), "TupleAssignExpr somehow has empty tuple expr." );
402                        return getCallArg( tuple->get_exprs().front(), pos );
403                } else {
404                        assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( callExpr ).c_str() );
405                }
406        }
407
408        namespace {
409                std::string funcName( Expression * func );
410
411                template<typename CallExpr>
412                std::string handleDerefName( CallExpr * expr ) {
413                        // (*f)(x) => should get name "f"
414                        std::string name = getFunctionName( expr );
415                        assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
416                        assertf( ! expr->get_args().empty(), "Can't get function name from dereference with no arguments" );
417                        return funcName( expr->get_args().front() );
418                }
419
420                std::string funcName( Expression * func ) {
421                        if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
422                                return nameExpr->get_name();
423                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
424                                return varExpr->get_var()->get_name();
425                        }       else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( func ) ) {
426                                return funcName( castExpr->get_arg() );
427                        } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( func ) ) {
428                                return memberExpr->get_member()->get_name();
429                        } else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) {
430                                return funcName( memberExpr->get_member() );
431                        } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( func ) ) {
432                                return handleDerefName( untypedExpr );
433                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( func ) ) {
434                                return handleDerefName( appExpr );
435                        } else {
436                                assertf( false, "Unexpected expression type being called as a function in call expression" );
437                        }
438                }
439        }
440
441        std::string getFunctionName( Expression * expr ) {
442                // there's some unforunate overlap here with getCalledFunction. Ideally this would be able to use getCalledFunction and
443                // return the name of the DeclarationWithType, but this needs to work for NameExpr and UntypedMemberExpr, where getCalledFunction
444                // can't possibly do anything reasonable.
445                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
446                        return funcName( appExpr->get_function() );
447                } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
448                        return funcName( untypedExpr->get_function() );
449                } else {
450                        std::cerr << expr << std::endl;
451                        assertf( false, "Unexpected expression type passed to getFunctionName" );
452                }
453        }
454
455        Type * getPointerBase( Type * type ) {
456                if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
457                        return ptrType->get_base();
458                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
459                        return arrayType->get_base();
460                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
461                        return refType->get_base();
462                } else {
463                        return NULL;
464                }
465        }
466
467        Type * isPointerType( Type * type ) {
468                if ( getPointerBase( type ) ) return type;
469                else return NULL;
470        }
471
472        class ConstExprChecker : public Visitor {
473        public:
474                ConstExprChecker() : isConstExpr( true ) {}
475
476                using Visitor::visit;
477
478                virtual void visit( __attribute((unused)) ApplicationExpr *applicationExpr ) { isConstExpr = false; }
479                virtual void visit( __attribute((unused)) UntypedExpr *untypedExpr ) { isConstExpr = false; }
480                virtual void visit( NameExpr *nameExpr ) {
481                        // xxx - temporary hack, because 0 and 1 really should be constexprs, even though they technically aren't in Cforall today
482                        if ( nameExpr->get_name() != "0" && nameExpr->get_name() != "1" ) isConstExpr = false;
483                }
484                // virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
485                virtual void visit( AddressExpr *addressExpr ) {
486                        // address of a variable or member expression is constexpr
487                        Expression * arg = addressExpr->get_arg();
488                        if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
489                }
490                virtual void visit( __attribute((unused)) LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
491                virtual void visit( __attribute((unused)) UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
492                virtual void visit( __attribute((unused)) MemberExpr *memberExpr ) { isConstExpr = false; }
493                virtual void visit( __attribute((unused)) VariableExpr *variableExpr ) { isConstExpr = false; }
494                // these might be okay?
495                // virtual void visit( SizeofExpr *sizeofExpr );
496                // virtual void visit( AlignofExpr *alignofExpr );
497                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
498                // virtual void visit( OffsetofExpr *offsetofExpr );
499                // virtual void visit( OffsetPackExpr *offsetPackExpr );
500                // virtual void visit( AttrExpr *attrExpr );
501                // virtual void visit( CommaExpr *commaExpr );
502                // virtual void visit( LogicalExpr *logicalExpr );
503                // virtual void visit( ConditionalExpr *conditionalExpr );
504                virtual void visit( __attribute((unused)) TypeExpr *typeExpr ) { isConstExpr = false; }
505                virtual void visit( __attribute((unused)) AsmExpr *asmExpr ) { isConstExpr = false; }
506                virtual void visit( __attribute((unused)) UntypedValofExpr *valofExpr ) { isConstExpr = false; }
507                virtual void visit( __attribute((unused)) CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
508                virtual void visit( __attribute((unused)) UntypedTupleExpr *tupleExpr ) { isConstExpr = false; }
509                virtual void visit( __attribute((unused)) TupleExpr *tupleExpr ) { isConstExpr = false; }
510                virtual void visit( __attribute((unused)) TupleAssignExpr *tupleExpr ) { isConstExpr = false; }
511
512                bool isConstExpr;
513        };
514
515        bool isConstExpr( Expression * expr ) {
516                if ( expr ) {
517                        ConstExprChecker checker;
518                        expr->accept( checker );
519                        return checker.isConstExpr;
520                }
521                return true;
522        }
523
524        bool isConstExpr( Initializer * init ) {
525                if ( init ) {
526                        ConstExprChecker checker;
527                        init->accept( checker );
528                        return checker.isConstExpr;
529                } // if
530                // for all intents and purposes, no initializer means const expr
531                return true;
532        }
533
534        bool isConstructor( const std::string & str ) { return str == "?{}"; }
535        bool isDestructor( const std::string & str ) { return str == "^?{}"; }
536        bool isAssignment( const std::string & str ) { return str == "?=?"; }
537        bool isCtorDtor( const std::string & str ) { return isConstructor( str ) || isDestructor( str ); }
538        bool isCtorDtorAssign( const std::string & str ) { return isCtorDtor( str ) || isAssignment( str ); }
539
540        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
541                FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
542                if ( ! function ) return 0;
543                if ( function->get_name() != fname ) return 0;
544                FunctionType * ftype = function->get_functionType();
545                if ( ftype->get_parameters().size() != 2 ) return 0;
546
547                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
548                Type * t2 = ftype->get_parameters().back()->get_type();
549                assert( t1 );
550
551                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
552                        return function;
553                } else {
554                        return nullptr;
555                }
556        }
557
558        FunctionDecl * isAssignment( Declaration * decl ) {
559                return isCopyFunction( decl, "?=?" );
560        }
561        FunctionDecl * isDestructor( Declaration * decl ) {
562                if ( isDestructor( decl->get_name() ) ) {
563                        return dynamic_cast< FunctionDecl * >( decl );
564                }
565                return nullptr;
566        }
567        FunctionDecl * isDefaultConstructor( Declaration * decl ) {
568                if ( isConstructor( decl->get_name() ) ) {
569                        if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
570                                if ( func->get_functionType()->get_parameters().size() == 1 ) {
571                                        return func;
572                                }
573                        }
574                }
575                return nullptr;
576        }
577        FunctionDecl * isCopyConstructor( Declaration * decl ) {
578                return isCopyFunction( decl, "?{}" );
579        }
580}
Note: See TracBrowser for help on using the repository browser.