Skip to content

Commit 170992c

Browse files
committed
AST: Add Throws flag and ThrowsLoc to AbstractFunctionDecl
The verifier now asserts that Throws, ThrowsLoc and isBodyThrowing() match up. Also, add /*Label=*/ comments where necessary to make the long argument lists easier to read, and cleaned up some inconsistent naming conventions. I caught a case where ClangImporter where we were passing in a loc as StaticLoc instead of FuncLoc, but probably this didn't affect anything.
1 parent 09c57d3 commit 170992c

25 files changed

+401
-294
lines changed

include/swift/AST/Decl.h

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,11 @@ class alignas(1 << DeclAlignInBits) Decl {
326326

327327
/// Whether we are overridden later.
328328
unsigned Overridden : 1;
329+
330+
/// Whether the function body throws.
331+
unsigned Throws : 1;
329332
};
330-
enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 10 };
333+
enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 11 };
331334
static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");
332335

333336
class FuncDeclBitfields {
@@ -4573,18 +4576,25 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
45734576

45744577
CaptureInfo Captures;
45754578

4579+
/// Location of the 'throws' token.
4580+
SourceLoc ThrowsLoc;
4581+
45764582
ImportAsMemberStatus IAMStatus;
45774583

4578-
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
4579-
SourceLoc NameLoc, unsigned NumParameterLists,
4584+
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent,
4585+
DeclName Name, SourceLoc NameLoc,
4586+
bool Throws, SourceLoc ThrowsLoc,
4587+
unsigned NumParameterLists,
45804588
GenericParamList *GenericParams)
45814589
: ValueDecl(Kind, Parent, Name, NameLoc),
45824590
DeclContext(DeclContextKind::AbstractFunctionDecl, Parent),
4583-
Body(nullptr), GenericParams(nullptr), GenericSig(nullptr) {
4591+
Body(nullptr), GenericParams(nullptr), GenericSig(nullptr),
4592+
ThrowsLoc(ThrowsLoc) {
45844593
setBodyKind(BodyKind::None);
45854594
setGenericParams(GenericParams);
45864595
AbstractFunctionDeclBits.NumParameterLists = NumParameterLists;
45874596
AbstractFunctionDeclBits.Overridden = false;
4597+
AbstractFunctionDeclBits.Throws = Throws;
45884598

45894599
// Verify no bitfield truncation.
45904600
assert(AbstractFunctionDeclBits.NumParameterLists == NumParameterLists);
@@ -4617,6 +4627,12 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
46174627
void setSelfIndex(uint8_t idx) { return IAMStatus.setSelfIndex(idx); }
46184628

46194629
public:
4630+
/// Retrieve the location of the 'throws' keyword, if present.
4631+
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
4632+
4633+
/// Returns true if the function body throws.
4634+
bool hasThrows() const { return AbstractFunctionDeclBits.Throws; }
4635+
46204636
// FIXME: Hack that provides names with keyword arguments for accessors.
46214637
DeclName getEffectiveFullName() const;
46224638

@@ -4831,9 +4847,6 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
48314847
/// Resolved during type checking
48324848
void setIsOverridden() { AbstractFunctionDeclBits.Overridden = true; }
48334849

4834-
/// Whether the function body is 'throws'.
4835-
bool isBodyThrowing() const;
4836-
48374850
/// Set information about the foreign error convention used by this
48384851
/// declaration.
48394852
void setForeignErrorConvention(const ForeignErrorConvention &convention);
@@ -4876,7 +4889,6 @@ class FuncDecl final : public AbstractFunctionDecl,
48764889

48774890
SourceLoc StaticLoc; // Location of the 'static' token or invalid.
48784891
SourceLoc FuncLoc; // Location of the 'func' token.
4879-
SourceLoc ThrowsLoc; // Location of the 'throws' token.
48804892
SourceLoc AccessorKeywordLoc; // Location of the accessor keyword, e.g. 'set'.
48814893

48824894
TypeLoc FnRetType;
@@ -4901,14 +4913,17 @@ class FuncDecl final : public AbstractFunctionDecl,
49014913
AddressorKind> OperatorAndAddressorKind;
49024914

49034915
FuncDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
4904-
SourceLoc FuncLoc, DeclName Name,
4905-
SourceLoc NameLoc, SourceLoc ThrowsLoc,
4916+
SourceLoc FuncLoc,
4917+
DeclName Name, SourceLoc NameLoc,
4918+
bool Throws, SourceLoc ThrowsLoc,
49064919
SourceLoc AccessorKeywordLoc,
49074920
unsigned NumParameterLists,
49084921
GenericParamList *GenericParams, Type Ty, DeclContext *Parent)
4909-
: AbstractFunctionDecl(DeclKind::Func, Parent, Name, NameLoc,
4922+
: AbstractFunctionDecl(DeclKind::Func, Parent,
4923+
Name, NameLoc,
4924+
Throws, ThrowsLoc,
49104925
NumParameterLists, GenericParams),
4911-
StaticLoc(StaticLoc), FuncLoc(FuncLoc), ThrowsLoc(ThrowsLoc),
4926+
StaticLoc(StaticLoc), FuncLoc(FuncLoc),
49124927
AccessorKeywordLoc(AccessorKeywordLoc),
49134928
OverriddenOrDerivedForOrBehaviorParamDecl(),
49144929
OperatorAndAddressorKind(nullptr, AddressorKind::NotAddressor) {
@@ -4926,31 +4941,35 @@ class FuncDecl final : public AbstractFunctionDecl,
49264941

49274942
static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
49284943
StaticSpellingKind StaticSpelling,
4929-
SourceLoc FuncLoc, DeclName Name,
4930-
SourceLoc NameLoc, SourceLoc ThrowsLoc,
4944+
SourceLoc FuncLoc,
4945+
DeclName Name, SourceLoc NameLoc,
4946+
bool Throws, SourceLoc ThrowsLoc,
49314947
SourceLoc AccessorKeywordLoc,
4932-
GenericParamList *GenericParams, Type Ty,
4933-
unsigned NumParameterLists,
4948+
GenericParamList *GenericParams,
4949+
unsigned NumParameterLists, Type Ty,
49344950
DeclContext *Parent,
49354951
ClangNode ClangN);
49364952

49374953
public:
49384954
/// Factory function only for use by deserialization.
49394955
static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc,
49404956
StaticSpellingKind StaticSpelling,
4941-
SourceLoc FuncLoc, DeclName Name,
4942-
SourceLoc NameLoc, SourceLoc ThrowsLoc,
4957+
SourceLoc FuncLoc,
4958+
DeclName Name, SourceLoc NameLoc,
4959+
bool Throws, SourceLoc ThrowsLoc,
49434960
SourceLoc AccessorKeywordLoc,
4944-
GenericParamList *GenericParams, Type Ty,
4945-
unsigned NumParameterLists,
4961+
GenericParamList *GenericParams,
4962+
unsigned NumParameterLists, Type Ty,
49464963
DeclContext *Parent);
49474964

49484965
static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
49494966
StaticSpellingKind StaticSpelling,
4950-
SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc,
4951-
SourceLoc ThrowsLoc, SourceLoc AccessorKeywordLoc,
4967+
SourceLoc FuncLoc,
4968+
DeclName Name, SourceLoc NameLoc,
4969+
bool Throws, SourceLoc ThrowsLoc,
4970+
SourceLoc AccessorKeywordLoc,
49524971
GenericParamList *GenericParams,
4953-
Type Ty, ArrayRef<ParameterList *> ParameterLists,
4972+
ArrayRef<ParameterList *> ParameterLists, Type Ty,
49544973
TypeLoc FnRetType, DeclContext *Parent,
49554974
ClangNode ClangN = ClangNode());
49564975

