Skip to content

Commit ee27df5

Browse files
committed
Revert "[OPENMP50]Add basic support for inscan reduction modifier."
This reverts commit 36ed0ce to fix a crash in scan_messages.cpp test.
1 parent 4bc8882 commit ee27df5

File tree

8 files changed

+57
-220
lines changed

8 files changed

+57
-220
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10101,19 +10101,6 @@ def err_omp_depobj_single_clause_expected : Error<
1010110101
"exactly one of 'depend', 'destroy', or 'update' clauses is expected">;
1010210102
def err_omp_scan_single_clause_expected : Error<
1010310103
"exactly one of 'inclusive' or 'exclusive' clauses is expected">;
10104-
def err_omp_inclusive_exclusive_not_reduction : Error<
10105-
"the list item must appear in 'reduction' clause with the 'inscan' modifier "
10106-
"of the parent directive">;
10107-
def err_omp_reduction_not_inclusive_exclusive : Error<
10108-
"the inscan reduction list item must appear as a list item in an 'inclusive' or"
10109-
" 'exclusive' clause on an inner 'omp scan' directive">;
10110-
def err_omp_wrong_inscan_reduction : Error<
10111-
"'inscan' modifier can be used only in 'omp for', 'omp simd', 'omp for simd',"
10112-
" 'omp parallel for', or 'omp parallel for simd' directive">;
10113-
def err_omp_inscan_reduction_expected : Error<
10114-
"expected 'reduction' clause with the 'inscan' modifier">;
10115-
def note_omp_previous_inscan_reduction : Note<
10116-
"'reduction' clause with 'inscan' modifier is used here">;
1011710104
def err_omp_expected_predefined_allocator : Error<
1011810105
"expected one of the predefined allocators for the variables with the static "
1011910106
"storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', "

clang/include/clang/Basic/OpenMPKinds.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,6 @@ OPENMP_DEPOBJ_CLAUSE(update)
11121112

11131113
// Modifiers for 'reduction' clause.
11141114
OPENMP_REDUCTION_MODIFIER(default)
1115-
OPENMP_REDUCTION_MODIFIER(inscan)
11161115

11171116
#undef OPENMP_REDUCTION_MODIFIER
11181117
#undef OPENMP_SCAN_CLAUSE

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 11 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,14 @@ class DSAStackTy {
6262
struct DSAVarData {
6363
OpenMPDirectiveKind DKind = OMPD_unknown;
6464
OpenMPClauseKind CKind = OMPC_unknown;
65-
unsigned Modifier = 0;
6665
const Expr *RefExpr = nullptr;
6766
DeclRefExpr *PrivateCopy = nullptr;
6867
SourceLocation ImplicitDSALoc;
6968
DSAVarData() = default;
7069
DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
7170
const Expr *RefExpr, DeclRefExpr *PrivateCopy,
72-
SourceLocation ImplicitDSALoc, unsigned Modifier)
73-
: DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
71+
SourceLocation ImplicitDSALoc)
72+
: DKind(DKind), CKind(CKind), RefExpr(RefExpr),
7473
PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
7574
};
7675
using OperatorOffsetTy =
@@ -81,7 +80,6 @@ class DSAStackTy {
8180
private:
8281
struct DSAInfo {
8382
OpenMPClauseKind Attributes = OMPC_unknown;
84-
unsigned Modifier = 0;
8583
/// Pointer to a reference expression and a flag which shows that the
8684
/// variable is marked as lastprivate(true) or not (false).
8785
llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
@@ -166,8 +164,6 @@ class DSAStackTy {
166164
/// List of globals marked as declare target link in this target region
167165
/// (isOpenMPTargetExecutionDirective(Directive) == true).
168166
llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
169-
/// List of decls used in inclusive/exclusive clauses of the scan directive.
170-
llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
171167
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
172168
Scope *CurScope, SourceLocation Loc)
173169
: Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -473,20 +469,9 @@ class DSAStackTy {
473469
/// parent directive.
474470
const ValueDecl *getParentLoopControlVariable(unsigned I) const;
475471

476-
/// Marks the specified decl \p D as used in scan directive.
477-
void markDeclAsUsedInScanDirective(ValueDecl *D) {
478-
if (SharingMapTy *Stack = getSecondOnStackOrNull())
479-
Stack->UsedInScanDirective.insert(D);
480-
}
481-
482-
/// Checks if the specified declaration was used in the inner scan directive.
483-
bool isUsedInScanDirective(ValueDecl *D) const {
484-
return getTopOfStack().UsedInScanDirective.count(D) > 0;
485-
}
486-
487472
/// Adds explicit data sharing attribute to the specified declaration.
488473
void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
489-
DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0);
474+
DeclRefExpr *PrivateCopy = nullptr);
490475

491476
/// Adds additional information for the reduction items with the reduction id
492477
/// represented as an operator.
@@ -1094,7 +1079,6 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
10941079
DVar.PrivateCopy = Data.PrivateCopy;
10951080
DVar.CKind = Data.Attributes;
10961081
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1097-
DVar.Modifier = Data.Modifier;
10981082
return DVar;
10991083
}
11001084

