Skip to content

Commit aa14bb4

Browse files
authored
Merge pull request #8970 from DougGregor/misc-fixes-4.0
[4.0] Collected fixes
2 parents 02a8d10 + 80183b6 commit aa14bb4

File tree

14 files changed

+135
-28
lines changed

14 files changed

+135
-28
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5308,6 +5308,10 @@ class FuncDecl final : public AbstractFunctionDecl,
53085308

53095309
/// True if the function is a defer body.
53105310
bool isDeferBody() const;
5311+
5312+
/// Perform basic checking to determine whether the @IBAction attribute can
5313+
/// be applied to this function.
5314+
bool isPotentialIBActionTarget() const;
53115315
};
53125316

53135317
/// \brief This represents a 'case' declaration in an 'enum', which may declare

lib/AST/ASTVerifier.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ class Verifier : public ASTWalker {
388388
// If we've checked types already, do some extra verification.
389389
if (!SF || SF->ASTStage >= SourceFile::TypeChecked) {
390390
verifyCheckedAlways(node);
391-
if (!HadError)
391+
if (!HadError && shouldVerifyChecked(node))
392392
verifyChecked(node);
393393
}
394394

@@ -405,6 +405,12 @@ class Verifier : public ASTWalker {
405405
bool shouldVerify(Pattern *S) { return true; }
406406
bool shouldVerify(Decl *S) { return true; }
407407

408+
// Default cases for whether we should verify a checked subtree.
409+
bool shouldVerifyChecked(Expr *E) { return !E->getType().isNull(); }
410+
bool shouldVerifyChecked(Stmt *S) { return true; }
411+
bool shouldVerifyChecked(Pattern *S) { return S->hasType(); }
412+
bool shouldVerifyChecked(Decl *S) { return true; }
413+
408414
// Default cases for cleaning up as we exit a node.
409415
void cleanup(Expr *E) { }
410416
void cleanup(Stmt *S) { }
@@ -782,20 +788,32 @@ class Verifier : public ASTWalker {
782788
verifyCheckedAlwaysBase(D);
783789
}
784790

791+
bool shouldVerifyChecked(ThrowStmt *S) {
792+
return shouldVerifyChecked(S->getSubExpr());
793+
}
794+
785795
void verifyChecked(ThrowStmt *S) {
786796
checkSameType(S->getSubExpr()->getType(),
787797
checkExceptionTypeExists("throw expression"),
788798
"throw operand");
789799
verifyCheckedBase(S);
790800
}
791801

802+
bool shouldVerifyChecked(CatchStmt *S) {
803+
return shouldVerifyChecked(S->getErrorPattern());
804+
}
805+
792806
void verifyChecked(CatchStmt *S) {
793807
checkSameType(S->getErrorPattern()->getType(),
794808
checkExceptionTypeExists("catch statement"),
795809
"catch pattern");
796810
verifyCheckedBase(S);
797811
}
798812

813+
bool shouldVerifyChecked(ReturnStmt *S) {
814+
return !S->hasResult() || shouldVerifyChecked(S->getResult());
815+
}
816+
799817
void verifyChecked(ReturnStmt *S) {
800818
auto func = Functions.back();
801819
Type resultType;
@@ -849,15 +867,19 @@ class Verifier : public ASTWalker {
849867
case StmtConditionElement::CK_Availability: break;
850868
case StmtConditionElement::CK_Boolean: {
851869
auto *E = elt.getBoolean();
852-
checkSameType(E->getType(), BuiltinIntegerType::get(1, Ctx),
853-
"condition type");
870+
if (shouldVerifyChecked(E))
871+
checkSameType(E->getType(), BuiltinIntegerType::get(1, Ctx),
872+
"condition type");
854873
break;
855874
}
856875

857876
case StmtConditionElement::CK_PatternBinding:
858-
checkSameType(elt.getPattern()->getType(),
859-
elt.getInitializer()->getType(),
860-
"conditional binding type");
877+
if (shouldVerifyChecked(elt.getPattern()) &&
878+
shouldVerifyChecked(elt.getInitializer())) {
879+
checkSameType(elt.getPattern()->getType(),
880+
elt.getInitializer()->getType(),
881+
"conditional binding type");
882+
}
861883
break;
862884
}
863885
}

lib/AST/ConformanceLookupTable.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,7 @@ ProtocolConformance *ConformanceLookupTable::getConformance(
809809
ModuleDecl *module = entry->getDeclContext()->getParentModule();
810810
auto inheritedConformance = module->lookupConformance(superclassTy,
811811
protocol,
812-
resolver)
813-
.getPointer();
812+
resolver);
814813

815814
// Form the inherited conformance.
816815
conformance = ctx.getInheritedConformance(

lib/AST/Decl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5111,6 +5111,12 @@ bool FuncDecl::isDeferBody() const {
51115111
return getName() == getASTContext().getIdentifier("$defer");
51125112
}
51135113

5114+
bool FuncDecl::isPotentialIBActionTarget() const {
5115+
return isInstanceMember() &&
5116+
getDeclContext()->getAsClassOrClassExtensionContext() &&
5117+
!isAccessor();
5118+
}
5119+
51145120
Type TypeBase::getSwiftNewtypeUnderlyingType() {
51155121
auto structDecl = getStructOrBoundGenericStruct();
51165122
if (!structDecl)

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3703,9 +3703,12 @@ namespace {
37033703
}
37043704

37053705
// Handle attributes.
3706-
if (decl->hasAttr<clang::IBActionAttr>())
3706+
if (decl->hasAttr<clang::IBActionAttr>() &&
3707+
isa<FuncDecl>(result) &&
3708+
cast<FuncDecl>(result)->isPotentialIBActionTarget()) {
37073709
result->getAttrs().add(
37083710
new (Impl.SwiftContext) IBActionAttr(/*IsImplicit=*/false));
3711+
}
37093712

37103713
// Check whether there's some special method to import.
37113714
if (!forceClassMethod) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,19 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
4242
/// This emits a diagnostic with a fixit to remove the attribute.
4343
template<typename ...ArgTypes>
4444
void diagnoseAndRemoveAttr(DeclAttribute *attr, ArgTypes &&...Args) {
45-
TC.diagnose(attr->getLocation(), std::forward<ArgTypes>(Args)...)
46-
.fixItRemove(attr->getRangeWithAt());
45+
assert(!D->hasClangNode() && "Clang imported propagated a bogus attribute");
46+
if (!D->hasClangNode()) {
47+
SourceLoc loc = attr->getLocation();
48+
assert(loc.isValid() && "Diagnosing attribute with invalid location");
49+
if (loc.isInvalid()) {
50+
loc = D->getLoc();
51+
}
52+
if (loc.isValid()) {
53+
TC.diagnose(loc, std::forward<ArgTypes>(Args)...)
54+
.fixItRemove(attr->getRangeWithAt());
55+
}
56+
}
57+
4758
attr->setInvalid();
4859
}
4960

@@ -304,10 +315,8 @@ void AttributeEarlyChecker::visitDynamicAttr(DynamicAttr *attr) {
304315
void AttributeEarlyChecker::visitIBActionAttr(IBActionAttr *attr) {
305316
// Only instance methods returning () can be IBActions.
306317
const FuncDecl *FD = cast<FuncDecl>(D);
307-
if (!FD->getDeclContext()->getAsClassOrClassExtensionContext() ||
308-
FD->isStatic() || FD->isAccessor())
318+
if (!FD->isPotentialIBActionTarget())
309319
return diagnoseAndRemoveAttr(attr, diag::invalid_ibaction_decl);
310-
311320
}
312321

313322
void AttributeEarlyChecker::visitIBDesignableAttr(IBDesignableAttr *attr) {
@@ -1627,7 +1636,7 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
16271636

16281637
// Form a new generic signature based on the old one.
16291638
GenericSignatureBuilder Builder(D->getASTContext(),
1630-
LookUpConformanceInModule(DC->getParentModule()));
1639+
TypeChecker::LookUpConformance(TC, DC));
16311640

16321641
// First, add the old generic signature.
16331642
Builder.addGenericSignature(genericSig);

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -797,8 +797,7 @@ TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) {
797797
addGenericParamTypes(gp, allGenericParams);
798798

799799
// Create the generic signature builder.
800-
GenericSignatureBuilder builder(Context,
801-
LookUpConformanceInModule(func->getParentModule()));
800+
GenericSignatureBuilder builder(Context, LookUpConformance(*this, func));
802801

803802
// Type check the function declaration, treating all generic type
804803
// parameters as dependent, unresolved.
@@ -1028,8 +1027,7 @@ TypeChecker::validateGenericSubscriptSignature(SubscriptDecl *subscript) {
10281027
addGenericParamTypes(gp, allGenericParams);
10291028

10301029
// Create the generic signature builder.
1031-
GenericSignatureBuilder builder(Context,
1032-
LookUpConformanceInModule(subscript->getParentModule()));
1030+
GenericSignatureBuilder builder(Context, LookUpConformance(*this, subscript));
10331031

10341032
// Type check the function declaration, treating all generic type
10351033
// parameters as dependent, unresolved.
@@ -1148,7 +1146,7 @@ GenericEnvironment *TypeChecker::checkGenericEnvironment(
11481146

11491147
// Create the generic signature builder.
11501148
ModuleDecl *module = dc->getParentModule();
1151-
GenericSignatureBuilder builder(Context, LookUpConformanceInModule(module));
1149+
GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
11521150

11531151
// Type check the generic parameters, treating all generic type
11541152
// parameters as dependent, unresolved.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -997,12 +997,13 @@ RequirementEnvironment::RequirementEnvironment(
997997
auto selfType = cast<GenericTypeParamType>(
998998
proto->getSelfInterfaceType()->getCanonicalType());
999999

1000-
// Construct a generic signature builder by collecting the constraints from the
1001-
// requirement and the context of the conformance together, because both
1002-
// define the capabilities of the requirement.
1000+
// Construct a generic signature builder by collecting the constraints
1001+
// from the requirement and the context of the conformance together,
1002+
// because both define the capabilities of the requirement.
10031003
GenericSignatureBuilder builder(
10041004
ctx,
1005-
LookUpConformanceInModule(conformanceDC->getParentModule()));
1005+
TypeChecker::LookUpConformance(tc, conformanceDC));
1006+
10061007
SmallVector<GenericTypeParamType*, 4> allGenericParams;
10071008

10081009
// Add the generic signature of the context of the conformance. This includes
@@ -4776,8 +4777,7 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
47764777
// FIXME: maybe this should be the conformance's type
47774778
proto->getDeclaredInterfaceType(), reqSig,
47784779
QuerySubstitutionMap{substitutions},
4779-
LookUpConformanceInModule(
4780-
Conformance->getDeclContext()->getParentModule()),
4780+
TypeChecker::LookUpConformance(TC, Conformance->getDeclContext()),
47814781
nullptr,
47824782
ConformanceCheckFlags::Used, &listener);
47834783

@@ -5268,6 +5268,21 @@ TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC,
52685268
: ConformsToProtocolResult::failure();
52695269
}
52705270

5271+
Optional<ProtocolConformanceRef>
5272+
TypeChecker::LookUpConformance::operator()(
5273+
CanType dependentType,
5274+
Type conformingReplacementType,
5275+
ProtocolType *conformedProtocol) const {
5276+
if (conformingReplacementType->isTypeParameter())
5277+
return ProtocolConformanceRef(conformedProtocol->getDecl());
5278+
5279+
return tc.conformsToProtocol(conformingReplacementType,
5280+
conformedProtocol->getDecl(),
5281+
dc,
5282+
(ConformanceCheckFlags::Used|
5283+
ConformanceCheckFlags::InExpression));
5284+
}
5285+
52715286
/// Mark any _ObjectiveCBridgeable conformances in the given type as "used".
52725287
///
52735288
/// These conformances might not appear in any substitution lists produced

lib/Sema/TypeCheckType.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ Type TypeChecker::applyUnboundGenericArguments(
743743
auto result =
744744
checkGenericArguments(dc, loc, noteLoc, unboundType, genericSig,
745745
QueryTypeSubstitutionMap{subs},
746-
LookUpConformanceInModule{dc->getParentModule()},
746+
LookUpConformance(*this, dc),
747747
unsatisfiedDependency);
748748

749749
switch (result) {
@@ -758,7 +758,7 @@ Type TypeChecker::applyUnboundGenericArguments(
758758

759759
// Apply the substitution map to the interface type of the declaration.
760760
resultType = resultType.subst(QueryTypeSubstitutionMap{subs},
761-
LookUpConformanceInModule(dc->getParentModule()),
761+
LookUpConformance(*this, dc),
762762
SubstFlags::UseErrorType);
763763

764764
if (isa<NominalTypeDecl>(decl)) {

lib/Sema/TypeChecker.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,6 +1814,23 @@ class TypeChecker final : public LazyResolver {
18141814
ConformanceCheckOptions options, SourceLoc ComplainLoc,
18151815
UnsatisfiedDependency *unsatisfiedDependency);
18161816

1817+
/// Functor class suitable for use as a \c LookupConformanceFn to look up a
1818+
/// conformance through a particular declaration context using the given
1819+
/// type checker.
1820+
class LookUpConformance {
1821+
TypeChecker &tc;
1822+
DeclContext *dc;
1823+
1824+
public:
1825+
explicit LookUpConformance(TypeChecker &tc, DeclContext *dc)
1826+
: tc(tc), dc(dc) { }
1827+
1828+
Optional<ProtocolConformanceRef>
1829+
operator()(CanType dependentType,
1830+
Type conformingReplacementType,
1831+
ProtocolType *conformedProtocol) const;
1832+
};
1833+
18171834
/// Completely check the given conformance.
18181835
void checkConformance(NormalProtocolConformance *conformance);
18191836

test/ClangImporter/Inputs/ibaction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@import ObjectiveC;
2+
3+
@protocol IBActionInProtocol
4+
-(void) __attribute__((ibaction)) actionMethod:(_Nullable id)param;
5+
@end
6+
7+
@interface ConformsToIBActionInProtocol : NSObject <IBActionInProtocol>
8+
@end
9+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-swift-frontend -emit-sil %s -import-objc-header %S/Inputs/ibaction.h -verify
2+
// REQUIRES: objc_interop
3+
4+
func foo(object: ConformsToIBActionInProtocol) {
5+
object.actionMethod(object)
6+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
protocol _P { }
2+
protocol P : _P { }
3+
4+
protocol Q {
5+
associatedtype A: P
6+
7+
func getArray() -> [RequiresP<A>]
8+
}
9+
10+
struct RequiresP<T: P> { }
11+
12+
struct MyStruct: P { }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %target-swift-frontend -emit-ir %S/Inputs/for_each_conformance_crashB.swift -primary-file %s -o -
2+
3+
extension Q where A == MyStruct {
4+
func foo() {
5+
for _ in getArray() { }
6+
}
7+
}

0 commit comments

Comments
 (0)