summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarphaman <arphaman@gmail.com>2013-09-13 10:27:19 +0100
committerarphaman <arphaman@gmail.com>2013-09-13 10:27:19 +0100
commitfbafdc64bcd3e478776b63fd716748a94550eed1 (patch)
tree09abfec5258d796641c5ff18c4b008bbc01b275e
parent7a8f2090a20942ad104389d26bb84d5f368135f0 (diff)
downloadflang-fbafdc64bcd3e478776b63fd716748a94550eed1.tar.gz
added support for records and member expressions in a DATA statement
-rw-r--r--include/flang/AST/Type.h4
-rw-r--r--lib/AST/ExprConstant.cpp17
-rw-r--r--lib/Sema/SemaDataStmt.cpp55
-rw-r--r--test/Sema/data.f9568
4 files changed, 137 insertions, 7 deletions
diff --git a/include/flang/AST/Type.h b/include/flang/AST/Type.h
index 9d7a31cbb9..62766c2f3e 100644
--- a/include/flang/AST/Type.h
+++ b/include/flang/AST/Type.h
@@ -725,6 +725,10 @@ public:
return ArrayRef<FieldDecl*>(Elems,ElemCount);
}
+ unsigned getElementCount() const {
+ return ElemCount;
+ }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElements());
}
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index a57e3f1e17..e0f08b5d7c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -53,6 +53,7 @@ public:
bool VisitImplicitCastExpr(const ImplicitCastExpr *E);
bool VisitVarExpr(const VarExpr *E);
bool VisitArrayConstructorExpr(const ArrayConstructorExpr *E);
+ bool VisitTypeConstructorExpr(const TypeConstructorExpr *E);
};
bool ConstExprVerifier::Eval(const Expr *E) {
@@ -97,11 +98,19 @@ bool ConstExprVerifier::VisitArrayConstructorExpr(const ArrayConstructorExpr *E)
return true;
}
+bool ConstExprVerifier::VisitTypeConstructorExpr(const TypeConstructorExpr *E) {
+ for(auto I : E->getArguments()) {
+ if(!Eval(I))
+ return false;
+ }
+ return true;
+}
+
struct IntValueTy : public llvm::APInt {
IntValueTy() {}
IntValueTy(uint64_t I) :
- llvm::APInt(64, I) {}
+ llvm::APInt(64, I, true) {}
template<typename T = int64_t>
bool IsProperSignedInt() const {
@@ -151,8 +160,10 @@ public:
};
int64_t IntExprEvaluator::getResult() const {
- if(Result.IsProperSignedInt())
- return int64_t(Result.getLimitedValue());
+ if(Result.IsProperSignedInt()) {
+ auto val = Result.getLimitedValue();
+ return int64_t(val);
+ }
return 1;
}
diff --git a/lib/Sema/SemaDataStmt.cpp b/lib/Sema/SemaDataStmt.cpp
index 5e16fd8971..b3c1e52c36 100644
--- a/lib/Sema/SemaDataStmt.cpp
+++ b/lib/Sema/SemaDataStmt.cpp
@@ -97,8 +97,8 @@ class DataStmtEngine : public ExprVisitor<DataStmtEngine> {
bool Done;
- ExprResult getAndCheckValue(QualType LHSType, Expr *LHS);
- ExprResult getAndCheckAnyValue(QualType LHSType, Expr *LHS);
+ ExprResult getAndCheckValue(QualType LHSType, const Expr *LHS);
+ ExprResult getAndCheckAnyValue(QualType LHSType, const Expr *LHS);
public:
DataStmtEngine(DataValueIterator &Vals, flang::Sema &S,
DiagnosticsEngine &Diag, SourceLocation Loc)
@@ -119,6 +119,9 @@ public:
void VisitArrayElementExpr(ArrayElementExpr *E);
ExprResult CreateSubstringExprInitializer(SubstringExpr *E, QualType CharTy);
void VisitSubstringExpr(SubstringExpr *E);
+ ExprResult CreateMemberExprInitializer(const MemberExpr *E,
+ const TypeConstructorExpr *Init = nullptr);
+ void VisitMemberExpr(MemberExpr *E);
void VisitImpliedDoExpr(ImpliedDoExpr *E);
void Emit(Stmt *S);
@@ -161,7 +164,7 @@ bool DataStmtEngine::CheckVar(VarExpr *E) {
}
ExprResult DataStmtEngine::getAndCheckValue(QualType LHSType,
- Expr *LHS) {
+ const Expr *LHS) {
if(!HasValues(LHS)) return ExprResult(true);
auto Value = Values.getValue();
Values.advance();
@@ -171,7 +174,7 @@ ExprResult DataStmtEngine::getAndCheckValue(QualType LHSType,
LHS);
}
-ExprResult DataStmtEngine::getAndCheckAnyValue(QualType LHSType, Expr *LHS) {
+ExprResult DataStmtEngine::getAndCheckAnyValue(QualType LHSType, const Expr *LHS) {
auto Val = getAndCheckValue(LHSType, LHS);
auto ET = LHSType.getSelfOrArrayElementType();
if(ET->isCharacterType() && Val.isUsable()) {
@@ -258,6 +261,11 @@ void DataStmtEngine::CreateArrayElementExprInitializer(ArrayElementExpr *E,
if(Parent) {
if(auto SE = dyn_cast<SubstringExpr>(Parent)) {
Val = CreateSubstringExprInitializer(SE, ElementType);
+ } else if(auto ME = dyn_cast<MemberExpr>(Parent)) {
+ if(Offset < Items.size()) {
+ const TypeConstructorExpr *Init = Items[Offset]? cast<TypeConstructorExpr>(Items[Offset]) : nullptr;
+ Val = CreateMemberExprInitializer(ME, Init);
+ }
} else llvm_unreachable("invalid expression");
} else Val = getAndCheckAnyValue(ElementType, E);
@@ -322,6 +330,45 @@ void DataStmtEngine::VisitSubstringExpr(SubstringExpr *E) {
VD->setInit(Val.get());
}
+ExprResult DataStmtEngine::CreateMemberExprInitializer(const MemberExpr *E,
+ const TypeConstructorExpr *Init) {
+ auto Field = E->getField();
+ auto Val = getAndCheckAnyValue(E->getType(), E);
+ if(!Val.isUsable())
+ return Sem.ExprError();
+
+ auto FieldCount = E->getTarget()->getType().getSelfOrArrayElementType()->asRecordType()->getElementCount();
+ SmallVector<Expr*, 16> Items(FieldCount);
+ if(Init) {
+ auto Args = Init->getArguments();
+ for(unsigned I = 0; I < FieldCount; ++I) Items[I] = Args[I];
+ } else {
+ for(unsigned I = 0; I < FieldCount; ++I) Items[I] = nullptr;
+ }
+ Items[Field->getIndex()] = Val.get();
+ return TypeConstructorExpr::Create(Context, Val.get()->getLocation(),
+ Field->getParent(), Items);
+}
+
+void DataStmtEngine::VisitMemberExpr(MemberExpr *E) {
+ if(auto AE = dyn_cast<ArrayElementExpr>(E->getTarget())) {
+ CreateArrayElementExprInitializer(AE, E);
+ return;
+ }
+
+ auto Target = dyn_cast<VarExpr>(E->getTarget());
+ if(!Target)
+ return VisitExpr(E);
+ if(CheckVar(Target))
+ return;
+
+ auto VD = Target->getVarDecl();
+ const TypeConstructorExpr *Init = VD->hasInit()? cast<TypeConstructorExpr>(VD->getInit()) : nullptr;
+ auto Val = CreateMemberExprInitializer(E, Init);
+ if(Val.isUsable())
+ VD->setInit(Val.get());
+}
+
void DataStmtEngine::VisitImpliedDoExpr(ImpliedDoExpr *E) {
auto Start = Sem.EvalAndCheckIntExpr(E->getInitialParameter(), 1);
auto End = Sem.EvalAndCheckIntExpr(E->getTerminalParameter(), 1);
diff --git a/test/Sema/data.f95 b/test/Sema/data.f95
index 85334195e4..5301f24974 100644
--- a/test/Sema/data.f95
+++ b/test/Sema/data.f95
@@ -1,4 +1,6 @@
! RUN: %flang -fsyntax-only -verify < %s
+! RUN: %flang -fsyntax-only -verify -ast-print %s 2>&1 | %file_check %s
+
PROGRAM datatest
INTEGER I, J, K, M, NNN, O, P, Q
REAL X,Y,Z, A, ZZZ
@@ -7,6 +9,11 @@ PROGRAM datatest
REAL R_ARR(10), R_ARR2(3), R_MULTIARR(2,3,4)
CHARACTER*(10) STR, STR_ARR(11)
+ type point
+ integer x,y
+ end type
+ type(point) point1, point2, pointArr(4)
+
PARAMETER (PI = 3.14, INDEX = 1)
DATA I / 1 /
@@ -69,4 +76,65 @@ PROGRAM datatest
DATA (I_ARR(I), I = INDEX, 10) / 10 * 0 /
DATA (I_ARR2(INDEX,J), J = 1,2) / 2*3 /
+ data point1 / Point(1,2) /
+ data point2 / Point(3,4) /
+
+ data point1%x, point1%y / 2*0 /
+
+ data pointArr / 4*Point(-1,1) /
+ data pointArr(1)%x / 13 / pointArr(2)%y / 42 /
+
END PROGRAM
+
+subroutine sub ! CHECK: i = 1
+ integer i, j, k ! CHECK: j = 0
+ data i / 1 / j, k / 2*0 / ! CHECK: k = 0
+end
+
+subroutine sub2
+ integer i_mat(2,2)
+ integer i_arr(2)
+
+ data i_mat / 2*1, 2*2 / ! CHECK: i_mat = (/1, 1, 2, 2 /)
+ data i_arr(1), i_arr(2) / 13, 42 / ! CHECK: i_arr = (/13, 42 /)
+end
+
+subroutine sub3
+ integer i_mat(2,2)
+ integer i_arr(4), i_arr2(-2:2)
+ integer two
+ parameter (two = 2)
+
+ data ((i_mat(i,j), j = 1,two), i = 1,2) / 4*3 / ! CHECK: i_mat = (/3, 3, 3, 3 /)
+ data (i_arr(i), i = 1,3), i_arr(4) / 11,12,13,14 / ! CHECK: i_arr = (/11, 12, 13, 14 /)
+ data i_arr(-2), (i_arr2(i), i = -1,2) / 100, 101, &
+ 102, 103, 104 / ! CHECK: i_arr2 = (/100, 101, 102, 103, 104 /)
+end
+
+subroutine sub4
+ character(len=10) str1, str2, str3 ! CHECK: str1 = 'Hello '
+ character(len=5) strArr(3), strArr2(3)
+
+ data str1 / 'Hello' / str2(:) / 'World' / ! CHECK: str2 = 'World '
+ data str3(2:4) / 'Flang' / ! CHECK: str3 = ' Fla '
+
+ data strArr / 3*'foobar' / ! CHECK: strarr = (/'fooba', 'fooba', 'fooba' /)
+ data strArr2(1) / 'Hello' /
+ data strArr2(2)(2:4) / '+' /
+ data (strArr2(i), i = 3,3) / 'funke' / ! CHECK: strarr2 = (/'Hello', ' + ', 'funke' /)
+end
+
+subroutine sub5
+ type point
+ integer x,y
+ end type
+ type(point) p1, p2, pArr(3) ! CHECK: p1 = point((-1), 1)
+ type(point) pArr2(3)
+
+ data p1 / Point(-1,1) / p2%x, p2%y / 13, 42 / ! CHECK: p2 = point(13, 42)
+ data pArr / 2*Point(0,7), Point(1,1) / ! CHECK: pArr = (/point(0,7), point(0,7), point(1,1) /)
+ data pArr2(1)%x, pArr2(1)%y / 2*16 / ! CHECK: pArr2 = (/point(16,16), point(1,2), point(3,4) /)
+ data pArr2(2), parr2(3) / point(1,2), point(3,4) /
+ ! FIXME: TODO: data (pArr2(i)%x, pArr2(i)%y, i = 2,3) / 1, 2, 3, 4 /
+
+end