Skip to content

Commit b4b99e9

Browse files
authored
Merge pull request #77248 from hamishknight/regex-avail-diag
[Sema] Add logic to diagnose regex feature availability
2 parents 1941996 + 9d4a786 commit b4b99e9

17 files changed

+413
-18
lines changed

include/swift/AST/ASTBridging.h

+68
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828

2929
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
3030

31+
namespace llvm {
32+
template<typename T> class ArrayRef;
33+
}
34+
3135
namespace swift {
3236
class Argument;
3337
class ASTContext;
@@ -42,6 +46,8 @@ class Identifier;
4246
class IfConfigClauseRangeInfo;
4347
struct LabeledStmtInfo;
4448
class ProtocolConformanceRef;
49+
class RegexLiteralPatternFeature;
50+
class RegexLiteralPatternFeatureKind;
4551
class Type;
4652
class CanType;
4753
class TypeBase;
@@ -1351,6 +1357,68 @@ BridgedPrefixUnaryExpr
13511357
BridgedPrefixUnaryExpr_createParsed(BridgedASTContext cContext,
13521358
BridgedExpr oper, BridgedExpr operand);
13531359

1360+
class BridgedRegexLiteralPatternFeatureKind final {
1361+
unsigned RawValue;
1362+
1363+
public:
1364+
BRIDGED_INLINE
1365+
SWIFT_NAME("init(rawValue:)")
1366+
BridgedRegexLiteralPatternFeatureKind(SwiftInt rawValue);
1367+
1368+
using UnbridgedTy = swift::RegexLiteralPatternFeatureKind;
1369+
1370+
BRIDGED_INLINE
1371+
BridgedRegexLiteralPatternFeatureKind(UnbridgedTy kind);
1372+
1373+
BRIDGED_INLINE
1374+
UnbridgedTy unbridged() const;
1375+
};
1376+
1377+
class BridgedRegexLiteralPatternFeature final {
1378+
BridgedCharSourceRange Range;
1379+
BridgedRegexLiteralPatternFeatureKind Kind;
1380+
1381+
public:
1382+
SWIFT_NAME("init(kind:at:)")
1383+
BridgedRegexLiteralPatternFeature(BridgedRegexLiteralPatternFeatureKind kind,
1384+
BridgedCharSourceRange range)
1385+
: Range(range), Kind(kind) {}
1386+
1387+
using UnbridgedTy = swift::RegexLiteralPatternFeature;
1388+
1389+
BRIDGED_INLINE
1390+
BridgedRegexLiteralPatternFeature(UnbridgedTy feature);
1391+
1392+
BRIDGED_INLINE
1393+
UnbridgedTy unbridged() const;
1394+
};
1395+
1396+
class BridgedRegexLiteralPatternFeatures final {
1397+
BridgedRegexLiteralPatternFeature *_Nullable Data;
1398+
SwiftInt Count;
1399+
1400+
public:
1401+
BridgedRegexLiteralPatternFeatures() : Data(nullptr), Count(0) {}
1402+
1403+
SWIFT_NAME("init(baseAddress:count:)")
1404+
BridgedRegexLiteralPatternFeatures(
1405+
BridgedRegexLiteralPatternFeature *_Nullable data, SwiftInt count)
1406+
: Data(data), Count(count) {}
1407+
1408+
using UnbridgedTy = llvm::ArrayRef<BridgedRegexLiteralPatternFeature>;
1409+
1410+
BRIDGED_INLINE
1411+
UnbridgedTy unbridged() const;
1412+
1413+
SWIFT_IMPORT_UNSAFE
1414+
BridgedRegexLiteralPatternFeature *_Nullable getData() const {
1415+
return Data;
1416+
}
1417+
SwiftInt getCount() const {
1418+
return Count;
1419+
}
1420+
};
1421+
13541422
SWIFT_NAME("BridgedRegexLiteralExpr.createParsed(_:loc:regexText:)")
13551423
BridgedRegexLiteralExpr
13561424
BridgedRegexLiteralExpr_createParsed(BridgedASTContext cContext,

include/swift/AST/ASTBridgingImpl.h

+36
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
#include "swift/AST/ASTContext.h"
1717
#include "swift/AST/ArgumentList.h"
1818
#include "swift/AST/Decl.h"
19+
#include "swift/AST/Expr.h"
1920
#include "swift/AST/IfConfigClauseRangeInfo.h"
2021
#include "swift/AST/Stmt.h"
2122
#include "swift/AST/ProtocolConformance.h"
2223
#include "swift/AST/ProtocolConformanceRef.h"
24+
#include "swift/Basic/Assertions.h"
2325

2426
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
2527

@@ -379,6 +381,40 @@ swift::IfConfigClauseRangeInfo BridgedIfConfigClauseRangeInfo::unbridged() const
379381
clauseKind);
380382
}
381383

