@@ -5488,112 +5488,103 @@ getConditionalCopyableAttrParams(const clang::RecordDecl *decl) {
54885488CxxEscapability
54895489ClangTypeEscapability::evaluate (Evaluator &evaluator,
54905490 EscapabilityLookupDescriptor desc) const {
5491- bool hadUnknown = false ;
5492- auto evaluateEscapability = [&](const clang::Type *type) {
5493- auto escapability = evaluateOrDefault (
5494- evaluator,
5495- ClangTypeEscapability ({type, desc.impl , desc.annotationOnly }),
5496- CxxEscapability::Unknown);
5497- if (escapability == CxxEscapability::Unknown)
5498- hadUnknown = true ;
5499- return escapability;
5500- };
5501-
5491+ bool hasUnknown = false ;
55025492 auto desugared = desc.type ->getUnqualifiedDesugaredType ();
55035493 if (const auto *recordType = desugared->getAs <clang::RecordType>()) {
55045494 auto recordDecl = recordType->getDecl ();
5505- if (hasNonEscapableAttr (recordDecl))
5506- return CxxEscapability::NonEscapable;
55075495 if (hasEscapableAttr (recordDecl))
55085496 return CxxEscapability::Escapable;
5509- auto injectedStlAnnotation =
5510- recordDecl->isInStdNamespace ()
5511- ? STLConditionalParams.find (recordDecl->getName ())
5512- : STLConditionalParams.end ();
5513- auto STLParams = injectedStlAnnotation != STLConditionalParams.end ()
5514- ? injectedStlAnnotation->second
5515- : std::vector<int >();
5516- auto conditionalParams = getConditionalEscapableAttrParams (recordDecl);
5517-
5518- if (!STLParams.empty () || !conditionalParams.empty ()) {
5519- HeaderLoc loc{recordDecl->getLocation ()};
5520- std::function checkArgEscapability =
5521- [&](clang::TemplateArgument &arg,
5522- StringRef argToCheck) -> std::optional<CxxEscapability> {
5523- if (arg.getKind () != clang::TemplateArgument::Type && desc.impl ) {
5524- desc.impl ->diagnose (loc, diag::type_template_parameter_expected,
5525- argToCheck);
5526- return CxxEscapability::Unknown;
5527- }
5497+ }
55285498
5529- auto argEscapability = evaluateEscapability (
5530- arg.getAsType ()->getUnqualifiedDesugaredType ());
5531- if (argEscapability == CxxEscapability::NonEscapable)
5532- return CxxEscapability::NonEscapable;
5533- return std::nullopt ;
5534- };
5535-
5536- auto result = checkConditionalParams<CxxEscapability>(
5537- recordDecl, STLParams, conditionalParams, checkArgEscapability);
5538- if (result.has_value ())
5539- return result.value ();
5540-
5541- if (desc.impl )
5542- for (auto name : conditionalParams)
5543- desc.impl ->diagnose (loc, diag::unknown_template_parameter, name);
5544-
5545- return hadUnknown ? CxxEscapability::Unknown : CxxEscapability::Escapable;
5546- }
5547- if (desc.annotationOnly )
5548- return CxxEscapability::Unknown;
5549- auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(recordDecl);
5550- if (recordDecl->getDefinition () &&
5551- (!cxxRecordDecl || cxxRecordDecl->isAggregate ())) {
5552- if (cxxRecordDecl) {
5553- for (auto base : cxxRecordDecl->bases ()) {
5554- auto baseEscapability = evaluateEscapability (
5555- base.getType ()->getUnqualifiedDesugaredType ());
5556- if (baseEscapability == CxxEscapability::NonEscapable)
5557- return CxxEscapability::NonEscapable;
5558- }
5559- }
5499+ llvm::SmallVector<const clang::Type *, 4 > stack;
5500+ // Keep track of Decls we've seen to avoid cycles
5501+ llvm::SmallDenseSet<const clang::Type *, 4 > seen;
5502+
5503+ auto maybePushToStack = [&](const clang::Type *type) {
5504+ auto desugared = type->getUnqualifiedDesugaredType ();
5505+ if (seen.insert (desugared).second )
5506+ stack.push_back (desugared);
5507+ };
5508+
5509+ maybePushToStack (desc.type );
5510+ while (!stack.empty ()) {
5511+ auto type = stack.back ();
5512+ stack.pop_back ();
5513+ if (const auto *recordType = type->getAs <clang::RecordType>()) {
5514+ auto recordDecl = recordType->getDecl ();
5515+ if (hasNonEscapableAttr (recordDecl))
5516+ return CxxEscapability::NonEscapable;
5517+ if (hasEscapableAttr (recordDecl))
5518+ continue ;
5519+ auto injectedStlAnnotation =
5520+ recordDecl->isInStdNamespace ()
5521+ ? STLConditionalParams.find (recordDecl->getName ())
5522+ : STLConditionalParams.end ();
5523+ auto STLParams = injectedStlAnnotation != STLConditionalParams.end ()
5524+ ? injectedStlAnnotation->second
5525+ : std::vector<int >();
5526+ auto conditionalParams = getConditionalEscapableAttrParams (recordDecl);
5527+
5528+ if (!STLParams.empty () || !conditionalParams.empty ()) {
5529+ HeaderLoc loc{recordDecl->getLocation ()};
5530+ std::function checkArgEscapability =
5531+ [&](clang::TemplateArgument &arg,
5532+ StringRef argToCheck) -> std::optional<CxxEscapability> {
5533+ if (arg.getKind () != clang::TemplateArgument::Type) {
5534+ if (desc.impl )
5535+ desc.impl ->diagnose (loc, diag::type_template_parameter_expected,
5536+ argToCheck);
5537+ hasUnknown = true ;
5538+ return std::nullopt ;
5539+ }
5540+ maybePushToStack (arg.getAsType ()->getUnqualifiedDesugaredType ());
5541+ // FIXME don't return anything
5542+ return std::nullopt ;
5543+ };
5544+
5545+ checkConditionalParams<CxxEscapability>(
5546+ recordDecl, STLParams, conditionalParams, checkArgEscapability);
5547+
5548+ if (desc.impl )
5549+ for (auto name : conditionalParams)
5550+ desc.impl ->diagnose (loc, diag::unknown_template_parameter, name);
55605551
5561- for ( auto field : recordDecl-> fields ()) {
5562- auto fieldEscapability = evaluateEscapability (
5563- field-> getType ()-> getUnqualifiedDesugaredType ());
5564- if (fieldEscapability == CxxEscapability::NonEscapable)
5565- return CxxEscapability::NonEscapable ;
5552+ continue ;
5553+ }
5554+ if (desc. annotationOnly ) {
5555+ hasUnknown = true ;
5556+ continue ;
55665557 }
5558+ auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(recordDecl);
5559+ if (recordDecl->getDefinition () &&
5560+ (!cxxRecordDecl || cxxRecordDecl->isAggregate ())) {
5561+ if (cxxRecordDecl) {
5562+ // TODO llvm::foreach ?
5563+ for (auto base : cxxRecordDecl->bases ())
5564+ maybePushToStack (base.getType ()->getUnqualifiedDesugaredType ());
5565+ }
55675566
5568- return hadUnknown ? CxxEscapability::Unknown : CxxEscapability::Escapable;
5567+ for (auto field : recordDecl->fields ())
5568+ maybePushToStack (field->getType ()->getUnqualifiedDesugaredType ());
5569+ continue ;
5570+ }
5571+ }
5572+ if (type->isArrayType ()) {
5573+ auto elemTy = cast<clang::ArrayType>(type)
5574+ ->getElementType ()
5575+ ->getUnqualifiedDesugaredType ();
5576+ maybePushToStack (elemTy);
5577+ } else if (const auto *vecTy = type->getAs <clang::VectorType>()) {
5578+ maybePushToStack (vecTy->getElementType ()->getUnqualifiedDesugaredType ());
5579+ } else if (type->isAnyPointerType () || type->isBlockPointerType () ||
5580+ type->isMemberPointerType () || type->isReferenceType ()) {
5581+ if (desc.annotationOnly )
5582+ hasUnknown = true ;
5583+ else
5584+ return CxxEscapability::NonEscapable;
55695585 }
55705586 }
5571- if (desugared->isArrayType ()) {
5572- auto elemTy = cast<clang::ArrayType>(desugared)
5573- ->getElementType ()
5574- ->getUnqualifiedDesugaredType ();
5575- return evaluateOrDefault (
5576- evaluator,
5577- ClangTypeEscapability ({elemTy, desc.impl , desc.annotationOnly }),
5578- CxxEscapability::Unknown);
5579- }
5580- if (const auto *vecTy = desugared->getAs <clang::VectorType>()) {
5581- return evaluateOrDefault (
5582- evaluator,
5583- ClangTypeEscapability (
5584- {vecTy->getElementType ()->getUnqualifiedDesugaredType (), desc.impl ,
5585- desc.annotationOnly }),
5586- CxxEscapability::Unknown);
5587- }
5588-
5589- // Base cases
5590- if (desugared->isAnyPointerType () || desugared->isBlockPointerType () ||
5591- desugared->isMemberPointerType () || desugared->isReferenceType ())
5592- return desc.annotationOnly ? CxxEscapability::Unknown
5593- : CxxEscapability::NonEscapable;
5594- if (desugared->isScalarType ())
5595- return CxxEscapability::Escapable;
5596- return CxxEscapability::Unknown;
5587+ return hasUnknown ? CxxEscapability::Unknown : CxxEscapability::Escapable;
55975588}
55985589
55995590void swift::simple_display (llvm::raw_ostream &out,
@@ -8541,7 +8532,7 @@ CxxValueSemantics::evaluate(Evaluator &evaluator,
85418532 if (importerImpl)
85428533 importerImpl->diagnose (
85438534 loc, diag::type_template_parameter_expected, argToCheck);
8544- return CxxValueSemanticsKind::Unknown ;
8535+ return std:: nullopt ;
85458536 }
85468537 maybePushToStack (arg.getAsType ()->getUnqualifiedDesugaredType ());
85478538 // FIXME: return std::nullopt for now, while we don't refactor ClangTypeEscapability request
0 commit comments