diff options
author | arphaman <arphaman@gmail.com> | 2013-09-13 10:27:19 +0100 |
---|---|---|
committer | arphaman <arphaman@gmail.com> | 2013-09-13 10:27:19 +0100 |
commit | fbafdc64bcd3e478776b63fd716748a94550eed1 (patch) | |
tree | 09abfec5258d796641c5ff18c4b008bbc01b275e | |
parent | 7a8f2090a20942ad104389d26bb84d5f368135f0 (diff) | |
download | flang-fbafdc64bcd3e478776b63fd716748a94550eed1.tar.gz |
added support for records and member expressions in a DATA statement
-rw-r--r-- | include/flang/AST/Type.h | 4 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaDataStmt.cpp | 55 | ||||
-rw-r--r-- | test/Sema/data.f95 | 68 |
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 |