@@ -1242,21 +1226,19 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
12421226
}
12431227

12441228
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1245-
DeclRefExpr *PrivateCopy, unsigned Modifier) {
1229+
DeclRefExpr *PrivateCopy) {
12461230
D = getCanonicalDecl(D);
12471231
if (A == OMPC_threadprivate) {
12481232
DSAInfo &Data = Threadprivates[D];
12491233
Data.Attributes = A;
12501234
Data.RefExpr.setPointer(E);
12511235
Data.PrivateCopy = nullptr;
1252-
Data.Modifier = Modifier;
12531236
} else {
12541237
DSAInfo &Data = getTopOfStack().SharingMap[D];
12551238
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
12561239
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
12571240
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
12581241
(isLoopControlVariable(D).first && A == OMPC_private));
1259-
Data.Modifier = Modifier;
12601242
if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
12611243
Data.RefExpr.setInt(/*IntVal=*/true);
12621244
return;
@@ -1268,7 +1250,6 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
12681250
Data.PrivateCopy = PrivateCopy;
12691251
if (PrivateCopy) {
12701252
DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1271-
Data.Modifier = Modifier;
12721253
Data.Attributes = A;
12731254
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
12741255
Data.PrivateCopy = nullptr;
@@ -1374,7 +1355,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
13741355
"set.");
13751356
TaskgroupDescriptor = I->TaskgroupReductionRef;
13761357
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
1377-
Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0);
1358+
Data.PrivateCopy, I->DefaultAttrLoc);
13781359
}
13791360
return DSAVarData();
13801361
}
@@ -1399,7 +1380,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
13991380
"set.");
14001381
TaskgroupDescriptor = I->TaskgroupReductionRef;
14011382
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
1402-
Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0);
1383+
Data.PrivateCopy, I->DefaultAttrLoc);
14031384
}
14041385
return DSAVarData();
14051386
}
@@ -1474,7 +1455,6 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
14741455
if (TI != Threadprivates.end()) {
14751456
DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
14761457
DVar.CKind = OMPC_threadprivate;
1477-
DVar.Modifier = TI->getSecond().Modifier;
14781458
return DVar;
14791459
}
14801460
if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
@@ -1566,7 +1546,6 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
15661546
DVar.CKind = Data.Attributes;
15671547
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
15681548
DVar.DKind = I->Directive;
1569-
DVar.Modifier = Data.Modifier;
15701549
return DVar;
15711550
}
15721551

@@ -1613,7 +1592,6 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
16131592
DVar.CKind = Data.Attributes;
16141593
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
16151594
DVar.DKind = I->Directive;
1616-
DVar.Modifier = Data.Modifier;
16171595
}
16181596

16191597
return DVar;
@@ -2337,64 +2315,11 @@ void Sema::EndOpenMPClause() {
23372315
DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
23382316
}
23392317

