https://github.com/akash-manna-sky created https://github.com/llvm/llvm-project/pull/225604
Fixes #154704 When a variable is implicitly mapped on `#pragma omp target`, Clang looks for a user-defined mapper for its type through ADL, and ADL may have to instantiate class template specializations named by the type's template arguments (for `std::map<int, int>` that's its allocator). Implicit map clauses carry no source location by design, and the "default" mapper id was stamped with that empty location, so the instantiation was recorded with an invalid point of instantiation and `setPointOfInstantiation` asserted. `buildUserDefinedMapperRef` now takes the location of the mapped list item and uses it for the ADL and the derived-class checks, which is what the other default-mapper lookups in `SemaOpenMP.cpp` already did. Diagnostics about the mapper id and the mapper reference itself keep the mapper-id location, so explicit `mapper(id)` behavior is unchanged. The instantiation is now attributed to the mapped variable inside the region, which is also where the "in instantiation requested here" note points. >From ec4b4aea04588281488aa5b98f0020ef214835cc Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Wed, 23 Sep 2026 11:42:41 +0530 Subject: [PATCH] [clang][OpenMP] Use the list item location as point of instantiation in mapper lookup Implicit map clauses have no source location, and the "default" mapper lookup inherited that invalid location as the point of instantiation for any class template specialization ADL had to complete, which asserted in setPointOfInstantiation. Thread the mapped list item's location into buildUserDefinedMapperRef and use it for the ADL and derived-class checks, matching what the other default-mapper lookups already do. Fixes #154704 --- clang/docs/ReleaseNotes.md | 2 ++ clang/lib/Sema/SemaOpenMP.cpp | 28 ++++++++++++++++------------ clang/test/OpenMP/gh154704.cpp | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 clang/test/OpenMP/gh154704.cpp diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index f4a34a37aff52e..d62c61d04c43c7 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -547,6 +547,8 @@ features cannot lower the translation-unit ABI level; - Fixed a crash when an `asm` label names the register for a global variable of incomplete type. (#GH219746) - Fixed an ICE hat occurred when using `__imag int/float` as lvalue in assignment. (#GH119498) - Fixed an assertion failure in `-Wsign-compare` when a negated or complemented vector of unsigned integers was compared against a signed constant. (#GH203575) +- Fixed an assertion failure when a variable implicitly mapped by an OpenMP `target` directive has a class type + (such as `std::map`) whose mapper lookup instantiates a class template specialization. (#GH154704) #### Bug Fixes to Compiler Builtins diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2e4d9f2f82f0b7..8303ac7b922542 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6042,7 +6042,8 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, - Expr *UnresolvedMapper); + Expr *UnresolvedMapper, + SourceLocation ItemLoc); /// Perform DFS through the structure/class data members trying to find /// member(s) with user-defined 'default' mapper and generate implicit map @@ -6114,7 +6115,7 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, DefaultMapperId.setLoc(E->getExprLoc()); ExprResult ER = buildUserDefinedMapperRef( S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId, - BaseType, /*UnresolvedMapper=*/nullptr); + BaseType, /*UnresolvedMapper=*/nullptr, E->getExprLoc()); if (ER.isInvalid()) continue; It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first; @@ -23565,12 +23566,15 @@ static bool checkMapConflicts( } // Look up the user-defined mapper given the mapper name and mapped type, and -// build a reference to it. +// build a reference to it. \a ItemLoc is the location of the mapped list item; +// it is used as the point of instantiation since \a MapperId has no location +// for implicit map clauses. static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, - Expr *UnresolvedMapper) { + Expr *UnresolvedMapper, + SourceLocation ItemLoc) { if (MapperIdScopeSpec.isInvalid()) return ExprError(); // Get the actual type for the array type. @@ -23636,7 +23640,7 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, } // Perform argument dependent lookup. if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet()) - argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups); + argumentDependentLookup(SemaRef, MapperId, ItemLoc, Type, Lookups); // Return the first user-defined mapper with the desired type. if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * { @@ -23649,9 +23653,9 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, // Find the first user-defined mapper with a type derived from the desired // type. if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( - Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * { + Lookups, [&SemaRef, Type, ItemLoc](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && - SemaRef.IsDerivedFrom(Loc, Type, D->getType()) && + SemaRef.IsDerivedFrom(ItemLoc, Type, D->getType()) && !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext())) return D; @@ -23659,11 +23663,11 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, })) { CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); - if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) { + if (SemaRef.IsDerivedFrom(ItemLoc, Type, VD->getType(), Paths)) { if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType( VD->getType().getUnqualifiedType()))) { if (SemaRef.CheckBaseClassAccess( - Loc, VD->getType(), Type, Paths.front(), + ItemLoc, VD->getType(), Type, Paths.front(), /*DiagID=*/0) != Sema::AR_inaccessible) { return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc); } @@ -23969,7 +23973,7 @@ static void checkMappableExpressionList( // Try to find the associated user-defined mapper. ExprResult ER = buildUserDefinedMapperRef( SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, - VE->getType().getCanonicalType(), UnresolvedMapper); + VE->getType().getCanonicalType(), UnresolvedMapper, ELoc); if (ER.isInvalid()) continue; MVLI.UDMapperList.push_back(ER.get()); @@ -24013,7 +24017,7 @@ static void checkMappableExpressionList( // Try to find the associated user-defined mapper. ExprResult ER = buildUserDefinedMapperRef( SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, - VE->getType().getCanonicalType(), UnresolvedMapper); + VE->getType().getCanonicalType(), UnresolvedMapper, ELoc); if (ER.isInvalid()) continue; MVLI.UDMapperList.push_back(ER.get()); @@ -24215,7 +24219,7 @@ static void checkMappableExpressionList( // Try to find the associated user-defined mapper. ExprResult ER = buildUserDefinedMapperRef( SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, - Type.getCanonicalType(), UnresolvedMapper); + Type.getCanonicalType(), UnresolvedMapper, ELoc); if (ER.isInvalid()) continue; diff --git a/clang/test/OpenMP/gh154704.cpp b/clang/test/OpenMP/gh154704.cpp new file mode 100644 index 00000000000000..bd160a6ec52d0e --- /dev/null +++ b/clang/test/OpenMP/gh154704.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -verify -fopenmp -fsyntax-only %s + +template <typename T> struct Less {}; + +template <typename K, typename V, typename C = Less<K>> struct Map { + V &operator[](const K &); +}; + +void no_crash() { + int keys[42], data[42]; + Map<int, int> map; + +#pragma omp target + { + for (int i = 0; i < 42; ++i) + map[keys[i]] = data[i]; + } +} + +template <typename T> struct Fails { + typename T::type t; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} +}; + +template <typename T, typename U = Fails<T>> struct Holder {}; + +void point_of_instantiation() { + Holder<int> h; + +#pragma omp target + { + (void)&h; // expected-note {{in instantiation of template class 'Fails<int>' requested here}} + } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
