llvm/flang/lib/semantics/semantics.cc
Tim Keith 30dd289247 [flang] Add FoldingContext to SemanticsContext
FoldingContext is now part of SemanticsContext. It is created at the
beginning with a default-constructed CharBlock as the location in its
ContextualMessages.

Add PushLocation() to ContextualMessages to remember the previous source
location and set a new one. The old one is restored when the returned
object goes out of scope.

SemanticsContext is now the only state passed in to class ExprAnalyzer,
class Mutator, AnalyzeExpr(), AnalyzeExpressions().

Add Say() convenience functions for reporting errors to ExprAnalyzer.

Original-commit: flang-compiler/f18@70c499ffc4
Reviewed-on: https://github.com/flang-compiler/f18/pull/215
Tree-same-pre-rewrite: false
2018-10-22 16:41:26 -07:00

107 lines
3 KiB
C++

// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "semantics.h"
#include "canonicalize-do.h"
#include "default-kinds.h"
#include "mod-file.h"
#include "resolve-labels.h"
#include "resolve-names.h"
#include "rewrite-parse-tree.h"
#include "scope.h"
#include "symbol.h"
#include <ostream>
namespace Fortran::semantics {
static void DoDumpSymbols(std::ostream &, const Scope &, int indent = 0);
static void PutIndent(std::ostream &, int indent);
SemanticsContext::SemanticsContext(
const IntrinsicTypeDefaultKinds &defaultKinds)
: defaultKinds_{defaultKinds},
intrinsics_{evaluate::IntrinsicProcTable::Configure(defaultKinds)},
foldingContext_{evaluate::FoldingContext{
parser::ContextualMessages{parser::CharBlock{}, &messages_}}} {}
bool SemanticsContext::AnyFatalError() const {
return !messages_.empty() &&
(warningsAreErrors_ || messages_.AnyFatalError());
}
bool Semantics::Perform() {
ValidateLabels(context_.messages(), program_);
if (AnyFatalError()) {
return false;
}
parser::CanonicalizeDo(program_);
ResolveNames(context_, program_);
if (AnyFatalError()) {
return false;
}
RewriteParseTree(context_, program_);
if (AnyFatalError()) {
return false;
}
ModFileWriter writer{context_};
writer.WriteAll();
if (AnyFatalError()) {
return false;
}
if (context_.debugExpressions()) {
AnalyzeExpressions(program_, context_);
}
return !AnyFatalError();
}
void Semantics::EmitMessages(std::ostream &os) const {
context_.messages().Emit(os, cooked_);
}
void Semantics::DumpSymbols(std::ostream &os) {
DoDumpSymbols(os, context_.globalScope());
}
void DoDumpSymbols(std::ostream &os, const Scope &scope, int indent) {
PutIndent(os, indent);
os << Scope::EnumToString(scope.kind()) << " scope:";
if (const auto *symbol{scope.symbol()}) {
os << ' ' << symbol->name().ToString();
}
os << '\n';
++indent;
for (const auto &pair : scope) {
const auto &symbol{*pair.second};
PutIndent(os, indent);
os << symbol << '\n';
if (const auto *details{symbol.detailsIf<GenericDetails>()}) {
if (const auto &type{details->derivedType()}) {
PutIndent(os, indent);
os << *type << '\n';
}
}
}
for (const auto &child : scope.children()) {
DoDumpSymbols(os, child, indent);
}
--indent;
}
static void PutIndent(std::ostream &os, int indent) {
for (int i = 0; i < indent; ++i) {
os << " ";
}
}
} // namespace Fortran::semantics