Skip to content

Commit

Permalink
Merge pull request swiftlang#77678 from swiftlang/gaborh/conditional-…
Browse files Browse the repository at this point in the history
…escapability

[cxx-interop] Support nested templates for conditional escapability
  • Loading branch information
Xazax-hun authored Nov 20, 2024
2 parents a7b1e78 + ad4bfef commit d3064c5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 20 deletions.
52 changes: 32 additions & 20 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Assertions.h"
Expand All @@ -51,6 +52,7 @@
#include "swift/Strings.h"
#include "swift/Subsystems.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
Expand Down Expand Up @@ -5080,31 +5082,41 @@ ClangTypeEscapability::evaluate(Evaluator &evaluator,
importer::getConditionalEscapableAttrParams(recordDecl);
if (!conditionalParams.empty()) {
auto specDecl = cast<clang::ClassTemplateSpecializationDecl>(recordDecl);
auto templateDecl = specDecl->getSpecializedTemplate();
SmallVector<std::pair<unsigned, StringRef>, 4> argumentsToCheck;
for (auto [idx, param] :
llvm::enumerate(*templateDecl->getTemplateParameters())) {
if (conditionalParams.erase(param->getName()))
argumentsToCheck.push_back(std::make_pair(idx, param->getName()));
}
HeaderLoc loc{recordDecl->getLocation()};
for (auto name : conditionalParams)
desc.impl.diagnose(loc, diag::unknown_template_parameter, name);

auto &argList = specDecl->getTemplateArgs();
for (auto argToCheck : argumentsToCheck) {
auto arg = argList[argToCheck.first];
if (arg.getKind() != clang::TemplateArgument::Type) {
desc.impl.diagnose(loc, diag::type_template_parameter_expected,
argToCheck.second);
return CxxEscapability::Unknown;
while (specDecl) {
auto templateDecl = specDecl->getSpecializedTemplate();
for (auto [idx, param] :
llvm::enumerate(*templateDecl->getTemplateParameters())) {
if (conditionalParams.erase(param->getName()))
argumentsToCheck.push_back(std::make_pair(idx, param->getName()));
}
auto &argList = specDecl->getTemplateArgs();
for (auto argToCheck : argumentsToCheck) {
auto arg = argList[argToCheck.first];
if (arg.getKind() != clang::TemplateArgument::Type) {
desc.impl.diagnose(loc, diag::type_template_parameter_expected,
argToCheck.second);
return CxxEscapability::Unknown;
}

auto argEscapability = evaluateEscapability(
arg.getAsType()->getUnqualifiedDesugaredType());
if (argEscapability == CxxEscapability::NonEscapable)
return CxxEscapability::NonEscapable;
auto argEscapability = evaluateEscapability(
arg.getAsType()->getUnqualifiedDesugaredType());
if (argEscapability == CxxEscapability::NonEscapable)
return CxxEscapability::NonEscapable;
}
clang::DeclContext *rec = specDecl;
specDecl = nullptr;
while ((rec = rec->getParent())) {
specDecl = dyn_cast<clang::ClassTemplateSpecializationDecl>(rec);
if (specDecl)
break;
}
}

for (auto name : conditionalParams)
desc.impl.diagnose(loc, diag::unknown_template_parameter, name);

return hadUnknown ? CxxEscapability::Unknown : CxxEscapability::Escapable;
}
if (desc.annotationOnly)
Expand Down
20 changes: 20 additions & 0 deletions test/Interop/Cxx/class/nonescapable-errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ struct SWIFT_ESCAPABLE_IF(F, S) MyType {
MyPair2<Owner, Owner> i1();
MyType<Owner, 0> i2();

template<typename T>
struct Outer {
struct NonTemplated {
template <typename S>
struct SWIFT_ESCAPABLE_IF(T, S) Inner {
T t;
S s;
};
};
};

Outer<View>::NonTemplated::Inner<Owner> j1();
Outer<Owner>::NonTemplated::Inner<View> j2();
Outer<Owner>::NonTemplated::Inner<Owner> j3();

//--- test.swift

import Test
Expand All @@ -85,6 +100,11 @@ public func noAnnotations() -> View {
// CHECK: nonescapable.h:38:39: error: template parameter 'Missing' does not exist
i2()
// CHECK: nonescapable.h:44:33: error: template parameter 'S' expected to be a type parameter
j1()
// CHECK: nonescapable.h:62:41: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
j2()
// CHECK: nonescapable.h:63:41: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
j3()
// CHECK-NOT: error
// CHECK-NOT: warning
return View()
Expand Down

0 comments on commit d3064c5

Please sign in to comment.