aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Semantics
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics')
-rw-r--r--flang/lib/Semantics/check-allocate.cpp33
-rw-r--r--flang/lib/Semantics/check-allocate.h1
-rw-r--r--flang/lib/Semantics/check-call.cpp6
-rw-r--r--flang/lib/Semantics/check-deallocate.cpp111
-rw-r--r--flang/lib/Semantics/check-declarations.cpp3
-rw-r--r--flang/lib/Semantics/check-omp-structure.cpp1
-rw-r--r--flang/lib/Semantics/expression.cpp2
-rw-r--r--flang/lib/Semantics/mod-file.cpp3
-rw-r--r--flang/lib/Semantics/resolve-directives.cpp17
-rw-r--r--flang/lib/Semantics/resolve-names.cpp121
10 files changed, 180 insertions, 118 deletions
diff --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp
index e019bbd..a411e20 100644
--- a/flang/lib/Semantics/check-allocate.cpp
+++ b/flang/lib/Semantics/check-allocate.cpp
@@ -26,6 +26,10 @@ struct AllocateCheckerInfo {
std::optional<evaluate::DynamicType> sourceExprType;
std::optional<parser::CharBlock> sourceExprLoc;
std::optional<parser::CharBlock> typeSpecLoc;
+ std::optional<parser::CharBlock> statSource;
+ std::optional<parser::CharBlock> msgSource;
+ const SomeExpr *statVar{nullptr};
+ const SomeExpr *msgVar{nullptr};
int sourceExprRank{0}; // only valid if gotMold || gotSource
bool gotStat{false};
bool gotMsg{false};
@@ -141,12 +145,15 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(
[&](const parser::StatOrErrmsg &statOrErr) {
common::visit(
common::visitors{
- [&](const parser::StatVariable &) {
+ [&](const parser::StatVariable &var) {
if (info.gotStat) { // C943
context.Say(
"STAT may not be duplicated in a ALLOCATE statement"_err_en_US);
}
info.gotStat = true;
+ info.statVar = GetExpr(context, var);
+ info.statSource =
+ parser::Unwrap<parser::Variable>(var)->GetSource();
},
[&](const parser::MsgVariable &var) {
WarnOnDeferredLengthCharacterScalar(context,
@@ -159,6 +166,9 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(
"ERRMSG may not be duplicated in a ALLOCATE statement"_err_en_US);
}
info.gotMsg = true;
+ info.msgVar = GetExpr(context, var);
+ info.msgSource =
+ parser::Unwrap<parser::Variable>(var)->GetSource();
},
},
statOrErr.u);
@@ -460,6 +470,16 @@ static bool HaveCompatibleLengths(
}
}
+bool AreSameAllocation(const SomeExpr *root, const SomeExpr *path) {
+ if (root && path) {
+ // For now we just use equality of expressions. If we implement a more
+ // sophisticated alias analysis we should use it here.
+ return *root == *path;
+ } else {
+ return false;
+ }
+}
+
bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
if (!ultimate_) {
CHECK(context.AnyFatalError());
@@ -690,6 +710,17 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
"Object in ALLOCATE must have DEVICE attribute when STREAM option is specified"_err_en_US);
}
}
+
+ if (const SomeExpr *allocObj{GetExpr(context, allocateObject_)}) {
+ if (AreSameAllocation(allocObj, allocateInfo_.statVar)) {
+ context.Say(allocateInfo_.statSource.value_or(name_.source),
+ "STAT variable in ALLOCATE must not be the variable being allocated"_err_en_US);
+ }
+ if (AreSameAllocation(allocObj, allocateInfo_.msgVar)) {
+ context.Say(allocateInfo_.msgSource.value_or(name_.source),
+ "ERRMSG variable in ALLOCATE must not be the variable being allocated"_err_en_US);
+ }
+ }
return RunCoarrayRelatedChecks(context);
}
diff --git a/flang/lib/Semantics/check-allocate.h b/flang/lib/Semantics/check-allocate.h
index e3f7f07..54f7380 100644
--- a/flang/lib/Semantics/check-allocate.h
+++ b/flang/lib/Semantics/check-allocate.h
@@ -24,5 +24,6 @@ public:
private:
SemanticsContext &context_;
};
+bool AreSameAllocation(const SomeExpr *root, const SomeExpr *path);
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CHECK_ALLOCATE_H_
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index c51d40b..995deaa 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -914,7 +914,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummyName);
}
// INTENT(OUT) and INTENT(IN OUT) cases are caught elsewhere
- } else {
+ } else if (!actualIsAllocatable &&
+ !dummy.ignoreTKR.test(common::IgnoreTKR::Pointer)) {
messages.Say(
"ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
dummyName);
@@ -929,7 +930,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummy, actual, *scope,
/*isAssumedRank=*/dummyIsAssumedRank, actualIsPointer);
}
- } else if (!actualIsPointer) {
+ } else if (!actualIsPointer &&
+ !dummy.ignoreTKR.test(common::IgnoreTKR::Pointer)) {
messages.Say(
"Actual argument associated with POINTER %s must also be POINTER unless INTENT(IN)"_err_en_US,
dummyName);
diff --git a/flang/lib/Semantics/check-deallocate.cpp b/flang/lib/Semantics/check-deallocate.cpp
index c1ebc5f..e6ce1b3 100644
--- a/flang/lib/Semantics/check-deallocate.cpp
+++ b/flang/lib/Semantics/check-deallocate.cpp
@@ -7,51 +7,87 @@
//===----------------------------------------------------------------------===//
#include "check-deallocate.h"
+#include "check-allocate.h"
#include "definable.h"
#include "flang/Evaluate/type.h"
#include "flang/Parser/message.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/tools.h"
+#include <optional>
namespace Fortran::semantics {
void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
+ bool gotStat{false}, gotMsg{false};
+ const SomeExpr *statVar{nullptr}, *msgVar{nullptr};
+ std::optional<parser::CharBlock> statSource;
+ std::optional<parser::CharBlock> msgSource;
+ for (const parser::StatOrErrmsg &deallocOpt :
+ std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) {
+ common::visit(
+ common::visitors{
+ [&](const parser::StatVariable &var) {
+ if (gotStat) {
+ context_.Say(
+ "STAT may not be duplicated in a DEALLOCATE statement"_err_en_US);
+ }
+ gotStat = true;
+ statVar = GetExpr(context_, var);
+ statSource = parser::Unwrap<parser::Variable>(var)->GetSource();
+ },
+ [&](const parser::MsgVariable &var) {
+ WarnOnDeferredLengthCharacterScalar(context_,
+ GetExpr(context_, var),
+ parser::UnwrapRef<parser::Variable>(var).GetSource(),
+ "ERRMSG=");
+ if (gotMsg) {
+ context_.Say(
+ "ERRMSG may not be duplicated in a DEALLOCATE statement"_err_en_US);
+ }
+ gotMsg = true;
+ msgVar = GetExpr(context_, var);
+ msgSource = parser::Unwrap<parser::Variable>(var)->GetSource();
+ },
+ },
+ deallocOpt.u);
+ }
for (const parser::AllocateObject &allocateObject :
std::get<std::list<parser::AllocateObject>>(deallocateStmt.t)) {
+ parser::CharBlock source;
common::visit(
common::visitors{
[&](const parser::Name &name) {
const Symbol *symbol{
name.symbol ? &name.symbol->GetUltimate() : nullptr};
- ;
+ source = name.source;
if (context_.HasError(symbol)) {
// already reported an error
} else if (!IsVariableName(*symbol)) {
- context_.Say(name.source,
+ context_.Say(source,
"Name in DEALLOCATE statement must be a variable name"_err_en_US);
} else if (!IsAllocatableOrObjectPointer(symbol)) { // C936
- context_.Say(name.source,
+ context_.Say(source,
"Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
- } else if (auto whyNot{WhyNotDefinable(name.source,
- context_.FindScope(name.source),
- {DefinabilityFlag::PointerDefinition,
- DefinabilityFlag::AcceptAllocatable,
- DefinabilityFlag::PotentialDeallocation},
- *symbol)}) {
+ } else if (auto whyNot{
+ WhyNotDefinable(source, context_.FindScope(source),
+ {DefinabilityFlag::PointerDefinition,
+ DefinabilityFlag::AcceptAllocatable,
+ DefinabilityFlag::PotentialDeallocation},
+ *symbol)}) {
// Catch problems with non-definability of the
// pointer/allocatable
context_
- .Say(name.source,
+ .Say(source,
"Name in DEALLOCATE statement is not definable"_err_en_US)
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
- } else if (auto whyNot{WhyNotDefinable(name.source,
- context_.FindScope(name.source),
- DefinabilityFlags{}, *symbol)}) {
+ } else if (auto whyNot{
+ WhyNotDefinable(source, context_.FindScope(source),
+ DefinabilityFlags{}, *symbol)}) {
// Catch problems with non-definability of the dynamic object
context_
- .Say(name.source,
+ .Say(source,
"Object in DEALLOCATE statement is not deallocatable"_err_en_US)
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
@@ -62,13 +98,12 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
[&](const parser::StructureComponent &structureComponent) {
// Only perform structureComponent checks if it was successfully
// analyzed by expression analysis.
- auto source{structureComponent.component.source};
+ source = structureComponent.component.source;
if (const auto *expr{GetExpr(context_, allocateObject)}) {
- if (const Symbol *
- symbol{structureComponent.component.symbol
- ? &structureComponent.component.symbol
- ->GetUltimate()
- : nullptr};
+ if (const Symbol *symbol{structureComponent.component.symbol
+ ? &structureComponent.component.symbol
+ ->GetUltimate()
+ : nullptr};
!IsAllocatableOrObjectPointer(symbol)) { // F'2023 C936
context_.Say(source,
"Component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
@@ -99,32 +134,16 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
},
},
allocateObject.u);
- }
- bool gotStat{false}, gotMsg{false};
- for (const parser::StatOrErrmsg &deallocOpt :
- std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) {
- common::visit(
- common::visitors{
- [&](const parser::StatVariable &) {
- if (gotStat) {
- context_.Say(
- "STAT may not be duplicated in a DEALLOCATE statement"_err_en_US);
- }
- gotStat = true;
- },
- [&](const parser::MsgVariable &var) {
- WarnOnDeferredLengthCharacterScalar(context_,
- GetExpr(context_, var),
- parser::UnwrapRef<parser::Variable>(var).GetSource(),
- "ERRMSG=");
- if (gotMsg) {
- context_.Say(
- "ERRMSG may not be duplicated in a DEALLOCATE statement"_err_en_US);
- }
- gotMsg = true;
- },
- },
- deallocOpt.u);
+ if (const SomeExpr *allocObj{GetExpr(context_, allocateObject)}) {
+ if (AreSameAllocation(allocObj, statVar)) {
+ context_.Say(statSource.value_or(source),
+ "STAT variable in DEALLOCATE must not be the variable being deallocated"_err_en_US);
+ }
+ if (AreSameAllocation(allocObj, msgVar)) {
+ context_.Say(msgSource.value_or(source),
+ "ERRMSG variable in DEALLOCATE must not be the variable being deallocated"_err_en_US);
+ }
+ }
}
}
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 549ee83..de407d3 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -949,7 +949,8 @@ void CheckHelper::CheckObjectEntity(
"!DIR$ IGNORE_TKR(R) may not apply in an ELEMENTAL procedure"_err_en_US);
}
if (IsPassedViaDescriptor(symbol)) {
- if (IsAllocatableOrObjectPointer(&symbol)) {
+ if (IsAllocatableOrObjectPointer(&symbol) &&
+ !ignoreTKR.test(common::IgnoreTKR::Pointer)) {
if (inExplicitExternalInterface) {
Warn(common::UsageWarning::IgnoreTKRUsage,
"!DIR$ IGNORE_TKR should not apply to an allocatable or pointer"_warn_en_US);
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index e094458f..aaaf1ec 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3390,6 +3390,7 @@ CHECK_SIMPLE_CLAUSE(Read, OMPC_read)
CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate)
CHECK_SIMPLE_CLAUSE(Groupprivate, OMPC_groupprivate)
CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads)
+CHECK_SIMPLE_CLAUSE(Threadset, OMPC_threadset)
CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch)
CHECK_SIMPLE_CLAUSE(Link, OMPC_link)
CHECK_SIMPLE_CLAUSE(Indirect, OMPC_indirect)
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 32aa6b1..c8167fd 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -834,7 +834,7 @@ Constant<TYPE> ReadRealLiteral(
auto valWithFlags{
Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())};
CHECK(p == source.end());
- RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
+ context.RealFlagWarnings(valWithFlags.flags, "conversion of REAL literal");
auto value{valWithFlags.value};
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
value = value.FlushSubnormalToZero();
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index 556259d..b419864 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -1021,6 +1021,9 @@ void ModFileWriter::PutObjectEntity(
case common::IgnoreTKR::Contiguous:
os << 'c';
break;
+ case common::IgnoreTKR::Pointer:
+ os << 'p';
+ break;
}
});
os << ") " << symbol.name() << '\n';
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 196755e..628068f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -26,6 +26,8 @@
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "flang/Support/Flags.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Frontend/OpenMP/OMP.h.inc"
#include "llvm/Support/Debug.h"
#include <list>
@@ -453,6 +455,21 @@ public:
return true;
}
+ bool Pre(const parser::OmpStylizedDeclaration &x) {
+ static llvm::StringMap<Symbol::Flag> map{
+ {"omp_in", Symbol::Flag::OmpInVar},
+ {"omp_orig", Symbol::Flag::OmpOrigVar},
+ {"omp_out", Symbol::Flag::OmpOutVar},
+ {"omp_priv", Symbol::Flag::OmpPrivVar},
+ };
+ if (auto &name{std::get<parser::ObjectName>(x.var.t)}; name.symbol) {
+ if (auto found{map.find(name.ToString())}; found != map.end()) {
+ ResolveOmp(name, found->second,
+ const_cast<Scope &>(DEREF(name.symbol).owner()));
+ }
+ }
+ return false;
+ }
bool Pre(const parser::OmpMetadirectiveDirective &x) {
PushContext(x.v.source, llvm::omp::Directive::OMPD_metadirective);
return true;
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 93faba7..220f1c9 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1605,6 +1605,12 @@ public:
Post(static_cast<const parser::OmpDirectiveSpecification &>(x));
}
+ void Post(const parser::OmpTypeName &);
+ bool Pre(const parser::OmpStylizedDeclaration &);
+ void Post(const parser::OmpStylizedDeclaration &);
+ bool Pre(const parser::OmpStylizedInstance &);
+ void Post(const parser::OmpStylizedInstance &);
+
bool Pre(const parser::OpenMPDeclareMapperConstruct &x) {
AddOmpSourceRange(x.source);
return true;
@@ -1615,18 +1621,6 @@ public:
return true;
}
- bool Pre(const parser::OmpInitializerProc &x) {
- auto &procDes = std::get<parser::ProcedureDesignator>(x.t);
- auto &name = std::get<parser::Name>(procDes.u);
- auto *symbol{FindSymbol(NonDerivedTypeScope(), name)};
- if (!symbol) {
- context().Say(name.source,
- "Implicit subroutine declaration '%s' in DECLARE REDUCTION"_err_en_US,
- name.source);
- }
- return true;
- }
-
bool Pre(const parser::OmpDeclareVariantDirective &x) {
AddOmpSourceRange(x.source);
return true;
@@ -1772,14 +1766,6 @@ public:
messageHandler().set_currStmtSource(std::nullopt);
}
- bool Pre(const parser::OmpTypeName &x) {
- BeginDeclTypeSpec();
- return true;
- }
- void Post(const parser::OmpTypeName &x) { //
- EndDeclTypeSpec();
- }
-
bool Pre(const parser::OpenMPConstruct &x) {
// Indicate that the current directive is not a declarative one.
declaratives_.push_back(nullptr);
@@ -1835,6 +1821,30 @@ void OmpVisitor::Post(const parser::OmpBlockConstruct &x) {
}
}
+void OmpVisitor::Post(const parser::OmpTypeName &x) {
+ x.declTypeSpec = GetDeclTypeSpec();
+}
+
+bool OmpVisitor::Pre(const parser::OmpStylizedDeclaration &x) {
+ BeginDecl();
+ Walk(x.type.get());
+ Walk(x.var);
+ return true;
+}
+
+void OmpVisitor::Post(const parser::OmpStylizedDeclaration &x) { //
+ EndDecl();
+}
+
+bool OmpVisitor::Pre(const parser::OmpStylizedInstance &x) {
+ PushScope(Scope::Kind::OtherConstruct, nullptr);
+ return true;
+}
+
+void OmpVisitor::Post(const parser::OmpStylizedInstance &x) { //
+ PopScope();
+}
+
bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
auto &mods{OmpGetModifiers(x)};
if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
@@ -1969,51 +1979,20 @@ void OmpVisitor::ProcessReductionSpecifier(
}
}
- auto &typeList{std::get<parser::OmpTypeNameList>(spec.t)};
-
- // Create a temporary variable declaration for the four variables
- // used in the reduction specifier and initializer (omp_out, omp_in,
- // omp_priv and omp_orig), with the type in the typeList.
- //
- // In theory it would be possible to create only variables that are
- // actually used, but that requires walking the entire parse-tree of the
- // expressions, and finding the relevant variables [there may well be other
- // variables involved too].
- //
- // This allows doing semantic analysis where the type is a derived type
- // e.g omp_out%x = omp_out%x + omp_in%x.
- //
- // These need to be temporary (in their own scope). If they are created
- // as variables in the outer scope, if there's more than one type in the
- // typelist, duplicate symbols will be reported.
- const parser::CharBlock ompVarNames[]{
- {"omp_in", 6}, {"omp_out", 7}, {"omp_priv", 8}, {"omp_orig", 8}};
-
- for (auto &t : typeList.v) {
- PushScope(Scope::Kind::OtherConstruct, nullptr);
- BeginDeclTypeSpec();
- // We need to walk t.u because Walk(t) does it's own BeginDeclTypeSpec.
- Walk(t.u);
+ reductionDetails->AddDecl(declaratives_.back());
- // Only process types we can find. There will be an error later on when
- // a type isn't found.
- if (const DeclTypeSpec *typeSpec{GetDeclTypeSpec()}) {
- reductionDetails->AddType(*typeSpec);
+ // Do not walk OmpTypeNameList. The types on the list will be visited
+ // during procesing of OmpCombinerExpression.
+ Walk(std::get<std::optional<parser::OmpCombinerExpression>>(spec.t));
+ Walk(clauses);
- for (auto &nm : ompVarNames) {
- ObjectEntityDetails details{};
- details.set_type(*typeSpec);
- MakeSymbol(nm, Attrs{}, std::move(details));
- }
+ for (auto &type : std::get<parser::OmpTypeNameList>(spec.t).v) {
+ // The declTypeSpec can be null if there is some semantic error.
+ if (type.declTypeSpec) {
+ reductionDetails->AddType(*type.declTypeSpec);
}
- EndDeclTypeSpec();
- Walk(std::get<std::optional<parser::OmpCombinerExpression>>(spec.t));
- Walk(clauses);
- PopScope();
}
- reductionDetails->AddDecl(declaratives_.back());
-
if (!symbol) {
symbol = &MakeSymbol(mangledName, Attrs{}, std::move(*reductionDetails));
}
@@ -9456,13 +9435,18 @@ bool ResolveNamesVisitor::SetProcFlag(
SayWithDecl(name, symbol,
"Implicit declaration of function '%s' has a different result type than in previous declaration"_err_en_US);
return false;
- } else if (symbol.has<ProcEntityDetails>()) {
- symbol.set(flag); // in case it hasn't been set yet
- if (flag == Symbol::Flag::Function) {
- ApplyImplicitRules(symbol);
- }
- if (symbol.attrs().test(Attr::INTRINSIC)) {
- AcquireIntrinsicProcedureFlags(symbol);
+ } else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
+ if (IsPointer(symbol) && !proc->type() && !proc->procInterface()) {
+ // PROCEDURE(), POINTER -- errors will be emitted later about a lack
+ // of known characteristics if used as a function
+ } else {
+ symbol.set(flag); // in case it hasn't been set yet
+ if (flag == Symbol::Flag::Function) {
+ ApplyImplicitRules(symbol);
+ }
+ if (symbol.attrs().test(Attr::INTRINSIC)) {
+ AcquireIntrinsicProcedureFlags(symbol);
+ }
}
} else if (symbol.GetType() && flag == Symbol::Flag::Subroutine) {
SayWithDecl(
@@ -10130,6 +10114,9 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
case 'c':
set.set(common::IgnoreTKR::Contiguous);
break;
+ case 'p':
+ set.set(common::IgnoreTKR::Pointer);
+ break;
case 'a':
set = common::ignoreTKRAll;
break;