diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaCUDA.cpp | 73 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 60 |
2 files changed, 45 insertions, 88 deletions
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index e448c3f89b9..9e101d16da9 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -158,82 +158,31 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, llvm_unreachable("All cases should've been handled by now."); } -void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller, - LookupResult &R) { - if (R.empty() || R.isSingleResult()) - return; - - // Gets the CUDA function preference for a call from Caller to Match. - auto GetCFP = [&](const NamedDecl *D) { - if (auto *Callee = dyn_cast<FunctionDecl>(D->getUnderlyingDecl())) - return IdentifyCUDAPreference(Caller, Callee); - return CFP_Never; - }; - - // Find the best call preference among the functions in R. - CUDAFunctionPreference BestCFP = GetCFP(*std::max_element( - R.begin(), R.end(), [&](const NamedDecl *D1, const NamedDecl *D2) { - return GetCFP(D1) < GetCFP(D2); - })); - - // Erase all functions with lower priority. - auto Filter = R.makeFilter(); - while (Filter.hasNext()) { - auto *Callee = dyn_cast<FunctionDecl>(Filter.next()->getUnderlyingDecl()); - if (Callee && GetCFP(Callee) < BestCFP) - Filter.erase(); - } - Filter.done(); -} - -template <typename T> -static void EraseUnwantedCUDAMatchesImpl( - Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl<T> &Matches, - std::function<const FunctionDecl *(const T &)> FetchDecl) { +void Sema::EraseUnwantedCUDAMatches( + const FunctionDecl *Caller, + SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) { if (Matches.size() <= 1) return; + using Pair = std::pair<DeclAccessPair, FunctionDecl*>; + // Gets the CUDA function preference for a call from Caller to Match. - auto GetCFP = [&](const T &Match) { - return S.IdentifyCUDAPreference(Caller, FetchDecl(Match)); + auto GetCFP = [&](const Pair &Match) { + return IdentifyCUDAPreference(Caller, Match.second); }; // Find the best call preference among the functions in Matches. - Sema::CUDAFunctionPreference BestCFP = GetCFP(*std::max_element( + CUDAFunctionPreference BestCFP = GetCFP(*std::max_element( Matches.begin(), Matches.end(), - [&](const T &M1, const T &M2) { return GetCFP(M1) < GetCFP(M2); })); + [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); })); // Erase all functions with lower priority. Matches.erase( - llvm::remove_if(Matches, - [&](const T &Match) { return GetCFP(Match) < BestCFP; }), + llvm::remove_if( + Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }), Matches.end()); } -void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller, - SmallVectorImpl<FunctionDecl *> &Matches){ - EraseUnwantedCUDAMatchesImpl<FunctionDecl *>( - *this, Caller, Matches, [](const FunctionDecl *item) { return item; }); -} - -void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller, - SmallVectorImpl<DeclAccessPair> &Matches) { - EraseUnwantedCUDAMatchesImpl<DeclAccessPair>( - *this, Caller, Matches, [](const DeclAccessPair &item) { - return dyn_cast<FunctionDecl>(item.getDecl()); - }); -} - -void Sema::EraseUnwantedCUDAMatches( - const FunctionDecl *Caller, - SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){ - EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>( - *this, Caller, Matches, - [](const std::pair<DeclAccessPair, FunctionDecl *> &item) { - return dyn_cast<FunctionDecl>(item.second); - }); -} - /// When an implicitly-declared special member has to invoke more than one /// base/field special member, conflicts may occur in the targets of these /// members. For example, if one base's member __host__ and another's is diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 9c5dba5a38a..a87e3db590e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1354,9 +1354,9 @@ static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) { namespace { struct UsualDeallocFnInfo { UsualDeallocFnInfo() : Found(), FD(nullptr) {} - UsualDeallocFnInfo(DeclAccessPair Found) + UsualDeallocFnInfo(Sema &S, DeclAccessPair Found) : Found(Found), FD(dyn_cast<FunctionDecl>(Found->getUnderlyingDecl())), - HasSizeT(false), HasAlignValT(false) { + HasSizeT(false), HasAlignValT(false), CUDAPref(Sema::CFP_Native) { // A function template declaration is never a usual deallocation function. if (!FD) return; @@ -1366,13 +1366,35 @@ namespace { HasSizeT = FD->getParamDecl(1)->getType()->isIntegerType(); HasAlignValT = !HasSizeT; } + + // In CUDA, determine how much we'd like / dislike to call this. + if (S.getLangOpts().CUDA) + if (auto *Caller = dyn_cast<FunctionDecl>(S.CurContext)) + CUDAPref = S.IdentifyCUDAPreference(Caller, FD); } operator bool() const { return FD; } + bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize, + bool WantAlign) const { + // C++17 [expr.delete]p10: + // If the type has new-extended alignment, a function with a parameter + // of type std::align_val_t is preferred; otherwise a function without + // such a parameter is preferred + if (HasAlignValT != Other.HasAlignValT) + return HasAlignValT == WantAlign; + + if (HasSizeT != Other.HasSizeT) + return HasSizeT == WantSize; + + // Use CUDA call preference as a tiebreaker. + return CUDAPref > Other.CUDAPref; + } + DeclAccessPair Found; FunctionDecl *FD; bool HasSizeT, HasAlignValT; + Sema::CUDAFunctionPreference CUDAPref; }; } @@ -1393,16 +1415,10 @@ static UsualDeallocFnInfo resolveDeallocationOverload( llvm::SmallVectorImpl<UsualDeallocFnInfo> *BestFns = nullptr) { UsualDeallocFnInfo Best; - // For CUDA, rank callability above anything else when ordering usual - // deallocation functions. - // FIXME: We should probably instead rank this between alignment (which - // affects correctness) and size (which is just an optimization). - if (S.getLangOpts().CUDA) - S.EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(S.CurContext), R); - for (auto I = R.begin(), E = R.end(); I != E; ++I) { - UsualDeallocFnInfo Info(I.getPair()); - if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD)) + UsualDeallocFnInfo Info(S, I.getPair()); + if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) || + Info.CUDAPref == Sema::CFP_Never) continue; if (!Best) { @@ -1412,21 +1428,12 @@ static UsualDeallocFnInfo resolveDeallocationOverload( continue; } - // C++17 [expr.delete]p10: - // If the type has new-extended alignment, a function with a parameter of - // type std::align_val_t is preferred; otherwise a function without such a - // parameter is preferred - if (Best.HasAlignValT == WantAlign && Info.HasAlignValT != WantAlign) - continue; - - if (Best.HasAlignValT == Info.HasAlignValT && - Best.HasSizeT == WantSize && Info.HasSizeT != WantSize) + if (Best.isBetterThan(Info, WantSize, WantAlign)) continue; // If more than one preferred function is found, all non-preferred // functions are eliminated from further consideration. - if (BestFns && (Best.HasAlignValT != Info.HasAlignValT || - Best.HasSizeT != Info.HasSizeT)) + if (BestFns && Info.isBetterThan(Best, WantSize, WantAlign)) BestFns->clear(); Best = Info; @@ -2373,7 +2380,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // is ill-formed. if (getLangOpts().CPlusPlus11 && isPlacementNew && isNonPlacementDeallocationFunction(*this, OperatorDelete)) { - UsualDeallocFnInfo Info(DeclAccessPair::make(OperatorDelete, AS_public)); + UsualDeallocFnInfo Info(*this, + DeclAccessPair::make(OperatorDelete, AS_public)); // Core issue, per mail to core reflector, 2016-10-09: // If this is a member operator delete, and there is a corresponding // non-sized member operator delete, this isn't /really/ a sized @@ -3118,9 +3126,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // function we just found. else if (OperatorDelete && isa<CXXMethodDecl>(OperatorDelete)) UsualArrayDeleteWantsSize = - UsualDeallocFnInfo( - DeclAccessPair::make(OperatorDelete, AS_public)) - .HasSizeT; + UsualDeallocFnInfo(*this, + DeclAccessPair::make(OperatorDelete, AS_public)) + .HasSizeT; } if (!PointeeRD->hasIrrelevantDestructor()) |