int Identifier::compare(Identifier other) const { // Handle empty identifiers. if (empty() || other.empty()) { if (empty() != other.empty()) { return other.empty() ? -1 : 1; } return 0; } return str().compare(other.str()); }
static void addParameters(ArrayRef<Identifier> &ArgNames, const ParameterList *paramList, TextEntity &Ent, SourceManager &SM, unsigned BufferID) { for (auto ¶m : *paramList) { StringRef Arg; if (!ArgNames.empty()) { Identifier Id = ArgNames.front(); Arg = Id.empty() ? "_" : Id.str(); ArgNames = ArgNames.slice(1); } if (auto typeRepr = param->getTypeLoc().getTypeRepr()) { SourceRange TypeRange = param->getTypeLoc().getSourceRange(); if (auto InOutTyR = dyn_cast_or_null<InOutTypeRepr>(typeRepr)) TypeRange = InOutTyR->getBase()->getSourceRange(); if (TypeRange.isInvalid()) continue; unsigned StartOffs = SM.getLocOffsetInBuffer(TypeRange.Start, BufferID); unsigned EndOffs = SM.getLocOffsetInBuffer(Lexer::getLocForEndOfToken(SM, TypeRange.End), BufferID); TextRange TR{ StartOffs, EndOffs-StartOffs }; TextEntity Param(param, Arg, TR, StartOffs); Ent.SubEntities.push_back(std::move(Param)); } } }
bool SemaAnnotator::passCallArgNames(Expr *Fn, TupleExpr *TupleE) { ValueDecl *D = extractDecl(Fn); if (!D) return true; // continue. ArrayRef<Identifier> ArgNames = TupleE->getElementNames(); ArrayRef<SourceLoc> ArgLocs = TupleE->getElementNameLocs(); for (auto i : indices(ArgNames)) { Identifier Name = ArgNames[i]; if (Name.empty()) continue; SourceLoc Loc = ArgLocs[i]; if (Loc.isInvalid()) continue; CharSourceRange Range{ Loc, Name.getLength() }; bool Continue = SEWalker.visitCallArgName(Name, Range, D); if (!Continue) { Cancelled = true; return false; } } return true; }
bool Identifier::validateID(const std::string & strPurportedID) { if (strPurportedID.empty()) return false; Identifier theID; const String strID(strPurportedID); App::Me().Crypto().Util().SetIDFromEncoded(strID, theID); return !theID.empty(); }
bool Blockchain::StoreOutgoing( const Identifier& senderNymID, const Identifier& accountID, const Identifier& recipientContactID, const proto::BlockchainTransaction& transaction) const { LOCK_ACCOUNT() const std::string sNymID = senderNymID.str(); const std::string sAccountID = accountID.str(); auto account = load_account(accountLock, sNymID, sAccountID); if (false == bool(account)) { otErr << OT_METHOD << __FUNCTION__ << ": Account does not exist." << std::endl; return false; } const auto& txid = transaction.txid(); account->add_outgoing(txid); auto saved = api_.Storage().Store(sNymID, account->type(), *account); if (false == saved) { otErr << OT_METHOD << __FUNCTION__ << ": Failed to save account." << std::endl; return false; } saved = api_.Storage().Store(transaction); if (false == saved) { otErr << OT_METHOD << __FUNCTION__ << ": Failed to save transaction." << std::endl; return false; } if (recipientContactID.empty()) { return true; } return activity_.AddBlockchainTransaction( senderNymID, recipientContactID, StorageBox::OUTGOINGBLOCKCHAIN, transaction); }
static void addParameters(ArrayRef<Identifier> &ArgNames, const Pattern *Pat, TextEntity &Ent, SourceManager &SM, unsigned BufferID) { if (auto ParenPat = dyn_cast<ParenPattern>(Pat)) { addParameters(ArgNames, ParenPat->getSubPattern(), Ent, SM, BufferID); return; } if (auto Tuple = dyn_cast<TuplePattern>(Pat)) { for (const auto &Elt : Tuple->getElements()) addParameters(ArgNames, Elt.getPattern(), Ent, SM, BufferID); return; } StringRef Arg; if (!ArgNames.empty()) { Identifier Id = ArgNames.front(); Arg = Id.empty() ? "_" : Id.str(); ArgNames = ArgNames.slice(1); } if (auto Typed = dyn_cast<TypedPattern>(Pat)) { VarDecl *VD = nullptr; if (auto Named = dyn_cast<NamedPattern>(Typed->getSubPattern())) { VD = Named->getDecl(); } SourceRange TypeRange = Typed->getTypeLoc().getSourceRange(); if (auto InOutTyR = dyn_cast_or_null<InOutTypeRepr>(Typed->getTypeLoc().getTypeRepr())) { TypeRange = InOutTyR->getBase()->getSourceRange(); } if (TypeRange.isInvalid()) return; unsigned StartOffs = SM.getLocOffsetInBuffer(TypeRange.Start, BufferID); unsigned EndOffs = SM.getLocOffsetInBuffer(Lexer::getLocForEndOfToken(SM, TypeRange.End), BufferID); TextRange TR{ StartOffs, EndOffs-StartOffs }; TextEntity Param(VD, Arg, TR, StartOffs); Ent.SubEntities.push_back(std::move(Param)); } }
/// Returns a string representation of the SubPath /// suitable for use in diagnostic text. Only supports the Projections /// that stored-property relaxation supports: struct stored properties /// and tuple elements. std::string AccessSummaryAnalysis::getSubPathDescription( SILType baseType, const IndexTrieNode *subPath, SILModule &M) { // Walk the trie to the root to collect the sequence (in reverse order). llvm::SmallVector<unsigned, 4> reversedIndices; const IndexTrieNode *I = subPath; while (!I->isRoot()) { reversedIndices.push_back(I->getIndex()); I = I->getParent(); } std::string sbuf; llvm::raw_string_ostream os(sbuf); SILType containingType = baseType; for (unsigned index : reversed(reversedIndices)) { os << "."; if (StructDecl *D = containingType.getStructOrBoundGenericStruct()) { auto iter = D->getStoredProperties().begin(); std::advance(iter, index); VarDecl *var = *iter; os << var->getBaseName(); containingType = containingType.getFieldType(var, M); continue; } if (auto tupleTy = containingType.getAs<TupleType>()) { Identifier elementName = tupleTy->getElement(index).getName(); if (elementName.empty()) os << index; else os << elementName; containingType = containingType.getTupleElementType(index); continue; } llvm_unreachable("Unexpected type in projection SubPath!"); } return os.str(); }
static void filterForDiscriminator(SmallVectorImpl<Result> &results, DebuggerClient *debugClient) { Identifier discriminator = debugClient->getPreferredPrivateDiscriminator(); if (discriminator.empty()) return; auto doesNotMatch = [discriminator](Result next) -> bool { return !matchesDiscriminator(discriminator, next); }; auto lastMatchIter = std::find_if_not(results.rbegin(), results.rend(), doesNotMatch); if (lastMatchIter == results.rend()) return; Result lastMatch = *lastMatchIter; auto newEnd = std::remove_if(results.begin(), lastMatchIter.base()-1, doesNotMatch); results.erase(newEnd, results.end()); results.push_back(lastMatch); }
Identifier ModuleFile::getDiscriminatorForPrivateValue(const ValueDecl *D) { Identifier discriminator = PrivateDiscriminatorsByValue.lookup(D); assert(!discriminator.empty() && "no discriminator found for decl"); return discriminator; }
void TypeChecker::checkForForbiddenPrefix(Identifier Ident) { if (!hasEnabledForbiddenTypecheckPrefix()) return; checkForForbiddenPrefix(Ident.empty() ? StringRef() : Ident.str()); }
Identifier SerializedASTFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const { Identifier discriminator = File.getDiscriminatorForPrivateValue(D); assert(!discriminator.empty() && "no discriminator found for value"); return discriminator; }
/// Performs the compile requested by the user. /// \returns true on error static bool performCompile(CompilerInstance &Instance, CompilerInvocation &Invocation, ArrayRef<const char *> Args, int &ReturnValue) { FrontendOptions opts = Invocation.getFrontendOptions(); FrontendOptions::ActionType Action = opts.RequestedAction; IRGenOptions &IRGenOpts = Invocation.getIRGenOptions(); bool inputIsLLVMIr = Invocation.getInputKind() == InputFileKind::IFK_LLVM_IR; if (inputIsLLVMIr) { auto &LLVMContext = llvm::getGlobalContext(); // Load in bitcode file. assert(Invocation.getInputFilenames().size() == 1 && "We expect a single input for bitcode input!"); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(Invocation.getInputFilenames()[0]); if (!FileBufOrErr) { Instance.getASTContext().Diags.diagnose(SourceLoc(), diag::error_open_input_file, Invocation.getInputFilenames()[0], FileBufOrErr.getError().message()); return true; } llvm::MemoryBuffer *MainFile = FileBufOrErr.get().get(); llvm::SMDiagnostic Err; std::unique_ptr<llvm::Module> Module = llvm::parseIR( MainFile->getMemBufferRef(), Err, LLVMContext); if (!Module) { // TODO: Translate from the diagnostic info to the SourceManager location // if available. Instance.getASTContext().Diags.diagnose(SourceLoc(), diag::error_parse_input_file, Invocation.getInputFilenames()[0], Err.getMessage()); return true; } // TODO: remove once the frontend understands what action it should perform IRGenOpts.OutputKind = getOutputKind(Action); return performLLVM(IRGenOpts, Instance.getASTContext(), Module.get()); } ReferencedNameTracker nameTracker; bool shouldTrackReferences = !opts.ReferenceDependenciesFilePath.empty(); if (shouldTrackReferences) Instance.setReferencedNameTracker(&nameTracker); if (Action == FrontendOptions::DumpParse || Action == FrontendOptions::DumpInterfaceHash) Instance.performParseOnly(); else Instance.performSema(); FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode; if (CrashMode == FrontendOptions::DebugCrashMode::AssertAfterParse) debugFailWithAssertion(); else if (CrashMode == FrontendOptions::DebugCrashMode::CrashAfterParse) debugFailWithCrash(); ASTContext &Context = Instance.getASTContext(); if (Action == FrontendOptions::REPL) { runREPL(Instance, ProcessCmdLine(Args.begin(), Args.end()), Invocation.getParseStdlib()); return false; } SourceFile *PrimarySourceFile = Instance.getPrimarySourceFile(); // We've been told to dump the AST (either after parsing or type-checking, // which is already differentiated in CompilerInstance::performSema()), // so dump or print the main source file and return. if (Action == FrontendOptions::DumpParse || Action == FrontendOptions::DumpAST || Action == FrontendOptions::PrintAST || Action == FrontendOptions::DumpTypeRefinementContexts || Action == FrontendOptions::DumpInterfaceHash) { SourceFile *SF = PrimarySourceFile; if (!SF) { SourceFileKind Kind = Invocation.getSourceFileKind(); SF = &Instance.getMainModule()->getMainSourceFile(Kind); } if (Action == FrontendOptions::PrintAST) SF->print(llvm::outs(), PrintOptions::printEverything()); else if (Action == FrontendOptions::DumpTypeRefinementContexts) SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr); else if (Action == FrontendOptions::DumpInterfaceHash) SF->dumpInterfaceHash(llvm::errs()); else SF->dump(); return false; } // If we were asked to print Clang stats, do so. if (opts.PrintClangStats && Context.getClangModuleLoader()) Context.getClangModuleLoader()->printStatistics(); if (!opts.DependenciesFilePath.empty()) (void)emitMakeDependencies(Context.Diags, *Instance.getDependencyTracker(), opts); if (shouldTrackReferences) emitReferenceDependencies(Context.Diags, Instance.getPrimarySourceFile(), *Instance.getDependencyTracker(), opts); if (Context.hadError()) return true; // FIXME: This is still a lousy approximation of whether the module file will // be externally consumed. bool moduleIsPublic = !Instance.getMainModule()->hasEntryPoint() && opts.ImplicitObjCHeaderPath.empty() && !Context.LangOpts.EnableAppExtensionRestrictions; // We've just been told to perform a parse, so we can return now. if (Action == FrontendOptions::Parse) { if (!opts.ObjCHeaderOutputPath.empty()) return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic); return false; } assert(Action >= FrontendOptions::EmitSILGen && "All actions not requiring SILGen must have been handled!"); std::unique_ptr<SILModule> SM = Instance.takeSILModule(); if (!SM) { if (opts.PrimaryInput.hasValue() && opts.PrimaryInput.getValue().isFilename()) { FileUnit *PrimaryFile = PrimarySourceFile; if (!PrimaryFile) { auto Index = opts.PrimaryInput.getValue().Index; PrimaryFile = Instance.getMainModule()->getFiles()[Index]; } SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(), None, opts.SILSerializeAll); } else { SM = performSILGeneration(Instance.getMainModule(), Invocation.getSILOptions(), opts.SILSerializeAll, true); } } // We've been told to emit SIL after SILGen, so write it now. if (Action == FrontendOptions::EmitSILGen) { // If we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL, opts.getSingleOutputFilename(), opts.EmitSortedSIL); } if (Action == FrontendOptions::EmitSIBGen) { // If we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance.getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(DC, serializationOpts, SM.get()); } return false; } // Perform "stable" optimizations that are invariant across compiler versions. if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses && runSILDiagnosticPasses(*SM)) return true; // Now if we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); SM->verify(); // Perform SIL optimization passes if optimizations haven't been disabled. // These may change across compiler versions. if (IRGenOpts.Optimize) { StringRef CustomPipelinePath = Invocation.getSILOptions().ExternalPassPipelineFilename; if (!CustomPipelinePath.empty()) { runSILOptimizationPassesWithFileSpecification(*SM, CustomPipelinePath); } else { runSILOptimizationPasses(*SM); } } else { runSILPassesForOnone(*SM); } SM->verify(); // Gather instruction counts if we are asked to do so. if (SM->getOptions().PrintInstCounts) { performSILInstCount(&*SM); } // Get the main source file's private discriminator and attach it to // the compile unit's flags. if (PrimarySourceFile) { Identifier PD = PrimarySourceFile->getPrivateDiscriminator(); if (!PD.empty()) IRGenOpts.DWARFDebugFlags += (" -private-discriminator "+PD.str()).str(); } if (!opts.ObjCHeaderOutputPath.empty()) { (void)printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic); } if (Action == FrontendOptions::EmitSIB) { auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance.getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(DC, serializationOpts, SM.get()); } return false; } if (!opts.ModuleOutputPath.empty() || !opts.ModuleDocOutputPath.empty()) { auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance.getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str(); serializationOpts.SerializeAllSIL = opts.SILSerializeAll; if (opts.SerializeBridgingHeader) serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath; serializationOpts.ModuleLinkName = opts.ModuleLinkName; serializationOpts.ExtraClangOptions = Invocation.getClangImporterOptions().ExtraArgs; if (!IRGenOpts.ForceLoadSymbolName.empty()) serializationOpts.AutolinkForceLoad = true; // Options contain information about the developer's computer, // so only serialize them if the module isn't going to be shipped to // the public. serializationOpts.SerializeOptionsForDebugging = !moduleIsPublic || opts.AlwaysSerializeDebuggingOptions; serialize(DC, serializationOpts, SM.get()); } if (Action == FrontendOptions::EmitModuleOnly) return false; } assert(Action >= FrontendOptions::EmitSIL && "All actions not requiring SILPasses must have been handled!"); // We've been told to write canonical SIL, so write it now. if (Action == FrontendOptions::EmitSIL) { return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL, opts.getSingleOutputFilename(), opts.EmitSortedSIL); } assert(Action >= FrontendOptions::Immediate && "All actions not requiring IRGen must have been handled!"); assert(Action != FrontendOptions::REPL && "REPL mode must be handled immediately after Instance.performSema()"); // Check if we had any errors; if we did, don't proceed to IRGen. if (Context.hadError()) return true; // Cleanup instructions/builtin calls not suitable for IRGen. performSILCleanup(SM.get()); // TODO: remove once the frontend understands what action it should perform IRGenOpts.OutputKind = getOutputKind(Action); if (Action == FrontendOptions::Immediate) { assert(!PrimarySourceFile && "-i doesn't work in -primary-file mode"); IRGenOpts.UseJIT = true; IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal; const ProcessCmdLine &CmdLine = ProcessCmdLine(opts.ImmediateArgv.begin(), opts.ImmediateArgv.end()); Instance.setSILModule(std::move(SM)); ReturnValue = RunImmediately(Instance, CmdLine, IRGenOpts, Invocation.getSILOptions()); return false; } // FIXME: We shouldn't need to use the global context here, but // something is persisting across calls to performIRGeneration. auto &LLVMContext = llvm::getGlobalContext(); if (PrimarySourceFile) { performIRGeneration(IRGenOpts, *PrimarySourceFile, SM.get(), opts.getSingleOutputFilename(), LLVMContext); } else { performIRGeneration(IRGenOpts, Instance.getMainModule(), SM.get(), opts.getSingleOutputFilename(), LLVMContext); } return false; }
/// parseTypeTupleBody /// type-tuple: /// '(' type-tuple-body? ')' /// type-tuple-body: /// type-tuple-element (',' type-tuple-element)* '...'? /// type-tuple-element: /// identifier ':' type /// type ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() { Parser::StructureMarkerRAII ParsingTypeTuple(*this, Tok); SourceLoc RPLoc, LPLoc = consumeToken(tok::l_paren); SourceLoc EllipsisLoc; unsigned EllipsisIdx; SmallVector<TypeRepr *, 8> ElementsR; // We keep track of the labels separately, and apply them at the end. SmallVector<std::tuple<Identifier, SourceLoc, Identifier, SourceLoc>, 4> Labels; ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc, tok::comma, /*OptionalSep=*/false, /*AllowSepAfterLast=*/false, diag::expected_rparen_tuple_type_list, [&] () -> ParserStatus { // If this is a deprecated use of the inout marker in an argument list, // consume the inout. SourceLoc InOutLoc; bool hasAnyInOut = false; bool hasValidInOut = false; if (consumeIf(tok::kw_inout, InOutLoc)) { hasAnyInOut = true; hasValidInOut = false; } // If the tuple element starts with a potential argument label followed by a // ':' or another potential argument label, then the identifier is an // element tag, and it is followed by a type annotation. if (Tok.canBeArgumentLabel() && (peekToken().is(tok::colon) || peekToken().canBeArgumentLabel())) { // Consume the name Identifier name; if (!Tok.is(tok::kw__)) name = Context.getIdentifier(Tok.getText()); SourceLoc nameLoc = consumeToken(); // If there is a second name, consume it as well. Identifier secondName; SourceLoc secondNameLoc; if (Tok.canBeArgumentLabel()) { if (!Tok.is(tok::kw__)) secondName = Context.getIdentifier(Tok.getText()); secondNameLoc = consumeToken(); } // Consume the ':'. if (!consumeIf(tok::colon)) diagnose(Tok, diag::expected_parameter_colon); SourceLoc postColonLoc = Tok.getLoc(); // Consume 'inout' if present. if (!hasAnyInOut && consumeIf(tok::kw_inout, InOutLoc)) { hasValidInOut = true; } SourceLoc extraneousInOutLoc; while (consumeIf(tok::kw_inout, extraneousInOutLoc)) { diagnose(Tok, diag::parameter_inout_var_let_repeated) .fixItRemove(extraneousInOutLoc); } // Parse the type annotation. ParserResult<TypeRepr> type = parseType(diag::expected_type); if (type.hasCodeCompletion()) return makeParserCodeCompletionStatus(); if (type.isNull()) return makeParserError(); if (!hasValidInOut && hasAnyInOut) { diagnose(Tok.getLoc(), diag::inout_as_attr_disallowed) .fixItRemove(InOutLoc) .fixItInsert(postColonLoc, "inout "); } // If an 'inout' marker was specified, build the type. Note that we bury // the inout locator within the named locator. This is weird but required // by sema apparently. if (InOutLoc.isValid()) type = makeParserResult(new (Context) InOutTypeRepr(type.get(), InOutLoc)); // Record the label. We will look at these at the end. if (Labels.empty()) { Labels.assign(ElementsR.size(), std::make_tuple(Identifier(), SourceLoc(), Identifier(), SourceLoc())); } Labels.push_back(std::make_tuple(name, nameLoc, secondName, secondNameLoc)); ElementsR.push_back(type.get()); } else { // Otherwise, this has to be a type. ParserResult<TypeRepr> type = parseType(); if (type.hasCodeCompletion()) return makeParserCodeCompletionStatus(); if (type.isNull()) return makeParserError(); if (InOutLoc.isValid()) type = makeParserResult(new (Context) InOutTypeRepr(type.get(), InOutLoc)); if (!Labels.empty()) { Labels.push_back(std::make_tuple(Identifier(), SourceLoc(), Identifier(), SourceLoc())); } ElementsR.push_back(type.get()); } // Parse '= expr' here so we can complain about it directly, rather // than dying when we see it. if (Tok.is(tok::equal)) { SourceLoc equalLoc = consumeToken(tok::equal); auto init = parseExpr(diag::expected_init_value); auto inFlight = diagnose(equalLoc, diag::tuple_type_init); if (init.isNonNull()) inFlight.fixItRemove(SourceRange(equalLoc, init.get()->getEndLoc())); } if (Tok.isEllipsis()) { if (EllipsisLoc.isValid()) { diagnose(Tok, diag::multiple_ellipsis_in_tuple) .highlight(EllipsisLoc) .fixItRemove(Tok.getLoc()); (void)consumeToken(); } else { EllipsisLoc = consumeToken(); EllipsisIdx = ElementsR.size() - 1; } } return makeParserSuccess(); }); if (EllipsisLoc.isValid() && ElementsR.empty()) { EllipsisLoc = SourceLoc(); } if (EllipsisLoc.isInvalid()) EllipsisIdx = ElementsR.size(); // If there were any labels, figure out which labels should go into the type // representation. if (!Labels.empty()) { assert(Labels.size() == ElementsR.size()); bool isFunctionType = Tok.isAny(tok::arrow, tok::kw_throws, tok::kw_rethrows); for (unsigned i : indices(ElementsR)) { auto ¤tLabel = Labels[i]; Identifier firstName = std::get<0>(currentLabel); SourceLoc firstNameLoc = std::get<1>(currentLabel); Identifier secondName = std::get<2>(currentLabel); SourceLoc secondNameLoc = std::get<3>(currentLabel); // True tuples have labels. if (!isFunctionType) { // If there were two names, complain. if (firstNameLoc.isValid() && secondNameLoc.isValid()) { auto diag = diagnose(firstNameLoc, diag::tuple_type_multiple_labels); if (firstName.empty()) { diag.fixItRemoveChars(firstNameLoc, ElementsR[i]->getStartLoc()); } else { diag.fixItRemove( SourceRange(Lexer::getLocForEndOfToken(SourceMgr,firstNameLoc), secondNameLoc)); } } // Form the named type representation. ElementsR[i] = new (Context) NamedTypeRepr(firstName, ElementsR[i], firstNameLoc); continue; } // If there was a first name, complain; arguments in function types are // always unlabeled. if (firstNameLoc.isValid() && !firstName.empty()) { auto diag = diagnose(firstNameLoc, diag::function_type_argument_label, firstName); if (secondNameLoc.isInvalid()) diag.fixItInsert(firstNameLoc, "_ "); else if (secondName.empty()) diag.fixItRemoveChars(firstNameLoc, ElementsR[i]->getStartLoc()); else diag.fixItReplace(SourceRange(firstNameLoc), "_"); } if (firstNameLoc.isValid() || secondNameLoc.isValid()) { // Form the named parameter type representation. ElementsR[i] = new (Context) NamedTypeRepr(secondName, ElementsR[i], secondNameLoc, firstNameLoc); } } } return makeParserResult(Status, TupleTypeRepr::create(Context, ElementsR, SourceRange(LPLoc, RPLoc), EllipsisLoc, EllipsisIdx)); }
DeclContext * ASTBuilder::findDeclContext(NodePointer node) { switch (node->getKind()) { case Demangle::Node::Kind::DeclContext: case Demangle::Node::Kind::Type: case Demangle::Node::Kind::BoundGenericClass: case Demangle::Node::Kind::BoundGenericEnum: case Demangle::Node::Kind::BoundGenericProtocol: case Demangle::Node::Kind::BoundGenericStructure: case Demangle::Node::Kind::BoundGenericTypeAlias: return findDeclContext(node->getFirstChild()); case Demangle::Node::Kind::Module: return findModule(node); case Demangle::Node::Kind::Class: case Demangle::Node::Kind::Enum: case Demangle::Node::Kind::Protocol: case Demangle::Node::Kind::Structure: case Demangle::Node::Kind::TypeAlias: { const auto &declNameNode = node->getChild(1); // Handle local declarations. if (declNameNode->getKind() == Demangle::Node::Kind::LocalDeclName) { // Find the AST node for the defining module. auto moduleNode = findModuleNode(node); if (!moduleNode) return nullptr; auto module = findModule(moduleNode); if (!module) return nullptr; // Look up the local type by its mangling. auto mangledName = Demangle::mangleNode(node); auto decl = module->lookupLocalType(mangledName); if (!decl) return nullptr; return dyn_cast<DeclContext>(decl); } StringRef name; StringRef relatedEntityKind; Identifier privateDiscriminator; if (declNameNode->getKind() == Demangle::Node::Kind::Identifier) { name = declNameNode->getText(); } else if (declNameNode->getKind() == Demangle::Node::Kind::PrivateDeclName) { name = declNameNode->getChild(1)->getText(); privateDiscriminator = Ctx.getIdentifier(declNameNode->getChild(0)->getText()); } else if (declNameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName) { name = declNameNode->getChild(0)->getText(); relatedEntityKind = declNameNode->getText(); // Ignore any other decl-name productions for now. } else { return nullptr; } // Do some special logic for foreign type declarations. if (privateDiscriminator.empty()) { if (auto foreignModuleKind = getForeignModuleKind(node->getChild(0))) { return findForeignTypeDecl(name, relatedEntityKind, foreignModuleKind.getValue(), node->getKind()); } } DeclContext *dc = findDeclContext(node->getChild(0)); if (!dc) { return nullptr; } return findTypeDecl(dc, Ctx.getIdentifier(name), privateDiscriminator, node->getKind()); } case Demangle::Node::Kind::Global: return findDeclContext(node->getChild(0)); case Demangle::Node::Kind::Extension: { auto *moduleDecl = dyn_cast_or_null<ModuleDecl>( findDeclContext(node->getChild(0))); if (!moduleDecl) return nullptr; auto *nominalDecl = dyn_cast_or_null<NominalTypeDecl>( findDeclContext(node->getChild(1))); if (!nominalDecl) return nullptr; CanGenericSignature genericSig; if (node->getNumChildren() > 2) genericSig = demangleGenericSignature(nominalDecl, node->getChild(2)); for (auto *ext : nominalDecl->getExtensions()) { if (ext->getParentModule() != moduleDecl) continue; if (!ext->isConstrainedExtension()) { if (!genericSig) return ext; continue; } if (ext->getGenericSignature()->getCanonicalSignature() == genericSig) { return ext; } } return nullptr; } // Bail out on other kinds of contexts. default: return nullptr; } }
/// Performs the compile requested by the user. /// \param Instance Will be reset after performIRGeneration when the verifier /// mode is NoVerify and there were no errors. /// \returns true on error static bool performCompile(std::unique_ptr<CompilerInstance> &Instance, CompilerInvocation &Invocation, ArrayRef<const char *> Args, int &ReturnValue, FrontendObserver *observer) { FrontendOptions opts = Invocation.getFrontendOptions(); FrontendOptions::ActionType Action = opts.RequestedAction; IRGenOptions &IRGenOpts = Invocation.getIRGenOptions(); bool inputIsLLVMIr = Invocation.getInputKind() == InputFileKind::IFK_LLVM_IR; if (inputIsLLVMIr) { auto &LLVMContext = getGlobalLLVMContext(); // Load in bitcode file. assert(Invocation.getInputFilenames().size() == 1 && "We expect a single input for bitcode input!"); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(Invocation.getInputFilenames()[0]); if (!FileBufOrErr) { Instance->getASTContext().Diags.diagnose(SourceLoc(), diag::error_open_input_file, Invocation.getInputFilenames()[0], FileBufOrErr.getError().message()); return true; } llvm::MemoryBuffer *MainFile = FileBufOrErr.get().get(); llvm::SMDiagnostic Err; std::unique_ptr<llvm::Module> Module = llvm::parseIR( MainFile->getMemBufferRef(), Err, LLVMContext); if (!Module) { // TODO: Translate from the diagnostic info to the SourceManager location // if available. Instance->getASTContext().Diags.diagnose(SourceLoc(), diag::error_parse_input_file, Invocation.getInputFilenames()[0], Err.getMessage()); return true; } // TODO: remove once the frontend understands what action it should perform IRGenOpts.OutputKind = getOutputKind(Action); return performLLVM(IRGenOpts, Instance->getASTContext(), Module.get()); } ReferencedNameTracker nameTracker; bool shouldTrackReferences = !opts.ReferenceDependenciesFilePath.empty(); if (shouldTrackReferences) Instance->setReferencedNameTracker(&nameTracker); if (Action == FrontendOptions::Parse || Action == FrontendOptions::DumpParse || Action == FrontendOptions::DumpInterfaceHash) Instance->performParseOnly(); else Instance->performSema(); if (Action == FrontendOptions::Parse) return Instance->getASTContext().hadError(); if (observer) { observer->performedSemanticAnalysis(*Instance); } FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode; if (CrashMode == FrontendOptions::DebugCrashMode::AssertAfterParse) debugFailWithAssertion(); else if (CrashMode == FrontendOptions::DebugCrashMode::CrashAfterParse) debugFailWithCrash(); ASTContext &Context = Instance->getASTContext(); if (Action == FrontendOptions::REPL) { runREPL(*Instance, ProcessCmdLine(Args.begin(), Args.end()), Invocation.getParseStdlib()); return Context.hadError(); } SourceFile *PrimarySourceFile = Instance->getPrimarySourceFile(); // We've been told to dump the AST (either after parsing or type-checking, // which is already differentiated in CompilerInstance::performSema()), // so dump or print the main source file and return. if (Action == FrontendOptions::DumpParse || Action == FrontendOptions::DumpAST || Action == FrontendOptions::PrintAST || Action == FrontendOptions::DumpScopeMaps || Action == FrontendOptions::DumpTypeRefinementContexts || Action == FrontendOptions::DumpInterfaceHash) { SourceFile *SF = PrimarySourceFile; if (!SF) { SourceFileKind Kind = Invocation.getSourceFileKind(); SF = &Instance->getMainModule()->getMainSourceFile(Kind); } if (Action == FrontendOptions::PrintAST) SF->print(llvm::outs(), PrintOptions::printEverything()); else if (Action == FrontendOptions::DumpScopeMaps) { ASTScope &scope = SF->getScope(); if (opts.DumpScopeMapLocations.empty()) { scope.expandAll(); } else if (auto bufferID = SF->getBufferID()) { SourceManager &sourceMgr = Instance->getSourceMgr(); // Probe each of the locations, and dump what we find. for (auto lineColumn : opts.DumpScopeMapLocations) { SourceLoc loc = sourceMgr.getLocForLineCol(*bufferID, lineColumn.first, lineColumn.second); if (loc.isInvalid()) continue; llvm::errs() << "***Scope at " << lineColumn.first << ":" << lineColumn.second << "***\n"; auto locScope = scope.findInnermostEnclosingScope(loc); locScope->print(llvm::errs(), 0, false, false); // Dump the AST context, too. if (auto dc = locScope->getDeclContext()) { dc->printContext(llvm::errs()); } // Grab the local bindings introduced by this scope. auto localBindings = locScope->getLocalBindings(); if (!localBindings.empty()) { llvm::errs() << "Local bindings: "; interleave(localBindings.begin(), localBindings.end(), [&](ValueDecl *value) { llvm::errs() << value->getFullName(); }, [&]() { llvm::errs() << " "; }); llvm::errs() << "\n"; } } llvm::errs() << "***Complete scope map***\n"; } // Print the resulting map. scope.print(llvm::errs()); } else if (Action == FrontendOptions::DumpTypeRefinementContexts) SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr); else if (Action == FrontendOptions::DumpInterfaceHash) SF->dumpInterfaceHash(llvm::errs()); else SF->dump(); return Context.hadError(); } // If we were asked to print Clang stats, do so. if (opts.PrintClangStats && Context.getClangModuleLoader()) Context.getClangModuleLoader()->printStatistics(); if (!opts.DependenciesFilePath.empty()) (void)emitMakeDependencies(Context.Diags, *Instance->getDependencyTracker(), opts); if (shouldTrackReferences) emitReferenceDependencies(Context.Diags, Instance->getPrimarySourceFile(), *Instance->getDependencyTracker(), opts); if (Context.hadError()) return true; // FIXME: This is still a lousy approximation of whether the module file will // be externally consumed. bool moduleIsPublic = !Instance->getMainModule()->hasEntryPoint() && opts.ImplicitObjCHeaderPath.empty() && !Context.LangOpts.EnableAppExtensionRestrictions; // We've just been told to perform a typecheck, so we can return now. if (Action == FrontendOptions::Typecheck) { if (!opts.ObjCHeaderOutputPath.empty()) return printAsObjC(opts.ObjCHeaderOutputPath, Instance->getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic); return Context.hadError(); } assert(Action >= FrontendOptions::EmitSILGen && "All actions not requiring SILGen must have been handled!"); std::unique_ptr<SILModule> SM = Instance->takeSILModule(); if (!SM) { if (opts.PrimaryInput.hasValue() && opts.PrimaryInput.getValue().isFilename()) { FileUnit *PrimaryFile = PrimarySourceFile; if (!PrimaryFile) { auto Index = opts.PrimaryInput.getValue().Index; PrimaryFile = Instance->getMainModule()->getFiles()[Index]; } SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(), None, opts.SILSerializeAll); } else { SM = performSILGeneration(Instance->getMainModule(), Invocation.getSILOptions(), opts.SILSerializeAll, true); } } if (observer) { observer->performedSILGeneration(*SM); } // We've been told to emit SIL after SILGen, so write it now. if (Action == FrontendOptions::EmitSILGen) { // If we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); return writeSIL(*SM, Instance->getMainModule(), opts.EmitVerboseSIL, opts.getSingleOutputFilename(), opts.EmitSortedSIL); } if (Action == FrontendOptions::EmitSIBGen) { // If we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance->getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(DC, serializationOpts, SM.get()); } return Context.hadError(); } // Perform "stable" optimizations that are invariant across compiler versions. if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses) { if (runSILDiagnosticPasses(*SM)) return true; if (observer) { observer->performedSILDiagnostics(*SM); } } else { // Even if we are not supposed to run the diagnostic passes, we still need // to run the ownership evaluator. if (runSILOwnershipEliminatorPass(*SM)) return true; } // Now if we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); { SharedTimer timer("SIL verification (pre-optimization)"); SM->verify(); } // Perform SIL optimization passes if optimizations haven't been disabled. // These may change across compiler versions. { SharedTimer timer("SIL optimization"); if (Invocation.getSILOptions().Optimization > SILOptions::SILOptMode::None) { StringRef CustomPipelinePath = Invocation.getSILOptions().ExternalPassPipelineFilename; if (!CustomPipelinePath.empty()) { runSILOptimizationPassesWithFileSpecification(*SM, CustomPipelinePath); } else { runSILOptimizationPasses(*SM); } } else { runSILPassesForOnone(*SM); } } if (observer) { observer->performedSILOptimization(*SM); } { SharedTimer timer("SIL verification (post-optimization)"); SM->verify(); } // Gather instruction counts if we are asked to do so. if (SM->getOptions().PrintInstCounts) { performSILInstCount(&*SM); } // Get the main source file's private discriminator and attach it to // the compile unit's flags. if (PrimarySourceFile) { Identifier PD = PrimarySourceFile->getPrivateDiscriminator(); if (!PD.empty()) IRGenOpts.DWARFDebugFlags += (" -private-discriminator "+PD.str()).str(); } if (!opts.ObjCHeaderOutputPath.empty()) { (void)printAsObjC(opts.ObjCHeaderOutputPath, Instance->getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic); } if (Action == FrontendOptions::EmitSIB) { auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance->getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(DC, serializationOpts, SM.get()); } return Context.hadError(); } if (!opts.ModuleOutputPath.empty() || !opts.ModuleDocOutputPath.empty()) { auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance->getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str(); serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str(); serializationOpts.SerializeAllSIL = opts.SILSerializeAll; if (opts.SerializeBridgingHeader) serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath; serializationOpts.ModuleLinkName = opts.ModuleLinkName; serializationOpts.ExtraClangOptions = Invocation.getClangImporterOptions().ExtraArgs; if (!IRGenOpts.ForceLoadSymbolName.empty()) serializationOpts.AutolinkForceLoad = true; // Options contain information about the developer's computer, // so only serialize them if the module isn't going to be shipped to // the public. serializationOpts.SerializeOptionsForDebugging = !moduleIsPublic || opts.AlwaysSerializeDebuggingOptions; serialize(DC, serializationOpts, SM.get()); } if (Action == FrontendOptions::EmitModuleOnly) return Context.hadError(); } assert(Action >= FrontendOptions::EmitSIL && "All actions not requiring SILPasses must have been handled!"); // We've been told to write canonical SIL, so write it now. if (Action == FrontendOptions::EmitSIL) { return writeSIL(*SM, Instance->getMainModule(), opts.EmitVerboseSIL, opts.getSingleOutputFilename(), opts.EmitSortedSIL); } assert(Action >= FrontendOptions::Immediate && "All actions not requiring IRGen must have been handled!"); assert(Action != FrontendOptions::REPL && "REPL mode must be handled immediately after Instance->performSema()"); // Check if we had any errors; if we did, don't proceed to IRGen. if (Context.hadError()) return true; // Cleanup instructions/builtin calls not suitable for IRGen. performSILCleanup(SM.get()); // TODO: remove once the frontend understands what action it should perform IRGenOpts.OutputKind = getOutputKind(Action); if (Action == FrontendOptions::Immediate) { assert(!PrimarySourceFile && "-i doesn't work in -primary-file mode"); IRGenOpts.UseJIT = true; IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal; const ProcessCmdLine &CmdLine = ProcessCmdLine(opts.ImmediateArgv.begin(), opts.ImmediateArgv.end()); Instance->setSILModule(std::move(SM)); if (observer) { observer->aboutToRunImmediately(*Instance); } ReturnValue = RunImmediately(*Instance, CmdLine, IRGenOpts, Invocation.getSILOptions()); return Context.hadError(); } // FIXME: We shouldn't need to use the global context here, but // something is persisting across calls to performIRGeneration. auto &LLVMContext = getGlobalLLVMContext(); std::unique_ptr<llvm::Module> IRModule; llvm::GlobalVariable *HashGlobal; if (PrimarySourceFile) { IRModule = performIRGeneration(IRGenOpts, *PrimarySourceFile, std::move(SM), opts.getSingleOutputFilename(), LLVMContext, 0, &HashGlobal); } else { IRModule = performIRGeneration(IRGenOpts, Instance->getMainModule(), std::move(SM), opts.getSingleOutputFilename(), LLVMContext, &HashGlobal); } // Just because we had an AST error it doesn't mean we can't performLLVM. bool HadError = Instance->getASTContext().hadError(); // If the AST Context has no errors but no IRModule is available, // parallelIRGen happened correctly, since parallel IRGen produces multiple // modules. if (!IRModule) { return HadError; } std::unique_ptr<llvm::TargetMachine> TargetMachine = createTargetMachine(IRGenOpts, Context); version::Version EffectiveLanguageVersion = Context.LangOpts.EffectiveLanguageVersion; DiagnosticEngine &Diags = Context.Diags; const DiagnosticOptions &DiagOpts = Invocation.getDiagnosticOptions(); // Delete the compiler instance now that we have an IRModule. if (DiagOpts.VerifyMode == DiagnosticOptions::NoVerify) { SM.reset(); Instance.reset(); } // Now that we have a single IR Module, hand it over to performLLVM. return performLLVM(IRGenOpts, &Diags, nullptr, HashGlobal, IRModule.get(), TargetMachine.get(), EffectiveLanguageVersion, opts.getSingleOutputFilename()) || HadError; }