forked from OSchip/llvm-project
[flang] begin unit testing
Original-commit: flang-compiler/f18@c8b691a4ae Reviewed-on: https://github.com/flang-compiler/f18/pull/212 Tree-same-pre-rewrite: false
This commit is contained in:
parent
ad9aede8ce
commit
62425d6021
|
@ -144,6 +144,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Word bits() const { return bits_; }
|
||||
|
||||
private:
|
||||
Word bits_{0};
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
namespace Fortran::evaluate {
|
||||
|
||||
struct ActualArgument {
|
||||
explicit ActualArgument(Expr<SomeType> &&x) : value{std::move(x)} {}
|
||||
explicit ActualArgument(CopyableIndirection<Expr<SomeType>> &&v)
|
||||
: value{std::move(v)} {}
|
||||
std::optional<DynamicType> GetType() const;
|
||||
|
|
|
@ -1095,18 +1095,16 @@ std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
|
|||
if (call.isSubroutineCall) {
|
||||
return std::nullopt; // TODO
|
||||
}
|
||||
// A given intrinsic may have multiple patterns in the maps. If any of them
|
||||
// succeeds, the buffered messages from previous failed pattern matches are
|
||||
// discarded. Otherwise, all messages generated by the failing patterns are
|
||||
// returned if the caller wants them.
|
||||
parser::Messages buffer;
|
||||
parser::ContextualMessages errors{
|
||||
messages ? messages->at() : call.name, &buffer};
|
||||
// Probe the specific intrinsic functions first.
|
||||
bool wantMessages{messages != nullptr && messages->messages() != nullptr};
|
||||
// Probe the specific intrinsic function table first.
|
||||
parser::Messages specificBuffer;
|
||||
parser::ContextualMessages specificErrors{
|
||||
messages ? messages->at() : call.name,
|
||||
wantMessages ? &specificBuffer : nullptr};
|
||||
std::string name{call.name.ToString()};
|
||||
auto specificRange{specificFuncs.equal_range(name)};
|
||||
for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
|
||||
if (auto specific{iter->second->Match(call, defaults, errors)}) {
|
||||
if (auto specific{iter->second->Match(call, defaults, specificErrors)}) {
|
||||
if (const char *genericName{iter->second->generic}) {
|
||||
specific->name = genericName;
|
||||
}
|
||||
|
@ -1114,9 +1112,14 @@ std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
|
|||
return specific;
|
||||
}
|
||||
}
|
||||
auto genericRange{specificFuncs.equal_range(name)};
|
||||
// Probe the generic intrinsic function table next.
|
||||
parser::Messages genericBuffer;
|
||||
parser::ContextualMessages genericErrors{
|
||||
messages ? messages->at() : call.name,
|
||||
wantMessages ? &genericBuffer : nullptr};
|
||||
auto genericRange{genericFuncs.equal_range(name)};
|
||||
for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
|
||||
if (auto specific{iter->second->Match(call, defaults, errors)}) {
|
||||
if (auto specific{iter->second->Match(call, defaults, genericErrors)}) {
|
||||
return specific;
|
||||
}
|
||||
}
|
||||
|
@ -1127,10 +1130,10 @@ std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
|
|||
// Can pass that context in, or return a token distinguishing
|
||||
// NULL, or represent NULL as a new kind of top-level expression
|
||||
} else if (call.argument.size() > 1) {
|
||||
errors.Say("too many arguments to NULL()"_err_en_US);
|
||||
genericErrors.Say("too many arguments to NULL()"_err_en_US);
|
||||
} else if (call.argument[0].keyword.has_value() &&
|
||||
call.argument[0].keyword->ToString() != "mold") {
|
||||
errors.Say("unknown argument '%s' to NULL()"_err_en_US,
|
||||
genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
|
||||
call.argument[0].keyword->ToString().data());
|
||||
} else {
|
||||
// TODO: Argument must be pointer, procedure pointer, or allocatable.
|
||||
|
@ -1139,9 +1142,13 @@ std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
|
|||
}
|
||||
}
|
||||
// No match
|
||||
CHECK(!buffer.empty());
|
||||
if (messages != nullptr && messages->messages() != nullptr) {
|
||||
messages->messages()->Annex(std::move(buffer));
|
||||
if (wantMessages) {
|
||||
if (genericBuffer.empty()) {
|
||||
CHECK(!specificBuffer.empty());
|
||||
messages->messages()->Annex(std::move(specificBuffer));
|
||||
} else {
|
||||
messages->messages()->Annex(std::move(genericBuffer));
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
@ -919,8 +919,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::FunctionReference &funcRef) {
|
|||
}},
|
||||
std::get<parser::ActualArg>(arg.t).u);
|
||||
if (actualArgExpr.has_value()) {
|
||||
CopyableIndirection<Expr<SomeType>> indExpr{std::move(*actualArgExpr)};
|
||||
arguments.emplace_back(std::move(indExpr));
|
||||
arguments.emplace_back(std::move(*actualArgExpr));
|
||||
if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
|
||||
arguments.back().keyword = argKW->v.source;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,16 @@ target_link_libraries(bit-population-count-test
|
|||
FortranEvaluateTesting
|
||||
)
|
||||
|
||||
add_executable(expression-test
|
||||
expression.cc
|
||||
)
|
||||
|
||||
target_link_libraries(expression-test
|
||||
FortranEvaluate
|
||||
FortranEvaluateTesting
|
||||
FortranParser
|
||||
)
|
||||
|
||||
add_executable(integer-test
|
||||
integer.cc
|
||||
)
|
||||
|
@ -44,6 +54,16 @@ target_link_libraries(integer-test
|
|||
FortranEvaluateTesting
|
||||
)
|
||||
|
||||
add_executable(intrinsics-test
|
||||
intrinsics.cc
|
||||
)
|
||||
|
||||
target_link_libraries(intrinsics-test
|
||||
FortranEvaluate
|
||||
FortranEvaluateTesting
|
||||
FortranParser
|
||||
)
|
||||
|
||||
add_executable(logical-test
|
||||
logical.cc
|
||||
)
|
||||
|
@ -63,16 +83,6 @@ target_link_libraries(real-test
|
|||
m
|
||||
)
|
||||
|
||||
add_executable(expression-test
|
||||
expression.cc
|
||||
)
|
||||
|
||||
target_link_libraries(expression-test
|
||||
FortranEvaluate
|
||||
FortranEvaluateTesting
|
||||
FortranParser
|
||||
)
|
||||
|
||||
add_executable(reshape-test
|
||||
reshape.cc
|
||||
)
|
||||
|
@ -87,6 +97,7 @@ add_test(NAME Expression COMMAND expression-test)
|
|||
add_test(NAME Leadz COMMAND leading-zero-bit-count-test)
|
||||
add_test(NAME PopPar COMMAND bit-population-count-test)
|
||||
add_test(NAME Integer COMMAND integer-test)
|
||||
add_test(NAME Intrinsics COMMAND intrinsics-test)
|
||||
add_test(NAME Logical COMMAND logical-test)
|
||||
add_test(NAME Real COMMAND real-test)
|
||||
add_test(NAME RESHAPE COMMAND reshape-test)
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
// 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 "../../lib/evaluate/intrinsics.h"
|
||||
#include "testing.h"
|
||||
#include "../../lib/evaluate/expression.h"
|
||||
#include "../../lib/evaluate/tools.h"
|
||||
#include "../../lib/parser/provenance.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
template<typename A> auto Const(A &&x) -> Constant<TypeOf<A>> {
|
||||
return Constant<TypeOf<A>>{std::move(x)};
|
||||
}
|
||||
|
||||
template<typename A> void Push(Arguments &args, A &&x) {
|
||||
args.emplace_back(AsGenericExpr(std::move(x)));
|
||||
}
|
||||
template<typename A, typename... As>
|
||||
void Push(Arguments &args, A &&x, As &&... xs) {
|
||||
args.emplace_back(AsGenericExpr(std::move(x)));
|
||||
Push(args, std::move(xs)...);
|
||||
}
|
||||
template<typename... As> Arguments Args(As &&... xs) {
|
||||
Arguments args;
|
||||
Push(args, std::move(xs)...);
|
||||
return args;
|
||||
}
|
||||
|
||||
void TestIntrinsics() {
|
||||
IntrinsicTypeDefaultKinds defaults;
|
||||
MATCH(4, defaults.defaultIntegerKind);
|
||||
MATCH(4, defaults.defaultRealKind);
|
||||
IntrinsicProcTable table{IntrinsicProcTable::Configure(defaults)};
|
||||
|
||||
parser::CookedSource cooked;
|
||||
std::string name{"abs"};
|
||||
cooked.Put(name.data(), name.size());
|
||||
cooked.PutProvenance(cooked.allSources().AddCompilerInsertion(name));
|
||||
cooked.Marshal();
|
||||
TEST(cooked.data() == name);
|
||||
parser::CharBlock nameCharBlock{cooked.data().data(), name.size()};
|
||||
CallCharacteristics call{nameCharBlock, Args(Const(value::Integer<32>{1}))};
|
||||
parser::Messages buffer;
|
||||
parser::ContextualMessages messages{cooked.data(), &buffer};
|
||||
std::optional<SpecificIntrinsic> si{table.Probe(call, &messages)};
|
||||
TEST(si.has_value());
|
||||
TEST(buffer.empty());
|
||||
buffer.Emit(std::cout, cooked);
|
||||
}
|
||||
} // namespace Fortran::evaluate
|
||||
|
||||
int main() {
|
||||
Fortran::evaluate::TestIntrinsics();
|
||||
return testing::Complete();
|
||||
}
|
Loading…
Reference in New Issue