source: src/ResolvExpr/Resolver.cc @ 496ffc17

Last change on this file since 496ffc17 was 7329b0a, checked in by Andrew Beach <ajbeach@…>, 5 months ago

advance_to_mutex has been replaced nextMutex.

  • Property mode set to 100644
File size: 44.8 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// Resolver.cc --
8//
9// Author           : Aaron B. Moss
10// Created On       : Sun May 17 12:17:01 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Thu Dec 14 18:44:43 2023
13// Update Count     : 251
14//
15
16#include <cassert>                       // for strict_dynamic_cast, assert
17#include <memory>                        // for allocator, allocator_traits<...
18#include <tuple>                         // for get
19#include <vector>                        // for vector
20
21#include "Candidate.hpp"
22#include "CandidateFinder.hpp"
23#include "CurrentObject.h"               // for CurrentObject
24#include "RenameVars.h"                  // for RenameVars, global_renamer
25#include "Resolver.h"
26#include "ResolveTypeof.h"
27#include "ResolveMode.hpp"               // for ResolveMode
28#include "typeops.h"                     // for extractResultType
29#include "Unify.h"                       // for unify
30#include "CompilationState.h"
31#include "AST/Decl.hpp"
32#include "AST/Init.hpp"
33#include "AST/Pass.hpp"
34#include "AST/Print.hpp"
35#include "AST/SymbolTable.hpp"
36#include "AST/Type.hpp"
37#include "Common/Eval.h"                 // for eval
38#include "Common/Iterate.hpp"            // for group_iterate
39#include "Common/SemanticError.h"        // for SemanticError
40#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
41#include "Common/ToString.hpp"           // for toCString
42#include "Common/UniqueName.h"           // for UniqueName
43#include "InitTweak/GenInit.h"
44#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
45#include "SymTab/Mangler.h"              // for Mangler
46#include "Tuples/Tuples.h"
47#include "Validate/FindSpecialDecls.h"   // for SizeType
48
49using namespace std;
50
51namespace ResolvExpr {
52        namespace {
53                /// Finds deleted expressions in an expression tree
54                struct DeleteFinder final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder> {
55                        const ast::DeletedExpr * result = nullptr;
56
57                        void previsit( const ast::DeletedExpr * expr ) {
58                                if ( result ) { visit_children = false; }
59                                else { result = expr; }
60                        }
61
62                        void previsit( const ast::Expr * expr ) {
63                                if ( result ) { visit_children = false; }
64                                if (expr->inferred.hasParams()) {
65                                        for (auto & imp : expr->inferred.inferParams() ) {
66                                                imp.second.expr->accept(*visitor);
67                                        }
68                                }
69                        }
70                };
71
72                struct ResolveDesignators final : public ast::WithShortCircuiting {
73                        ResolveContext& context;
74                        bool result = false;
75
76                        ResolveDesignators( ResolveContext& _context ): context{_context} {};
77
78                        void previsit( const ast::Node * ) {
79                                // short circuit if we already know there are designations
80                                if ( result ) visit_children = false;
81                        }
82
83                        void previsit( const ast::Designation * des ) {
84                                if ( result ) visit_children = false;
85                                else if ( ! des->designators.empty() ) {
86                                        if ( (des->designators.size() == 1) ) {
87                                                const ast::Expr * designator = des->designators.at(0);
88                                                if ( const ast::NameExpr * designatorName = dynamic_cast<const ast::NameExpr *>(designator) ) {
89                                                        auto candidates = context.symtab.lookupId(designatorName->name);
90                                                        for ( auto candidate : candidates ) {
91                                                                if ( dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type()) ) {
92                                                                        result = true;
93                                                                        break;
94                                                                }
95                                                        }
96                                                }
97                                        }
98                                        visit_children = false;
99                                }
100                        }
101                };
102        } // anonymous namespace
103        /// Check if this expression is or includes a deleted expression
104        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
105                return ast::Pass<DeleteFinder>::read( expr );
106        }
107
108        namespace {
109                /// always-accept candidate filter
110                bool anyCandidate( const Candidate & ) { return true; }
111
112                /// Calls the CandidateFinder and finds the single best candidate
113                CandidateRef findUnfinishedKindExpression(
114                        const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
115                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolveMode mode = {}
116                ) {
117                        if ( ! untyped ) return nullptr;
118
119                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
120                        static unsigned recursion_level = 0;
121
122                        ++recursion_level;
123                        ast::TypeEnvironment env;
124                        CandidateFinder finder( context, env );
125                        finder.allowVoid = true;
126                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
127                        --recursion_level;
128
129                        // produce a filtered list of candidates
130                        CandidateList candidates;
131                        for ( auto & cand : finder.candidates ) {
132                                if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
133                        }
134
135                        // produce invalid error if no candidates
136                        if ( candidates.empty() ) {
137                                SemanticError( untyped,
138                                        toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
139                                        "expression: ") );
140                        }
141
142                        // search for cheapest candidate
143                        CandidateList winners;
144                        bool seen_undeleted = false;
145                        for ( CandidateRef & cand : candidates ) {
146                                int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
147
148                                if ( c > 0 ) continue;  // skip more expensive than winner
149
150                                if ( c < 0 ) {
151                                        // reset on new cheapest
152                                        seen_undeleted = ! findDeletedExpr( cand->expr );
153                                        winners.clear();
154                                } else /* if ( c == 0 ) */ {
155                                        if ( findDeletedExpr( cand->expr ) ) {
156                                                // skip deleted expression if already seen one equivalent-cost not
157                                                if ( seen_undeleted ) continue;
158                                        } else if ( ! seen_undeleted ) {
159                                                // replace list of equivalent-cost deleted expressions with one non-deleted
160                                                winners.clear();
161                                                seen_undeleted = true;
162                                        }
163                                }
164
165                                winners.emplace_back( std::move( cand ) );
166                        }
167
168                        // promote candidate.cvtCost to .cost
169                        // promoteCvtCost( winners );
170
171                        // produce ambiguous errors, if applicable
172                        if ( winners.size() != 1 ) {
173                                std::ostringstream stream;
174                                stream << "Cannot choose between " << winners.size() << " alternatives for "
175                                        << kind << (kind != "" ? " " : "") << "expression\n";
176                                ast::print( stream, untyped );
177                                stream << " Alternatives are:\n";
178                                print( stream, winners, 1 );
179                                SemanticError( untyped->location, stream.str() );
180                        }
181
182                        // single selected choice
183                        CandidateRef & choice = winners.front();
184
185                        // fail on only expression deleted
186                        if ( ! seen_undeleted ) {
187                                SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
188                                "includes deleted identifier in " );
189                        }
190
191                        return std::move( choice );
192                }
193
194                /// Strips extraneous casts out of an expression
195                struct StripCasts final {
196                        const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
197                                if (
198                                        castExpr->isGenerated == ast::GeneratedCast
199                                        && typesCompatible( castExpr->arg->result, castExpr->result )
200                                ) {
201                                        // generated cast is the same type as its argument, remove it after keeping env
202                                        return ast::mutate_field(
203                                                castExpr->arg.get(), &ast::Expr::env, castExpr->env );
204                                }
205                                return castExpr;
206                        }
207
208                        static void strip( ast::ptr< ast::Expr > & expr ) {
209                                ast::Pass< StripCasts > stripper;
210                                expr = expr->accept( stripper );
211                        }
212                };
213
214                /// Swaps argument into expression pointer, saving original environment
215                void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
216                        ast::ptr< ast::TypeSubstitution > env = expr->env;
217                        expr.set_and_mutate( newExpr )->env = env;
218                }
219
220                /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
221                void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) {
222                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
223                                if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
224                                        // cast is to the same type as its argument, remove it
225                                        swap_and_save_env( expr, castExpr->arg );
226                                }
227                        }
228                }
229
230
231        } // anonymous namespace
232/// Establish post-resolver invariants for expressions
233                void finishExpr(
234                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
235                        const ast::TypeSubstitution * oldenv = nullptr
236                ) {
237                        // set up new type substitution for expression
238                        ast::ptr< ast::TypeSubstitution > newenv =
239                                 oldenv ? oldenv : new ast::TypeSubstitution{};
240                        env.writeToSubstitution( *newenv.get_and_mutate() );
241                        expr.get_and_mutate()->env = std::move( newenv );
242                        // remove unncecessary casts
243                        StripCasts::strip( expr );
244                }
245
246        ast::ptr< ast::Expr > resolveInVoidContext(
247                const ast::Expr * expr, const ResolveContext & context,
248                ast::TypeEnvironment & env
249        ) {
250                assertf( expr, "expected a non-null expression" );
251
252                // set up and resolve expression cast to void
253                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
254                CandidateRef choice = findUnfinishedKindExpression(
255                        untyped, context, "", anyCandidate, ResolveMode::withAdjustment() );
256
257                // a cast expression has either 0 or 1 interpretations (by language rules);
258                // if 0, an exception has already been thrown, and this code will not run
259                const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
260                env = std::move( choice->env );
261
262                return castExpr->arg;
263        }
264
265        /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
266                /// context.
267                ast::ptr< ast::Expr > findVoidExpression(
268                        const ast::Expr * untyped, const ResolveContext & context
269                ) {
270                        ast::TypeEnvironment env;
271                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
272                        finishExpr( newExpr, env, untyped->env );
273                        return newExpr;
274                }
275
276        namespace {
277
278
279                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
280                /// lowest cost, returning the resolved version
281                ast::ptr< ast::Expr > findKindExpression(
282                        const ast::Expr * untyped, const ResolveContext & context,
283                        std::function<bool(const Candidate &)> pred = anyCandidate,
284                        const std::string & kind = "", ResolveMode mode = {}
285                ) {
286                        if ( ! untyped ) return {};
287                        CandidateRef choice =
288                                findUnfinishedKindExpression( untyped, context, kind, pred, mode );
289                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
290                        return std::move( choice->expr );
291                }
292
293                /// Resolve `untyped` to the single expression whose candidate is the best match
294                ast::ptr< ast::Expr > findSingleExpression(
295                        const ast::Expr * untyped, const ResolveContext & context
296                ) {
297                        Stats::ResolveTime::start( untyped );
298                        auto res = findKindExpression( untyped, context );
299                        Stats::ResolveTime::stop();
300                        return res;
301                }
302        } // anonymous namespace
303
304        ast::ptr< ast::Expr > findSingleExpression(
305                const ast::Expr * untyped, const ast::Type * type,
306                const ResolveContext & context
307        ) {
308                assert( untyped && type );
309                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
310                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
311                removeExtraneousCast( newExpr );
312                return newExpr;
313        }
314
315        namespace {
316                bool structOrUnion( const Candidate & i ) {
317                        const ast::Type * t = i.expr->result->stripReferences();
318                        return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
319                }
320                /// Predicate for "Candidate has integral type"
321                bool hasIntegralType( const Candidate & i ) {
322                        const ast::Type * type = i.expr->result;
323
324                        if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
325                                return bt->isInteger();
326                        } else if (
327                                dynamic_cast< const ast::EnumInstType * >( type )
328                                || dynamic_cast< const ast::ZeroType * >( type )
329                                || dynamic_cast< const ast::OneType * >( type )
330                        ) {
331                                return true;
332                        } else return false;
333                }
334
335                /// Resolve `untyped` as an integral expression, returning the resolved version
336                ast::ptr< ast::Expr > findIntegralExpression(
337                        const ast::Expr * untyped, const ResolveContext & context
338                ) {
339                        return findKindExpression( untyped, context, hasIntegralType, "condition" );
340                }
341
342                /// check if a type is a character type
343                bool isCharType( const ast::Type * t ) {
344                        if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
345                                return bt->kind == ast::BasicType::Char
346                                        || bt->kind == ast::BasicType::SignedChar
347                                        || bt->kind == ast::BasicType::UnsignedChar;
348                        }
349                        return false;
350                }
351
352                /// Advance a type itertor to the next mutex parameter
353                template<typename Iter>
354                inline bool nextMutex( Iter & it, const Iter & end ) {
355                        while ( it != end && ! (*it)->is_mutex() ) { ++it; }
356                        return it != end;
357                }
358        }
359
360        class Resolver final
361        : public ast::WithSymbolTable, public ast::WithGuards,
362          public ast::WithVisitorRef<Resolver>, public ast::WithShortCircuiting,
363          public ast::WithStmtsToAdd<> {
364
365                ast::ptr< ast::Type > functionReturn = nullptr;
366                ast::CurrentObject currentObject;
367                // for work previously in GenInit
368                static InitTweak::ManagedTypes managedTypes;
369                ResolveContext context;
370
371                bool inEnumDecl = false;
372
373        public:
374                static size_t traceId;
375                Resolver( const ast::TranslationGlobal & global ) :
376                        ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd),
377                        context{ symtab, global } {}
378                Resolver( const ResolveContext & context ) :
379                        ast::WithSymbolTable{ context.symtab },
380                        context{ symtab, context.global } {}
381
382                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
383                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
384                const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
385                void previsit( const ast::AggregateDecl * );
386                void previsit( const ast::StructDecl * );
387                void previsit( const ast::EnumDecl * );
388                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
389
390                const ast::ArrayType * previsit( const ast::ArrayType * );
391                const ast::PointerType * previsit( const ast::PointerType * );
392
393                const ast::ExprStmt *        previsit( const ast::ExprStmt * );
394                const ast::AsmExpr *         previsit( const ast::AsmExpr * );
395                const ast::AsmStmt *         previsit( const ast::AsmStmt * );
396                const ast::IfStmt *          previsit( const ast::IfStmt * );
397                const ast::WhileDoStmt *     previsit( const ast::WhileDoStmt * );
398                const ast::ForStmt *         previsit( const ast::ForStmt * );
399                const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
400                const ast::CaseClause *      previsit( const ast::CaseClause * );
401                const ast::BranchStmt *      previsit( const ast::BranchStmt * );
402                const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
403                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
404                const ast::CatchClause *     previsit( const ast::CatchClause * );
405                const ast::CatchClause *     postvisit( const ast::CatchClause * );
406                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
407                const ast::WithStmt *        previsit( const ast::WithStmt * );
408
409                const ast::SingleInit *      previsit( const ast::SingleInit * );
410                const ast::ListInit *        previsit( const ast::ListInit * );
411                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
412
413                const ast::EnumPosExpr *         previsit( const ast::EnumPosExpr * );
414
415                void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
416
417                void beginScope() { managedTypes.beginScope(); }
418                void endScope() { managedTypes.endScope(); }
419                bool on_error(ast::ptr<ast::Decl> & decl);
420        };
421        // size_t Resolver::traceId = Stats::Heap::new_stacktrace_id("Resolver");
422
423        InitTweak::ManagedTypes Resolver::managedTypes;
424
425        void resolve( ast::TranslationUnit& translationUnit ) {
426                ast::Pass< Resolver >::run( translationUnit, translationUnit.global );
427        }
428
429        ast::ptr< ast::Init > resolveCtorInit(
430                const ast::ConstructorInit * ctorInit, const ResolveContext & context
431        ) {
432                assert( ctorInit );
433                ast::Pass< Resolver > resolver( context );
434                return ctorInit->accept( resolver );
435        }
436
437        const ast::Expr * resolveStmtExpr(
438                const ast::StmtExpr * stmtExpr, const ResolveContext & context
439        ) {
440                assert( stmtExpr );
441                ast::Pass< Resolver > resolver( context );
442                auto ret = mutate(stmtExpr->accept(resolver));
443                strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
444                return ret;
445        }
446
447        namespace {
448                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
449                        std::string name = attr->normalizedName();
450                        if (name == "constructor" || name == "destructor") {
451                                if (attr->params.size() == 1) {
452                                        auto arg = attr->params.front();
453                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
454                                        auto result = eval(arg);
455
456                                        auto mutAttr = mutate(attr);
457                                        mutAttr->params.front() = resolved;
458                                        if (! result.hasKnownValue) {
459                                                SemanticWarning(loc, Warning::GccAttributes,
460                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
461                                        }
462                                        else {
463                                                auto priority = result.knownValue;
464                                                if (priority < 101) {
465                                                        SemanticWarning(loc, Warning::GccAttributes,
466                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
467                                                } else if (priority < 201 && ! buildingLibrary()) {
468                                                        SemanticWarning(loc, Warning::GccAttributes,
469                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
470                                                }
471                                        }
472                                        return mutAttr;
473                                } else if (attr->params.size() > 1) {
474                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
475                                } else {
476                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
477                                }
478                        }
479                        return attr;
480                }
481        }
482
483        const ast::FunctionDecl * Resolver::previsit( const ast::FunctionDecl * functionDecl ) {
484                GuardValue( functionReturn );
485
486                assert (functionDecl->unique());
487                if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
488                        SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
489                }
490
491                if (!functionDecl->isTypeFixed) {
492                        auto mutDecl = mutate(functionDecl);
493                        auto mutType = mutDecl->type.get_and_mutate();
494
495                        for (auto & attr: mutDecl->attributes) {
496                                attr = handleAttribute(mutDecl->location, attr, context );
497                        }
498
499                        // handle assertions
500
501                        symtab.enterScope();
502                        mutType->forall.clear();
503                        mutType->assertions.clear();
504                        for (auto & typeParam : mutDecl->type_params) {
505                                symtab.addType(typeParam);
506                                mutType->forall.emplace_back(new ast::TypeInstType(typeParam));
507                        }
508                        for (auto & asst : mutDecl->assertions) {
509                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context);
510                                symtab.addId(asst);
511                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
512                        }
513
514                        // temporarily adds params to symbol table.
515                        // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
516
517                        std::vector<ast::ptr<ast::Type>> paramTypes;
518                        std::vector<ast::ptr<ast::Type>> returnTypes;
519
520                        for (auto & param : mutDecl->params) {
521                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context);
522                                symtab.addId(param);
523                                paramTypes.emplace_back(param->get_type());
524                        }
525                        for (auto & ret : mutDecl->returns) {
526                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context);
527                                returnTypes.emplace_back(ret->get_type());
528                        }
529                        // since function type in decl is just a view of param types, need to update that as well
530                        mutType->params = std::move(paramTypes);
531                        mutType->returns = std::move(returnTypes);
532
533                        auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID));
534
535                        std::list<ast::ptr<ast::Stmt>> newStmts;
536                        resolveWithExprs (mutDecl->withExprs, newStmts);
537
538                        if (mutDecl->stmts) {
539                                auto mutStmt = mutDecl->stmts.get_and_mutate();
540                                mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
541                                mutDecl->stmts = mutStmt;
542                        }
543
544                        symtab.leaveScope();
545
546                        mutDecl->type = renamedType;
547                        mutDecl->mangleName = Mangle::mangle(mutDecl);
548                        mutDecl->isTypeFixed = true;
549                        functionDecl = mutDecl;
550                }
551                managedTypes.handleDWT(functionDecl);
552
553                functionReturn = extractResultType( functionDecl->type );
554                return functionDecl;
555        }
556
557        const ast::FunctionDecl * Resolver::postvisit( const ast::FunctionDecl * functionDecl ) {
558                // default value expressions have an environment which shouldn't be there and trips up
559                // later passes.
560                assert( functionDecl->unique() );
561                ast::FunctionType * mutType = mutate( functionDecl->type.get() );
562
563                for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
564                        if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
565                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
566                                        if ( init->value->env == nullptr ) continue;
567                                        // clone initializer minus the initializer environment
568                                        auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
569                                        auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
570                                        auto mutValue = mutate( mutInit->value.get() );
571
572                                        mutValue->env = nullptr;
573                                        mutInit->value = mutValue;
574                                        mutParam->init = mutInit;
575                                        mutType->params[i] = mutParam;
576
577                                        assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
578                                }
579                        }
580                }
581                mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
582                return functionDecl;
583        }
584
585        const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) {
586                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
587                // class-variable `initContext` is changed multiple times because the LHS is analyzed
588                // twice. The second analysis changes `initContext` because a function type can contain
589                // object declarations in the return and parameter types. Therefore each value of
590                // `initContext` is retained so the type on the first analysis is preserved and used for
591                // selecting the RHS.
592                GuardValue( currentObject );
593
594                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
595                        // enumerator initializers should not use the enum type to initialize, since the
596                        // enum type is still incomplete at this point. Use `int` instead.
597
598                        if ( auto enumBase = dynamic_cast< const ast::EnumInstType * >
599                                ( objectDecl->get_type() )->base->base ) {
600                                objectDecl = fixObjectType( objectDecl, context );
601                                currentObject = ast::CurrentObject{
602                                        objectDecl->location,
603                                        enumBase
604                                };
605                        } else {
606                                objectDecl = fixObjectType( objectDecl, context );
607                                currentObject = ast::CurrentObject{
608                                        objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
609                        }
610
611                }
612                else {
613                        if ( !objectDecl->isTypeFixed ) {
614                                auto newDecl = fixObjectType(objectDecl, context);
615                                auto mutDecl = mutate(newDecl);
616
617                                // generate CtorInit wrapper when necessary.
618                                // in certain cases, fixObjectType is called before reaching
619                                // this object in visitor pass, thus disabling CtorInit codegen.
620                                // this happens on aggregate members and function parameters.
621                                if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
622                                        // constructed objects cannot be designated
623                                        if ( InitTweak::isDesignated( mutDecl->init ) ) {
624                                                ast::Pass<ResolveDesignators> res( context );
625                                                maybe_accept( mutDecl->init.get(), res );
626                                                if ( !res.core.result ) {
627                                                        SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object.\n"
628                                                                                   "If this is really what you want, initialize with @=." );
629                                                }
630                                        }
631                                        // constructed objects should not have initializers nested too deeply
632                                        if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
633
634                                        mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
635                                }
636
637                                objectDecl = mutDecl;
638                        }
639                        currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
640                }
641
642                return objectDecl;
643        }
644
645        void Resolver::previsit( const ast::AggregateDecl * _aggDecl ) {
646                auto aggDecl = mutate(_aggDecl);
647                assertf(aggDecl == _aggDecl, "type declarations must be unique");
648
649                for (auto & member: aggDecl->members) {
650                        // nested type decls are hoisted already. no need to do anything
651                        if (auto obj = member.as<ast::ObjectDecl>()) {
652                                member = fixObjectType(obj, context);
653                        }
654                }
655        }
656
657        void Resolver::previsit( const ast::StructDecl * structDecl ) {
658                previsit(static_cast<const ast::AggregateDecl *>(structDecl));
659                managedTypes.handleStruct(structDecl);
660        }
661
662        void Resolver::previsit( const ast::EnumDecl * ) {
663                // in case we decide to allow nested enums
664                GuardValue( inEnumDecl );
665                inEnumDecl = true;
666                // don't need to fix types for enum fields
667        }
668
669        const ast::StaticAssertDecl * Resolver::previsit(
670                const ast::StaticAssertDecl * assertDecl
671        ) {
672                return ast::mutate_field(
673                        assertDecl, &ast::StaticAssertDecl::cond,
674                        findIntegralExpression( assertDecl->cond, context ) );
675        }
676
677        template< typename PtrType >
678        const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
679                if ( type->dimension ) {
680                        const ast::Type * sizeType = context.global.sizeType.get();
681                        ast::ptr< ast::Expr > dimension = findSingleExpression( type->dimension, sizeType, context );
682                        assertf(dimension->env->empty(), "array dimension expr has nonempty env");
683                        dimension.get_and_mutate()->env = nullptr;
684                        ast::mutate_field( type, &PtrType::dimension, dimension );
685                }
686                return type;
687        }
688
689        const ast::ArrayType * Resolver::previsit( const ast::ArrayType * at ) {
690                return handlePtrType( at, context );
691        }
692
693        const ast::PointerType * Resolver::previsit( const ast::PointerType * pt ) {
694                return handlePtrType( pt, context );
695        }
696
697        const ast::ExprStmt * Resolver::previsit( const ast::ExprStmt * exprStmt ) {
698                visit_children = false;
699                assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
700
701                return ast::mutate_field(
702                        exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) );
703        }
704
705        const ast::AsmExpr * Resolver::previsit( const ast::AsmExpr * asmExpr ) {
706                visit_children = false;
707
708                asmExpr = ast::mutate_field(
709                        asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) );
710
711                return asmExpr;
712        }
713
714        const ast::AsmStmt * Resolver::previsit( const ast::AsmStmt * asmStmt ) {
715                visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
716                visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
717                visit_children = false;
718                return asmStmt;
719        }
720
721        const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) {
722                return ast::mutate_field(
723                        ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
724        }
725
726        const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) {
727                return ast::mutate_field(
728                        whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
729        }
730
731        const ast::ForStmt * Resolver::previsit( const ast::ForStmt * forStmt ) {
732                if ( forStmt->cond ) {
733                        forStmt = ast::mutate_field(
734                                forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) );
735                }
736
737                if ( forStmt->inc ) {
738                        forStmt = ast::mutate_field(
739                                forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) );
740                }
741
742                return forStmt;
743        }
744
745        const ast::SwitchStmt * Resolver::previsit( const ast::SwitchStmt * switchStmt ) {
746                GuardValue( currentObject );
747                switchStmt = ast::mutate_field(
748                        switchStmt, &ast::SwitchStmt::cond,
749                        findIntegralExpression( switchStmt->cond, context ) );
750                currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
751                return switchStmt;
752        }
753
754        const ast::CaseClause * Resolver::previsit( const ast::CaseClause * caseStmt ) {
755                if ( caseStmt->cond ) {
756                        std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
757                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
758                                "expression." );
759
760                        ast::ptr< ast::Expr > untyped =
761                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
762                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context );
763
764                        // case condition cannot have a cast in C, so it must be removed here, regardless of
765                        // whether it would perform a conversion.
766                        if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
767                                swap_and_save_env( newExpr, castExpr->arg );
768                        }
769
770                        caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr );
771                }
772                return caseStmt;
773        }
774
775        const ast::BranchStmt * Resolver::previsit( const ast::BranchStmt * branchStmt ) {
776                visit_children = false;
777                // must resolve the argument of a computed goto
778                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
779                        // computed goto argument is void*
780                        ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
781                        branchStmt = ast::mutate_field(
782                                branchStmt, &ast::BranchStmt::computedTarget,
783                                findSingleExpression( branchStmt->computedTarget, target, context ) );
784                }
785                return branchStmt;
786        }
787
788        const ast::ReturnStmt * Resolver::previsit( const ast::ReturnStmt * returnStmt ) {
789                visit_children = false;
790                if ( returnStmt->expr ) {
791                        returnStmt = ast::mutate_field(
792                                returnStmt, &ast::ReturnStmt::expr,
793                                findSingleExpression( returnStmt->expr, functionReturn, context ) );
794                }
795                return returnStmt;
796        }
797
798        const ast::ThrowStmt * Resolver::previsit( const ast::ThrowStmt * throwStmt ) {
799                visit_children = false;
800                if ( throwStmt->expr ) {
801                        const ast::StructDecl * exceptionDecl =
802                                symtab.lookupStruct( "__cfaehm_base_exception_t" );
803                        assert( exceptionDecl );
804                        ast::ptr< ast::Type > exceptType =
805                                new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
806                        throwStmt = ast::mutate_field(
807                                throwStmt, &ast::ThrowStmt::expr,
808                                findSingleExpression( throwStmt->expr, exceptType, context ) );
809                }
810                return throwStmt;
811        }
812
813        const ast::CatchClause * Resolver::previsit( const ast::CatchClause * catchClause ) {
814                // Until we are very sure this invarent (ifs that move between passes have then)
815                // holds, check it. This allows a check for when to decode the mangling.
816                if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) {
817                        assert( ifStmt->then );
818                }
819                // Encode the catchStmt so the condition can see the declaration.
820                if ( catchClause->cond ) {
821                        ast::CatchClause * clause = mutate( catchClause );
822                        clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body );
823                        clause->cond = nullptr;
824                        return clause;
825                }
826                return catchClause;
827        }
828
829        const ast::CatchClause * Resolver::postvisit( const ast::CatchClause * catchClause ) {
830                // Decode the catchStmt so everything is stored properly.
831                const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>();
832                if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
833                        assert( ifStmt->cond );
834                        assert( ifStmt->else_ );
835                        ast::CatchClause * clause = ast::mutate( catchClause );
836                        clause->cond = ifStmt->cond;
837                        clause->body = ifStmt->else_;
838                        // ifStmt should be implicately deleted here.
839                        return clause;
840                }
841                return catchClause;
842        }
843
844        const ast::WaitForStmt * Resolver::previsit( const ast::WaitForStmt * stmt ) {
845                visit_children = false;
846
847                // Resolve all clauses first
848                for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
849                        const ast::WaitForClause & clause = *stmt->clauses[i];
850
851                        ast::TypeEnvironment env;
852                        CandidateFinder funcFinder( context, env );
853
854                        // Find all candidates for a function in canonical form
855                        funcFinder.find( clause.target, ResolveMode::withAdjustment() );
856
857                        if ( funcFinder.candidates.empty() ) {
858                                stringstream ss;
859                                ss << "Use of undeclared indentifier '";
860                                ss << clause.target.strict_as< ast::NameExpr >()->name;
861                                ss << "' in call to waitfor";
862                                SemanticError( stmt->location, ss.str() );
863                        }
864
865                        if ( clause.target_args.empty() ) {
866                                SemanticError( stmt->location,
867                                        "Waitfor clause must have at least one mutex parameter");
868                        }
869
870                        // Find all alternatives for all arguments in canonical form
871                        std::vector< CandidateFinder > argFinders =
872                                funcFinder.findSubExprs( clause.target_args );
873
874                        // List all combinations of arguments
875                        std::vector< CandidateList > possibilities;
876                        combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
877
878                        // For every possible function:
879                        // * try matching the arguments to the parameters, not the other way around because
880                        //   more arguments than parameters
881                        CandidateList funcCandidates;
882                        std::vector< CandidateList > argsCandidates;
883                        SemanticErrorException errors;
884                        for ( CandidateRef & func : funcFinder.candidates ) {
885                                try {
886                                        auto pointerType = dynamic_cast< const ast::PointerType * >(
887                                                func->expr->result->stripReferences() );
888                                        if ( ! pointerType ) {
889                                                SemanticError( stmt->location, func->expr->result.get(),
890                                                        "candidate not viable: not a pointer type\n" );
891                                        }
892
893                                        auto funcType = pointerType->base.as< ast::FunctionType >();
894                                        if ( ! funcType ) {
895                                                SemanticError( stmt->location, func->expr->result.get(),
896                                                        "candidate not viable: not a function type\n" );
897                                        }
898
899                                        {
900                                                auto param    = funcType->params.begin();
901                                                auto paramEnd = funcType->params.end();
902
903                                                if( ! nextMutex( param, paramEnd ) ) {
904                                                        SemanticError( stmt->location, funcType,
905                                                                "candidate function not viable: no mutex parameters\n");
906                                                }
907                                        }
908
909                                        CandidateRef func2{ new Candidate{ *func } };
910                                        // strip reference from function
911                                        func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
912
913                                        // Each argument must be matched with a parameter of the current candidate
914                                        for ( auto & argsList : possibilities ) {
915                                                try {
916                                                        // Declare data structures needed for resolution
917                                                        ast::OpenVarSet open;
918                                                        ast::AssertionSet need, have;
919                                                        ast::TypeEnvironment resultEnv{ func->env };
920                                                        // Add all type variables as open so that those not used in the
921                                                        // parameter list are still considered open
922                                                        resultEnv.add( funcType->forall );
923
924                                                        // load type variables from arguments into one shared space
925                                                        for ( auto & arg : argsList ) {
926                                                                resultEnv.simpleCombine( arg->env );
927                                                        }
928
929                                                        // Make sure we don't widen any existing bindings
930                                                        resultEnv.forbidWidening();
931
932                                                        // Find any unbound type variables
933                                                        resultEnv.extractOpenVars( open );
934
935                                                        auto param = funcType->params.begin();
936                                                        auto paramEnd = funcType->params.end();
937
938                                                        unsigned n_mutex_param = 0;
939
940                                                        // For every argument of its set, check if it matches one of the
941                                                        // parameters. The order is important
942                                                        for ( auto & arg : argsList ) {
943                                                                // Ignore non-mutex arguments
944                                                                if ( ! nextMutex( param, paramEnd ) ) {
945                                                                        // We ran out of parameters but still have arguments.
946                                                                        // This function doesn't match
947                                                                        SemanticError( stmt->location, funcType,
948                                                                                toString("candidate function not viable: too many mutex "
949                                                                                "arguments, expected ", n_mutex_param, "\n" ) );
950                                                                }
951
952                                                                ++n_mutex_param;
953
954                                                                // Check if the argument matches the parameter type in the current scope.
955                                                                // ast::ptr< ast::Type > paramType = (*param)->get_type();
956
957                                                                if (
958                                                                        ! unify(
959                                                                                arg->expr->result, *param, resultEnv, need, have, open )
960                                                                ) {
961                                                                        // Type doesn't match
962                                                                        stringstream ss;
963                                                                        ss << "candidate function not viable: no known conversion "
964                                                                                "from '";
965                                                                        ast::print( ss, *param );
966                                                                        ss << "' to '";
967                                                                        ast::print( ss, arg->expr->result );
968                                                                        ss << "' with env '";
969                                                                        ast::print( ss, resultEnv );
970                                                                        ss << "'\n";
971                                                                        SemanticError( stmt->location, funcType, ss.str() );
972                                                                }
973
974                                                                ++param;
975                                                        }
976
977                                                        // All arguments match!
978
979                                                        // Check if parameters are missing
980                                                        if ( nextMutex( param, paramEnd ) ) {
981                                                                do {
982                                                                        ++n_mutex_param;
983                                                                        ++param;
984                                                                } while ( nextMutex( param, paramEnd ) );
985
986                                                                // We ran out of arguments but still have parameters left; this
987                                                                // function doesn't match
988                                                                SemanticError( stmt->location, funcType,
989                                                                        toString( "candidate function not viable: too few mutex "
990                                                                        "arguments, expected ", n_mutex_param, "\n" ) );
991                                                        }
992
993                                                        // All parameters match!
994
995                                                        // Finish the expressions to tie in proper environments
996                                                        finishExpr( func2->expr, resultEnv );
997                                                        for ( CandidateRef & arg : argsList ) {
998                                                                finishExpr( arg->expr, resultEnv );
999                                                        }
1000
1001                                                        // This is a match, store it and save it for later
1002                                                        funcCandidates.emplace_back( std::move( func2 ) );
1003                                                        argsCandidates.emplace_back( std::move( argsList ) );
1004
1005                                                } catch ( SemanticErrorException & e ) {
1006                                                        errors.append( e );
1007                                                }
1008                                        }
1009                                } catch ( SemanticErrorException & e ) {
1010                                        errors.append( e );
1011                                }
1012                        }
1013
1014                        // Make sure correct number of arguments
1015                        if( funcCandidates.empty() ) {
1016                                SemanticErrorException top( stmt->location,
1017                                        "No alternatives for function in call to waitfor" );
1018                                top.append( errors );
1019                                throw top;
1020                        }
1021
1022                        if( argsCandidates.empty() ) {
1023                                SemanticErrorException top( stmt->location,
1024                                        "No alternatives for arguments in call to waitfor" );
1025                                top.append( errors );
1026                                throw top;
1027                        }
1028
1029                        if( funcCandidates.size() > 1 ) {
1030                                SemanticErrorException top( stmt->location,
1031                                        "Ambiguous function in call to waitfor" );
1032                                top.append( errors );
1033                                throw top;
1034                        }
1035                        if( argsCandidates.size() > 1 ) {
1036                                SemanticErrorException top( stmt->location,
1037                                        "Ambiguous arguments in call to waitfor" );
1038                                top.append( errors );
1039                                throw top;
1040                        }
1041                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
1042
1043                        // build new clause
1044                        auto clause2 = new ast::WaitForClause( clause.location );
1045
1046                        clause2->target = funcCandidates.front()->expr;
1047
1048                        clause2->target_args.reserve( clause.target_args.size() );
1049                        const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );
1050                        for ( auto arg : argsCandidates.front() ) {
1051                                const auto & loc = stmt->location;
1052
1053                                ast::Expr * init = new ast::CastExpr( loc,
1054                                        new ast::UntypedExpr( loc,
1055                                                new ast::NameExpr( loc, "get_monitor" ),
1056                                                { arg->expr }
1057                                        ),
1058                                        new ast::PointerType(
1059                                                new ast::StructInstType(
1060                                                        decl_monitor
1061                                                )
1062                                        )
1063                                );
1064
1065                                clause2->target_args.emplace_back( findSingleExpression( init, context ) );
1066                        }
1067
1068                        // Resolve the conditions as if it were an IfStmt, statements normally
1069                        clause2->when_cond = findSingleExpression( clause.when_cond, context );
1070                        clause2->stmt = clause.stmt->accept( *visitor );
1071
1072                        // set results into stmt
1073                        auto n = mutate( stmt );
1074                        n->clauses[i] = clause2;
1075                        stmt = n;
1076                }
1077
1078                if ( stmt->timeout_stmt ) {
1079                        // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
1080                        ast::ptr< ast::Type > target =
1081                                new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
1082                        auto timeout_time = findSingleExpression( stmt->timeout_time, target, context );
1083                        auto timeout_cond = findSingleExpression( stmt->timeout_cond, context );
1084                        auto timeout_stmt = stmt->timeout_stmt->accept( *visitor );
1085
1086                        // set results into stmt
1087                        auto n = mutate( stmt );
1088                        n->timeout_time = std::move( timeout_time );
1089                        n->timeout_cond = std::move( timeout_cond );
1090                        n->timeout_stmt = std::move( timeout_stmt );
1091                        stmt = n;
1092                }
1093
1094                if ( stmt->else_stmt ) {
1095                        // resolve the condition like IfStmt, stmts normally
1096                        auto else_cond = findSingleExpression( stmt->else_cond, context );
1097                        auto else_stmt = stmt->else_stmt->accept( *visitor );
1098
1099                        // set results into stmt
1100                        auto n = mutate( stmt );
1101                        n->else_cond = std::move( else_cond );
1102                        n->else_stmt = std::move( else_stmt );
1103                        stmt = n;
1104                }
1105
1106                return stmt;
1107        }
1108
1109        const ast::WithStmt * Resolver::previsit( const ast::WithStmt * withStmt ) {
1110                auto mutStmt = mutate(withStmt);
1111                resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
1112                return mutStmt;
1113        }
1114
1115        void Resolver::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
1116                for (auto & expr : exprs) {
1117                        // only struct- and union-typed expressions are viable candidates
1118                        expr = findKindExpression( expr, context, structOrUnion, "with expression" );
1119
1120                        // if with expression might be impure, create a temporary so that it is evaluated once
1121                        if ( Tuples::maybeImpure( expr ) ) {
1122                                static UniqueName tmpNamer( "_with_tmp_" );
1123                                const CodeLocation loc = expr->location;
1124                                auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
1125                                expr = new ast::VariableExpr( loc, tmp );
1126                                stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
1127                                if ( InitTweak::isConstructable( tmp->type ) ) {
1128                                        // generate ctor/dtor and resolve them
1129                                        tmp->init = InitTweak::genCtorInit( loc, tmp );
1130                                }
1131                                // since tmp is freshly created, this should modify tmp in-place
1132                                tmp->accept( *visitor );
1133                        }
1134                        else if (expr->env && expr->env->empty()) {
1135                                expr = ast::mutate_field(expr.get(), &ast::Expr::env, nullptr);
1136                        }
1137                }
1138        }
1139
1140
1141        const ast::SingleInit * Resolver::previsit( const ast::SingleInit * singleInit ) {
1142                visit_children = false;
1143                // resolve initialization using the possibilities as determined by the `currentObject`
1144                // cursor.
1145                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
1146                        singleInit->location, singleInit->value, currentObject.getOptions() };
1147                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context );
1148                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
1149
1150                // move cursor to the object that is actually initialized
1151                currentObject.setNext( initExpr->designation );
1152
1153                // discard InitExpr wrapper and retain relevant pieces.
1154                // `initExpr` may have inferred params in the case where the expression specialized a
1155                // function pointer, and newExpr may already have inferParams of its own, so a simple
1156                // swap is not sufficient
1157                ast::Expr::InferUnion inferred = initExpr->inferred;
1158                swap_and_save_env( newExpr, initExpr->expr );
1159                newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
1160
1161                // get the actual object's type (may not exactly match what comes back from the resolver
1162                // due to conversions)
1163                const ast::Type * initContext = currentObject.getCurrentType();
1164
1165                removeExtraneousCast( newExpr );
1166
1167                // check if actual object's type is char[]
1168                if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
1169                        if ( isCharType( at->base ) ) {
1170                                // check if the resolved type is char*
1171                                if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
1172                                        if ( isCharType( pt->base ) ) {
1173                                                // strip cast if we're initializing a char[] with a char*
1174                                                // e.g. char x[] = "hello"
1175                                                if ( auto ce = newExpr.as< ast::CastExpr >() ) {
1176                                                        swap_and_save_env( newExpr, ce->arg );
1177                                                }
1178                                        }
1179                                }
1180                        }
1181                }
1182
1183                // move cursor to next object in preparation for next initializer
1184                currentObject.increment();
1185
1186                // set initializer expression to resolved expression
1187                return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
1188        }
1189
1190        const ast::ListInit * Resolver::previsit( const ast::ListInit * listInit ) {
1191                // move cursor into brace-enclosed initializer-list
1192                currentObject.enterListInit( listInit->location );
1193
1194                assert( listInit->designations.size() == listInit->initializers.size() );
1195                for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
1196                        // iterate designations and initializers in pairs, moving the cursor to the current
1197                        // designated object and resolving the initializer against that object
1198                        listInit = ast::mutate_field_index(
1199                                listInit, &ast::ListInit::designations, i,
1200                                currentObject.findNext( listInit->designations[i] ) );
1201                        listInit = ast::mutate_field_index(
1202                                listInit, &ast::ListInit::initializers, i,
1203                                listInit->initializers[i]->accept( *visitor ) );
1204                }
1205
1206                // move cursor out of brace-enclosed initializer-list
1207                currentObject.exitListInit();
1208
1209                visit_children = false;
1210                return listInit;
1211        }
1212
1213        const ast::ConstructorInit * Resolver::previsit( const ast::ConstructorInit * ctorInit ) {
1214                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
1215                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
1216
1217                // found a constructor - can get rid of C-style initializer
1218                // xxx - Rob suggests this field is dead code
1219                ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
1220
1221                // intrinsic single-parameter constructors and destructors do nothing. Since this was
1222                // implicitly generated, there's no way for it to have side effects, so get rid of it to
1223                // clean up generated code
1224                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
1225                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
1226                }
1227                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
1228                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
1229                }
1230
1231                return ctorInit;
1232        }
1233
1234        const ast::EnumPosExpr * Resolver::previsit( const ast::EnumPosExpr * enumPos ) {
1235                visitor->maybe_accept( enumPos, &ast::EnumPosExpr::expr );
1236                return enumPos;
1237        }
1238
1239        // suppress error on autogen functions and mark invalid autogen as deleted.
1240        bool Resolver::on_error(ast::ptr<ast::Decl> & decl) {
1241                if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
1242                        // xxx - can intrinsic gen ever fail?
1243                        if (functionDecl->linkage == ast::Linkage::AutoGen) {
1244                                auto mutDecl = mutate(functionDecl);
1245                                mutDecl->isDeleted = true;
1246                                mutDecl->stmts = nullptr;
1247                                decl = mutDecl;
1248                                return false;
1249                        }
1250                }
1251                return true;
1252        }
1253
1254} // namespace ResolvExpr
1255
1256// Local Variables: //
1257// tab-width: 4 //
1258// mode: c++ //
1259// compile-command: "make install" //
1260// End: //
Note: See TracBrowser for help on using the repository browser.