Skip to content

Commit d3064c5

Browse files
authoredNov 20, 2024
Merge pull request swiftlang#77678 from swiftlang/gaborh/conditional-escapability
[cxx-interop] Support nested templates for conditional escapability
2 parents a7b1e78 + ad4bfef commit d3064c5

File tree

2 files changed

+52
-20
lines changed

2 files changed

+52
-20
lines changed
 

‎lib/ClangImporter/ClangImporter.cpp

+32-20
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "swift/AST/NameLookupRequests.h"
3737
#include "swift/AST/PrettyStackTrace.h"
3838
#include "swift/AST/SourceFile.h"
39+
#include "swift/AST/Type.h"
3940
#include "swift/AST/TypeCheckRequests.h"
4041
#include "swift/AST/Types.h"
4142
#include "swift/Basic/Assertions.h"
@@ -51,6 +52,7 @@
5152
#include "swift/Strings.h"
5253
#include "swift/Subsystems.h"
5354
#include "clang/AST/ASTContext.h"
55+
#include "clang/AST/DeclBase.h"
5456
#include "clang/AST/DeclCXX.h"
5557
#include "clang/AST/DeclTemplate.h"
5658
#include "clang/AST/Mangle.h"
@@ -5080,31 +5082,41 @@ ClangTypeEscapability::evaluate(Evaluator &evaluator,
50805082
importer::getConditionalEscapableAttrParams(recordDecl);
50815083
if (!conditionalParams.empty()) {
50825084
auto specDecl = cast<clang::ClassTemplateSpecializationDecl>(recordDecl);
5083-
auto templateDecl = specDecl->getSpecializedTemplate();
50845085
SmallVector<std::pair<unsigned, StringRef>, 4> argumentsToCheck;
5085-
for (auto [idx, param] :
5086-
llvm::enumerate(*templateDecl->getTemplateParameters())) {
5087-
if (conditionalParams.erase(param->getName()))
5088-
argumentsToCheck.push_back(std::make_pair(idx, param->getName()));
5089-
}
50905086
HeaderLoc loc{recordDecl->getLocation()};
5091-
for (auto name : conditionalParams)
5092-
desc.impl.diagnose(loc, diag::unknown_template_parameter, name);
5093-
5094-
auto &argList = specDecl->getTemplateArgs();
5095-
for (auto argToCheck : argumentsToCheck) {
5096-
auto arg = argList[argToCheck.first];
5097-
if (arg.getKind() != clang::TemplateArgument::Type) {
5098-
desc.impl.diagnose(loc, diag::type_template_parameter_expected,
5099-
argToCheck.second);
5100-
return CxxEscapability::Unknown;
5087+
while (specDecl) {
5088+
auto templateDecl = specDecl->getSpecializedTemplate();
5089+
for (auto [idx, param] :
5090+
llvm::enumerate(*templateDecl->getTemplateParameters())) {
5091+
if (conditionalParams.erase(param->getName()))
5092+
argumentsToCheck.push_back(std::make_pair(idx, param->getName()));
51015093
}
5094+
auto &argList = specDecl->getTemplateArgs();
5095+
for (auto argToCheck : argumentsToCheck) {
5096+
auto arg = argList[argToCheck.first];
5097+
if (arg.getKind() != clang::TemplateArgument::Type) {
5098+
desc.impl.diagnose(loc, diag::type_template_parameter_expected,
5099+
argToCheck.second);
5100+
return CxxEscapability::Unknown;
5101+
}
51025102

5103-
auto argEscapability = evaluateEscapability(
5104-
arg.getAsType()->getUnqualifiedDesugaredType());
5105-
if (argEscapability == CxxEscapability::NonEscapable)
5106-
return CxxEscapability::NonEscapable;
5103+
auto argEscapability = evaluateEscapability(
5104+
arg.getAsType()->getUnqualifiedDesugaredType());
5105+
if (argEscapability == CxxEscapability::NonEscapable)
5106+
return CxxEscapability::NonEscapable;
5107+
}
5108+
clang::DeclContext *rec = specDecl;
5109+
specDecl = nullptr;
5110+
while ((rec = rec->getParent())) {
5111+
specDecl = dyn_cast<clang::ClassTemplateSpecializationDecl>(rec);
5112+
if (specDecl)
5113+
break;
5114+
}
51075115
}
5116+
5117+
for (auto name : conditionalParams)
5118+
desc.impl.diagnose(loc, diag::unknown_template_parameter, name);
5119+
51085120
return hadUnknown ? CxxEscapability::Unknown : CxxEscapability::Escapable;
51095121
}
51105122
if (desc.annotationOnly)

‎test/Interop/Cxx/class/nonescapable-errors.swift

+20
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,21 @@ struct SWIFT_ESCAPABLE_IF(F, S) MyType {
6161
MyPair2<Owner, Owner> i1();
6262
MyType<Owner, 0> i2();
6363

64+
template<typename T>
65+
struct Outer {
66+
struct NonTemplated {
67+
template <typename S>
68+
struct SWIFT_ESCAPABLE_IF(T, S) Inner {
69+
T t;
70+
S s;
71+
};
72+
};
73+
};
74+
75+
Outer<View>::NonTemplated::Inner<Owner> j1();
76+
Outer<Owner>::NonTemplated::Inner<View> j2();
77+
Outer<Owner>::NonTemplated::Inner<Owner> j3();
78+
6479
//--- test.swift
6580

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

0 commit comments

Comments
 (0)