384+
//===----------------------------------------------------------------------===//
385+
// MARK: BridgedRegexLiteralPatternFeature
386+
//===----------------------------------------------------------------------===//
387+
388+
BridgedRegexLiteralPatternFeatureKind::BridgedRegexLiteralPatternFeatureKind(
389+
SwiftInt rawValue)
390+
: RawValue(rawValue) {
391+
ASSERT(rawValue >= 0);
392+
ASSERT(rawValue == RawValue);
393+
}
394+
395+
BridgedRegexLiteralPatternFeatureKind::BridgedRegexLiteralPatternFeatureKind(
396+
UnbridgedTy kind)
397+
: RawValue(kind.getRawValue()) {}
398+
399+
BridgedRegexLiteralPatternFeatureKind::UnbridgedTy
400+
BridgedRegexLiteralPatternFeatureKind::unbridged() const {
401+
return UnbridgedTy(RawValue);
402+
}
403+
404+
BridgedRegexLiteralPatternFeature::BridgedRegexLiteralPatternFeature(
405+
UnbridgedTy feature)
406+
: Range(feature.getRange()), Kind(feature.getKind()) {}
407+
408+
BridgedRegexLiteralPatternFeature::UnbridgedTy
409+
BridgedRegexLiteralPatternFeature::unbridged() const {
410+
return UnbridgedTy(Kind.unbridged(), Range.unbridged());
411+
}
412+
413+
BridgedRegexLiteralPatternFeatures::UnbridgedTy
414+
BridgedRegexLiteralPatternFeatures::unbridged() const {
415+
return UnbridgedTy(Data, Count);
416+
}
417+
382418
//===----------------------------------------------------------------------===//
383419
// MARK: BridgedStmtConditionElement
384420
//===----------------------------------------------------------------------===//

include/swift/AST/DiagnosticEngine.h

+3
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,9 @@ namespace swift {
755755
/// Add a character-based range to the currently-active diagnostic.
756756
InFlightDiagnostic &highlightChars(SourceLoc Start, SourceLoc End);
757757

758+
/// Add a character-based range to the currently-active diagnostic.
759+
InFlightDiagnostic &highlightChars(CharSourceRange Range);
760+
758761
static const char *fixItStringFor(const FixItID id);
759762

760763
/// Get the best location where an 'import' fixit might be offered.

include/swift/AST/DiagnosticsSema.def

+4
Original file line numberDiff line numberDiff line change
@@ -5964,6 +5964,10 @@ ERROR(regex_capture_types_failed_to_decode,none,
59645964
"failed to decode capture types for regular expression literal; this may "
59655965
"be a compiler bug", ())
59665966

5967+
ERROR(regex_feature_unavailable, none,
5968+
"%0 is only available in %1 %2 or newer",
5969+
(StringRef, StringRef, llvm::VersionTuple))
5970+
59675971
ERROR(must_import_regex_builder_module,none,
59685972
"regex builder requires the 'RegexBuilder' module be imported'", ())
59695973

include/swift/AST/Expr.h

+47
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,50 @@ class InterpolatedStringLiteralExpr : public LiteralExpr {
992992
}
993993
};
994994

995+
/// The opaque kind of a RegexLiteralExpr feature, which should only be
996+
/// interpreted by the compiler's regex parsing library.
997+
class RegexLiteralPatternFeatureKind final {
998+
unsigned RawValue;
999+
1000+
public:
1001+
RegexLiteralPatternFeatureKind(unsigned rawValue) : RawValue(rawValue) {}
1002+
1003+
unsigned getRawValue() const { return RawValue; }
1004+
1005+
AvailabilityRange getAvailability(ASTContext &ctx) const;
1006+
StringRef getDescription(ASTContext &ctx) const;
1007+
1008+
friend llvm::hash_code
1009+
hash_value(const RegexLiteralPatternFeatureKind &kind) {
1010+
return llvm::hash_value(kind.getRawValue());
1011+
}
1012+
1013+
friend bool operator==(const RegexLiteralPatternFeatureKind &lhs,
1014+
const RegexLiteralPatternFeatureKind &rhs) {
1015+
return lhs.getRawValue() == rhs.getRawValue();
1016+
}
1017+
1018+
friend bool operator!=(const RegexLiteralPatternFeatureKind &lhs,
1019+
const RegexLiteralPatternFeatureKind &rhs) {
1020+
return !(lhs == rhs);
1021+
}
1022+
};
1023+
1024+
/// A specific feature used in a RegexLiteralExpr, needed for availability
1025+
/// diagnostics.
1026+
class RegexLiteralPatternFeature final {
1027+
RegexLiteralPatternFeatureKind Kind;
1028+
CharSourceRange Range;
1029+
1030+
public:
1031+
RegexLiteralPatternFeature(RegexLiteralPatternFeatureKind kind,
1032+
CharSourceRange range)
1033+
: Kind(kind), Range(range) {}
1034+
1035+
RegexLiteralPatternFeatureKind getKind() const { return Kind; }
1036+
CharSourceRange getRange() const { return Range; }
1037+
};
1038+
9951039
/// A regular expression literal e.g '(a|c)*'.
9961040
class RegexLiteralExpr : public LiteralExpr {
9971041
ASTContext *Ctx;
@@ -1021,6 +1065,9 @@ class RegexLiteralExpr : public LiteralExpr {
10211065
/// Retrieve the version of the regex string.
10221066
unsigned getVersion() const;
10231067

1068+
/// Retrieve any features used in the regex pattern.
1069+
ArrayRef<RegexLiteralPatternFeature> getPatternFeatures() const;
1070+
10241071
SourceRange getSourceRange() const { return Loc; }
10251072

10261073
static bool classof(const Expr *E) {

include/swift/AST/TypeCheckRequests.h

+42
Original file line numberDiff line numberDiff line change
@@ -5110,6 +5110,7 @@ struct RegexLiteralPatternInfo {
51105110
StringRef RegexToEmit;
51115111
Type RegexType;
51125112
size_t Version;
5113+
ArrayRef<RegexLiteralPatternFeature> Features;
51135114
};
51145115

51155116
/// Parses the regex pattern for a given regex literal using the
@@ -5131,6 +5132,47 @@ class RegexLiteralPatternInfoRequest
51315132
bool isCached() const { return true; }
51325133
};
51335134

5135+
/// The description for a given regex pattern feature. This is cached since
5136+
/// the resulting string is allocated in the ASTContext for ease of bridging.
5137+
class RegexLiteralFeatureDescriptionRequest
5138+
: public SimpleRequest<RegexLiteralFeatureDescriptionRequest,
5139+
StringRef(RegexLiteralPatternFeatureKind,
5140+
ASTContext *),
5141+
RequestFlags::Cached> {
5142+
public:
5143+
using SimpleRequest::SimpleRequest;
5144+
5145+
private:
5146+
friend SimpleRequest;
5147+
5148+
StringRef evaluate(Evaluator &evaluator, RegexLiteralPatternFeatureKind kind,
5149+
ASTContext *ctx) const;
5150+
5151+
public:
5152+
bool isCached() const { return true; }
5153+
};
5154+
5155+
/// The availability range for a given regex pattern feature.
5156+
class RegexLiteralFeatureAvailabilityRequest
5157+
: public SimpleRequest<RegexLiteralFeatureAvailabilityRequest,
5158+
AvailabilityRange(RegexLiteralPatternFeatureKind,
5159+
ASTContext *),
5160+
RequestFlags::Uncached> {
5161+
public:
5162+
using SimpleRequest::SimpleRequest;
5163+
5164+
private:
5165+
friend SimpleRequest;
5166+
5167+
AvailabilityRange evaluate(Evaluator &evaluator,
5168+
RegexLiteralPatternFeatureKind kind,
5169+
ASTContext *ctx) const;
5170+
};
5171+
5172+
void simple_display(llvm::raw_ostream &out,
5173+
RegexLiteralPatternFeatureKind kind);
5174+
SourceLoc extractNearestSourceLoc(RegexLiteralPatternFeatureKind kind);
5175+
51345176
class IsUnsafeRequest
51355177
: public SimpleRequest<IsUnsafeRequest,
51365178
bool(Decl *decl),

include/swift/AST/TypeCheckerTypeIDZone.def

+6
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,12 @@ SWIFT_REQUEST(TypeChecker, SuppressesConformanceRequest,
595595
SWIFT_REQUEST(TypeChecker, RegexLiteralPatternInfoRequest,
596596
RegexLiteralPatternInfo(const RegexLiteralExpr *),
597597
Cached, NoLocationInfo)
598+
SWIFT_REQUEST(TypeChecker, RegexLiteralFeatureDescriptionRequest,
599+
StringRef(RegexLiteralPatternFeatureKind, ASTContext *),
600+
Cached, NoLocationInfo)
601+
SWIFT_REQUEST(TypeChecker, RegexLiteralFeatureAvailabilityRequest,
602+
AvailabilityRange(RegexLiteralPatternFeatureKind, ASTContext *),
603+
Uncached, NoLocationInfo)
598604

599605
SWIFT_REQUEST(TypeChecker, CaptureInfoRequest,
600606
CaptureInfo(AbstractFunctionDecl *),

include/swift/Basic/BasicBridging.h

+19
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,25 @@ class BridgedCharSourceRangeVector {
413413
#endif
414414
};
415415

416+
//===----------------------------------------------------------------------===//
417+
// MARK: BridgedSwiftVersion
418+
//===----------------------------------------------------------------------===//
419+
420+
class BridgedSwiftVersion {
421+
unsigned Major;
422+
unsigned Minor;
423+
424+
public:
425+
BridgedSwiftVersion() : Major(0), Minor(0) {}
426+
427+
BRIDGED_INLINE
428+
SWIFT_NAME("init(major:minor:)")
429+
BridgedSwiftVersion(SwiftInt major, SwiftInt minor);
430+
431+
unsigned getMajor() const { return Major; }
432+
unsigned getMinor() const { return Minor; }
433+
};
434+
416435
SWIFT_END_NULLABILITY_ANNOTATIONS
417436

418437
#ifndef PURE_BRIDGING_MODE

include/swift/Basic/BasicBridgingImpl.h

+12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef SWIFT_BASIC_BASICBRIDGINGIMPL_H
1414
#define SWIFT_BASIC_BASICBRIDGINGIMPL_H
1515

16+
#include "swift/Basic/Assertions.h"
17+
1618
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
1719

1820
//===----------------------------------------------------------------------===//
@@ -123,6 +125,16 @@ swift::CharSourceRange BridgedCharSourceRange::unbridged() const {
123125
return swift::CharSourceRange(Start.unbridged(), ByteLength);
124126
}
125127

128+
//===----------------------------------------------------------------------===//
129+
// MARK: BridgedSwiftVersion
130+
//===----------------------------------------------------------------------===//
131+
132+
BridgedSwiftVersion::BridgedSwiftVersion(SwiftInt major, SwiftInt minor)
133+
: Major(major), Minor(minor) {
134+
ASSERT(major >= 0 && minor >= 0);
135+
ASSERT(major == Major && minor == Minor);
136+
}
137+
126138
SWIFT_END_NULLABILITY_ANNOTATIONS
127139

128140
#endif // SWIFT_BASIC_BASICBRIDGINGIMPL_H

include/swift/Bridging/ASTGen.h

+16-6
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,22 @@ bool swift_ASTGen_lexRegexLiteral(const char *_Nonnull *_Nonnull curPtrPtr,
103103
bool mustBeRegex,
104104
BridgedNullableDiagnosticEngine diagEngine);
105105

106-
bool swift_ASTGen_parseRegexLiteral(BridgedStringRef inputPtr,
107-
size_t *_Nonnull versionOut,
108-
void *_Nonnull UnsafeMutableRawPointer,
109-
size_t captureStructureSize,
110-
BridgedSourceLoc diagLoc,
111-
BridgedDiagnosticEngine diagEngine);
106+
bool swift_ASTGen_parseRegexLiteral(
107+
BridgedStringRef inputPtr, size_t *_Nonnull versionOut,
108+
void *_Nonnull UnsafeMutableRawPointer, size_t captureStructureSize,
109+
BridgedRegexLiteralPatternFeatures *_Nonnull featuresOut,
110+
BridgedSourceLoc diagLoc, BridgedDiagnosticEngine diagEngine);
111+
112+
void swift_ASTGen_freeBridgedRegexLiteralPatternFeatures(
113+
BridgedRegexLiteralPatternFeatures features);
114+
115+
void swift_ASTGen_getSwiftVersionForRegexPatternFeature(
116+
BridgedRegexLiteralPatternFeatureKind kind,
117+
BridgedSwiftVersion *_Nonnull versionOut);
118+
119+
void swift_ASTGen_getDescriptionForRegexPatternFeature(
120+
BridgedRegexLiteralPatternFeatureKind kind, BridgedASTContext astContext,
121+
BridgedStringRef *_Nonnull descriptionOut);
112122

113123
intptr_t swift_ASTGen_configuredRegions(
114124
BridgedASTContext astContext,

lib/AST/DiagnosticEngine.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ InFlightDiagnostic &InFlightDiagnostic::highlightChars(SourceLoc Start,
225225
return *this;
226226
}
227227

228+
InFlightDiagnostic &InFlightDiagnostic::highlightChars(CharSourceRange Range) {
229+
assert(IsActive && "Cannot modify an inactive diagnostic");
230+
if (Engine && Range.getStart().isValid())
231+
Engine->getActiveDiagnostic().addRange(Range);
232+
return *this;
233+
}
234+
228235
/// Add an insertion fix-it to the currently-active diagnostic. The
229236
/// text is inserted immediately *after* the token specified.
230237
///

0 commit comments

Comments
 (0)