diff --git a/CHANGES.current b/CHANGES.current index 3a10743e5..c78242886 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-07: jmarrec + #1158 #2286 Add basic support for C++11 attributes. These are now + crudely ignored by SWIG's parser's tokeniser, which is better that + failing with a parse error. + 2022-07-05: ianlancetaylor [Go] #2245 Handle NULL pointers for string* conversions. Rearrange generation of director methods and rename diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 52764eeef..7618b6dbe 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -1089,7 +1089,9 @@ Use the preprocessor to work around this for now:

-Attributes such as those shown below, are not yet supported and will give a syntax error. +Attributes such as those shown below, are supported since SWIG 4.1.0 but are +currently crudely ignored by the parser's tokeniser so they have no effect on +SWIG's code generation.

diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index bf0e52f02..c654807d7 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -583,6 +583,7 @@ CPP11_TEST_CASES += \
 	cpp11_alias_nested_template_scoping \
 	cpp11_alignment \
 	cpp11_alternate_function_syntax \
+	cpp11_attribute_specifiers \
 	cpp11_constexpr \
 	cpp11_decltype \
 	cpp11_default_delete \
diff --git a/Examples/test-suite/cpp11_attribute_specifiers.i b/Examples/test-suite/cpp11_attribute_specifiers.i
new file mode 100644
index 000000000..063e431e0
--- /dev/null
+++ b/Examples/test-suite/cpp11_attribute_specifiers.i
@@ -0,0 +1,50 @@
+%module cpp11_attribute_specifiers
+
+%inline %{
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // We're using a deprecated attribute here...
+#pragma GCC diagnostic ignored "-Wattributes"              // likely is C++20
+#pragma GCC diagnostic ignored "-Wunused-variable"         // We are using an unused variable on purpose here
+#pragma GCC diagnostic ignored "-Wunused-parameter"        // We are using an unused param on purpose here
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#pragma clang diagnostic ignored "-Wattributes"
+#pragma clang diagnostic ignored "-Wunused-variable"
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#endif
+
+
+[[noreturn]] void noReturn() { throw; }
+[[nodiscard]] bool noDiscard() { return true; }
+[[nodiscard, deprecated("This has been replaced")]] bool noDiscardDeprecated() { return true; }
+void maybeUnused1([[maybe_unused]] bool b) { }
+bool maybeUnused2(bool a, [[maybe_unused]] bool b) { return a; }
+
+[[deprecated, nodiscard]] bool likely([[maybe_unused]] bool a, bool b) {
+  [[maybe_unused]] bool c = b;
+  if (b) [[likely]] {
+    return true;
+  } else [[unlikely]] {
+    if(a) {
+      return true;
+    }
+  }
+  return false;
+}
+
+struct [[nodiscard]] S { };
+
+const char *test_string_literal() { return "Test [[ and ]] in string literal"; }
+
+#if 0
+// Check that SWIG doesn't choke on ]] when it's not part of an attribute.
+// FIXME: SWIG's parser doesn't handle this case currently.
+int *a;
+int b = a[a[0]];
+#endif
+
+%}
diff --git a/Examples/test-suite/php/cpp11_attribute_specifiers_runme.php b/Examples/test-suite/php/cpp11_attribute_specifiers_runme.php
new file mode 100644
index 000000000..2336b319a
--- /dev/null
+++ b/Examples/test-suite/php/cpp11_attribute_specifiers_runme.php
@@ -0,0 +1,14 @@
+ 0));
+      if (tok <= 0) {
+        Swig_error(cparse_file, cparse_line, "Unbalanced double brackets, missing closing (']]'). Reached end of input.\n");
+      }
+      break;
+
+    case SWIG_TOKEN_RRBRACKET:
+      /* Turn an unmatched ]] back into two ] - e.g. `a[a[0]]` */
+      scanner_next_token(RBRACKET);
+      return RBRACKET;
+
       /* Look for multi-character sequences */
       
     case SWIG_TOKEN_RSTRING:
diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c
index 65f534a79..b03a07a5b 100644
--- a/Source/Swig/scanner.c
+++ b/Source/Swig/scanner.c
@@ -596,10 +596,6 @@ static int look(Scanner *s) {
 	state = 3;
       else if (c == '\\')
 	return SWIG_TOKEN_BACKSLASH;
-      else if (c == '[')
-	return SWIG_TOKEN_LBRACKET;
-      else if (c == ']')
-	return SWIG_TOKEN_RBRACKET;
       else if (c == '@')
 	return SWIG_TOKEN_AT;
       else if (c == '$')
@@ -637,6 +633,10 @@ static int look(Scanner *s) {
 
       else if (c == '.')
 	state = 100;		/* Maybe a number, maybe ellipsis, just a period */
+      else if (c == '[')
+        state = 102;            /* Maybe a bracket or a double bracket */
+      else if (c == ']')
+        state = 103;            /* Maybe a bracket or a double bracket */
       else if (isdigit(c))
 	state = 8;		/* A numerical value */
       else
@@ -1358,6 +1358,31 @@ static int look(Scanner *s) {
       }
       break;
 
+    /* A left bracket or a double left bracket */
+    case 102:
+
+      if ((c = nextchar(s)) == 0) {
+        return SWIG_TOKEN_LBRACKET;
+      } else if (c == '[') {
+        return SWIG_TOKEN_LLBRACKET;
+      } else {
+        retract(s, 1);
+        return SWIG_TOKEN_LBRACKET;
+      }
+      break;
+
+    /* a right bracket or a double right bracket */
+    case 103:
+      if ((c = nextchar(s)) == 0) {
+        return SWIG_TOKEN_RBRACKET;
+      } else if (c == ']') {
+        return SWIG_TOKEN_RRBRACKET;
+      } else {
+        retract(s, 1);
+        return SWIG_TOKEN_RBRACKET;
+      }
+      break;
+
     case 200:			/* PLUS, PLUSPLUS, PLUSEQUAL */
       if ((c = nextchar(s)) == 0)
 	return SWIG_TOKEN_PLUS;
diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h
index 4f66de8a2..526413a14 100644
--- a/Source/Swig/swigscan.h
+++ b/Source/Swig/swigscan.h
@@ -71,6 +71,8 @@ extern void         Scanner_locator(Scanner *, String *loc);
 #define   SWIG_TOKEN_WSTRING      33       /* L"str" */
 #define   SWIG_TOKEN_WCHAR        34       /* L'c' */
 #define   SWIG_TOKEN_ELLIPSIS     35       /* ... */
+#define   SWIG_TOKEN_LLBRACKET    36       /* [[ */
+#define   SWIG_TOKEN_RRBRACKET    37       /* ]] */
 
 #define   SWIG_TOKEN_ILLEGAL      99
 #define   SWIG_TOKEN_ERROR        -1