@@ -5013,7 +5032,6 @@ class FuncDecl final : public AbstractFunctionDecl,
50135032

50145033
SourceLoc getStaticLoc() const { return StaticLoc; }
50155034
SourceLoc getFuncLoc() const { return FuncLoc; }
5016-
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
50175035
SourceLoc getAccessorKeywordLoc() const {return AccessorKeywordLoc; }
50185036

50195037
SourceLoc getStartLoc() const {
@@ -5427,9 +5445,6 @@ class ConstructorDecl : public AbstractFunctionDecl {
54275445
/// The location of the '!' or '?' for a failable initializer.
54285446
SourceLoc FailabilityLoc;
54295447

5430-
// Location of the 'throws' token.
5431-
SourceLoc ThrowsLoc;
5432-
54335448
ParameterList *ParameterLists[2];
54345449

54355450
/// The type of the initializing constructor.
@@ -5449,9 +5464,10 @@ class ConstructorDecl : public AbstractFunctionDecl {
54495464
public:
54505465
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
54515466
OptionalTypeKind Failability, SourceLoc FailabilityLoc,
5452-
ParamDecl *selfParam, ParameterList *BodyParams,
5467+
bool Throws, SourceLoc ThrowsLoc,
5468+
ParamDecl *SelfParam, ParameterList *BodyParams,
54535469
GenericParamList *GenericParams,
5454-
SourceLoc throwsLoc, DeclContext *Parent);
5470+
DeclContext *Parent);
54555471

54565472
void setParameterLists(ParamDecl *selfParam, ParameterList *bodyParams);
54575473

@@ -5590,9 +5606,6 @@ class ConstructorDecl : public AbstractFunctionDecl {
55905606
/// Retrieve the location of the '!' or '?' in a failable initializer.
55915607
SourceLoc getFailabilityLoc() const { return FailabilityLoc; }
55925608

5593-
/// Retrieve the location of the 'throws' keyword, if present.
5594-
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
5595-
55965609
/// Whether the implementation of this method is a stub that traps at runtime.
55975610
bool hasStubImplementation() const {
55985611
return ConstructorDeclBits.HasStubImplementation;

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
5353
/// in source control, you should also update the comment to briefly
5454
/// describe what change you made. The content of this comment isn't important;
5555
/// it just ensures a conflict if two people change the module format.
56-
const uint16_t VERSION_MINOR = 249; // Last change: SIL clang decls
56+
const uint16_t VERSION_MINOR = 250; // Last change: Add Throws bit
5757

5858
using DeclID = PointerEmbeddedInt<unsigned, 31>;
5959
using DeclIDField = BCFixed<31>;
@@ -851,6 +851,7 @@ namespace decls_block {
851851
BCFixed<1>, // implicit?
852852
BCFixed<1>, // objc?
853853
BCFixed<1>, // stub implementation?
854+
BCFixed<1>, // throws?
854855
CtorInitializerKindField, // initializer kind
855856
TypeIDField, // type (signature)
856857
TypeIDField, // type (interface)
@@ -904,6 +905,7 @@ namespace decls_block {
904905
BCFixed<1>, // explicitly objc?
905906
BCFixed<1>, // mutating?
906907
BCFixed<1>, // has dynamic self?
908+
BCFixed<1>, // throws?
907909
BCVBR<5>, // number of parameter patterns
908910
TypeIDField, // type (signature)
909911
TypeIDField, // interface type

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,7 +2067,7 @@ static AbstractFunctionDecl *lookupObjCMethodInType(
20672067

20682068
void AbstractFunctionDecl::setForeignErrorConvention(
20692069
const ForeignErrorConvention &conv) {
2070-
assert(isBodyThrowing() && "setting error convention on non-throwing decl");
2070+
assert(hasThrows() && "setting error convention on non-throwing decl");
20712071
auto &conventionsMap = getASTContext().Impl.ForeignErrorConventions;
20722072
assert(!conventionsMap.count(this) && "error convention already set");
20732073
conventionsMap.insert({this, conv});
@@ -2077,7 +2077,7 @@ Optional<ForeignErrorConvention>
20772077
AbstractFunctionDecl::getForeignErrorConvention() const {
20782078
if (!isObjC() && !getAttrs().hasAttribute<CDeclAttr>())
20792079
return None;
2080-
if (!isBodyThrowing())
2080+
if (!hasThrows())
20812081
return None;
20822082
auto &conventionsMap = getASTContext().Impl.ForeignErrorConventions;
20832083
auto it = conventionsMap.find(this);

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2613,7 +2613,7 @@ void PrintAST::printFunctionParameters(AbstractFunctionDecl *AFD) {
26132613
});
26142614
}
26152615

2616-
if (AFD->isBodyThrowing()) {
2616+
if (AFD->hasThrows()) {
26172617
if (AFD->getAttrs().hasAttribute<RethrowsAttr>())
26182618
Printer << " " << tok::kw_rethrows;
26192619
else

lib/AST/ASTVerifier.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,8 +2226,8 @@ struct ASTNodeBase {};
22262226
// Throwing @objc methods must have a foreign error convention.
22272227
if (AFD->isObjC() &&
22282228
static_cast<bool>(AFD->getForeignErrorConvention())
2229-
!= AFD->isBodyThrowing()) {
2230-
if (AFD->isBodyThrowing())
2229+
!= AFD->hasThrows()) {
2230+
if (AFD->hasThrows())
22312231
Out << "@objc method throws but does not have a foreign error "
22322232
<< "convention";
22332233
else
@@ -2236,6 +2236,29 @@ struct ASTNodeBase {};
22362236
abort();
22372237
}
22382238

2239+
// If a decl has the Throws bit set, the ThrowsLoc should be valid,
2240+
// and vice versa, unless the decl was imported, de-serialized, or
2241+
// implicit.
2242+
if (!AFD->isImplicit() &&
2243+
isa<SourceFile>(AFD->getModuleScopeContext()) &&
2244+
(AFD->getThrowsLoc().isValid() != AFD->hasThrows())) {
2245+
Out << "function 'throws' location does not match 'throws' flag\n";
2246+
AFD->dump(Out);
2247+
abort();
2248+
}
2249+
2250+
// If a decl has the Throws bit set, the function type should throw,
2251+
// and vice versa.
2252+
auto fnTy = AFD->getType()->castTo<AnyFunctionType>();
2253+
for (unsigned i = 1, e = AFD->getNaturalArgumentCount(); i != e; ++i)
2254+
fnTy = fnTy->getResult()->castTo<AnyFunctionType>();
2255+
2256+
if (AFD->hasThrows() != fnTy->getExtInfo().throws()) {
2257+
Out << "function 'throws' flag does not match function type\n";
2258+
AFD->dump(Out);
2259+
abort();
2260+
}
2261+
22392262
if (AFD->getForeignErrorConvention()
22402263
&& !AFD->isObjC() && !AFD->getAttrs().hasAttribute<CDeclAttr>()) {
22412264
Out << "foreign error convention on non-@objc, non-@_cdecl function\n";

lib/AST/Builtins.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,15 @@ getBuiltinFunction(Identifier Id, ArrayRef<Type> argTypes, Type ResType,
159159
auto *paramList = ParameterList::create(Context, params);
160160

161161
DeclName Name(Context, Id, paramList);
162-
auto FD = FuncDecl::create(Context, SourceLoc(), StaticSpellingKind::None,
163-
SourceLoc(), Name, SourceLoc(), SourceLoc(),
164-
SourceLoc(), /*GenericParams=*/nullptr, FnType,
165-
paramList, TypeLoc::withoutLoc(ResType), DC);
162+
auto FD = FuncDecl::create(Context, /*StaticLoc=*/SourceLoc(),
163+
StaticSpellingKind::None,
164+
/*FuncLoc=*/SourceLoc(),
165+
Name, /*NameLoc=*/SourceLoc(),
166+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
167+
/*AccessorKeywordLoc=*/SourceLoc(),
168+
/*GenericParams=*/nullptr,
169+
paramList, FnType,
170+
TypeLoc::withoutLoc(ResType), DC);
166171
FD->setImplicit();
167172
FD->setAccessibility(Accessibility::Public);
168173
return FD;
@@ -194,7 +199,6 @@ getBuiltinGenericFunction(Identifier Id,
194199
requirements.push_back(Requirement(RequirementKind::WitnessMarker,
195200
param, Type()));
196201
}
197-
198202
GenericSignature *Sig = GenericSignature::get(GenericParamTypes,requirements);
199203

200204
Type InterfaceType = GenericFunctionType::get(Sig,
@@ -221,10 +225,13 @@ getBuiltinGenericFunction(Identifier Id,
221225
ResBodyType, GenericParams, Info);
222226

223227
DeclName Name(Context, Id, paramList);
224-
auto func = FuncDecl::create(Context, SourceLoc(), StaticSpellingKind::None,
225-
SourceLoc(), Name,
226-
SourceLoc(), SourceLoc(), SourceLoc(),
227-
GenericParams, FnType, paramList,
228+
auto func = FuncDecl::create(Context, /*StaticLoc=*/SourceLoc(),
229+
StaticSpellingKind::None,
230+
/*FuncLoc=*/SourceLoc(),
231+
Name, /*NameLoc=*/SourceLoc(),
232+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
233+
/*AccessorKeywordLoc=*/SourceLoc(),
234+
GenericParams, paramList, FnType,
228235
TypeLoc::withoutLoc(ResBodyType), DC);
229236

230237
func->setInterfaceType(InterfaceType);

0 commit comments

Comments
 (0)