Author: abataev Date: Wed Sep 12 09:31:59 2018 New Revision: 342062 URL: http://llvm.org/viewvc/llvm-project?rev=342062&view=rev Log: [OPENMP] Fix PR38902: support ADL for declare reduction constructs.
Added support for argument-dependent lookup when trying to find the required declare reduction decl. Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp cfe/trunk/test/OpenMP/declare_reduction_ast_print.cpp Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=342062&r1=342061&r2=342062&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original) +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Sep 12 09:31:59 2018 @@ -10068,6 +10068,79 @@ static T filterLookupForUDR(SmallVectorI return T(); } +static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { + assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); + + for (auto RD : D->redecls()) { + // Don't bother with extra checks if we already know this one isn't visible. + if (RD == D) + continue; + + auto ND = cast<NamedDecl>(RD); + if (LookupResult::isVisible(SemaRef, ND)) + return ND; + } + + return nullptr; +} + +static void +argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &ReductionId, + SourceLocation Loc, QualType Ty, + SmallVectorImpl<UnresolvedSet<8>> &Lookups) { + // Find all of the associated namespaces and classes based on the + // arguments we have. + Sema::AssociatedNamespaceSet AssociatedNamespaces; + Sema::AssociatedClassSet AssociatedClasses; + OpaqueValueExpr OVE(Loc, Ty, VK_LValue); + SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces, + AssociatedClasses); + + // C++ [basic.lookup.argdep]p3: + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains [...] then Y is + // empty. Otherwise Y is the set of declarations found in the + // namespaces associated with the argument types as described + // below. The set of declarations found by the lookup of the name + // is the union of X and Y. + // + // Here, we compute Y and add its members to the overloaded + // candidate set. + for (auto *NS : AssociatedNamespaces) { + // When considering an associated namespace, the lookup is the + // same as the lookup performed when the associated namespace is + // used as a qualifier (3.4.3.2) except that: + // + // -- Any using-directives in the associated namespace are + // ignored. + // + // -- Any namespace-scope friend functions declared in + // associated classes are visible within their respective + // namespaces even if they are not visible during an ordinary + // lookup (11.4). + DeclContext::lookup_result R = NS->lookup(ReductionId.getName()); + for (auto *D : R) { + auto *Underlying = D; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + + if (!isa<OMPDeclareReductionDecl>(Underlying)) + continue; + + if (!SemaRef.isVisible(D)) { + D = findAcceptableDecl(SemaRef, D); + if (!D) + continue; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + } + Lookups.emplace_back(); + Lookups.back().addDecl(Underlying); + } + } +} + static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, @@ -10086,7 +10159,7 @@ buildDeclareReductionRef(Sema &SemaRef, } while (S && !S->isDeclScope(D)); if (S) S = S->getParent(); - Lookups.push_back(UnresolvedSet<8>()); + Lookups.emplace_back(); Lookups.back().append(Lookup.begin(), Lookup.end()); Lookup.clear(); } @@ -10113,6 +10186,8 @@ buildDeclareReductionRef(Sema &SemaRef, })) { UnresolvedSet<8> ResSet; for (const UnresolvedSet<8> &Set : Lookups) { + if (Set.empty()) + continue; ResSet.append(Set.begin(), Set.end()); // The last item marks the end of all declarations at the specified scope. ResSet.addDecl(Set[Set.size() - 1]); @@ -10122,6 +10197,36 @@ buildDeclareReductionRef(Sema &SemaRef, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end()); } + // Lookup inside the classes. + // C++ [over.match.oper]p3: + // For a unary operator @ with an operand of a type whose + // cv-unqualified version is T1, and for a binary operator @ with + // a left operand of a type whose cv-unqualified version is T1 and + // a right operand of a type whose cv-unqualified version is T2, + // three sets of candidate functions, designated member + // candidates, non-member candidates and built-in candidates, are + // constructed as follows: + // -- If T1 is a complete class type or a class currently being + // defined, the set of member candidates is the result of the + // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, + // the set of member candidates is empty. + LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); + Lookup.suppressDiagnostics(); + if (const auto *TyRec = Ty->getAs<RecordType>()) { + // Complete the type if it can be completed. + // If the type is neither complete nor being defined, bail out now. + if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() || + TyRec->getDecl()->getDefinition()) { + Lookup.clear(); + SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl()); + if (Lookup.empty()) { + Lookups.emplace_back(); + Lookups.back().append(Lookup.begin(), Lookup.end()); + } + } + } + // Perform ADL. + argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups); if (auto *VD = filterLookupForUDR<ValueDecl *>( Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && Modified: cfe/trunk/test/OpenMP/declare_reduction_ast_print.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_reduction_ast_print.cpp?rev=342062&r1=342061&r2=342062&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/declare_reduction_ast_print.cpp (original) +++ cfe/trunk/test/OpenMP/declare_reduction_ast_print.cpp Wed Sep 12 09:31:59 2018 @@ -10,6 +10,15 @@ #ifndef HEADER #define HEADER +template <typename T> +void bar(T &x, T &y) { x.a += y.a; } + +namespace N1 +{ + struct A { int a; A() : a(0) {} }; + #pragma omp declare reduction(+: A : bar(omp_out, omp_in)) +}; + #pragma omp declare reduction(+ : int, char : omp_out *= omp_in) // CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in){{$}} // CHECK-NEXT: #pragma omp declare reduction (+ : char : omp_out *= omp_in) @@ -66,6 +75,11 @@ int main() { // TODO-CHECK: #pragma omp parallel reduction(::fun: sss) { } + N1::A a; + // CHECK: #pragma omp parallel reduction(+: a) + #pragma omp parallel reduction(+: a) + { + } return foo(15); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits