mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Make c++ defer looks like a swift one
This commit is contained in:
@@ -18,11 +18,12 @@
|
||||
#ifndef __SWIFT_DEFER_H
|
||||
#define __SWIFT_DEFER_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace swift {
|
||||
template <typename F>
|
||||
class DoAtScopeExit {
|
||||
F &Fn;
|
||||
DoAtScopeExit(DoAtScopeExit&) = delete;
|
||||
void operator=(DoAtScopeExit&) = delete;
|
||||
public:
|
||||
DoAtScopeExit(F &Fn) : Fn(Fn){}
|
||||
@@ -30,8 +31,17 @@ namespace swift {
|
||||
Fn();
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
struct DeferTask {};
|
||||
template<typename F>
|
||||
DoAtScopeExit<typename std::decay<F>::type> operator+(DeferTask, F&& fn) {
|
||||
return DoAtScopeExit<typename std::decay<F>::type>(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define DEFER_CONCAT_IMPL(x, y) x##y
|
||||
#define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y)
|
||||
|
||||
@@ -39,16 +49,13 @@ namespace swift {
|
||||
/// This macro is used to register a function / lambda to be run on exit from a
|
||||
/// scope. Its typical use looks like:
|
||||
///
|
||||
/// defer([&]{
|
||||
/// defer {
|
||||
/// stuff
|
||||
/// })
|
||||
/// };
|
||||
///
|
||||
#define defer(x) \
|
||||
auto DEFER_MACRO_CONCAT(defer_func, __LINE__) = (x); \
|
||||
swift::DoAtScopeExit<decltype(DEFER_MACRO_CONCAT(defer_func, __LINE__))> \
|
||||
DEFER_MACRO_CONCAT(defer_local, __LINE__)\
|
||||
(DEFER_MACRO_CONCAT(defer_func, __LINE__));
|
||||
#define defer \
|
||||
auto DEFER_MACRO_CONCAT(defer_func, __COUNTER__) = \
|
||||
::swift::detail::DeferTask() + [&]()
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -3643,7 +3643,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
|
||||
// No matter what error path we take, make sure the
|
||||
// PatternBindingDecl/TopLevel code block are added.
|
||||
defer([&]{
|
||||
defer {
|
||||
// If we didn't parse any patterns, don't create the pattern binding decl.
|
||||
if (PBDEntries.empty())
|
||||
return;
|
||||
@@ -3683,7 +3683,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
// specific spot to get it in before any accessors, which SILGen seems to
|
||||
// want.
|
||||
Decls.insert(Decls.begin()+NumDeclsInResult, PBD);
|
||||
});
|
||||
};
|
||||
|
||||
do {
|
||||
Pattern *pattern;
|
||||
|
||||
@@ -84,7 +84,7 @@ void IterativeTypeChecker::satisfy(TypeCheckRequest request) {
|
||||
|
||||
// Add this request to the stack of active requests.
|
||||
ActiveRequests.push_back(request);
|
||||
defer([&] { ActiveRequests.pop_back(); });
|
||||
defer { ActiveRequests.pop_back(); };
|
||||
|
||||
while (true) {
|
||||
// Process this requirement, enumerating dependencies if anything else needs
|
||||
|
||||
@@ -356,7 +356,7 @@ void TypeChecker::checkInheritanceClause(Decl *decl,
|
||||
{
|
||||
bool iBTC = decl->isBeingTypeChecked();
|
||||
decl->setIsBeingTypeChecked();
|
||||
defer([&]{decl->setIsBeingTypeChecked(iBTC); });
|
||||
defer {decl->setIsBeingTypeChecked(iBTC); };
|
||||
|
||||
// Validate the type.
|
||||
if (validateType(inherited, DC, options, resolver)) {
|
||||
@@ -1219,9 +1219,9 @@ static void validatePatternBindingDecl(TypeChecker &tc,
|
||||
|
||||
// On any path out of this function, make sure to mark the binding as done
|
||||
// being type checked.
|
||||
defer([&]{
|
||||
defer {
|
||||
binding->setIsBeingTypeChecked(false);
|
||||
});
|
||||
};
|
||||
|
||||
// Resolve the pattern.
|
||||
auto *pattern = tc.resolvePattern(binding->getPattern(entryNumber),
|
||||
@@ -6239,7 +6239,7 @@ static Type checkExtensionGenericParams(
|
||||
};
|
||||
|
||||
ext->setIsBeingTypeChecked(true);
|
||||
defer([ext] { ext->setIsBeingTypeChecked(false); });
|
||||
defer { ext->setIsBeingTypeChecked(false); };
|
||||
|
||||
// Validate the generic type signature.
|
||||
bool invalid = false;
|
||||
|
||||
@@ -890,7 +890,7 @@ namespace {
|
||||
}
|
||||
// Recursively check the transitive captures.
|
||||
capturePath.push_back(func);
|
||||
defer([&]{ capturePath.pop_back(); });
|
||||
defer { capturePath.pop_back(); };
|
||||
for (auto capture : func->getCaptureInfo().getCaptures())
|
||||
if (!validateForwardCapture(capture.getDecl()))
|
||||
return false;
|
||||
|
||||
@@ -2922,9 +2922,9 @@ void ConformanceChecker::resolveTypeWitnesses() {
|
||||
// Track when we are checking type witnesses.
|
||||
ProtocolConformanceState initialState = Conformance->getState();
|
||||
Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
|
||||
defer([&] {
|
||||
defer {
|
||||
Conformance->setState(initialState);
|
||||
});
|
||||
};
|
||||
|
||||
for (auto member : Proto->getMembers()) {
|
||||
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
|
||||
@@ -3251,11 +3251,11 @@ void ConformanceChecker::resolveTypeWitnesses() {
|
||||
valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
|
||||
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
|
||||
++numValueWitnessesInProtocolExtensions;
|
||||
defer([&]{
|
||||
defer {
|
||||
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
|
||||
--numValueWitnessesInProtocolExtensions;
|
||||
valueWitnesses.pop_back();
|
||||
});
|
||||
};
|
||||
|
||||
// Introduce each of the type witnesses into the hash table.
|
||||
bool failed = false;
|
||||
@@ -3635,7 +3635,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
|
||||
// Note that we're resolving this witness.
|
||||
assert(ResolvingWitnesses.count(requirement) == 0 && "Currently resolving");
|
||||
ResolvingWitnesses.insert(requirement);
|
||||
defer([&]{ ResolvingWitnesses.erase(requirement); });
|
||||
defer { ResolvingWitnesses.erase(requirement); };
|
||||
|
||||
// Make sure we've validated the requirement.
|
||||
if (!requirement->hasType())
|
||||
@@ -3934,7 +3934,7 @@ checkConformsToProtocol(TypeChecker &TC,
|
||||
|
||||
// Note that we are checking this conformance now.
|
||||
conformance->setState(ProtocolConformanceState::Checking);
|
||||
defer([&] { conformance->setState(ProtocolConformanceState::Complete); });
|
||||
defer { conformance->setState(ProtocolConformanceState::Complete); };
|
||||
|
||||
// If the protocol requires a class, non-classes are a non-starter.
|
||||
if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {
|
||||
|
||||
Reference in New Issue
Block a user