2318+
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2319+
ArrayRef<OMPClause *> Clauses);
23402320
static std::pair<ValueDecl *, bool>
23412321
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
23422322
SourceRange &ERange, bool AllowArraySection = false);
2343-
2344-
/// Check consistency of the reduction clauses.
2345-
static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2346-
ArrayRef<OMPClause *> Clauses) {
2347-
bool InscanFound = false;
2348-
SourceLocation InscanLoc;
2349-
// OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2350-
// A reduction clause without the inscan reduction-modifier may not appear on
2351-
// a construct on which a reduction clause with the inscan reduction-modifier
2352-
// appears.
2353-
for (OMPClause *C : Clauses) {
2354-
if (C->getClauseKind() != OMPC_reduction)
2355-
continue;
2356-
auto *RC = cast<OMPReductionClause>(C);
2357-
if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2358-
InscanFound = true;
2359-
InscanLoc = RC->getModifierLoc();
2360-
break;
2361-
}
2362-
}
2363-
if (InscanFound) {
2364-
for (OMPClause *C : Clauses) {
2365-
if (C->getClauseKind() != OMPC_reduction)
2366-
continue;
2367-
auto *RC = cast<OMPReductionClause>(C);
2368-
if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2369-
S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2370-
? RC->getBeginLoc()
2371-
: RC->getModifierLoc(),
2372-
diag::err_omp_inscan_reduction_expected);
2373-
S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2374-
continue;
2375-
}
2376-
for (Expr *Ref : RC->varlists()) {
2377-
assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2378-
SourceLocation ELoc;
2379-
SourceRange ERange;
2380-
Expr *SimpleRefExpr = Ref;
2381-
auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2382-
/*AllowArraySection=*/true);
2383-
ValueDecl *D = Res.first;
2384-
if (!D)
2385-
continue;
2386-
if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2387-
S.Diag(Ref->getExprLoc(),
2388-
diag::err_omp_reduction_not_inclusive_exclusive)
2389-
<< Ref->getSourceRange();
2390-
}
2391-
}
2392-
}
2393-
}
2394-
}
2395-
2396-
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2397-
ArrayRef<OMPClause *> Clauses);
23982323
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
23992324
bool WithInit);
24002325

@@ -2471,7 +2396,6 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
24712396
// Check allocate clauses.
24722397
if (!CurContext->isDependentContext())
24732398
checkAllocateClauses(*this, DSAStack, D->clauses());
2474-
checkReductionClauses(*this, DSAStack, D->clauses());
24752399
}
24762400

