blob: a0456856d8e2f66c20f09ebd3cf6d93c22a10ce5 [file] [log] [blame]
//===--- ASTGen.cpp -------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Parse/ASTGen.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/SourceManager.h"
#include "DebuggerContextChange.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
#include "swift/Parse/Parser.h"
#include "swift/Parse/Scope.h"
using namespace swift;
using namespace swift::syntax;
SourceLoc ASTGen::generate(const TokenSyntax &Tok, const SourceLoc Loc) {
return advanceLocBegin(Loc, Tok);
}
SourceLoc ASTGen::generateIdentifierDeclName(const syntax::TokenSyntax &Tok,
const SourceLoc Loc,
Identifier &Id) {
StringRef text;
if (Tok.getText() == "Any")
// Special handle 'Any' because we don't want to accidantaly declare 'Any'
// type in any way.
text = "#Any";
else
text = Tok.getIdentifierText();
Id = Context.getIdentifier(text);
return advanceLocBegin(Loc, Tok);
}
Decl *ASTGen::generate(const DeclSyntax &D, const SourceLoc Loc) {
Decl *DeclAST = nullptr;
if (auto associatedTypeDecl = D.getAs<AssociatedtypeDeclSyntax>()) {
DeclAST = generate(*associatedTypeDecl, Loc);
} else if (auto typealiasDecl = D.getAs<TypealiasDeclSyntax>()) {
DeclAST = generate(*typealiasDecl, Loc);
} else {
llvm_unreachable("unsupported decl kind");
}
return DeclAST;
}
DeclAttributes
ASTGen::generateDeclAttributes(const Syntax &D, SourceLoc Loc,
bool includeComments) {
// Find the AST attribute-list from the lookup table.
if (auto firstTok = D.getFirstToken()) {
auto declLoc = advanceLocBegin(Loc, *firstTok);
if (hasDeclAttributes(declLoc))
return getDeclAttributes(declLoc);
}
return DeclAttributes();
}
MutableArrayRef<TypeLoc>
ASTGen::generate(const TypeInheritanceClauseSyntax &clause, SourceLoc Loc,
bool allowClassRequirement) {
SmallVector<TypeLoc, 2> inherited;
bool hasClass = false;
for (const auto elem : clause.getInheritedTypeCollection()) {
const auto &tySyntax = elem.getTypeName();
if (tySyntax.is<ClassRestrictionTypeSyntax>()) {
// Accept 'class' only if it's allowed and it's the first one.
if (!allowClassRequirement || hasClass)
continue;
hasClass = true;
}
if (auto ty = generate(tySyntax, Loc))
inherited.emplace_back(ty);
}
return Context.AllocateCopy(inherited);
}
TypeDecl *ASTGen::generate(const AssociatedtypeDeclSyntax &D,
const SourceLoc Loc) {
if (!isa<ProtocolDecl>(P.CurDeclContext)) {
// This is already diagnosed in Parser.
return nullptr;
}
auto idToken = D.getIdentifier();
if (idToken.isMissing())
return nullptr;
auto keywordLoc = advanceLocBegin(Loc, D.getAssociatedtypeKeyword());
Identifier name;
SourceLoc nameLoc = generateIdentifierDeclName(idToken, Loc, name);
DeclAttributes attrs = generateDeclAttributes(D, Loc, true);
DebuggerContextChange DCC(P, name, DeclKind::AssociatedType);
ArrayRef<TypeLoc> inherited;
if (const auto inheritanceClause = D.getInheritanceClause())
inherited =
generate(*inheritanceClause, Loc, /*allowClassRequirement=*/true);
TypeRepr *defaultTy = nullptr;
if (const auto init = D.getInitializer())
defaultTy = generate(init->getValue(), Loc);
TrailingWhereClause *trailingWhere = nullptr;
if (auto whereClause = D.getGenericWhereClause())
trailingWhere = generate(*whereClause, Loc);
auto assocType = new (Context)
AssociatedTypeDecl(P.CurDeclContext, keywordLoc, name, nameLoc, defaultTy,
trailingWhere);
assocType->getAttrs() = attrs;
if (!inherited.empty())
assocType->setInherited(Context.AllocateCopy(inherited));
addToScope(assocType);
return assocType;
}
TypeDecl *ASTGen::generate(const TypealiasDeclSyntax &D, const SourceLoc Loc) {
auto idToken = D.getIdentifier();
if (idToken.isMissing())
return nullptr;
auto keywordLoc = advanceLocBegin(Loc, D.getTypealiasKeyword());
Identifier name;
SourceLoc nameLoc = generateIdentifierDeclName(idToken, Loc, name);
auto attrs = generateDeclAttributes(D, Loc, true);
SourceLoc equalLoc;
DebuggerContextChange DCC(P, name, DeclKind::TypeAlias);
Optional<Scope> GenericScope;
GenericParamList *genericParams = nullptr;
GenericScope.emplace(&P, ScopeKind::Generics);
if (auto clause = D.getGenericParameterClause())
genericParams = generate(*clause, Loc);
auto *TAD = new (Context) TypeAliasDecl(keywordLoc, equalLoc, name, nameLoc,
genericParams, P.CurDeclContext);
P.setLocalDiscriminator(TAD);
TAD->getAttrs() = attrs;
TypeRepr *underlyingType = nullptr;
SourceLoc typeEndLoc;
if (auto init = D.getInitializer()) {
Parser::ContextChange CC(P, TAD);
equalLoc = generate(init->getEqual(), Loc);
underlyingType = generate(init->getValue(), Loc);
if (auto lastToken = init->getLastToken())
typeEndLoc = generate(*lastToken, Loc);
}
TAD->setUnderlyingTypeRepr(underlyingType);
SourceLoc whereLoc;
if (auto clause = D.getGenericWhereClause()) {
whereLoc = advanceLocBegin(Loc, clause->getWhereKeyword());
Parser::ContextChange CC(P, TAD);
generateFreeStandingGenericWhereClause(*clause, Loc, genericParams);
}
P.diagnoseWhereClauseInGenericParamList(genericParams, whereLoc);
if (equalLoc.isInvalid())
return nullptr;
GenericScope.reset();
addToScope(TAD);
return DCC.fixupParserResult(TAD).getPtrOrNull();
}
void ASTGen::generateFreeStandingGenericWhereClause(
const syntax::GenericWhereClauseSyntax &syntax, const SourceLoc Loc,
GenericParamList *genericParams) {
SourceLoc whereLoc = generate(syntax.getWhereKeyword(), Loc);
if (!genericParams) {
P.diagnose(whereLoc, diag::where_without_generic_params,
unsigned(Parser::WhereClauseKind::Declaration));
return;
}
// Push the generic parameters back into a local scope so that references
// will find them.
Scope S(&P, ScopeKind::Generics);
for (auto pd : genericParams->getParams())
addToScope(pd);
SmallVector<RequirementRepr, 4> requirements;
requirements.reserve(syntax.getRequirementList().size());
for (auto elem : syntax.getRequirementList()) {
if (auto req = generate(elem, Loc))
requirements.push_back(*req);
}
if (requirements.empty())
return;
genericParams->addTrailingWhereClause(Context, whereLoc, requirements);
}
TrailingWhereClause *ASTGen::generate(const GenericWhereClauseSyntax &syntax,
const SourceLoc Loc) {
SourceLoc whereLoc = advanceLocBegin(Loc, syntax.getWhereKeyword());
SmallVector<RequirementRepr, 4> requirements;
requirements.reserve(syntax.getRequirementList().size());
for (auto elem : syntax.getRequirementList()) {
if (auto req = generate(elem, Loc))
requirements.push_back(*req);
}
if (requirements.empty())
return nullptr;
return TrailingWhereClause::create(Context, whereLoc, requirements);
}
Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) {
Expr *result = nullptr;
if (auto identifierExpr = E.getAs<IdentifierExprSyntax>())
result = generate(*identifierExpr, Loc);
else if (auto specializeExpr = E.getAs<SpecializeExprSyntax>())
result = generate(*specializeExpr, Loc);
else if (auto editorPlaceHolderExpr = E.getAs<EditorPlaceholderExprSyntax>())
result = generate(*editorPlaceHolderExpr, Loc);
else if (auto integerLiteralExpr = E.getAs<IntegerLiteralExprSyntax>())
result = generate(*integerLiteralExpr, Loc);
else if (auto floatLiteralExpr = E.getAs<FloatLiteralExprSyntax>())
result = generate(*floatLiteralExpr, Loc);
else if (auto nilLiteral = E.getAs<NilLiteralExprSyntax>())
result = generate(*nilLiteral, Loc);
else if (auto boolLiteral = E.getAs<BooleanLiteralExprSyntax>())
result = generate(*boolLiteral, Loc);
else if (auto poundFileExpr = E.getAs<PoundFileExprSyntax>())
result = generate(*poundFileExpr, Loc);
else if (auto poundLineExpr = E.getAs<PoundLineExprSyntax>())
result = generate(*poundLineExpr, Loc);
else if (auto poundColumnExpr = E.getAs<PoundColumnExprSyntax>())
result = generate(*poundColumnExpr, Loc);
else if (auto poundFunctionExpr = E.getAs<PoundFunctionExprSyntax>())
result = generate(*poundFunctionExpr, Loc);
else if (auto poundDsohandleExpr = E.getAs<PoundDsohandleExprSyntax>())
result = generate(*poundDsohandleExpr, Loc);
else
llvm_unreachable("unsupported expression");
return result;
}
std::pair<DeclName, DeclNameLoc> ASTGen::generateUnqualifiedDeclName(
const TokenSyntax &idTok, const Optional<DeclNameArgumentsSyntax> &args,
const SourceLoc Loc) {
SourceLoc baseNameLoc = advanceLocBegin(Loc, idTok);
DeclBaseName baseName;
if (idTok.getTokenKind() == tok::kw_init)
baseName = DeclBaseName::createConstructor();
else if (idTok.getTokenKind() == tok::kw_deinit)
baseName = DeclBaseName::createDestructor();
else if (idTok.getTokenKind() == tok::kw_subscript)
baseName = DeclBaseName::createSubscript();
else
baseName = Context.getIdentifier(idTok.getIdentifierText());
if (!args)
return {DeclName(baseName), DeclNameLoc(baseNameLoc)};
// FIXME: Remove this block and use 'Loc'.
// This is needed for the case 'idTok' and 'args' are not in the same tree.
// i.e. Call from parseUnqualifiedDeclName().
SourceLoc argsLeadingLoc = Loc;
if (!args->getParent()) {
argsLeadingLoc = Loc.getAdvancedLoc(idTok.getTextLength());
} else {
assert(idTok.getData().getParent() == args->getData().getParent() &&
idTok.getIndexInParent() + 1 == args->getIndexInParent() &&
"'idTok' must be immediately followed by 'args'");
}
SmallVector<Identifier, 2> argumentLabels;
SmallVector<SourceLoc, 2> argumentLabelLocs;
for (auto arg : args->getArguments()) {
Identifier label;
if (!arg.getName().isMissing() &&
arg.getName().getTokenKind() != tok::kw__) {
label = Context.getIdentifier(arg.getName().getIdentifierText());
}
argumentLabels.push_back(label);
argumentLabelLocs.push_back(advanceLocBegin(argsLeadingLoc,
*arg.getFirstToken()));
}
SourceLoc lParenLoc = advanceLocBegin(argsLeadingLoc, args->getLeftParen());
SourceLoc rParenLoc = advanceLocBegin(argsLeadingLoc, args->getRightParen());
DeclName name(Context, baseName, argumentLabels);
DeclNameLoc nameLoc;
if (argumentLabelLocs.empty())
nameLoc = DeclNameLoc(baseNameLoc);
else
nameLoc = DeclNameLoc(Context, baseNameLoc, lParenLoc, argumentLabelLocs,
rParenLoc);
return {name, nameLoc};
}
Expr *ASTGen::generate(const IdentifierExprSyntax &E, const SourceLoc Loc) {
auto idTok = E.getIdentifier();
DeclName name;
DeclNameLoc nameLoc;
std::tie(name, nameLoc) = generateUnqualifiedDeclName(
E.getIdentifier(), E.getDeclNameArguments(), Loc);
ValueDecl *D = nullptr;
if (!P.InPoundIfEnvironment) {
D = lookupInScope(name);
// FIXME: We want this to work: "var x = { x() }", but for now it's better
// to disallow it than to crash.
if (D) {
for (auto activeVar : P.DisabledVars) {
if (activeVar != D)
continue;
P.diagnose(nameLoc.getBaseNameLoc(), P.DisabledVarReason);
return new (Context) ErrorExpr(nameLoc.getSourceRange());
}
} else {
for (auto activeVar : P.DisabledVars) {
if (activeVar->getFullName() != name)
continue;
P.diagnose(nameLoc.getBaseNameLoc(), P.DisabledVarReason);
return new (Context) ErrorExpr(nameLoc.getSourceRange());
}
}
}
if (!D) {
return new (Context)
UnresolvedDeclRefExpr(name, DeclRefKind::Ordinary, nameLoc);
}
if (auto TD = dyn_cast<TypeDecl>(D)) {
// When parsing default argument expressions for generic functions,
// we haven't built a FuncDecl or re-parented the GenericTypeParamDecls
// to the FuncDecl yet. Other than that, we should only ever find
// global or local declarations here.
assert(!TD->getDeclContext()->isTypeContext() ||
isa<GenericTypeParamDecl>(TD));
return TypeExpr::createForDecl(nameLoc.getBaseNameLoc(), TD,
/*DeclContext=*/nullptr,
/*inplicit=*/false);
}
return new (Context) DeclRefExpr(D, nameLoc, /*implicit=*/false);
}
Expr *ASTGen::generate(const EditorPlaceholderExprSyntax &E, const SourceLoc Loc) {
assert(!E.getIdentifier().isMissing());
auto text = E.getIdentifier().getText();
auto tokLoc = advanceLocBegin(Loc, E.getIdentifier());
return P.parseExprEditorPlaceholder(tokLoc, text);
}
Expr *ASTGen::generate(const SpecializeExprSyntax &E, const SourceLoc Loc) {
auto base = generate(E.getExpression(), Loc);
SourceLoc lAngleLoc, rAngleLoc;
SmallVector<TypeRepr *, 4> argTyRs;
generate(E.getGenericArgumentClause(), Loc, lAngleLoc, rAngleLoc, argTyRs);
if (argTyRs.empty())
return base;
SmallVector<TypeLoc, 4> args;
args.assign(argTyRs.begin(), argTyRs.end());
return UnresolvedSpecializeExpr::create(Context, base, lAngleLoc, args,
rAngleLoc);
}
Expr *ASTGen::generate(const IntegerLiteralExprSyntax &Expr,
const SourceLoc Loc) {
auto Digits = Expr.getDigits();
auto Text = copyAndStripUnderscores(Digits.getText());
auto DigitsLoc = advanceLocBegin(Loc, Digits);
return new (Context) IntegerLiteralExpr(Text, DigitsLoc);
}
Expr *ASTGen::generate(const FloatLiteralExprSyntax &Expr,
const SourceLoc Loc) {
auto Digits = Expr.getFloatingDigits();
auto Text = copyAndStripUnderscores(Digits.getText());
auto DigitsLoc = advanceLocBegin(Loc, Digits);
return new (Context) FloatLiteralExpr(Text, DigitsLoc);
}
Expr *ASTGen::generate(const NilLiteralExprSyntax &Expr, const SourceLoc Loc) {
auto Nil = Expr.getNilKeyword();
auto NilLoc = advanceLocBegin(Loc, Nil);
return new (Context) NilLiteralExpr(NilLoc);
}
Expr *ASTGen::generate(const BooleanLiteralExprSyntax &Expr,
const SourceLoc Loc) {
auto Boolean = Expr.getBooleanLiteral();
auto Value = Boolean.getTokenKind() == tok::kw_true;
auto BooleanLoc = advanceLocBegin(Loc, Boolean);
return new (Context) BooleanLiteralExpr(Value, BooleanLoc);
}
Expr *ASTGen::generate(const PoundFileExprSyntax &Expr, const SourceLoc Loc) {
return generateMagicIdentifierLiteralExpression(Expr.getPoundFile(), Loc);
}
Expr *ASTGen::generate(const PoundLineExprSyntax &Expr, const SourceLoc Loc) {
return generateMagicIdentifierLiteralExpression(Expr.getPoundLine(), Loc);
}
Expr *ASTGen::generate(const PoundColumnExprSyntax &Expr, const SourceLoc Loc) {
return generateMagicIdentifierLiteralExpression(Expr.getPoundColumn(), Loc);
}
Expr *ASTGen::generate(const PoundFunctionExprSyntax &Expr,
const SourceLoc Loc) {
return generateMagicIdentifierLiteralExpression(Expr.getPoundFunction(), Loc);
}
Expr *ASTGen::generate(const PoundDsohandleExprSyntax &Expr,
const SourceLoc Loc) {
return generateMagicIdentifierLiteralExpression(Expr.getPoundDsohandle(),
Loc);
}
Expr *ASTGen::generate(const UnknownExprSyntax &Expr, const SourceLoc Loc) {
if (Expr.getNumChildren() == 1 && Expr.getChild(0)->isToken()) {
Syntax Token = *Expr.getChild(0);
tok Kind = Token.getRaw()->getTokenKind();
switch (Kind) {
case tok::kw___FILE__:
case tok::kw___LINE__:
case tok::kw___COLUMN__:
case tok::kw___FUNCTION__:
case tok::kw___DSO_HANDLE__: {
auto MagicKind = getMagicIdentifierLiteralKind(Kind);
auto KindLoc = advanceLocBegin(Loc, Token);
return new (Context) MagicIdentifierLiteralExpr(MagicKind, KindLoc);
}
default:
return nullptr;
}
}
return nullptr;
}
TypeRepr *ASTGen::generate(const TypeSyntax &Type, const SourceLoc Loc,
bool IsSILFuncDecl) {
TypeRepr *TypeAST = nullptr;
if (auto SimpleIdentifier = Type.getAs<SimpleTypeIdentifierSyntax>())
TypeAST = generate(*SimpleIdentifier, Loc);
else if (auto MemberIdentifier = Type.getAs<MemberTypeIdentifierSyntax>())
TypeAST = generate(*MemberIdentifier, Loc);
else if (auto Composition = Type.getAs<CompositionTypeSyntax>())
TypeAST = generate(*Composition, Loc);
else if (auto Function = Type.getAs<FunctionTypeSyntax>())
TypeAST = generate(*Function, Loc);
else if (auto Metatype = Type.getAs<MetatypeTypeSyntax>())
TypeAST = generate(*Metatype, Loc);
else if (auto Array = Type.getAs<ArrayTypeSyntax>())
TypeAST = generate(*Array, Loc);
else if (auto Dictionary = Type.getAs<DictionaryTypeSyntax>())
TypeAST = generate(*Dictionary, Loc);
else if (auto Tuple = Type.getAs<TupleTypeSyntax>())
TypeAST = generate(*Tuple, Loc);
else if (auto Some = Type.getAs<SomeTypeSyntax>())
TypeAST = generate(*Some, Loc);
else if (auto Optional = Type.getAs<OptionalTypeSyntax>())
TypeAST = generate(*Optional, Loc);
else if (auto Unwrapped = Type.getAs<ImplicitlyUnwrappedOptionalTypeSyntax>())
TypeAST = generate(*Unwrapped, Loc);
else if (auto Attributed = Type.getAs<AttributedTypeSyntax>())
TypeAST = generate(*Attributed, Loc);
else if (auto ClassRestriction = Type.getAs<ClassRestrictionTypeSyntax>())
TypeAST = generate(*ClassRestriction, Loc);
else if (auto SILBoxType = Type.getAs<SILBoxTypeSyntax>())
TypeAST = generate(*SILBoxType, Loc, IsSILFuncDecl);
else if (auto SILFunctionType = Type.getAs<SILFunctionTypeSyntax>())
TypeAST = generate(*SILFunctionType, Loc, IsSILFuncDecl);
else if (auto CompletionTy = Type.getAs<CodeCompletionTypeSyntax>())
TypeAST = generate(*CompletionTy, Loc);
else if (auto Unknown = Type.getAs<UnknownTypeSyntax>())
TypeAST = generate(*Unknown, Loc);
return cacheType(Type, TypeAST);
}
TypeRepr *ASTGen::generate(const FunctionTypeSyntax &Type,
const SourceLoc Loc) {
TupleTypeRepr *ArgumentTypes = nullptr;
SourceLoc VoidLoc;
if (Type.getLeftParen().isMissing() && Type.getArguments().size() == 1) {
if (auto ident = Type.getArguments()[0]
.getType()
.getAs<SimpleTypeIdentifierSyntax>()) {
if (!ident->getGenericArgumentClause().hasValue() &&
ident->getName().getText() == "Void")
VoidLoc = advanceLocBegin(Loc, ident->getName());
}
}
if (VoidLoc.isValid())
ArgumentTypes = TupleTypeRepr::createEmpty(Context, VoidLoc);
else {
ArgumentTypes = generateTuple(Type.getLeftParen(), Type.getArguments(),
Type.getRightParen(), Loc,
/*IsFunction=*/true);
}
if (!ArgumentTypes)
return nullptr;
auto ThrowsLoc = Type.getThrowsOrRethrowsKeyword()
? generate(*Type.getThrowsOrRethrowsKeyword(), Loc)
: SourceLoc();
auto ArrowLoc = generate(Type.getArrow(), Loc);
auto ReturnType = generate(Type.getReturnType(), Loc);
if (!ReturnType)
return nullptr;
return new (Context)
FunctionTypeRepr(nullptr, ArgumentTypes, ThrowsLoc, ArrowLoc, ReturnType);
}
TupleTypeRepr *ASTGen::generateTuple(const TokenSyntax &LParen,
const TupleTypeElementListSyntax &Elements,
const TokenSyntax &RParen,
const SourceLoc Loc, bool IsFunction) {
auto LPLoc = generate(LParen, Loc);
auto RPLoc = generate(RParen, Loc);
SmallVector<TupleTypeReprElement, 4> TupleElements;
SourceLoc EllipsisLoc;
unsigned EllipsisIdx = Elements.size();
for (unsigned i = 0; i < Elements.getNumChildren(); i++) {
auto Element = Elements.getChild(i)->castTo<TupleTypeElementSyntax>();
TupleTypeReprElement ElementAST;
if (auto Name = Element.getName()) {
ElementAST.NameLoc = generate(*Name, Loc);
ElementAST.Name = Name->getText() == "_"
? Identifier()
: Context.getIdentifier(Name->getIdentifierText());
}
if (auto Colon = Element.getColon())
ElementAST.ColonLoc = generate(*Colon, Loc);
if (auto SecondName = Element.getSecondName()) {
ElementAST.SecondNameLoc = generate(*SecondName, Loc);
ElementAST.SecondName =
SecondName->getText() == "_"
? Identifier()
: Context.getIdentifier(SecondName->getIdentifierText());
if (IsFunction) {
// Form the named parameter type representation.
ElementAST.UnderscoreLoc = ElementAST.NameLoc;
ElementAST.Name = ElementAST.SecondName;
ElementAST.NameLoc = ElementAST.SecondNameLoc;
}
}
ElementAST.Type = generate(Element.getType(), Loc);
if (auto InOut = Element.getInOut()) {
// don't apply multiple inout specifiers to a type: that's invalid and was
// already reported in the parser, handle gracefully
if (!isa<InOutTypeRepr>(ElementAST.Type)) {
auto InOutLoc = generate(*InOut, Loc);
ElementAST.Type =
new (Context) InOutTypeRepr(ElementAST.Type, InOutLoc);
}
}
if (auto Comma = Element.getTrailingComma())
ElementAST.TrailingCommaLoc = generate(*Comma, Loc);
if (auto Ellipsis = Element.getEllipsis()) {
EllipsisLoc = generate(*Ellipsis, Loc);
if (EllipsisIdx == Elements.size())
EllipsisIdx = i;
}
TupleElements.push_back(ElementAST);
}
return TupleTypeRepr::create(Context, TupleElements, {LPLoc, RPLoc},
EllipsisLoc, EllipsisIdx);
}
TypeAttributes ASTGen::generateTypeAttributes(const AttributeListSyntax &syntax,
const SourceLoc Loc) {
TypeAttributes attrs;
for (auto elem : syntax) {
auto attrSyntax = elem.castTo<AttributeSyntax>();
if (attrSyntax.getAttributeName().isMissing())
continue;
auto attrName = attrSyntax.getAttributeName().getText();
auto atLoc = advanceLocBegin(Loc, attrSyntax.getAtSignToken());
if (attrs.AtLoc.isInvalid())
attrs.AtLoc = atLoc;
auto attr = TypeAttributes::getAttrKindFromString(attrName);
if (attr == TAK_Count)
continue;
if (attrs.has(attr)) {
P.diagnose(atLoc, diag::duplicate_attribute, /*isModifier=*/false);
continue;
}
auto arg = attrSyntax.getArgument();
if (attr == TAK_sil_weak || attr == TAK_sil_unowned) {
if (attrs.hasOwnership()) {
P.diagnose(atLoc, diag::duplicate_attribute, /*isModifier*/false);
}
} else if (attr == TAK_convention) {
// @convention(block)
// @convention(witness_method: ProtocolName)
if (!arg)
continue;
if (auto conventionNameTok = arg->getAs<TokenSyntax>()) {
assert(conventionNameTok->getTokenKind() == tok::identifier);
auto convention =
Context.getIdentifier(conventionNameTok->getIdentifierText());
attrs.convention = convention.str();
} else if (auto witness =
arg->getAs<NamedAttributeStringArgumentSyntax>()) {
assert(witness->getNameTok().getIdentifierText() == "witness_method");
if (witness->getStringOrDeclname().isMissing())
continue;
auto protocolName =
witness->getStringOrDeclname().castTo<DeclNameSyntax>();
auto protocol = Context.getIdentifier(
protocolName.getDeclBaseName().getIdentifierText());
attrs.convention = "witness_method";
attrs.conventionWitnessMethodProtocol = protocol.str();
} else {
continue;
}
} else if (attr == TAK_opened) {
// @opened("01234567-89ab-cdef-0123-111111111111")
if (!arg)
continue;
assert(arg->castTo<TokenSyntax>().getTokenKind() ==
tok::string_literal);
auto tokText = arg->castTo<TokenSyntax>().getText();
auto literalText = tokText.slice(1, tokText.size() - 1);
attrs.OpenedID = UUID::fromString(literalText.str().c_str());
} else if (attr == TAK__opaqueReturnTypeOf) {
// @_opaqueReturnTypeOf("$sMangledName", 0)
if (!arg)
continue;
auto opaqueArg =
arg->castTo<OpaqueReturnTypeOfAttributeArgumentsSyntax>();
auto manglingTok = opaqueArg.getMangledName();
auto indexTok = opaqueArg.getIndex();
if (manglingTok.isMissing() || indexTok.isMissing())
continue;
auto tokText = manglingTok.getText();
auto mangling =
Context.getIdentifier(tokText.slice(1, tokText.size() - 1));
unsigned index;
if (indexTok.getText().getAsInteger(10, index))
continue;
attrs.setOpaqueReturnTypeOf(mangling.str(), index);
// SWIFT_ENABLE_TENSORFLOW
} else if (attr == TAK_differentiable) {
if (arg) {
auto argSyntax = arg->getAs<TokenSyntax>();
attrs.linear = argSyntax->getTokenKind() == tok::identifier &&
argSyntax->getIdentifierText() == "linear";
} else {
attrs.linear = false;
}
}
attrs.setAttr(attr, atLoc);
}
return attrs;
}
TypeRepr *ASTGen::generate(const AttributedTypeSyntax &Type,
const SourceLoc Loc) {
auto TypeAST = generate(Type.getBaseType(), Loc);
if (!TypeAST)
return nullptr;
if (auto Attributes = Type.getAttributes()) {
TypeAttributes attrs = generateTypeAttributes(*Attributes, Loc);
if (!attrs.empty())
TypeAST = new (Context) AttributedTypeRepr(attrs, TypeAST);
}
if (auto Specifier = Type.getSpecifier()) {
auto SpecifierLoc = generate(*Specifier, Loc);
auto SpecifierText = Specifier->getText();
// don't apply multiple specifiers to a type: that's invalid and was already
// reported in the parser, handle gracefully
if (!isa<SpecifierTypeRepr>(TypeAST)) {
if (SpecifierText == "inout")
TypeAST = new (Context) InOutTypeRepr(TypeAST, SpecifierLoc);
else if (SpecifierText == "__owned")
TypeAST = new (Context) OwnedTypeRepr(TypeAST, SpecifierLoc);
else if (SpecifierText == "__shared")
TypeAST = new (Context) SharedTypeRepr(TypeAST, SpecifierLoc);
}
}
return TypeAST;
}
TypeRepr *ASTGen::generate(const TupleTypeSyntax &Type, const SourceLoc Loc) {
return generateTuple(Type.getLeftParen(), Type.getElements(),
Type.getRightParen(), Loc);
}
TypeRepr *ASTGen::generate(const SomeTypeSyntax &Type, const SourceLoc Loc) {
auto Some = Type.getSomeSpecifier();
auto SomeLoc = generate(Some, Loc);
auto BaseType = generate(Type.getBaseType(), Loc);
return new (Context) OpaqueReturnTypeRepr(SomeLoc, BaseType);
}
TypeRepr *ASTGen::generate(const CompositionTypeSyntax &Type,
const SourceLoc Loc) {
auto Elements = Type.getElements();
auto FirstElem = Elements[0];
auto LastElem = Elements[Elements.size() - 1];
SmallVector<TypeRepr *, 4> ElemTypes;
for (unsigned i = 0; i < Elements.size(); i++) {
auto ElemType = Elements[i].getType();
TypeRepr *ElemTypeR = nullptr;
if (auto Some = ElemType.getAs<SomeTypeSyntax>()) {
// the invalid `some` after an ampersand was already diagnosed by the
// parser, handle it gracefully
ElemTypeR = generate(Some->getBaseType(), Loc);
} else {
ElemTypeR = generate(ElemType, Loc);
}
if (ElemTypeR) {
if (auto Comp = dyn_cast<CompositionTypeRepr>(ElemTypeR)) {
// Accept protocol<P1, P2> & P3; explode it.
auto TyRs = Comp->getTypes();
ElemTypes.append(TyRs.begin(), TyRs.end());
} else {
ElemTypes.push_back(ElemTypeR);
}
}
}
auto FirstTypeLoc = advanceLocBegin(Loc, FirstElem);
auto FirstAmpersandLoc = advanceLocBegin(Loc, *FirstElem.getAmpersand());
auto LastTypeLoc = advanceLocBegin(Loc, *LastElem.getLastToken());
return CompositionTypeRepr::create(Context, ElemTypes, FirstTypeLoc,
{FirstAmpersandLoc, LastTypeLoc});
}
void ASTGen::gatherTypeIdentifierComponents(
const TypeSyntax &Component, const SourceLoc Loc,
SmallVectorImpl<ComponentIdentTypeRepr *> &Components) {
if (auto SimpleIdentifier = Component.getAs<SimpleTypeIdentifierSyntax>()) {
auto ComponentType = generateIdentifier(*SimpleIdentifier, Loc);
Components.push_back(ComponentType);
return;
}
if (auto MemberIdentifier = Component.getAs<MemberTypeIdentifierSyntax>()) {
auto ComponentType = generateIdentifier(*MemberIdentifier, Loc);
Components.push_back(ComponentType);
gatherTypeIdentifierComponents(MemberIdentifier->getBaseType(), Loc,
Components);
return;
}
llvm_unreachable("unexpected type identifier component");
}
template <typename T>
TypeRepr *ASTGen::generateSimpleOrMemberIdentifier(const T &Type,
const SourceLoc Loc) {
SmallVector<ComponentIdentTypeRepr *, 4> Components;
gatherTypeIdentifierComponents(Type, Loc, Components);
std::reverse(Components.begin(), Components.end());
auto IdentType = IdentTypeRepr::create(Context, Components);
auto FirstComponent = IdentType->getComponentRange().front();
// Lookup element #0 through our current scope chains in case it is some
// thing local (this returns null if nothing is found).
if (auto Entry = lookupInScope(FirstComponent->getIdentifier())) {
if (auto *TD = dyn_cast<TypeDecl>(Entry))
FirstComponent->setValue(TD, nullptr);
}
return IdentType;
}
template <typename T>
ComponentIdentTypeRepr *ASTGen::generateIdentifier(const T &Type,
const SourceLoc Loc) {
auto IdentifierLoc = advanceLocBegin(Loc, Type.getName());
auto Identifier = Context.getIdentifier(Type.getName().getIdentifierText());
if (auto Clause = Type.getGenericArgumentClause()) {
SourceLoc lAngleLoc, rAngleLoc;
SmallVector<TypeRepr *, 4> args;
generate(*Clause, Loc, lAngleLoc, rAngleLoc, args);
if (!args.empty())
return GenericIdentTypeRepr::create(Context, IdentifierLoc, Identifier,
args, {lAngleLoc, rAngleLoc});
}
return new (Context) SimpleIdentTypeRepr(IdentifierLoc, Identifier);
}
TypeRepr *ASTGen::generate(const SimpleTypeIdentifierSyntax &Type,
const SourceLoc Loc) {
if (Type.getName().getTokenKind() == tok::kw_Any) {
auto AnyLoc = advanceLocBegin(Loc, Type.getName());
return CompositionTypeRepr::createEmptyComposition(Context, AnyLoc);
}
return generateSimpleOrMemberIdentifier(Type, Loc);
}
TypeRepr *ASTGen::generate(const MemberTypeIdentifierSyntax &Type,
SourceLoc Loc) {
return generateSimpleOrMemberIdentifier(Type, Loc);
}
TypeRepr *ASTGen::generate(const DictionaryTypeSyntax &Type,
const SourceLoc Loc) {
TypeRepr *ValueType = generate(Type.getValueType(), Loc);
TypeRepr *KeyType = generate(Type.getKeyType(), Loc);
if (!ValueType || !KeyType)
return nullptr;
auto ColonLoc = advanceLocBegin(Loc, Type.getColon());
SourceLoc LBracketLoc, RBracketLoc;
if (Type.getLeftSquareBracket().isPresent())
LBracketLoc = advanceLocBegin(Loc, Type.getLeftSquareBracket());
else
LBracketLoc = advanceLocBegin(Loc, *Type.getFirstToken());
if (Type.getRightSquareBracket().isPresent())
RBracketLoc = advanceLocBegin(Loc, Type.getRightSquareBracket());
else
RBracketLoc = advanceLocBegin(Loc, *Type.getLastToken());
SourceRange Range{LBracketLoc, RBracketLoc};
return new (Context) DictionaryTypeRepr(KeyType, ValueType, ColonLoc, Range);
}
TypeRepr *ASTGen::generate(const ArrayTypeSyntax &Type, SourceLoc Loc) {
TypeRepr *ElementType = generate(Type.getElementType(), Loc);
if (!ElementType)
return nullptr;
SourceLoc LBracketLoc, RBracketLoc;
if (Type.getLeftSquareBracket().isPresent())
LBracketLoc = advanceLocBegin(Loc, Type.getLeftSquareBracket());
else
LBracketLoc = advanceLocBegin(Loc, *Type.getFirstToken());
if (Type.getRightSquareBracket().isPresent())
RBracketLoc = advanceLocBegin(Loc, Type.getRightSquareBracket());
else
RBracketLoc = advanceLocBegin(Loc, *Type.getLastToken());
return new (Context) ArrayTypeRepr(ElementType, {LBracketLoc, RBracketLoc});
}
TypeRepr *ASTGen::generate(const MetatypeTypeSyntax &Type,
const SourceLoc Loc) {
TypeRepr *BaseType = generate(Type.getBaseType(), Loc);
auto TypeOrProtocol = Type.getTypeOrProtocol();
auto TypeOrProtocolLoc = advanceLocBegin(Loc, TypeOrProtocol);
if (TypeOrProtocol.getText() == "Type")
return new (Context) MetatypeTypeRepr(BaseType, TypeOrProtocolLoc);
return new (Context) ProtocolTypeRepr(BaseType, TypeOrProtocolLoc);
}
TypeRepr *ASTGen::generate(const OptionalTypeSyntax &Type,
const SourceLoc Loc) {
TypeRepr *WrappedType = generate(Type.getWrappedType(), Loc);
auto QuestionLoc = advanceLocBegin(Loc, Type.getQuestionMark());
return new (Context) OptionalTypeRepr(WrappedType, QuestionLoc);
}
TypeRepr *ASTGen::generate(const ImplicitlyUnwrappedOptionalTypeSyntax &Type,
const SourceLoc Loc) {
TypeRepr *WrappedType = generate(Type.getWrappedType(), Loc);
auto ExclamationLoc = advanceLocBegin(Loc, Type.getExclamationMark());
return new (Context)
ImplicitlyUnwrappedOptionalTypeRepr(WrappedType, ExclamationLoc);
}
TypeRepr *
ASTGen::generate(const ClassRestrictionTypeSyntax &Type, const SourceLoc Loc) {
auto classLoc = advanceLocBegin(Loc, Type);
return new (Context)
SimpleIdentTypeRepr(classLoc, Context.getIdentifier("AnyObject"));
}
TypeRepr *ASTGen::generate(const SILBoxTypeSyntax &Type, const SourceLoc Loc,
bool IsSILFuncDecl) {
if (Type.getRightBrace().isMissing())
return nullptr;
// If this is part of a sil function decl, generic parameters are visible in
// the function body; otherwise, they are visible when parsing the type.
Optional<Scope> GenericsScope;
if (!IsSILFuncDecl)
GenericsScope.emplace(&P, ScopeKind::Generics);
GenericParamList *generics = nullptr;
if (auto genericParamsSyntax = Type.getGenericParameterClauses())
generics = generate(*genericParamsSyntax, Loc);
SmallVector<SILBoxTypeRepr::Field, 4> Fields;
for (auto field : Type.getFields()) {
auto specifier = field.getSpecifier();
if (specifier.isMissing())
return nullptr;
bool Mutable;
if (specifier.getTokenKind() == tok::kw_let)
Mutable = false;
else if (specifier.getTokenKind() == tok::kw_var)
Mutable = true;
else
return nullptr;
SourceLoc VarOrLetLoc = advanceLocBegin(Loc, specifier);;
auto fieldTy = generate(field.getType(), Loc);
if (!fieldTy)
return nullptr;
Fields.emplace_back(VarOrLetLoc, Mutable, fieldTy);
}
GenericsScope.reset();
auto LBraceLoc = advanceLocBegin(Loc, Type.getLeftBrace());
auto RBraceLoc = advanceLocBegin(Loc, Type.getRightBrace());
SourceLoc LAngleLoc, RAngleLoc;
SmallVector<TypeRepr *, 4> Args;
if (auto genericArgs = Type.getGenericArgumentClause()) {
if (genericArgs->getRightAngleBracket().isMissing())
return nullptr;
generate(*genericArgs, Loc, LAngleLoc, RAngleLoc, Args);
}
auto SILType = SILBoxTypeRepr::create(Context, generics, LBraceLoc, Fields,
RBraceLoc, LAngleLoc, Args, RAngleLoc);
return SILType;
}
TypeRepr *ASTGen::generate(const SILFunctionTypeSyntax &Type,
const SourceLoc Loc, bool IsSILFuncDecl) {
// If this is part of a sil function decl, generic parameters are visible in
// the function body; otherwise, they are visible when parsing the type.
Optional<Scope> GenericsScope;
if (!IsSILFuncDecl)
GenericsScope.emplace(&P, ScopeKind::Generics);
GenericParamList *generics = nullptr;
if (auto genericParamsSyntax = Type.getGenericParameterClauses())
generics = generate(*genericParamsSyntax, Loc);
auto tyR = cast<FunctionTypeRepr>(generate(Type.getFunction(), Loc));
return new (Context)
FunctionTypeRepr(generics, tyR->getArgsTypeRepr(), tyR->getThrowsLoc(),
tyR->getArrowLoc(), tyR->getResultTypeRepr());
}
TypeRepr *ASTGen::generate(const CodeCompletionTypeSyntax &Type,
const SourceLoc Loc) {
auto base = Type.getBase();
if (!base) {
if (P.CodeCompletion)
P.CodeCompletion->completeTypeSimpleBeginning();
return nullptr;
}
if (P.CodeCompletion) {
if (auto *parsedTyR = generate(*base, Loc)) {
P.CodeCompletion->setParsedTypeLoc(parsedTyR);
if (Type.getPeriod())
P.CodeCompletion->completeTypeIdentifierWithDot();
else
P.CodeCompletion->completeTypeIdentifierWithoutDot();
}
}
// Return nullptr to typecheck this TypeRepr independently in code completion.
return nullptr;
}
TypeRepr *ASTGen::generate(const UnknownTypeSyntax &Type, const SourceLoc Loc) {
auto ChildrenCount = Type.getNumChildren();
// Recover from old-style protocol composition:
// `protocol` `<` protocols `>`
if (ChildrenCount >= 2) {
auto keyword = Type.getChild(0)->getAs<TokenSyntax>();
if (keyword && keyword->getText() == "protocol") {
auto keywordLoc = advanceLocBegin(Loc, *keyword);
auto LAngle = Type.getChild(1);
auto RAngle = Type.getChild(ChildrenCount - 1);
auto LAngleLoc = advanceLocBegin(Loc, *LAngle);
auto RAngleLoc = advanceLocBegin(Loc, *RAngle);
SmallVector<TypeRepr *, 4> protocols;
for (unsigned i = 2; i < Type.getNumChildren(); i++) {
if (auto elem = Type.getChild(i)->getAs<TypeSyntax>())
if (auto proto = generate(*elem, Loc))
protocols.push_back(proto);
}
return CompositionTypeRepr::create(Context, protocols, keywordLoc,
{LAngleLoc, RAngleLoc});
}
}
// Create ErrorTypeRepr for keywords.
if (ChildrenCount == 1) {
auto Keyword = Type.getChild(0)->getAs<TokenSyntax>();
if (Keyword && isTokenKeyword(Keyword->getTokenKind())) {
auto ErrorLoc = generate(*Keyword, Loc);
return new (Context) ErrorTypeRepr(ErrorLoc);
}
}
// Create empty TupleTypeRepr for types starting with `(`.
if (ChildrenCount >= 1) {
auto LParen = Type.getChild(0)->getAs<TokenSyntax>();
if (LParen && LParen->getTokenKind() == tok::l_paren) {
// generate child 'TypeSyntax' anyway to trigger the side effects e.g.
// code-completion.
for (size_t i = 1; i != ChildrenCount; ++i) {
auto elem = *Type.getChild(i);
if (auto ty = elem.getAs<TypeSyntax>())
(void)generate(*ty, Loc);
}
auto LParenLoc = advanceLocBegin(Loc, *LParen);
auto EndLoc =
advanceLocBegin(Loc, *Type.getChild(Type.getNumChildren() - 1));
return TupleTypeRepr::createEmpty(Context, {LParenLoc, EndLoc});
}
}
// generate child 'TypeSyntax' anyway to trigger the side effects e.g.
// code-completion.
for (size_t i = 0; i != ChildrenCount; ++i) {
auto elem = *Type.getChild(i);
if (auto ty = elem.getAs<TypeSyntax>())
(void)generate(*ty, Loc);
}
// let's hope the main `generate` method can find this node in the type map
return nullptr;
}
void
ASTGen::generate(const GenericArgumentClauseSyntax &clause, const SourceLoc Loc,
SourceLoc &lAngleLoc, SourceLoc &rAngleLoc,
SmallVectorImpl<TypeRepr *> &args) {
lAngleLoc = advanceLocBegin(Loc, clause.getLeftAngleBracket());
rAngleLoc = advanceLocBegin(Loc, clause.getRightAngleBracket());
assert(args.empty());
for (auto Arg : clause.getArguments()) {
auto tyR = generate(Arg.getArgumentType(), Loc);
if (!tyR)
tyR = new (Context) ErrorTypeRepr(advanceLocBegin(Loc, Arg));
args.push_back(tyR);
}
}
StringRef ASTGen::copyAndStripUnderscores(StringRef Orig, ASTContext &Context) {
char *start = static_cast<char *>(Context.Allocate(Orig.size(), 1));
char *p = start;
if (p) {
for (char c : Orig) {
if (c != '_') {
*p++ = c;
}
}
}
return StringRef(start, p - start);
}
GenericParamList *
ASTGen::generate(const GenericParameterClauseListSyntax &clauses,
const SourceLoc Loc) {
GenericParamList *curr = nullptr;
// The first one is the outmost generic parameter list.
for (const auto &clause : clauses) {
auto params = generate(clause, Loc);
if (!params)
continue;
params->setOuterParameters(curr);
curr = params;
}
return curr;
}
GenericParamList *ASTGen::generate(const GenericParameterClauseSyntax &clause,
const SourceLoc Loc) {
SmallVector<GenericTypeParamDecl *, 4> params;
params.reserve(clause.getGenericParameterList().getNumChildren());
for (auto elem : clause.getGenericParameterList()) {
auto nameTok = elem.getName();
if (nameTok.isMissing())
break;
DeclAttributes attrs = generateDeclAttributes(elem, Loc, false);
Identifier name = Context.getIdentifier(elem.getName().getIdentifierText());
SourceLoc nameLoc = advanceLocBegin(Loc, elem.getName());
// We always create generic type parameters with an invalid depth.
// Semantic analysis fills in the depth when it processes the generic
// parameter list.
auto param = new (Context)
GenericTypeParamDecl(P.CurDeclContext, name, nameLoc,
GenericTypeParamDecl::InvalidDepth, params.size());
if (auto inherited = elem.getInheritedType()) {
if (auto ty = generate(*inherited, Loc)) {
SmallVector<TypeLoc, 1> constraints = {ty};
param->setInherited(Context.AllocateCopy(constraints));
}
}
// Attach attributes.
param->getAttrs() = attrs;
// Add this parameter to the scope.
addToScope(param);
params.push_back(param);
}
if (params.empty())
return nullptr;
SourceLoc whereLoc;
SmallVector<RequirementRepr, 4> requirements;
if (auto whereClause = clause.getObsoletedWhereClause()) {
requirements.reserve(whereClause->getRequirementList().size());
for (auto elem : whereClause->getRequirementList()) {
if (auto req = generate(elem, Loc))
requirements.push_back(*req);
}
// There's an invariant that valid 'where' loc means that there's at
// at least one valid requirement.
if (!requirements.empty())
whereLoc = advanceLocBegin(Loc, whereClause->getWhereKeyword());
}
auto lAngleLoc = advanceLocBegin(Loc, clause.getLeftAngleBracket());
auto rAngleLoc = advanceLocBegin(Loc, clause.getRightAngleBracket());
return GenericParamList::create(Context, lAngleLoc, params, whereLoc,
requirements, rAngleLoc);
}
Optional<RequirementRepr>
ASTGen::generate(const syntax::GenericRequirementSyntax &req,
const SourceLoc Loc) {
if (auto sameTypeReq = req.getBody().getAs<SameTypeRequirementSyntax>()) {
auto firstType = generate(sameTypeReq->getLeftTypeIdentifier(), Loc);
auto secondType = generate(sameTypeReq->getRightTypeIdentifier(), Loc);
if (!firstType || !secondType)
return None;
return RequirementRepr::getSameType(
firstType, advanceLocBegin(Loc, sameTypeReq->getEqualityToken()),
secondType);
} else if (auto conformanceReq =
req.getBody().getAs<ConformanceRequirementSyntax>()) {
auto firstType = generate(conformanceReq->getLeftTypeIdentifier(), Loc);
auto secondType = generate(conformanceReq->getRightTypeIdentifier(), Loc);
if (!firstType || !secondType)
return None;
return RequirementRepr::getTypeConstraint(
firstType, advanceLocBegin(Loc, conformanceReq->getColon()),
secondType);
} else if (auto layoutReq = req.getBody().getAs<LayoutRequirementSyntax>()) {
auto firstType = generate(layoutReq->getLeftTypeIdentifier(), Loc);
auto layout = generate(layoutReq->getLayoutConstraint(), Loc);
if (!firstType || layout.isNull())
return None;
auto colonLoc = advanceLocBegin(Loc, layoutReq->getColon());
auto layoutLoc = advanceLocBegin(Loc, layoutReq->getLayoutConstraint());
return RequirementRepr::getLayoutConstraint(
firstType, colonLoc, LayoutConstraintLoc(layout, layoutLoc));
} else {
llvm_unreachable("invalid syntax kind for requirement body");
}
}
static LayoutConstraintKind getLayoutConstraintKind(Identifier &id,
ASTContext &Ctx) {
if (id == Ctx.Id_TrivialLayout)
return LayoutConstraintKind::TrivialOfExactSize;
if (id == Ctx.Id_TrivialAtMostLayout)
return LayoutConstraintKind::TrivialOfAtMostSize;
if (id == Ctx.Id_RefCountedObjectLayout)
return LayoutConstraintKind::RefCountedObject;
if (id == Ctx.Id_NativeRefCountedObjectLayout)
return LayoutConstraintKind::NativeRefCountedObject;
if (id == Ctx.Id_ClassLayout)
return LayoutConstraintKind::Class;
if (id == Ctx.Id_NativeClassLayout)
return LayoutConstraintKind::NativeClass;
return LayoutConstraintKind::UnknownLayout;
}
LayoutConstraint ASTGen::generate(const LayoutConstraintSyntax &constraint,
const SourceLoc Loc) {
auto name = Context.getIdentifier(constraint.getName().getIdentifierText());
auto constraintKind = getLayoutConstraintKind(name, Context);
assert(constraintKind != LayoutConstraintKind::UnknownLayout);
// Non-trivial constraint kinds don't have size/alignment.
// TODO: Diagnose if it's supplied?
if (!LayoutConstraintInfo::isTrivial(constraintKind))
return LayoutConstraint::getLayoutConstraint(constraintKind, Context);
// '_Trivial' without explicit size/alignment.
if (!constraint.getSize())
return LayoutConstraint::getLayoutConstraint(LayoutConstraintKind::Trivial,
Context);
int size = 0;
if (auto sizeSyntax = constraint.getSize())
sizeSyntax->getText().getAsInteger(10, size);
assert(size >= 0);
int alignment = 0;
if (auto alignmentSyntax = constraint.getAlignment())
alignmentSyntax->getText().getAsInteger(10, alignment);
assert(alignment >= 0);
return LayoutConstraint::getLayoutConstraint(constraintKind, size, alignment,
Context);
}
SourceLoc ASTGen::advanceLocBegin(const SourceLoc &Loc, const Syntax &Node) {
return Loc.getAdvancedLoc(Node.getAbsolutePosition().getOffset());
}
StringRef ASTGen::copyAndStripUnderscores(StringRef Orig) {
return copyAndStripUnderscores(Orig, Context);
}
Expr *
ASTGen::generateMagicIdentifierLiteralExpression(const TokenSyntax &PoundToken,
const SourceLoc Loc) {
auto Kind = getMagicIdentifierLiteralKind(PoundToken.getTokenKind());
auto KindLoc = advanceLocBegin(Loc, PoundToken);
return new (Context) MagicIdentifierLiteralExpr(Kind, KindLoc);
}
MagicIdentifierLiteralExpr::Kind
ASTGen::getMagicIdentifierLiteralKind(tok Kind) {
switch (Kind) {
case tok::kw___COLUMN__:
case tok::pound_column:
return MagicIdentifierLiteralExpr::Kind::Column;
case tok::kw___FILE__:
case tok::pound_file:
return MagicIdentifierLiteralExpr::Kind::File;
case tok::kw___FUNCTION__:
case tok::pound_function:
return MagicIdentifierLiteralExpr::Kind::Function;
case tok::kw___LINE__:
case tok::pound_line:
return MagicIdentifierLiteralExpr::Kind::Line;
case tok::kw___DSO_HANDLE__:
case tok::pound_dsohandle:
return MagicIdentifierLiteralExpr::Kind::DSOHandle;
default:
llvm_unreachable("not a magic literal");
}
}
ValueDecl *ASTGen::lookupInScope(DeclName Name) {
return P.lookupInScope(Name);
}
void ASTGen::addToScope(ValueDecl *D, bool diagnoseRedefinitions) {
P.addToScope(D, diagnoseRedefinitions);
}
TypeRepr *ASTGen::cacheType(TypeSyntax Type, TypeRepr *TypeAST) {
TypeCache[Type.getId()] = TypeAST;
return TypeAST;
}
TypeRepr *ASTGen::lookupType(TypeSyntax Type) {
auto Found = TypeCache.find(Type.getId());
return Found != TypeCache.end() ? Found->second : nullptr;
}
void ASTGen::addDeclAttributes(DeclAttributes attrs, SourceLoc Loc) {
ParsedDeclAttrs.insert({Loc, attrs});
}
bool ASTGen::hasDeclAttributes(SourceLoc Loc) const {
return ParsedDeclAttrs.find(Loc) != ParsedDeclAttrs.end();
}
DeclAttributes ASTGen::getDeclAttributes(SourceLoc Loc) const {
return ParsedDeclAttrs.find(Loc)->second;
}