Skip to content

Commit

Permalink
ALLOCATE support in Parser and Sema
Browse files Browse the repository at this point in the history
Add types for allocation statement and array expression. Do basic verification
for the array alocation semantics in ALLOCATE. Minor additition to the test.

Create a more general type for allocation expression (instead of array
allocation), but leave other cases unimplemented for now. Type of the
allocation is the type of the target expression, which may not be correct in
all cases.

Add Sema support for ALLOCATE statements.

For llvm-fortran#22
  • Loading branch information
ppenzin committed Mar 15, 2019
1 parent a14dd26 commit 5730ae3
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 2 deletions.
20 changes: 20 additions & 0 deletions include/fort/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,26 @@ class ImplicitTempArrayExpr : public ImplicitArrayOperationExpr {
static bool classof(const ImplicitTempArrayExpr *) { return true; }
};

//===----------------------------------------------------------------------===//
/// AllocExpr - dynamic allocation specification
class AllocExpr : public DesignatorExpr {
ArrayType *AllocShape;

// TODO explicit type parameter
AllocExpr(ASTContext &C, SourceLocation Loc, Expr *E, ArrayType *Shape);

public:
static AllocExpr *Create(ASTContext &C, Expr *E, ArrayType *Shape);

ArrayType *getShape() const { return AllocShape; }
bool isArrayAlloc() const { return AllocShape != nullptr; }

static bool classof(const Expr *E) {
return E->getExprClass() == AllocExprClass;
}
static bool classof(const AllocExpr *) { return true; }
};

//===----------------------------------------------------------------------===//

/// EvaluatedArraySpec - represents an evaluated array specification.
Expand Down
17 changes: 17 additions & 0 deletions include/fort/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,23 @@ class AssignmentStmt : public Stmt {
}
};

/// AllocateStmt
class AllocateStmt : public Stmt, public MultiArgumentExpr {
AllocateStmt(ASTContext &C, SourceLocation Loc, ArrayRef<Expr *> allocs,
Expr *StmtLabel);

public:
static AllocateStmt *Create(ASTContext &C, SourceLocation Loc,
ArrayRef<Expr *> Allocs, Expr *StmtLabel);

ArrayRef<Expr *> getAllocationList() const { return getArguments(); }

static bool classof(const AllocateStmt *) { return true; }
static bool classof(const Stmt *S) {
return S->getStmtClass() == AllocateStmtClass;
}
};