24772401
DSAStack->pop();
@@ -14187,11 +14111,9 @@ struct ReductionData {
1418714111
SmallVector<Decl *, 4> ExprCaptures;
1418814112
/// List of postupdate expressions.
1418914113
SmallVector<Expr *, 4> ExprPostUpdates;
14190-
/// Reduction modifier.
14191-
unsigned RedModifier = 0;
1419214114
ReductionData() = delete;
1419314115
/// Reserves required memory for the reduction data.
14194-
ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
14116+
ReductionData(unsigned Size) {
1419514117
Vars.reserve(Size);
1419614118
Privates.reserve(Size);
1419714119
LHSs.reserve(Size);
@@ -14909,8 +14831,7 @@ static bool actOnOMPReductionKindClause(
1490914831
}
1491014832
// All reduction items are still marked as reduction (to do not increase
1491114833
// code base size).
14912-
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref,
14913-
RD.RedModifier);
14834+
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
1491414835
if (CurrDir == OMPD_taskgroup) {
1491514836
if (DeclareReductionRef.isUsable())
1491614837
Stack->addTaskgroupReductionData(D, ReductionIdRange,
@@ -14937,22 +14858,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
1493714858
<< getOpenMPClauseName(OMPC_reduction);
1493814859
return nullptr;
1493914860
}
14940-
// OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
14941-
// A reduction clause with the inscan reduction-modifier may only appear on a
14942-
// worksharing-loop construct, a worksharing-loop SIMD construct, a simd
14943-
// construct, a parallel worksharing-loop construct or a parallel
14944-
// worksharing-loop SIMD construct.
14945-
if (Modifier == OMPC_REDUCTION_inscan &&
14946-
(DSAStack->getCurrentDirective() != OMPD_for &&
14947-
DSAStack->getCurrentDirective() != OMPD_for_simd &&
14948-
DSAStack->getCurrentDirective() != OMPD_simd &&
14949-
DSAStack->getCurrentDirective() != OMPD_parallel_for &&
14950-
DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
14951-
Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
14952-
return nullptr;
14953-
}
1495414861

14955-
ReductionData RD(VarList.size(), Modifier);
14862+
ReductionData RD(VarList.size());
1495614863
if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
1495714864
StartLoc, LParenLoc, ColonLoc, EndLoc,
1495814865
ReductionIdScopeSpec, ReductionId,
@@ -18254,19 +18161,6 @@ OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
1825418161
if (!D)
1825518162
continue;
1825618163

18257-
const DSAStackTy::DSAVarData DVar =
18258-
DSAStack->getTopDSA(D, /*FromParent=*/true);
18259-
// OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
18260-
// A list item that appears in the inclusive or exclusive clause must appear
18261-
// in a reduction clause with the inscan modifier on the enclosing
18262-
// worksharing-loop, worksharing-loop SIMD, or simd construct.
18263-
if (DVar.CKind != OMPC_reduction ||
18264-
DVar.Modifier != OMPC_REDUCTION_inscan)
18265-
Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
18266-
<< RefExpr->getSourceRange();
18267-
18268-
if (DSAStack->getParentDirective() != OMPD_unknown)
18269-
DSAStack->markDeclAsUsedInScanDirective(D);
1827018164
Vars.push_back(RefExpr);
1827118165
}
1827218166

@@ -18295,19 +18189,6 @@ OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
1829518189
if (!D)
1829618190
continue;
1829718191

18298-
const DSAStackTy::DSAVarData DVar =
18299-
DSAStack->getTopDSA(D, /*FromParent=*/true);
18300-
// OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
18301-
// A list item that appears in the inclusive or exclusive clause must appear
18302-
// in a reduction clause with the inscan modifier on the enclosing
18303-
// worksharing-loop, worksharing-loop SIMD, or simd construct.
18304-
if (DVar.CKind != OMPC_reduction ||
18305-
DVar.Modifier != OMPC_REDUCTION_inscan)
18306-
Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
18307-
<< RefExpr->getSourceRange();
18308-
18309-
if (DSAStack->getParentDirective() != OMPD_unknown)
18310-
DSAStack->markDeclAsUsedInScanDirective(D);
1831118192
Vars.push_back(RefExpr);
1831218193
}
1831318194

clang/test/OpenMP/nesting_of_regions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2892,7 +2892,7 @@ void foo() {
28922892
}
28932893
#pragma omp parallel for simd
28942894
for (int i = 0; i < 10; ++i) {
2895-
#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
2895+
#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
28962896
bar();
28972897
}
28982898
#pragma omp parallel for simd

clang/test/OpenMP/parallel_for_reduction_messages.cpp

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 150 -o - %s -Wuninitialized
2-
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
3-
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
1+
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s -Wuninitialized
2+
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
3+
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
44

5-
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 150 -o - %s -Wuninitialized
6-
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
7-
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
5+
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s -Wuninitialized
6+
// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
7+
// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
88

99
extern int omp_default_mem_alloc;
1010
void xxx(int argc) {
@@ -78,14 +78,6 @@ class S5 {
7878
#pragma omp for reduction(+:a) // expected-error {{reduction variable must be shared}}
7979
for (int i = 0; i < 10; ++i)
8080
::foo();
81-
#pragma omp parallel for reduction(inscan, +:a)
82-
for (int i = 0; i < 10; ++i) {
83-
#pragma omp scan inclusive(a)
84-
}
85-
#pragma omp parallel for reduction(inscan, +:a)
86-
for (int i = 0; i < 10; ++i) {
87-
#pragma omp scan exclusive(a)
88-
}
8981
}
9082
};
9183
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
@@ -341,21 +333,5 @@ int main(int argc, char **argv) {
341333
for (int i = 0; i < 10; ++i)
342334
m++;
343335

344-
#pragma omp parallel for reduction(inscan, + : m) reduction(*: fl) reduction(default, &&: j) // expected-error 2 {{expected 'reduction' clause with the 'inscan' modifier}} expected-note 2 {{'reduction' clause with 'inscan' modifier is used here}}
345-
for (int i = 0; i < 10; ++i) {
346-
#pragma omp scan exclusive(m)
347-
m++;
348-
}
349-
#pragma omp parallel for reduction(inscan, + : m, fl, j) // expected-error 2 {{the inscan reduction list item must appear as a list item in an 'inclusive' or 'exclusive' clause on an inner 'omp scan' directive}}
350-
for (int i = 0; i < 10; ++i) {
351-
#pragma omp scan exclusive(m)
352-
m++;
353-
}
354-
#pragma omp parallel for reduction(inscan, + : m, fl, j) // expected-error 2 {{the inscan reduction list item must appear as a list item in an 'inclusive' or 'exclusive' clause on an inner 'omp scan' directive}}
355-
for (int i = 0; i < 10; ++i) {
356-
#pragma omp scan inclusive(m)
357-
m++;
358-
}
359-
360336
return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
361337
}

0 commit comments

Comments
 (0)