Skip to content

Commit 0b4a54f

Browse files
committed
CMake: detect and refuse broken std::regex
Swift SVN r32256
1 parent 82fd400 commit 0b4a54f

File tree

5 files changed

+72
-22
lines changed

5 files changed

+72
-22
lines changed

CMakeLists.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ endif()
205205
# Include CMake modules
206206
#
207207

208+
include(CheckCXXSourceRuns)
208209
include(CMakeParseArguments)
209210
include(SwiftTranslateFlag)
210211
include(SwiftHandleGybSources)
@@ -305,6 +306,34 @@ if(XCODE)
305306
swift_common_xcode_cxx_config()
306307
endif()
307308

309+
function(check_working_std_regex result_var_name)
310+
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
311+
# Apple operating systems use libc++, which has a working std::regex.
312+
set("${result_var_name}" TRUE PARENT_SCOPE)
313+
else()
314+
# libstdc++ 4.8 has an incomplete std::regex implementation, and crashes
315+
# on many regexes.
316+
# libstdc++ 4.9 works.
317+
set(std_regex_test_source
318+
"
319+
#include <regex>
320+
const std::regex broken_regex{
321+
\"([a]+)\",
322+
std::regex::ECMAScript | std::regex::nosubs};
323+
324+
int main() {}
325+
")
326+
327+
check_cxx_source_runs("${std_regex_test_source}" result)
328+
if (result)
329+
set("${result_var_name}" TRUE PARENT_SCOPE)
330+
else()
331+
set("${result_var_name}" FALSE PARENT_SCOPE)
332+
endif()
333+
endif()
334+
endfunction()
335+
check_working_std_regex(SWIFT_HAVE_WORKING_STD_REGEX)
336+
308337
#
309338
# Enable additional warnings.
310339
#

include/swift/Config.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66

77
#cmakedefine SWIFT_ENABLE_OBJECT_LITERALS 1
88
#cmakedefine SWIFT_ENABLE_TARGET_TVOS 1
9+
#cmakedefine SWIFT_HAVE_WORKING_STD_REGEX 1
910

1011
#endif // SWIFT_CONFIG_H

lib/IDE/SyntaxModel.cpp

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/Basic/SourceManager.h"
2323
#include "swift/Parse/Lexer.h"
2424
#include "swift/Parse/Token.h"
25+
#include "swift/Config.h"
2526
#include "swift/Subsystems.h"
2627
#include "llvm/ADT/StringSwitch.h"
2728
#include "llvm/Support/MemoryBuffer.h"
@@ -238,8 +239,8 @@ class ModelASTWalker : public ASTWalker {
238239
unsigned BufferID;
239240
std::vector<StructureElement> SubStructureStack;
240241
SourceLoc LastLoc;
241-
static const std::regex URLRxs[3];
242-
static const std::regex DocCommentRxs[3];
242+
static const std::regex &getURLRegex(unsigned Index);
243+
static const std::regex &getDocCommentRegex(unsigned Index);
243244

244245
Optional<SyntaxNode> parseFieldNode(StringRef Text, StringRef OrigText,
245246
SourceLoc OrigLoc);
@@ -307,26 +308,32 @@ class ModelASTWalker : public ASTWalker {
307308
}
308309
};
309310

310-
const std::regex ModelASTWalker::URLRxs[3] = {
311+
const std::regex &ModelASTWalker::getURLRegex(unsigned Index) {
312+
static const std::regex Regexes[3] = {
311313
std::regex{ RegexStrURL, std::regex::ECMAScript | std::regex::nosubs },
312314
std::regex{ RegexStrMailURL, std::regex::ECMAScript | std::regex::nosubs },
313315
std::regex{ RegexStrRadarURL, std::regex::ECMAScript | std::regex::nosubs }
314-
};
316+
};
317+
return Regexes[Index];
318+
}
315319

316-
const std::regex ModelASTWalker::DocCommentRxs[3] = {
317-
std::regex {
318-
RegexStrParameter,
319-
std::regex::egrep | std::regex::icase | std::regex::optimize
320-
},
321-
std::regex {
322-
RegexStrDocCommentParametersHeading,
323-
std::regex::egrep | std::regex::icase | std::regex::optimize
324-
},
325-
std::regex {
326-
RegexStrDocCommentField,
327-
std::regex::egrep | std::regex::icase | std::regex::optimize
328-
}
329-
};
320+
const std::regex &ModelASTWalker::getDocCommentRegex(unsigned Index) {
321+
static const std::regex Regexes[3] = {
322+
std::regex {
323+
RegexStrParameter,
324+
std::regex::egrep | std::regex::icase | std::regex::optimize
325+
},
326+
std::regex {
327+
RegexStrDocCommentParametersHeading,
328+
std::regex::egrep | std::regex::icase | std::regex::optimize
329+
},
330+
std::regex {
331+
RegexStrDocCommentField,
332+
std::regex::egrep | std::regex::icase | std::regex::optimize
333+
}
334+
};
335+
return Regexes[Index];
336+
}
330337

331338
SyntaxStructureKind syntaxStructureKindFromNominalTypeDecl(NominalTypeDecl *N) {
332339
if (isa<ClassDecl>(N))
@@ -1291,6 +1298,10 @@ bool ModelASTWalker::processComment(CharSourceRange Range) {
12911298
bool ModelASTWalker::findUrlStartingLoc(StringRef Text,
12921299
unsigned &Start,
12931300
std::regex &Regex) {
1301+
#ifndef SWIFT_HAVE_WORKING_STD_REGEX
1302+
return false;
1303+
#endif
1304+
12941305
static const auto MailToPosition = std::find(URLProtocols.begin(),
12951306
URLProtocols.end(),
12961307
"mailto");
@@ -1306,11 +1317,11 @@ bool ModelASTWalker::findUrlStartingLoc(StringRef Text,
13061317
Text.substr(Index - It->size(), It->size()) == *It) {
13071318
Start = Index - It->size();
13081319
if (It < MailToPosition)
1309-
Regex = URLRxs[0];
1320+
Regex = getURLRegex(0);
13101321
else if (It < RadarPosition)
1311-
Regex = URLRxs[1];
1322+
Regex = getURLRegex(1);
13121323
else
1313-
Regex = URLRxs[2];
1324+
Regex = getURLRegex(2);
13141325
return true;
13151326
}
13161327
}
@@ -1350,8 +1361,13 @@ bool ModelASTWalker::searchForURL(CharSourceRange Range) {
13501361
Optional<SyntaxNode> ModelASTWalker::parseFieldNode(StringRef Text,
13511362
StringRef OrigText,
13521363
SourceLoc OrigLoc) {
1364+
#ifndef SWIFT_HAVE_WORKING_STD_REGEX
1365+
return None;
1366+
#endif
1367+
13531368
std::match_results<StringRef::iterator> Matches;
1354-
for (auto &Rx : DocCommentRxs) {
1369+
for (unsigned i = 0; i != 3; ++i) {
1370+
auto &Rx = getDocCommentRegex(i);
13551371
bool HadMatch = std::regex_search(Text.begin(), Text.end(), Matches, Rx);
13561372
if (HadMatch)
13571373
break;

test/IDE/coloring.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %target-swift-ide-test -syntax-coloring -source-filename %s | FileCheck %s
22
// RUN: %target-swift-ide-test -syntax-coloring -typecheck -source-filename %s | FileCheck %s
3+
// XFAIL: broken_std_regex
34

45
#line 17 "abc.swift"
56
// CHECK: <#kw>#line</#kw> <int>17</int> <str>"abc.swift"</str>

test/lit.site.cfg.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ if "@SWIFT_ENABLE_OBJECT_LITERALS@" == "TRUE":
3737
if "@SWIFT_OPTIMIZED@" == "TRUE":
3838
config.available_features.add("optimized_stdlib")
3939

40+
if "@SWIFT_HAVE_WORKING_STD_REGEX@" == "FALSE":
41+
config.available_features.add('broken_std_regex')
42+
4043
# Let the main config do the real work.
4144
if config.test_exec_root is None:
4245
config.test_exec_root = os.path.dirname(os.path.realpath(__file__))

0 commit comments

Comments
 (0)