/// DeallocateStmt
class DeallocateStmt : public Stmt, public MultiArgumentExpr {
DeallocateStmt(ASTContext &C, SourceLocation Loc, ArrayRef<Expr *> ids,
Expand Down
1 change: 1 addition & 0 deletions include/fort/Basic/ExprNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def MemberExpr : DExpr<DesignatorExpr>;
def SubstringExpr : DExpr<DesignatorExpr>;
def ArrayElementExpr : DExpr<DesignatorExpr>;
def ArraySectionExpr : DExpr<DesignatorExpr>;
def AllocExpr : DExpr<DesignatorExpr>;
def ImplicitArrayOperationExpr : Expr<1>;
def ImplicitArrayPackExpr : DExpr<ImplicitArrayOperationExpr>;
def ImplicitTempArrayExpr : DExpr<ImplicitArrayOperationExpr>;
Expand Down
1 change: 1 addition & 0 deletions include/fort/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def StopStmt : Stmt;
def ReturnStmt : Stmt;
def CallStmt : Stmt;
def AssignmentStmt : Stmt;
def AllocateStmt : Stmt;
def DeallocateStmt : Stmt;
def PrintStmt : Stmt;
def WriteStmt : Stmt;
7 changes: 7 additions & 0 deletions include/fort/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,9 @@ class Sema {
FormatSpec *FS, ArrayRef<ExprResult> OutputItemList,
Expr *StmtLabel);

StmtResult ActOnAllocateStmt(ASTContext &C, SourceLocation Loc,
ArrayRef<ExprResult> AllocList, Expr *StmtLabel);

StmtResult ActOnDeallocateStmt(ASTContext &C, SourceLocation Loc,
ArrayRef<ExprResult> IDList, Expr *StmtLabel);
// FIXME: TODO:
Expand Down Expand Up @@ -971,6 +974,10 @@ class Sema {
/// operations.
Expr *ActOnArrayArgument(VarDecl *Arg, Expr *E);

/// Returns an array that is passed to a function, with optional implcit
/// operations.
Expr *ActOnArrayAlloc(VarDecl *Decl, ArrayRef<ArraySpec *> Dimensions);

/// Returns true if an array expression needs a temporary storage array.
bool ArrayExprNeedsTemp(const Expr *E);

Expand Down
17 changes: 17 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class ASTDumper : public ConstStmtVisitor<ASTDumper>,
void VisitStopStmt(const StopStmt *S);
void VisitReturnStmt(const ReturnStmt *S);
void VisitCallStmt(const CallStmt *S);
void VisitAllocateStmt(const AllocateStmt *S);
void VisitDeallocateStmt(const DeallocateStmt *S);
void VisitAssignmentStmt(const AssignmentStmt *S);
void VisitPrintStmt(const PrintStmt *S);
Expand Down Expand Up @@ -132,6 +133,7 @@ class ASTDumper : public ConstStmtVisitor<ASTDumper>,
void VisitCallExpr(const CallExpr *E);
void VisitIntrinsicCallExpr(const IntrinsicCallExpr *E);
void VisitImpliedDoExpr(const ImpliedDoExpr *E);
void VisitAllocExpr(const AllocExpr *E);
void VisitArrayConstructorExpr(const ArrayConstructorExpr *E);
void VisitTypeConstructorExpr(const TypeConstructorExpr *E);
void VisitRangeExpr(const RangeExpr *E);
Expand Down Expand Up @@ -660,6 +662,12 @@ void ASTDumper::VisitCallStmt(const CallStmt *S) {
OS << ")\n";
}

void ASTDumper::VisitAllocateStmt(const AllocateStmt *S) {
OS << "allocate(";
dumpExprList(S->getArguments());
OS << ")\n";
}

void ASTDumper::VisitDeallocateStmt(const DeallocateStmt *S) {
OS << "deallocate(";
dumpExprList(S->getArguments());
Expand Down Expand Up @@ -940,6 +948,15 @@ void ASTDumper::VisitImpliedDoExpr(const ImpliedDoExpr *E) {
OS << ')';
}

void ASTDumper::VisitAllocExpr(const AllocExpr *E) {
dumpExprList(E->getTarget());
for (auto Dim : *E->getShape()) {
OS << "(";
dumpArraySpec(Dim);
OS << ")";
}
}

void ASTDumper::VisitArrayConstructorExpr(const ArrayConstructorExpr *E) {
OS << "(/";
dumpExprList(E->getItems());
Expand Down
8 changes: 8 additions & 0 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,14 @@ ImplicitTempArrayExpr *ImplicitTempArrayExpr::Create(ASTContext &C, Expr *E) {
return new (C) ImplicitTempArrayExpr(E->getLocation(), E);
}

AllocExpr::AllocExpr(ASTContext &C, SourceLocation Loc, Expr *E,
ArrayType *Shape)
: DesignatorExpr(AllocExprClass, E->getType(), Loc, E), AllocShape(Shape) {}

AllocExpr *AllocExpr::Create(ASTContext &C, Expr *E, ArrayType *Shape) {
return new (C) AllocExpr(C, E->getLocation(), E, Shape);
}

FunctionRefExpr::FunctionRefExpr(SourceLocation Loc, SourceLocation LocEnd,
const FunctionDecl *Func, QualType T)
: Expr(FunctionRefExprClass, T, Loc), NameLocEnd(LocEnd), Function(Func) {}
Expand Down
13 changes: 13 additions & 0 deletions lib/AST/Stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,19 @@ AssignmentStmt *AssignmentStmt::Create(ASTContext &C, SourceLocation Loc,
return new (C) AssignmentStmt(Loc, LHS, RHS, StmtLabel);
}

//===----------------------------------------------------------------------===//
// Allocate Statement
//===----------------------------------------------------------------------===//

AllocateStmt::AllocateStmt(ASTContext &C, SourceLocation Loc,
ArrayRef<Expr *> allocs, Expr *StmtLabel)
: Stmt(AllocateStmtClass, Loc, StmtLabel), MultiArgumentExpr(C, allocs) {}

AllocateStmt *AllocateStmt::Create(ASTContext &C, SourceLocation Loc,
ArrayRef<Expr *> Allocs, Expr *StmtLabel) {
return new (C) AllocateStmt(C, Loc, Allocs, StmtLabel);
}

//===----------------------------------------------------------------------===//
// Deallocate Statement
//===----------------------------------------------------------------------===//
Expand Down
17 changes: 15 additions & 2 deletions lib/Parse/ParseExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,10 @@ Parser::StmtResult Parser::ParseALLOCATEStmt() {
// TODO [ type-spec :: ]

// allocation-list
SmallVector<ExprResult, 4> Alloc;
bool HasErrors = false;
do {
Expr *AE = nullptr;
auto ID = Tok.getIdentifierInfo();
auto IDLoc = Tok.getLocation();
if (!ExpectAndConsume(tok::identifier))
Expand All @@ -696,15 +699,25 @@ Parser::StmtResult Parser::ParseALLOCATEStmt() {
Diag.Report(IDLoc, diag::err_expected_array_spec);
return StmtError();
}
auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, ID);
if (VD) {
AE = Actions.ActOnArrayAlloc(VD, Dimensions);
}
if (AE)
Alloc.push_back(AE);
else
HasErrors = true;
} while (ConsumeIfPresent(tok::comma));

if (HasErrors)
return StmtError();

// TODO [ , alloc-opt-list ]

if (!ExpectAndConsume(tok::r_paren))
return StmtError();

// FIXME Sema
return StmtResult();
return Actions.ActOnAllocateStmt(Context, Loc, Alloc, StmtLabel);
}

/// ParseDEALLOCATEStmt - Parse the DEALLOCATE statement.
Expand Down
26 changes: 26 additions & 0 deletions lib/Sema/SemaExecStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,32 @@ StmtResult Sema::ActOnCallStmt(ASTContext &C, SourceLocation Loc,
return Result;
}

StmtResult Sema::ActOnAllocateStmt(ASTContext &C, SourceLocation Loc,
ArrayRef<ExprResult> AllocList,
Expr *StmtLabel) {
SmallVector<Expr *, 4> AllocExprList;
for (auto A : AllocList) {
if (!A.isUsable()) {
// TODO error
continue;
}
auto AE = A.takeAs<AllocExpr>();
if (!AE) {
// TODO assert or error
} else
AllocExprList.push_back(AE);
}

Stmt *Result = AllocateStmt::Create(C, Loc, AllocExprList, StmtLabel);

getCurrentBody()->Append(Result);

if (StmtLabel)
DeclareStatementLabel(StmtLabel, Result);

return Result;
}

StmtResult Sema::ActOnDeallocateStmt(ASTContext &C, SourceLocation Loc,
ArrayRef<ExprResult> IDList,
Expr *StmtLabel) {
Expand Down
16 changes: 16 additions & 0 deletions lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,22 @@ Expr *Sema::ActOnArrayArgument(VarDecl *Arg, Expr *E) {
return E;
}

Expr *Sema::ActOnArrayAlloc(VarDecl *Decl, ArrayRef<ArraySpec *> Dimensions) {
auto DeclType = Decl->getType();
// TODO verify Decl is an array
if (!DeclType->isArrayType()) { /* TODO Implicit declaration or error */
}
auto ATy = DeclType->asArrayType();
// TODO check whether shape is compatible with declaration
if (ATy->getDimensionCount() != Dimensions.size()) { /* TODO Error */
}
auto ElemType = ATy->getElementType();
auto VE = VarExpr::Create(Context, Decl->getSourceRange(), Decl);
auto Shape = ArrayType::Create(Context, ElemType, Dimensions);
auto E = AllocExpr::Create(Context, VE, Shape);
return E;
}

ExprResult Sema::ActOnCallExpr(ASTContext &C, SourceLocation Loc,
SourceLocation RParenLoc, SourceLocation IDLoc,
FunctionDecl *Function,
Expand Down
2 changes: 2 additions & 0 deletions test/Parser/dynamicAssociation.f95
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ program a
allocate(b(10,10) ! expected-error {{expected ')'}}
allocate(a) ! expected-error {{expected '('}}
continue ! expected-error@-1 {{expected array specification}}
allocate(a(10))
allocate(b(10), c(10, 10, 10))
deallocate(.5) ! expected-error {{expected identifier}}
deallocate(c ! expected-error {{expected ')'}}
deallocate(a,) ! expected-error {{expected identifier}}
Expand Down
2 changes: 2 additions & 0 deletions test/Sema/dynamicAssociation.f95
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ program a
implicit none
integer, allocatable :: a(10), c(5) ! CHECK: integer, allocatable array a
continue ! CHECK: integer, allocatable array c
allocate(b(3)) ! expected-error {{use of undeclared identifier 'b'}}
allocate(a(10), c(5)) ! CHECK: allocate(a(10), c(5))
deallocate(b) ! expected-error {{use of undeclared identifier 'b'}}
deallocate(a,c) ! CHECK: deallocate(a, c)
end program

0 comments on commit 5730ae3

Please sign in to comment.