Skip to content

Commit a6da8a8

Browse files
author
Josh Learn
committed
Support constant diagnostics on constructors
This change includes a fix to allow the diagnostics for constantness in function arguments to work properly for constructors. This change also includes some minor code cleanup in the constantness diagnostic pass.
1 parent 1f1a03c commit a6da8a8

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

lib/Sema/ConstantnessSemaDiagnostics.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,26 @@ static bool isOSLogDynamicObject(NominalTypeDecl *nominal) {
6060
/// Return true iff the parameter \p param of function \c funDecl is required to
6161
/// be a constant. This is true if either the function is an os_log function or
6262
/// it is an atomics operation and the parameter represents the ordering.
63-
static bool isParamRequiredToBeConstant(FuncDecl *funcDecl, ParamDecl *param) {
63+
static bool isParamRequiredToBeConstant(AbstractFunctionDecl *funcDecl, ParamDecl *param) {
6464
assert(funcDecl && param && "funcDecl and param must not be null");
65+
Type paramType;
66+
NominalTypeDecl *nominal;
67+
StructDecl *structDecl;
6568
if (hasSemanticsAttr(funcDecl, semantics::OSLOG_REQUIRES_CONSTANT_ARGUMENTS))
6669
return true;
6770
if (hasSemanticsAttr(funcDecl, semantics::OSLOG_LOG_WITH_LEVEL)) {
6871
// We are looking at a top-level os_log function that accepts level and
6972
// possibly custom log object. Those need not be constants, but every other
7073
// parameter must be.
71-
Type paramType = param->getType();
72-
NominalTypeDecl *nominal = paramType->getNominalOrBoundGenericNominal();
74+
paramType = param->getType();
75+
nominal = paramType->getNominalOrBoundGenericNominal();
7376
return !nominal || !isOSLogDynamicObject(nominal);
7477
}
7578
if (!hasSemanticsAttr(funcDecl,
7679
semantics::ATOMICS_REQUIRES_CONSTANT_ORDERINGS))
7780
return false;
78-
Type paramType = param->getType();
79-
StructDecl *structDecl = paramType->getStructOrBoundGenericStruct();
81+
paramType = param->getType();
82+
structDecl = paramType->getStructOrBoundGenericStruct();
8083
if (!structDecl)
8184
return false;
8285
return isAtomicOrderingDecl(structDecl);
@@ -160,7 +163,7 @@ static Expr *checkConstantness(Expr *expr) {
160163
Decl *declContext = paramDecl->getDeclContext()->getAsDecl();
161164
if (!declContext)
162165
return expr;
163-
FuncDecl *funcDecl = dyn_cast<FuncDecl>(declContext);
166+
AbstractFunctionDecl *funcDecl = dyn_cast<AbstractFunctionDecl>(declContext);
164167
if (!funcDecl || !isParamRequiredToBeConstant(funcDecl, paramDecl))
165168
return expr;
166169
continue;
@@ -247,7 +250,7 @@ static bool isStringType(Type type) {
247250
/// Otherwise, if the expression is a nominal type, report that it must be
248251
/// static member of the type.
249252
static void diagnoseError(Expr *errorExpr, const ASTContext &astContext,
250-
FuncDecl *funcDecl) {
253+
AbstractFunctionDecl *funcDecl) {
251254
DiagnosticEngine &diags = astContext.Diags;
252255
Type exprType = errorExpr->getType();
253256
SourceLoc errorLoc = errorExpr->getLoc();
@@ -322,9 +325,9 @@ static void diagnoseConstantArgumentRequirementOfCall(const CallExpr *callExpr,
322325
assert(callExpr && callExpr->getType() &&
323326
"callExpr should have a valid type");
324327
ValueDecl *calledDecl = callExpr->getCalledValue();
325-
if (!calledDecl || !isa<FuncDecl>(calledDecl))
328+
if (!calledDecl || !isa<AbstractFunctionDecl>(calledDecl))
326329
return;
327-
FuncDecl *callee = cast<FuncDecl>(calledDecl);
330+
AbstractFunctionDecl *callee = cast<AbstractFunctionDecl>(calledDecl);
328331

329332
// Collect argument indices that are required to be constants.
330333
SmallVector<unsigned, 4> constantArgumentIndices;

test/Sema/diag_constantness_check.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,20 @@ func testConstantRange(x: Int) {
344344
constantClosedRange(x: x...10)
345345
// expected-error@-1 {{argument must be an integer literal}}
346346
}
347+
348+
struct ConstructorTest {
349+
@_semantics("oslog.requires_constant_arguments")
350+
init(x: Int) { }
351+
352+
@_semantics("oslog.requires_constant_arguments")
353+
init(_ x: Int) { }
354+
}
355+
356+
func testConstructorAnnotation(x: Int) {
357+
let _ = ConstructorTest(x: 10)
358+
let _ = ConstructorTest(x: x)
359+
// expected-error@-1 {{argument must be an integer literal}}
360+
let _ = ConstructorTest(10)
361+
let _ = ConstructorTest(x)
362+
// expected-error@-1 {{argument must be an integer literal}}
363+
}

0 commit comments

Comments
 (0)