Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/KnownIdentifiers.def
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ IDENTIFIER_(nsError)

// Custom string interpolation type used by os log APIs.
IDENTIFIER(OSLogMessage)
// Types that are specialy handled in diagnostics for the os log APIs.
IDENTIFIER(OSLog)
IDENTIFIER(OSLogType)

// Atomics ordering type identifiers.
IDENTIFIER(AtomicLoadOrdering)
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/SemanticAttrs.def
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ SEMANTICS_ATTR(OPTIMIZE_SIL_SPECIALIZE_GENERIC_SIZE_NEVER,
SEMANTICS_ATTR(OSLOG_MESSAGE_INIT_INTERPOLATION, "oslog.message.init_interpolation")
SEMANTICS_ATTR(OSLOG_MESSAGE_INIT_STRING_LITERAL, "oslog.message.init_stringliteral")
SEMANTICS_ATTR(OSLOG_REQUIRES_CONSTANT_ARGUMENTS, "oslog.requires_constant_arguments")
SEMANTICS_ATTR(OSLOG_LOG_WITH_LEVEL, "oslog.log_with_level")
SEMANTICS_ATTR(ATOMICS_REQUIRES_CONSTANT_ORDERINGS, "atomics.requires_constant_orderings")

SEMANTICS_ATTR(TYPE_CHECKER_OPEN_EXISTENTIAL, "typechecker._openExistential(_:do:)")
Expand Down
17 changes: 17 additions & 0 deletions lib/Sema/ConstantnessSemaDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,30 @@ static bool isAtomicOrderingDecl(StructDecl *structDecl) {
structName == astContext.Id_AtomicUpdateOrdering);
}

/// Return true iff the given nominal type decl \p nominal has a name that
/// matches one of the known OSLog types that need not be a constant in the new
/// os_log APIs.
static bool isOSLogDynamicObject(NominalTypeDecl *nominal) {
ASTContext &astContext = nominal->getASTContext();
Identifier name = nominal->getName();
return (name == astContext.Id_OSLog || name == astContext.Id_OSLogType);
}

/// Return true iff the parameter \p param of function \c funDecl is required to
/// be a constant. This is true if either the function is an os_log function or
/// it is an atomics operation and the parameter represents the ordering.
static bool isParamRequiredToBeConstant(FuncDecl *funcDecl, ParamDecl *param) {
assert(funcDecl && param && "funcDecl and param must not be null");
if (hasSemanticsAttr(funcDecl, semantics::OSLOG_REQUIRES_CONSTANT_ARGUMENTS))
return true;
if (hasSemanticsAttr(funcDecl, semantics::OSLOG_LOG_WITH_LEVEL)) {
// We are looking at a top-level os_log function that accepts level and
// possibly custom log object. Those need not be constants, but every other
// parameter must be.
Type paramType = param->getType();
NominalTypeDecl *nominal = paramType->getNominalOrBoundGenericNominal();
return !nominal || !isOSLogDynamicObject(nominal);
}
if (!hasSemanticsAttr(funcDecl,
semantics::ATOMICS_REQUIRES_CONSTANT_ORDERINGS))
return false;
Expand Down
26 changes: 26 additions & 0 deletions test/Sema/diag_constantness_check_os_log.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,29 @@ func testOSLogInterpolationExtension(a: MyStruct) {
// the appendInterpolation overload is not marked as constant_evaluable.
_osLogTestHelper("Error at line: \(a: a)")
}

// Test that @_semantics("oslog.log_with_level") permits values of type OSLog and
// OSLogType to not be constants.

class OSLog { }
class OSLogType { }

@_semantics("oslog.log_with_level")
func osLogWithLevel(_ level: OSLogType, log: OSLog, _ message: OSLogMessage) {
}

func testNonConstantLogObjectLevel(
level: OSLogType,
log: OSLog,
message: OSLogMessage
) {
osLogWithLevel(level, log: log, "message with no payload")
var levelOpt: OSLogType? = nil
levelOpt = level

let logClosure = { log }
osLogWithLevel(levelOpt!, log: logClosure(), "A string \("hello")")

osLogWithLevel(level, log: log, message)
// expected-error@-1 {{argument must be a string interpolation}}
}