Skip to content

Commit d85873e

Browse files
committed
Parse bounds declarations for function return values.
This extends parsing of function declarators to parse bounds expressions for function return values. A return bounds expression is declared by following a parameter list with ':' bounds-expression. The return bounds information is propagated to the representation of function declarations in clang. It is not propagated yet to function types because there is no way to represent it in function types. I have opened issue #20 to track taht and added a few TODO's to the code code flagging where the information will need to be added. Testing: - Add feature tests for parsing return bounds. The tests are in in the file return_bounds.c, which will be committed separately to the checkedc Github repo. - Passes existing clang regression test baseline.
1 parent 9b85c1c commit d85873e

File tree

9 files changed

+86
-8
lines changed

9 files changed

+86
-8
lines changed

include/clang/AST/Decl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,8 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
15841584
/// 'enum Y' in 'void f(enum Y {AA} x) {}'.
15851585
ArrayRef<NamedDecl *> DeclsInPrototypeScope;
15861586

1587+
BoundsExpr *ReturnBoundsExpr;
1588+
15871589
LazyDeclStmtPtr Body;
15881590

15891591
// FIXME: This can be packed into the bitfields in DeclContext.
@@ -1687,7 +1689,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
16871689
StartLoc),
16881690
DeclContext(DK),
16891691
redeclarable_base(C),
1690-
ParamInfo(nullptr), Body(),
1692+
ParamInfo(nullptr), ReturnBoundsExpr(nullptr), Body(),
16911693
SClass(S),
16921694
IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
16931695
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
@@ -2065,6 +2067,11 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
20652067
/// computed linkage of symbol, see getLinkage.
20662068
StorageClass getStorageClass() const { return StorageClass(SClass); }
20672069

2070+
/// \brief Returns the bounds expression for the return value of this function, if
2071+
/// any.
2072+
BoundsExpr *getReturnBoundsExpr() { return ReturnBoundsExpr; }
2073+
void setReturnBoundsExpr(BoundsExpr *E) { ReturnBoundsExpr = E; }
2074+
20682075
/// \brief Determine whether the "inline" keyword was specified for this
20692076
/// function.
20702077
bool isInlineSpecified() const { return IsInlineSpecified; }

include/clang/Sema/DeclSpec.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,11 +1287,18 @@ struct DeclaratorChunk {
12871287
/// \brief The end location of the exception specification, if any.
12881288
unsigned ExceptionSpecLocEnd;
12891289

1290+
/// The location of the ':' for the return bounds expression in the source
1291+
unsigned ReturnBoundsColon;
1292+
12901293
/// Params - This is a pointer to a new[]'d array of ParamInfo objects that
12911294
/// describe the parameters specified by this function declarator. null if
12921295
/// there are no parameters specified.
12931296
ParamInfo *Params;
12941297

1298+
/// The bounds for the value returned by the function. Null if there is
1299+
/// no bounds specified.
1300+
BoundsExpr *ReturnBounds;
1301+
12951302
union {
12961303
/// \brief Pointer to a new[]'d array of TypeAndRange objects that
12971304
/// contain the types in the function's dynamic exception specification
@@ -1352,6 +1359,10 @@ struct DeclaratorChunk {
13521359
return SourceLocation::getFromRawEncoding(RParenLoc);
13531360
}
13541361

1362+
SourceLocation getReturnBoundsColon() const {
1363+
return SourceLocation::getFromRawEncoding(ReturnBoundsColon);
1364+
}
1365+
13551366
SourceLocation getExceptionSpecLocBeg() const {
13561367
return SourceLocation::getFromRawEncoding(ExceptionSpecLocBeg);
13571368
}
@@ -1408,6 +1419,9 @@ struct DeclaratorChunk {
14081419

14091420
/// \brief Get the trailing-return-type for this function declarator.
14101421
ParsedType getTrailingReturnType() const { return TrailingReturnType; }
1422+
1423+
/// \brief The bounds expression for the return value
1424+
BoundsExpr *getReturnBounds() const { return ReturnBounds; }
14111425
};
14121426

14131427
struct BlockPointerTypeInfo : TypeInfoCommon {
@@ -1552,6 +1566,8 @@ struct DeclaratorChunk {
15521566
CachedTokens *ExceptionSpecTokens,
15531567
SourceLocation LocalRangeBegin,
15541568
SourceLocation LocalRangeEnd,
1569+
SourceLocation ReturnBoundsColonLoc,
1570+
BoundsExpr *ReturnBoundsExpr,
15551571
Declarator &TheDeclarator,
15561572
TypeResult TrailingReturnType =
15571573
TypeResult());

include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4116,6 +4116,7 @@ class Sema {
41164116

41174117
void ActOnBoundsExpr(VarDecl *D, BoundsExpr *Expr);
41184118
void ActOnInvalidBoundsExpr(VarDecl *D);
4119+
BoundsExpr *CreateInvalidBoundsExpr();
41194120

41204121
//===---------------------------- Clang Extensions ----------------------===//
41214122

lib/Parse/ParseDecl.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5586,6 +5586,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
55865586
/// dynamic-exception-specification
55875587
/// noexcept-specification
55885588
///
5589+
/// For Checked C, after the parameter-list, it also parses the optional return
5590+
/// bounds expression for the function declarator:
5591+
/// [Checked C] ':' bounds-expression
5592+
////
55895593
void Parser::ParseFunctionDeclarator(Declarator &D,
55905594
ParsedAttributes &FirstArgAttrs,
55915595
BalancedDelimiterTracker &Tracker,
@@ -5626,6 +5630,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
56265630
SourceLocation LParenLoc, RParenLoc;
56275631
LParenLoc = Tracker.getOpenLocation();
56285632
StartLoc = LParenLoc;
5633+
SourceLocation BoundsColonLoc;
5634+
BoundsExpr *ReturnBoundsExpr = nullptr;
56295635

56305636
if (isFunctionDeclaratorIdentifierList()) {
56315637
if (RequiresArg)
@@ -5741,6 +5747,17 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
57415747
}
57425748
}
57435749

5750+
if (getLangOpts().CheckedC && Tok.is(tok::colon)) {
5751+
BoundsColonLoc = Tok.getLocation();
5752+
ConsumeToken();
5753+
ExprResult BoundsExprResult = ParseBoundsExpression();
5754+
if (BoundsExprResult.isInvalid()) {
5755+
ReturnBoundsExpr = Actions.CreateInvalidBoundsExpr();
5756+
SkipUntil(tok::l_brace, SkipUntilFlags::StopAtSemi | SkipUntilFlags::StopBeforeMatch);
5757+
} else
5758+
ReturnBoundsExpr = cast<BoundsExpr>(BoundsExprResult.get());
5759+
}
5760+
57445761
// Remember that we parsed a function type, and remember the attributes.
57455762
D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto,
57465763
IsAmbiguous,
@@ -5760,7 +5777,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
57605777
NoexceptExpr.isUsable() ?
57615778
NoexceptExpr.get() : nullptr,
57625779
ExceptionSpecTokens,
5763-
StartLoc, LocalEndLoc, D,
5780+
StartLoc, LocalEndLoc,
5781+
BoundsColonLoc, ReturnBoundsExpr,
5782+
D,
57645783
TrailingReturnType),
57655784
FnAttrs, EndLoc);
57665785
}

lib/Parse/ParseExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2971,6 +2971,8 @@ ExprResult Parser::ParseBlockLiteralExpression() {
29712971
/*NoexceptExpr=*/nullptr,
29722972
/*ExceptionSpecTokens=*/nullptr,
29732973
CaretLoc, CaretLoc,
2974+
/*ReturnBoundsColon=*/NoLoc,
2975+
/*ReturnBoundsExpr=*/nullptr,
29742976
ParamInfo),
29752977
attrs, CaretLoc);
29762978

lib/Parse/ParseExprCXX.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
12211221
NoexceptExpr.isUsable() ?
12221222
NoexceptExpr.get() : nullptr,
12231223
/*ExceptionSpecTokens*/nullptr,
1224-
LParenLoc, FunLocalRangeEnd, D,
1224+
LParenLoc, FunLocalRangeEnd,
1225+
/*ReturnBoundsColon=*/NoLoc,
1226+
/*ReturnBoundsExpr=*/nullptr,
1227+
D,
12251228
TrailingReturnType),
12261229
Attr, DeclEndLoc);
12271230
} else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
@@ -1290,7 +1293,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
12901293
/*NumExceptions=*/0,
12911294
/*NoexceptExpr=*/nullptr,
12921295
/*ExceptionSpecTokens=*/nullptr,
1293-
DeclLoc, DeclEndLoc, D,
1296+
DeclLoc, DeclEndLoc,
1297+
/*ReturnBoundsColon=*/NoLoc,
1298+
/*ReturnBoundsExpr=*/nullptr,
1299+
D,
12941300
TrailingReturnType),
12951301
Attr, DeclEndLoc);
12961302
}

lib/Sema/DeclSpec.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
175175
CachedTokens *ExceptionSpecTokens,
176176
SourceLocation LocalRangeBegin,
177177
SourceLocation LocalRangeEnd,
178+
SourceLocation ReturnBoundsColonLoc,
179+
BoundsExpr *ReturnBoundsExpr,
178180
Declarator &TheDeclarator,
179181
TypeResult TrailingReturnType) {
180182
assert(!(TypeQuals & DeclSpec::TQ_atomic) &&
@@ -210,6 +212,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
210212
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
211213
TrailingReturnType.isInvalid();
212214
I.Fun.TrailingReturnType = TrailingReturnType.get();
215+
I.Fun.ReturnBoundsColon = ReturnBoundsColonLoc.getRawEncoding();
216+
I.Fun.ReturnBounds = ReturnBoundsExpr;
213217

214218
assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow");
215219
assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow");

lib/Sema/SemaDecl.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7973,6 +7973,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
79737973
// Finally, we know we have the right number of parameters, install them.
79747974
NewFD->setParams(Params);
79757975

7976+
// TODO: clang-checked-issue #20. Issue #20 is attaching bounds information
7977+
// to function types. After it is address, we need to make sure that bounds
7978+
// information is propgated to newFD from the FunctionPrototype instance.
7979+
if (D.isFunctionDeclarator()) {
7980+
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
7981+
NewFD->setReturnBoundsExpr(FTI.getReturnBounds());
7982+
}
7983+
79767984
// Find all anonymous symbols defined during the declaration of this function
79777985
// and add to NewFD. This lets us track decls such 'enum Y' in:
79787986
//
@@ -10880,13 +10888,19 @@ void Sema::ActOnInvalidBoundsExpr(VarDecl *D) {
1088010888
if (!D)
1088110889
return;
1088210890

10891+
BoundsExpr *InvalidExpr = CreateInvalidBoundsExpr();
10892+
D->setBoundsExpr(InvalidExpr);
10893+
}
10894+
10895+
BoundsExpr *Sema::CreateInvalidBoundsExpr() {
1088310896
ExprResult Result =
1088410897
ActOnNullaryBoundsExpr(SourceLocation(),
1088510898
NullaryBoundsExpr::Kind::Invalid,
1088610899
SourceLocation());
10887-
1088810900
if (!Result.isInvalid())
10889-
D->setBoundsExpr(cast<BoundsExpr>(Result.get()));
10901+
return cast<BoundsExpr>(Result.get());
10902+
else
10903+
return nullptr;
1089010904
}
1089110905

1089210906
Decl *
@@ -11613,7 +11627,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
1161311627
/*NumExceptions=*/0,
1161411628
/*NoexceptExpr=*/nullptr,
1161511629
/*ExceptionSpecTokens=*/nullptr,
11616-
Loc, Loc, D),
11630+
Loc, Loc,
11631+
/*ReturnBoundsColon=*/NoLoc,
11632+
/*ReturnBoundsExpr=*/nullptr, D),
1161711633
DS.getAttributes(),
1161811634
SourceLocation());
1161911635
D.SetIdentifier(&II, Loc);

lib/Sema/SemaType.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,10 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
718718
/*NumExceptions=*/0,
719719
/*NoexceptExpr=*/nullptr,
720720
/*ExceptionSpecTokens=*/nullptr,
721-
loc, loc, declarator));
721+
loc, loc,
722+
/*ReturnBoundsColon=*/NoLoc,
723+
/*ReturnBoundsExpr=*/nullptr,
724+
declarator));
722725

723726
// For consistency, make sure the state still has us as processing
724727
// the decl spec.
@@ -4238,6 +4241,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
42384241
SmallVector<QualType, 16> ParamTys;
42394242
ParamTys.reserve(FTI.NumParams);
42404243

4244+
// TODO: checkedc-clang issue #20: represent bounds information
4245+
// in function types. The code below will need to be updated
4246+
// to add the bounds information to the FunctionType.
4247+
42414248
SmallVector<FunctionProtoType::ExtParameterInfo, 16>
42424249
ExtParameterInfos(FTI.NumParams);
42434250
bool HasAnyInterestingExtParameterInfos = false;

0 commit comments

Comments
 (0)