Files
swift-mirror/lib/Parse/ASTGen.cpp
Rintaro Ishizaki d9eba19b74 [SyntaxParse] Fix ASAN issue
rdar://problem/55711699
rdar://problem/55711787
rdar://problem/55711952
2019-09-25 21:27:44 -07:00

792 lines
29 KiB
C++

//===--- 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/Basic/SourceManager.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
#include "swift/Parse/Parser.h"
using namespace swift;
using namespace swift::syntax;
SourceLoc ASTGen::generate(const TokenSyntax &Tok, const SourceLoc Loc) {
return advanceLocBegin(Loc, Tok);
}
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) {
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 CompletionTy = Type.getAs<CodeCompletionTypeSyntax>())
TypeAST = generate(*CompletionTy, Loc);
else if (auto Unknown = Type.getAs<UnknownTypeSyntax>())
TypeAST = generate(*Unknown, Loc);
// todo [gsoc]: handle InheritedTypeSyntax & ClassRestrictionTypeSyntax?
if (!TypeAST && hasType(advanceLocBegin(Loc, Type)))
TypeAST = getType(advanceLocBegin(Loc, Type));
return cacheType(Type, TypeAST);
}
TypeRepr *ASTGen::generate(const FunctionTypeSyntax &Type,
const SourceLoc Loc) {
auto ArgumentTypes = generateTuple(Type.getLeftParen(), Type.getArguments(),
Type.getRightParen(), Loc,
/*IsFunction=*/true);
auto ThrowsLoc = Type.getThrowsOrRethrowsKeyword()
? generate(*Type.getThrowsOrRethrowsKeyword(), Loc)
: SourceLoc();
auto ArrowLoc = generate(Type.getArrow(), Loc);
auto ReturnType = generate(Type.getReturnType(), Loc);
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);
}
TypeRepr *ASTGen::generate(const AttributedTypeSyntax &Type,
const SourceLoc Loc) {
// todo [gsoc]: improve this after refactoring attribute parsing
auto TypeAST = generate(Type.getBaseType(), Loc);
if (auto Attributes = Type.getAttributes()) {
TypeAttributes TypeAttrs;
for (auto Attribute : *Attributes) {
auto Attr = Attribute.castTo<AttributeSyntax>();
auto AttrNameStr = Attr.getAttributeName().getText();
auto AtLoc = advanceLocBegin(Loc, Attr.getAtSignToken());
auto AttrKind = TypeAttributes::getAttrKindFromString(AttrNameStr);
TypeAttrs.setAttr(AttrKind, AtLoc);
if (AttrKind == TAK_convention) {
auto Argument = Attr.getArgument()->castTo<TokenSyntax>();
auto Convention = Context.getIdentifier(Argument.getIdentifierText());
TypeAttrs.convention = Convention.str();
}
if (AttrKind == TAK_opened) {
auto AttrText = Attr.getArgument()->castTo<TokenSyntax>().getText();
auto LiteralText = AttrText.slice(1, AttrText.size() - 1);
TypeAttrs.OpenedID = UUID::fromString(LiteralText.str().c_str());
}
if (TypeAttrs.AtLoc.isInvalid())
TypeAttrs.AtLoc = AtLoc;
}
if (!TypeAttrs.empty())
TypeAST = new (Context) AttributedTypeRepr(TypeAttrs, 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()) {
auto Args = Clause->getArguments();
if (!Args.empty()) {
auto LAngleLoc = advanceLocBegin(Loc, Clause->getLeftAngleBracket());
auto RAngleLoc = advanceLocBegin(Loc, Clause->getRightAngleBracket());
SourceRange Range{LAngleLoc, RAngleLoc};
auto ArgsAST = generate(Args, Loc);
return GenericIdentTypeRepr::create(Context, IdentifierLoc, Identifier,
ArgsAST, Range);
}
}
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);
}
if (Type.getName().getText() == "class") {
auto classLoc = advanceLocBegin(Loc, Type.getName());
return new (Context)
SimpleIdentTypeRepr(classLoc, Context.getIdentifier("AnyObject"));
}
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);
auto LBraceLoc = advanceLocBegin(Loc, Type.getLeftSquareBracket());
auto ColonLoc = advanceLocBegin(Loc, Type.getColon());
auto RBraceLoc = advanceLocBegin(Loc, Type.getRightSquareBracket());
SourceRange Range{LBraceLoc, RBraceLoc};
return new (Context) DictionaryTypeRepr(KeyType, ValueType, ColonLoc, Range);
}
TypeRepr *ASTGen::generate(const ArrayTypeSyntax &Type, SourceLoc Loc) {
TypeRepr *ElementType = generate(Type.getElementType(), Loc);
SourceLoc LBraceLoc, RBraceLoc;
if (Type.getLeftSquareBracket().isPresent())
LBraceLoc = advanceLocBegin(Loc, Type.getLeftSquareBracket());
else
LBraceLoc = advanceLocBegin(Loc, Type.getElementType());
if (Type.getLeftSquareBracket().isPresent())
RBraceLoc = advanceLocBegin(Loc, Type.getRightSquareBracket());
else
RBraceLoc = advanceLocBegin(Loc, *Type.getLastToken());
return new (Context) ArrayTypeRepr(ElementType, {LBraceLoc, RBraceLoc});
}
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 CodeCompletionTypeSyntax &Type,
const SourceLoc Loc) {
auto base = Type.getBase();
if (!base)
return nullptr;
TypeRepr *parsedTyR = generate(*base, Loc);
if (parsedTyR) {
if (P.CodeCompletion)
P.CodeCompletion->setParsedTypeLoc(parsedTyR);
}
return parsedTyR;
}
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) {
auto LParenLoc = advanceLocBegin(Loc, *LParen);
auto EndLoc =
advanceLocBegin(Loc, *Type.getChild(Type.getNumChildren() - 1));
return TupleTypeRepr::createEmpty(Context, {LParenLoc, EndLoc});
}
}
// let's hope the main `generate` method can find this node in the type map
return nullptr;
}
SmallVector<TypeRepr *, 4>
ASTGen::generate(const GenericArgumentListSyntax &Args, const SourceLoc Loc) {
SmallVector<TypeRepr *, 4> Types;
Types.resize(Args.size());
for (int i = Args.size() - 1; i >= 0; i--) {
auto Arg = Args.getChild(i).getValue().castTo<GenericArgumentSyntax>();
auto Type = generate(Arg, Loc);
Types[i] = Type;
}
return Types;
}
TypeRepr *ASTGen::generate(const GenericArgumentSyntax &Arg,
const SourceLoc Loc) {
return generate(Arg.getArgumentType(), Loc);
}
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()) {
DeclAttributes attrs;
if (auto attrsSyntax = elem.getAttributes()) {
if (auto firstTok = attrsSyntax->getFirstToken()) {
auto attrsLoc = advanceLocBegin(Loc, *firstTok);
if (hasDeclAttributes(attrsLoc))
attrs = getDeclAttributes(attrsLoc);
}
}
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 = {generate(*inherited, Loc)};
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::addType(TypeRepr *Type, const SourceLoc Loc) {
Types.insert({Loc, Type});
}
bool ASTGen::hasType(const SourceLoc Loc) const {
return Types.find(Loc) != Types.end();
}
TypeRepr *ASTGen::getType(const SourceLoc Loc) const {
return Types.find(Loc)->second;
}
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;
}