1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
//===- SemaIO.cpp - IO AST Builder and Semantic Analysis Implementation --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "flang/Sema/Sema.h"
#include "flang/Sema/DeclSpec.h"
#include "flang/Sema/SemaDiagnostic.h"
#include "flang/Sema/SemaInternal.h"
#include "flang/AST/ASTContext.h"
#include "flang/AST/Decl.h"
#include "flang/AST/Expr.h"
#include "flang/AST/FormatSpec.h"
#include "flang/AST/IOSpec.h"
#include "flang/Basic/Diagnostic.h"
namespace flang {
StarFormatSpec *Sema::ActOnStarFormatSpec(ASTContext &C, SourceLocation Loc) {
return StarFormatSpec::Create(C, Loc);
}
static void CheckStmtLabelIsFormat(DiagnosticsEngine &Diags, Stmt *S, Expr *Label) {
if(!isa<FormatStmt>(S)) {
Diags.Report(Label->getLocation(), diag::err_fmt_spec_stmt_label_not_format)
<< Label->getSourceRange();
Diags.Report(S->getStmtLabel()->getLocation(), diag::note_stmt_label_declared_at)
<< S->getStmtLabel()->getSourceRange();
}
}
void StmtLabelResolver::VisitLabelFormatSpec(LabelFormatSpec *FS) {
CheckStmtLabelIsFormat(Diags, StmtLabelDecl, Info.StmtLabel);
FS->setLabel(StmtLabelReference(StmtLabelDecl));
}
LabelFormatSpec *Sema::ActOnLabelFormatSpec(ASTContext &C, SourceLocation Loc,
ExprResult Label) {
if(isa<IntegerConstantExpr>(Label.get())) {
auto Decl = getCurrentStmtLabelScope()->Resolve(Label.get());
if(!Decl) {
auto Result = LabelFormatSpec::Create(C, Loc, StmtLabelReference());
getCurrentStmtLabelScope()->DeclareForwardReference(
StmtLabelScope::ForwardDecl(Label.get(), Result));
return Result;
} else {
CheckStmtLabelIsFormat(Diags, Decl, Label.get());
return LabelFormatSpec::Create(C, Loc, StmtLabelReference(Decl));
}
}
// FIXME: TODO.
return LabelFormatSpec::Create(C, Loc, StmtLabelReference());
}
FormatSpec *Sema::ActOnExpressionFormatSpec(ASTContext &C, SourceLocation Loc,
Expr *E) {
auto Type = E->getType();
if(Type->isCharacterType())
return CharacterExpFormatSpec::Create(C, Loc, E);
if(auto Var = dyn_cast<VarExpr>(E)) {
if(Type->isIntegerType())
return VarLabelFormatSpec::Create(C, Loc, Var);
}
Diags.Report(Loc, diag::err_typecheck_expected_format_spec)
<< Type << E->getSourceRange();
// Return an empty character literal spec when an error occurs.
return CharacterExpFormatSpec::Create(C, Loc,
CharacterConstantExpr::Create(Context, Loc, "", C.CharacterTy));
}
ExternalStarUnitSpec *Sema::ActOnStarUnitSpec(ASTContext &C, SourceLocation Loc,
bool IsLabeled) {
return ExternalStarUnitSpec::Create(C, Loc, IsLabeled);
}
UnitSpec *Sema::ActOnUnitSpec(ASTContext &C, ExprResult Value, SourceLocation Loc,
bool IsLabeled) {
// FIXME: TODO
return nullptr;
}
StmtResult Sema::ActOnPrintStmt(ASTContext &C, SourceLocation Loc, FormatSpec *FS,
ArrayRef<ExprResult> OutputItemList,
Expr *StmtLabel) {
SmallVector<Expr *, 8> OutputList;
for(auto I : OutputItemList) OutputList.push_back(I.take());
auto Result = PrintStmt::Create(C, Loc, FS, OutputList, StmtLabel);
getCurrentBody()->Append(Result);
if(StmtLabel) DeclareStatementLabel(StmtLabel, Result);
return Result;
}
StmtResult Sema::ActOnWriteStmt(ASTContext &C, SourceLocation Loc,
UnitSpec *US, FormatSpec *FS,
ArrayRef<ExprResult> OutputItemList,
Expr *StmtLabel) {
// FIXME: TODO
SmallVector<Expr *, 8> OutputList;
for(auto I : OutputItemList) OutputList.push_back(I.take());
auto Result = WriteStmt::Create(C, Loc, US, FS, OutputList, StmtLabel);
getCurrentBody()->Append(Result);
if(StmtLabel) DeclareStatementLabel(StmtLabel, Result);
return Result;
}
} // end namespace flang
|