aboutsummaryrefslogtreecommitdiff
path: root/Source/CParse/parser.y
diff options
context:
space:
mode:
authorAlistair Delva <adelva@google.com>2024-04-10 14:15:29 -0700
committerAlistair Delva <adelva@google.com>2024-04-11 12:58:28 -0700
commitd0f0f90be16c2ac553b5fa08512045273135147a (patch)
tree5d9ebb7a04807ea8a609ddd18b0162bc87530e4b /Source/CParse/parser.y
parent6ffc1dbf29ba98c4d8aa71ebc9b484e973fe1030 (diff)
downloadswig-d0f0f90be16c2ac553b5fa08512045273135147a.tar.gz
Change-Id: I47cef2be94299220d80265d949a95b58eee2c23b
Diffstat (limited to 'Source/CParse/parser.y')
-rw-r--r--Source/CParse/parser.y2700
1 files changed, 1445 insertions, 1255 deletions
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 470b7d065..4a7040d96 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -4,45 +4,59 @@
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
- * and at http://www.swig.org/legal.html.
+ * and at https://www.swig.org/legal.html.
*
* parser.y
*
- * YACC parser for SWIG. The grammar is a somewhat broken subset of C/C++.
+ * Bison parser for SWIG. The grammar is a somewhat broken subset of C/C++.
* This file is a bit of a mess and probably needs to be rewritten at
* some point. Beware.
* ----------------------------------------------------------------------------- */
-/* There are 6 known shift-reduce conflicts in this file, fail compilation if any
- more are introduced.
+%require "3.5"
+
+/* There are a small number of known shift-reduce conflicts in this file, fail
+ compilation if any more are introduced.
Please don't increase the number of the conflicts if at all possible. And if
you really have no choice but to do it, make sure you clearly document each
new conflict in this file.
*/
-%expect 6
+%expect 7
+
+/* Make the internal token numbers the same as the external token numbers
+ * which saves Bison generating a lookup table to map between them, giving
+ * a smaller and faster generated parser.
+ */
+%define api.token.raw
%{
-#define yylex yylex
+/* doh.h uses #pragma GCC poison with GCC to prevent direct calls to certain
+ * standard C library functions being introduced, but those cause errors due
+ * to checks like `#if defined YYMALLOC || defined malloc` in the bison
+ * template code. We can't easily arrange to include headers after that
+ * template code, so instead we disable the problematic poisoning for this
+ * file.
+ */
+#define DOH_NO_POISON_MALLOC_FREE
#include "swig.h"
#include "cparse.h"
#include "preprocessor.h"
#include <ctype.h>
-/* We do this for portability */
-#undef alloca
-#define alloca malloc
+#define YYMALLOC Malloc
+#define YYFREE Free
/* -----------------------------------------------------------------------------
* Externals
* ----------------------------------------------------------------------------- */
-int yyparse();
+int yyparse(void);
/* NEW Variables */
-static Node *top = 0; /* Top of the generated parse tree */
+static void *top = 0; /* Top of the generated parse tree */
static int unnamed = 0; /* Unnamed datatype counter */
static Hash *classes = 0; /* Hash table of classes */
static Hash *classes_typedefs = 0; /* Hash table of typedef classes: typedef struct X {...} Y; */
@@ -54,7 +68,7 @@ static String *Classprefix = 0;
static String *Namespaceprefix = 0;
static int inclass = 0;
static Node *currentOuterClass = 0; /* for nested classes */
-static const char *last_cpptype = 0;
+static String *last_cpptype = 0;
static int inherit_list = 0;
static Parm *template_parameters = 0;
static int parsing_template_declaration = 0;
@@ -64,12 +78,11 @@ static int template_reduce = 0;
static int cparse_externc = 0;
int ignore_nested_classes = 0;
int kwargs_supported = 0;
+
/* -----------------------------------------------------------------------------
* Doxygen Comment Globals
* ----------------------------------------------------------------------------- */
static String *currentDeclComment = NULL; /* Comment of C/C++ declaration. */
-static Node *previousNode = NULL; /* Pointer to the previous node (for post comments) */
-static Node *currentNode = NULL; /* Pointer to the current node (for post comments) */
/* -----------------------------------------------------------------------------
* Assist Functions
@@ -84,9 +97,6 @@ static void yyerror (const char *e) {
static Node *new_node(const_String_or_char_ptr tag) {
Node *n = Swig_cparse_new_node(tag);
- /* Remember the previous node in case it will need a post-comment */
- previousNode = currentNode;
- currentNode = n;
return n;
}
@@ -223,6 +233,49 @@ static int cplus_mode = 0;
#define CPLUS_PRIVATE 2
#define CPLUS_PROTECTED 3
+/* storage classes */
+
+#define SWIG_STORAGE_CLASS_EXTERNC 0x0001
+#define SWIG_STORAGE_CLASS_EXTERNCPP 0x0002
+#define SWIG_STORAGE_CLASS_EXTERN 0x0004
+#define SWIG_STORAGE_CLASS_STATIC 0x0008
+#define SWIG_STORAGE_CLASS_TYPEDEF 0x0010
+#define SWIG_STORAGE_CLASS_VIRTUAL 0x0020
+#define SWIG_STORAGE_CLASS_FRIEND 0x0040
+#define SWIG_STORAGE_CLASS_EXPLICIT 0x0080
+#define SWIG_STORAGE_CLASS_CONSTEXPR 0x0100
+#define SWIG_STORAGE_CLASS_THREAD_LOCAL 0x0200
+
+/* Test if multiple bits are set in x. */
+static int multiple_bits_set(unsigned x) { return (x & (x - 1)) != 0; }
+
+static const char* storage_class_string(int c) {
+ switch (c) {
+ case SWIG_STORAGE_CLASS_EXTERNC:
+ return "extern \"C\"";
+ case SWIG_STORAGE_CLASS_EXTERNCPP:
+ return "extern \"C++\"";
+ case SWIG_STORAGE_CLASS_EXTERN:
+ return "extern";
+ case SWIG_STORAGE_CLASS_STATIC:
+ return "static";
+ case SWIG_STORAGE_CLASS_TYPEDEF:
+ return "typedef";
+ case SWIG_STORAGE_CLASS_VIRTUAL:
+ return "virtual";
+ case SWIG_STORAGE_CLASS_FRIEND:
+ return "friend";
+ case SWIG_STORAGE_CLASS_EXPLICIT:
+ return "explicit";
+ case SWIG_STORAGE_CLASS_CONSTEXPR:
+ return "constexpr";
+ case SWIG_STORAGE_CLASS_THREAD_LOCAL:
+ return "thread_local";
+ }
+ assert(0);
+ return "<unknown>";
+}
+
/* include types */
static int import_mode = 0;
@@ -259,7 +312,7 @@ static String *yyrename = 0;
/* Forward renaming operator */
-static String *resolve_create_node_scope(String *cname, int is_class_definition);
+static String *resolve_create_node_scope(String *cname, int is_class_definition, int *errored);
Hash *Swig_cparse_features(void) {
@@ -268,7 +321,14 @@ Hash *Swig_cparse_features(void) {
return features_hash;
}
-/* Fully qualify any template parameters */
+/* -----------------------------------------------------------------------------
+ * feature_identifier_fix()
+ *
+ * If a template, return template with all template parameters fully resolved.
+ *
+ * This is a copy and modification of typemap_identifier_fix.
+ * ----------------------------------------------------------------------------- */
+
static String *feature_identifier_fix(String *s) {
String *tp = SwigType_istemplate_templateprefix(s);
if (tp) {
@@ -337,21 +397,15 @@ static String *make_name(Node *n, String *name,SwigType *decl) {
}
/* Generate an unnamed identifier */
-static String *make_unnamed() {
+static String *make_unnamed(void) {
unnamed++;
return NewStringf("$unnamed%d$",unnamed);
}
-/* Return if the node is a friend declaration */
-static int is_friend(Node *n) {
- return Cmp(Getattr(n,"storage"),"friend") == 0;
-}
-
static int is_operator(String *name) {
return Strncmp(name,"operator ", 9) == 0;
}
-
/* Add declaration list to symbol table */
static int add_only_one = 0;
@@ -364,38 +418,51 @@ static void add_symbols(Node *n) {
}
while (n) {
String *symname = 0;
- /* for friends, we need to pop the scope once */
String *old_prefix = 0;
Symtab *old_scope = 0;
- int isfriend = inclass && is_friend(n);
+ int isfriend = inclass && Checkattr(n, "storage", "friend");
int iscdecl = Cmp(nodeType(n),"cdecl") == 0;
int only_csymbol = 0;
if (inclass) {
String *name = Getattr(n, "name");
if (isfriend) {
- /* for friends, we need to add the scopename if needed */
+ /* For friends, set the scope to the same as the class that the friend is defined/declared in, that is, pop scope once */
String *prefix = name ? Swig_scopename_prefix(name) : 0;
old_prefix = Namespaceprefix;
old_scope = Swig_symbol_popscope();
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
if (!prefix) {
+ /* To check - this should probably apply to operators too */
if (name && !is_operator(name) && Namespaceprefix) {
- String *nname = NewStringf("%s::%s", Namespaceprefix, name);
- Setattr(n,"name",nname);
- Delete(nname);
+ String *friendusing = NewStringf("using namespace %s;", Namespaceprefix);
+ Setattr(n, "friendusing", friendusing);
+ Delete(friendusing);
}
} else {
- Symtab *st = Swig_symbol_getscope(prefix);
- String *ns = st ? Getattr(st,"name") : prefix;
- String *base = Swig_scopename_last(name);
- String *nname = NewStringf("%s::%s", ns, base);
- Setattr(n,"name",nname);
- Delete(nname);
- Delete(base);
- Delete(prefix);
+ /* Qualified friend declarations should not be possible as they are ignored in the parse tree */
+ /* TODO: uncomment out for swig-4.3.0
+ assert(0);
+ */
+ }
+ } else if (Equal(nodeType(n), "using")) {
+ String *uname = Getattr(n, "uname");
+ Node *cls = current_class ? current_class : currentOuterClass; /* Current class seems to vary depending on whether it is a template class or a plain class */
+ String *nprefix = 0;
+ String *nlast = 0;
+ Swig_scopename_split(uname, &nprefix, &nlast);
+ if (Swig_item_in_list(Getattr(cls, "baselist"), nprefix) || Swig_item_in_list(Getattr(cls, "protectedbaselist"), nprefix) || Swig_item_in_list(Getattr(cls, "privatebaselist"), nprefix)) {
+ String *plain_name = SwigType_istemplate(nprefix) ? SwigType_templateprefix(nprefix) : nprefix;
+ if (Equal(nlast, plain_name)) {
+ /* Using declaration looks like it is using a constructor in an immediate base class - change the constructor name for this class.
+ * C++11 requires using declarations for inheriting base constructors to be in the immediate base class.
+ * Note that we don't try and look up the constructor in the base class as the constructor may be an implicit/implied constructor and hence not exist. */
+ Symtab *stab = Swig_symbol_current();
+ String *nname = Getattr(stab, "name");
+ Setattr(n, "name", nname);
+ SetFlag(n, "usingctor");
+ }
}
- Namespaceprefix = 0;
} else {
/* for member functions, we need to remove the redundant
class scope if provided, as in
@@ -444,9 +511,12 @@ static void add_symbols(Node *n) {
}
}
} else {
- Setattr(n,"access", "public");
+ Setattr(n, "access", "public");
}
+ } else if (extendmode && !inclass) {
+ Setattr(n, "access", "public");
}
+
if (Getattr(n,"sym:name")) {
n = nextSibling(n);
continue;
@@ -475,11 +545,10 @@ static void add_symbols(Node *n) {
} else {
ty = type;
}
- if (!SwigType_ismutable(ty) || (storage && Strstr(storage, "constexpr"))) {
- SetFlag(n,"hasconsttype");
- SetFlag(n,"feature:immutable");
+ if (storage && (Strstr(storage, "constexpr") || (Strstr(storage, "static") && !SwigType_ismutable(ty)))) {
+ SetFlag(n, "hasconsttype");
}
- if (tmp) Delete(tmp);
+ Delete(tmp);
}
if (!type) {
Printf(stderr,"notype name %s\n", name);
@@ -528,6 +597,13 @@ static void add_symbols(Node *n) {
n = nextSibling(n);
continue;
}
+
+ if (GetFlag(n, "valueignored")) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_PARSE_ASSIGNED_VALUE, Getfile(n), Getline(n), "Value assigned to %s not used due to limited parsing implementation.\n", SwigType_namestr(Getattr(n, "name")));
+ SWIG_WARN_NODE_END(n);
+ }
+
if (cparse_cplusplus) {
String *value = Getattr(n, "value");
if (value && Strcmp(value, "delete") == 0) {
@@ -546,6 +622,19 @@ static void add_symbols(Node *n) {
SetFlag(n, "feature:ignore");
}
}
+ if (Equal(Getattr(n, "type"), "auto")) {
+ /* Ignore functions with an auto return type and no trailing return type
+ * Use Getattr instead of GetFlag to handle explicit ignore and explicit not ignore */
+ if (!(Getattr(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0)) {
+ SWIG_WARN_NODE_BEGIN(n);
+ if (SwigType_isfunction(Getattr(n, "decl")))
+ Swig_warning(WARN_CPP14_AUTO, Getfile(n), Getline(n), "Unable to deduce auto return type for '%s' (ignored).\n", Swig_name_decl(n));
+ else
+ Swig_warning(WARN_CPP11_AUTO, Getfile(n), Getline(n), "Unable to deduce auto type for variable '%s' (ignored).\n", Swig_name_decl(n));
+ SWIG_WARN_NODE_END(n);
+ SetFlag(n, "feature:ignore");
+ }
+ }
}
if (only_csymbol || GetFlag(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0) {
/* Only add to C symbol table and continue */
@@ -579,44 +668,11 @@ static void add_symbols(Node *n) {
c = Swig_symbol_add(symname,n);
if (c != n) {
- /* symbol conflict attempting to add in the new symbol */
- if (Getattr(n,"sym:weak")) {
- Setattr(n,"sym:name",symname);
- } else {
- String *e = NewStringEmpty();
- String *en = NewStringEmpty();
- String *ec = NewStringEmpty();
- int redefined = Swig_need_redefined_warn(n,c,inclass);
- if (redefined) {
- Printf(en,"Identifier '%s' redefined (ignored)",symname);
- Printf(ec,"previous definition of '%s'",symname);
- } else {
- Printf(en,"Redundant redeclaration of '%s'",symname);
- Printf(ec,"previous declaration of '%s'",symname);
- }
- if (Cmp(symname,Getattr(n,"name"))) {
- Printf(en," (Renamed from '%s')", SwigType_namestr(Getattr(n,"name")));
- }
- Printf(en,",");
- if (Cmp(symname,Getattr(c,"name"))) {
- Printf(ec," (Renamed from '%s')", SwigType_namestr(Getattr(c,"name")));
- }
- Printf(ec,".");
- SWIG_WARN_NODE_BEGIN(n);
- if (redefined) {
- Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en);
- Swig_warning(WARN_PARSE_REDEFINED,Getfile(c),Getline(c),"%s\n",ec);
- } else if (!is_friend(n) && !is_friend(c)) {
- Swig_warning(WARN_PARSE_REDUNDANT,Getfile(n),Getline(n),"%s\n",en);
- Swig_warning(WARN_PARSE_REDUNDANT,Getfile(c),Getline(c),"%s\n",ec);
- }
- SWIG_WARN_NODE_END(n);
- Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(n),Getline(n),en,
- Getfile(c),Getline(c),ec);
- Setattr(n,"error",e);
- Delete(e);
- Delete(en);
- Delete(ec);
+ /* symbol conflict attempting to add in the new symbol */
+ if (Getattr(n,"sym:weak")) {
+ Setattr(n,"sym:name",symname);
+ } else {
+ Swig_symbol_conflict_warn(n, c, symname, inclass);
}
}
}
@@ -862,7 +918,7 @@ static void add_typedef_name(Node *n, Node *declnode, String *oldName, Symtab *c
/* If the class name is qualified. We need to create or lookup namespace entries */
-static Symtab *set_scope_to_global() {
+static Symtab *set_scope_to_global(void) {
Symtab *symtab = Swig_symbol_global_scope();
Swig_symbol_setscope(symtab);
return symtab;
@@ -902,37 +958,45 @@ static Node *nscope_inner = 0;
* The scopes required for the symbol name are resolved and/or created, if required.
* For example AA::BB::CC as input returns CC and creates the namespace AA then inner
* namespace BB in the current scope. */
-static String *resolve_create_node_scope(String *cname, int is_class_definition) {
+static String *resolve_create_node_scope(String *cname_in, int is_class_definition, int *errored) {
Symtab *gscope = 0;
Node *cname_node = 0;
+ String *cname = cname_in;
String *last = Swig_scopename_last(cname);
nscope = 0;
nscope_inner = 0;
+ *errored = 0;
- if (Strncmp(cname,"::" ,2) != 0) {
+ if (Strncmp(cname, "::", 2) == 0) {
if (is_class_definition) {
- /* Only lookup symbols which are in scope via a using declaration but not via a using directive.
- For example find y via 'using x::y' but not y via a 'using namespace x'. */
- cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
- if (!cname_node) {
- Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
- if (full_lookup_node) {
- /* This finds a symbol brought into scope via both a using directive and a using declaration. */
- Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
- if (last_node == full_lookup_node)
- cname_node = last_node;
- }
+ Swig_error(cparse_file, cparse_line, "Using the unary scope operator :: in class definition '%s' is invalid.\n", SwigType_namestr(cname));
+ *errored = 1;
+ return last;
+ }
+ cname = NewString(Char(cname) + 2);
+ }
+ if (is_class_definition) {
+ /* Only lookup symbols which are in scope via a using declaration but not via a using directive.
+ For example find y via 'using x::y' but not y via a 'using namespace x'. */
+ cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
+ if (!cname_node) {
+ Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
+ if (full_lookup_node) {
+ /* This finds a symbol brought into scope via both a using directive and a using declaration. */
+ Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
+ if (last_node == full_lookup_node)
+ cname_node = last_node;
}
- } else {
- /* For %template, the template needs to be in scope via any means. */
- cname_node = Swig_symbol_clookup(cname, 0);
}
+ } else {
+ /* For %template, the template needs to be in scope via any means. */
+ cname_node = Swig_symbol_clookup(cname, 0);
}
#if RESOLVE_DEBUG
if (!cname_node)
- Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname);
+ Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname_in);
else
- Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname);
+ Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname_in);
#endif
if (cname_node) {
@@ -1014,8 +1078,9 @@ Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found
if (fail) {
String *cname_resolved = NewStringf("%s::%s", found_scopename, last);
- Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n", cname, cname_resolved, current_scopename, found_scopename);
- cname = Copy(last);
+ Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n",
+ SwigType_namestr(cname_in), SwigType_namestr(cname_resolved), SwigType_namestr(current_scopename), SwigType_namestr(found_scopename));
+ *errored = 1;
Delete(cname_resolved);
}
}
@@ -1024,22 +1089,17 @@ Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found
Delete(found_scopename);
}
} else if (!is_class_definition) {
- /* A template instantiation requires a template to be found in scope... fail here too?
- Swig_error(cparse_file, cparse_line, "No template found to instantiate '%s' with %%template.\n", cname);
- */
+ /* A template instantiation requires a template to be found in scope */
+ Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", SwigType_namestr(cname_in));
+ *errored = 1;
}
- if (Swig_scopename_check(cname)) {
+ if (*errored)
+ return last;
+
+ if (Swig_scopename_check(cname) && !*errored) {
Node *ns;
String *prefix = Swig_scopename_prefix(cname);
- if (prefix && (Strncmp(prefix,"::",2) == 0)) {
-/* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */
- /* Use the global scope */
- String *nprefix = NewString(Char(prefix)+2);
- Delete(prefix);
- prefix= nprefix;
- gscope = set_scope_to_global();
- }
if (Len(prefix) == 0) {
String *base = Copy(last);
/* Use the global scope, but we need to add a 'global' namespace. */
@@ -1056,11 +1116,13 @@ Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found
/* Try to locate the scope */
ns = Swig_symbol_clookup(prefix,0);
if (!ns) {
- Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix);
+ Swig_error(cparse_file, cparse_line, "Undefined scope '%s'\n", SwigType_namestr(prefix));
+ *errored = 1;
} else {
Symtab *nstab = Getattr(ns,"symtab");
if (!nstab) {
- Swig_error(cparse_file,cparse_line, "'%s' is not defined as a valid scope.\n", prefix);
+ Swig_error(cparse_file, cparse_line, "'%s' is not defined as a valid scope.\n", SwigType_namestr(prefix));
+ *errored = 1;
ns = 0;
} else {
/* Check if the node scope is the current scope */
@@ -1137,10 +1199,10 @@ Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found
}
/* look for simple typedef name in typedef list */
-static String *try_to_find_a_name_for_unnamed_structure(const char *storage, Node *decls) {
+static String *try_to_find_a_name_for_unnamed_structure(const String *storage, Node *decls) {
String *name = 0;
Node *n = decls;
- if (storage && (strcmp(storage, "typedef") == 0)) {
+ if (storage && Equal(storage, "typedef")) {
for (; n; n = nextSibling(n)) {
if (!Len(Getattr(n, "decl"))) {
name = Copy(Getattr(n, "name"));
@@ -1170,7 +1232,7 @@ static void update_nested_classes(Node *n)
* Create the nested class/struct/union as a forward declaration.
* ----------------------------------------------------------------------------- */
-static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, String *name, Node *cpp_opt_declarators) {
+static Node *nested_forward_declaration(const String *storage, const String *kind, String *sname, String *name, Node *cpp_opt_declarators) {
Node *nn = 0;
if (sname) {
@@ -1187,10 +1249,10 @@ static Node *nested_forward_declaration(const char *storage, const char *kind, S
/* Add any variable instances. Also add in any further typedefs of the nested type.
Note that anonymous typedefs (eg typedef struct {...} a, b;) are treated as class forward declarations */
if (cpp_opt_declarators) {
- int storage_typedef = (storage && (strcmp(storage, "typedef") == 0));
+ int storage_typedef = (storage && Equal(storage, "typedef"));
int variable_of_anonymous_type = !sname && !storage_typedef;
if (!variable_of_anonymous_type) {
- int anonymous_typedef = !sname && (storage && (strcmp(storage, "typedef") == 0));
+ int anonymous_typedef = !sname && storage_typedef;
Node *n = cpp_opt_declarators;
SwigType *type = name;
while (n) {
@@ -1217,7 +1279,7 @@ static Node *nested_forward_declaration(const char *storage, const char *kind, S
Node *n = nn;
if (!GetFlag(n, "feature:ignore")) {
SWIG_WARN_NODE_BEGIN(n);
- Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", kind, sname ? sname : name);
+ Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (%s ignored)\n", kind, SwigType_namestr(sname ? sname : name));
SWIG_WARN_NODE_END(n);
}
} else {
@@ -1233,7 +1295,7 @@ Node *Swig_cparse(File *f) {
scanner_file(f);
top = 0;
yyparse();
- return top;
+ return (Node *)top;
}
static void single_new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
@@ -1428,7 +1490,7 @@ static void default_arguments(Node *n) {
Delete(pl);
}
- /* copy specific attributes for global (or in a namespace) template functions - these are not templated class methods */
+ /* copy specific attributes for global (or in a namespace) template functions - these are not class template methods */
if (strcmp(cntype,"template") == 0) {
Node *templatetype = Getattr(function,"templatetype");
Node *symtypename = Getattr(function,"sym:typename");
@@ -1546,6 +1608,11 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
String *val;
String *rawval;
int type;
+ /* The type code for the argument when the top level operator is unary.
+ * This is useful because our grammar parses cases such as (7)*6 as a
+ * cast applied to an unary operator.
+ */
+ int unary_arg_type;
String *qualifier;
String *refqualifier;
String *bitfield;
@@ -1587,20 +1654,23 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
Node *node;
};
+/* Define special token END for end of input. */
+%token END 0
+
%token <id> ID
%token <str> HBLOCK
%token <id> POUND
%token <id> STRING WSTRING
%token <loc> INCLUDE IMPORT INSERT
%token <str> CHARCONST WCHARCONST
-%token <dtype> NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL
+%token <dtype> NUM_INT NUM_DOUBLE NUM_FLOAT NUM_LONGDOUBLE NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL
%token <intvalue> TYPEDEF
-%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64
-%token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD
+%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64
+%token LPAREN RPAREN COMMA SEMI EXTERN LBRACE RBRACE PERIOD ELLIPSIS
%token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
%token BEGINFILE ENDOFFILE
%token ILLEGAL CONSTANT
-%token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
+%token RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
%token ENUM
%token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH EXPLICIT
%token STATIC_ASSERT CONSTEXPR THREAD_LOCAL DECLTYPE AUTO NOEXCEPT /* C++11 keywords */
@@ -1608,10 +1678,10 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
%token USING
%token <node> NAMESPACE
%token NATIVE INLINE
-%token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT
+%token TYPEMAP ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT
%token WARN
%token LESSTHAN GREATERTHAN DELETE_KW DEFAULT
-%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO
+%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO LESSEQUALGREATER
%token ARROW
%token QUESTIONMARK
%token TYPES PARMS
@@ -1624,7 +1694,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
%token <str> DOXYGENSTRING
%token <str> DOXYGENPOSTSTRING
-%left CAST
+%precedence CAST
%left QUESTIONMARK
%left LOR
%left LAND
@@ -1632,28 +1702,33 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
%left XOR
%left AND
%left EQUALTO NOTEQUALTO
-%left GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO
+/* We don't currently allow < and > in any context where the associativity or
+ * precedence matters and Bison warns about that.
+ */
+%left /* GREATERTHAN LESSTHAN */ GREATERTHANOREQUALTO LESSTHANOREQUALTO
+%left LESSEQUALGREATER
%left LSHIFT RSHIFT
%left PLUS MINUS
%left STAR SLASH MODULO
-%left UMINUS NOT LNOT
-%left DCOLON
+%precedence UMINUS NOT LNOT
+%token DCOLON
%type <node> program interface declaration swig_directive ;
/* SWIG directives */
%type <node> extend_directive apply_directive clear_directive constant_directive ;
-%type <node> echo_directive except_directive fragment_directive include_directive inline_directive ;
-%type <node> insert_directive module_directive name_directive native_directive ;
+%type <node> echo_directive fragment_directive include_directive inline_directive ;
+%type <node> insert_directive module_directive native_directive ;
%type <node> pragma_directive rename_directive feature_directive varargs_directive typemap_directive ;
%type <node> types_directive template_directive warn_directive ;
/* C declarations */
-%type <node> c_declaration c_decl c_decl_tail c_enum_key c_enum_inherit c_enum_decl c_enum_forward_decl c_constructor_decl;
+%type <node> c_declaration c_decl c_decl_tail c_enum_inherit c_enum_decl c_enum_forward_decl c_constructor_decl;
%type <node> enumlist enumlist_item edecl_with_dox edecl;
+%type <id> c_enum_key;
/* C++ declarations */
-%type <node> cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl cpp_alternate_rettype;
+%type <node> cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl;
%type <node> cpp_members cpp_member cpp_member_no_dox;
%type <node> cpp_constructor_decl cpp_destructor_decl cpp_protection_decl cpp_conversion_operator cpp_static_assert;
%type <node> cpp_swig_directive cpp_template_possible cpp_opt_declarators ;
@@ -1663,19 +1738,21 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
/* Misc */
%type <id> identifier;
%type <dtype> initializer cpp_const exception_specification cv_ref_qualifier qualifiers_exception_specification;
-%type <id> storage_class extern_string;
-%type <pl> parms ptail rawparms varargs_parms ;
-%type <pl> templateparameters templateparameterstail;
+%type <str> storage_class;
+%type <intvalue> storage_class_raw storage_class_list;
+%type <pl> parms rawparms varargs_parms ;
+%type <pl> templateparameterstail;
%type <p> parm_no_dox parm valparm rawvalparms valparms valptail ;
%type <p> typemap_parm tm_list tm_tail ;
%type <p> templateparameter ;
-%type <id> templcpptype cpptype classkey classkeyopt access_specifier;
+%type <type> templcpptype cpptype classkey classkeyopt;
+%type <id> access_specifier;
%type <node> base_specifier;
-%type <str> ellipsis variadic;
-%type <type> type rawtype type_right anon_bitfield_type decltype ;
+%type <str> variadic_opt;
+%type <type> type rawtype type_right anon_bitfield_type decltype decltypeexpr cpp_alternate_rettype;
%type <bases> base_list inherit raw_inherit;
%type <dtype> definetype def_args etype default_delete deleted_definition explicit_default;
-%type <dtype> expr exprnum exprcompound valexpr exprmem;
+%type <dtype> expr exprnum exprsimple exprcompound valexpr exprmem callparms callptail;
%type <id> ename ;
%type <id> less_valparms_greater;
%type <str> type_qualifier;
@@ -1692,14 +1769,42 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
%type <str> idcolon idcolontail idcolonnt idcolontailnt idtemplate idtemplatetemplate stringbrace stringbracesemi;
%type <str> string stringnum wstring;
%type <tparms> template_parms;
-%type <dtype> cpp_end cpp_vend;
+%type <dtype> cpp_vend;
%type <intvalue> rename_namewarn;
%type <ptype> type_specifier primitive_type_list ;
%type <node> fname stringtype;
%type <node> featattr;
-%type <node> lambda_introducer lambda_body;
+%type <node> lambda_introducer lambda_body lambda_template;
%type <pl> lambda_tail;
%type <str> virt_specifier_seq virt_specifier_seq_opt;
+%type <str> class_virt_specifier_opt;
+
+%{
+
+/* C++ decltype/auto type deduction. */
+static SwigType *deduce_type(const struct Define *dtype) {
+ Node *n;
+ if (!dtype->val) return NULL;
+ n = Swig_symbol_clookup(dtype->val, 0);
+ if (n) {
+ if (Strcmp(nodeType(n),"enumitem") == 0) {
+ /* For an enumitem, the "type" attribute gives us the underlying integer
+ * type - we want the "type" attribute from the enum itself, which is
+ * "parentNode".
+ */
+ n = Getattr(n, "parentNode");
+ }
+ return Getattr(n, "type");
+ } else if (dtype->type != T_AUTO && dtype->type != T_UNKNOWN) {
+ /* Try to deduce the type from the T_* type code. */
+ String *deduced_type = NewSwigType(dtype->type);
+ if (Len(deduced_type) > 0) return deduced_type;
+ Delete(deduced_type);
+ }
+ return NULL;
+}
+
+%}
%%
@@ -1722,23 +1827,23 @@ program : interface {
Setattr($1,"module",module_node);
top = $1;
}
- | PARSETYPE parm SEMI {
+ | PARSETYPE parm END {
top = Copy(Getattr($2,"type"));
Delete($2);
}
| PARSETYPE error {
top = 0;
}
- | PARSEPARM parm SEMI {
+ | PARSEPARM parm END {
top = $2;
}
| PARSEPARM error {
top = 0;
}
- | PARSEPARMS LPAREN parms RPAREN SEMI {
+ | PARSEPARMS LPAREN parms RPAREN END {
top = $3;
}
- | PARSEPARMS error SEMI {
+ | PARSEPARMS error {
top = 0;
}
;
@@ -1763,23 +1868,22 @@ interface : interface declaration {
}
$$ = $1;
}
- | empty {
+ | %empty {
$$ = new_node("top");
}
;
-declaration : swig_directive { $$ = $1; }
- | c_declaration { $$ = $1; }
- | cpp_declaration { $$ = $1; }
+declaration : swig_directive
+ | c_declaration
+ | cpp_declaration
| SEMI { $$ = 0; }
| error {
- $$ = 0;
if (cparse_unknown_directive) {
Swig_error(cparse_file, cparse_line, "Unknown directive '%s'.\n", cparse_unknown_directive);
} else {
Swig_error(cparse_file, cparse_line, "Syntax error in input(1).\n");
}
- SWIG_exit(EXIT_FAILURE);
+ Exit(EXIT_FAILURE);
}
/* Out of class constructor/destructor declarations */
| c_constructor_decl {
@@ -1808,27 +1912,25 @@ declaration : swig_directive { $$ = $1; }
* SWIG DIRECTIVES
* ====================================================================== */
-swig_directive : extend_directive { $$ = $1; }
- | apply_directive { $$ = $1; }
- | clear_directive { $$ = $1; }
- | constant_directive { $$ = $1; }
- | echo_directive { $$ = $1; }
- | except_directive { $$ = $1; }
- | fragment_directive { $$ = $1; }
- | include_directive { $$ = $1; }
- | inline_directive { $$ = $1; }
- | insert_directive { $$ = $1; }
- | module_directive { $$ = $1; }
- | name_directive { $$ = $1; }
- | native_directive { $$ = $1; }
- | pragma_directive { $$ = $1; }
- | rename_directive { $$ = $1; }
- | feature_directive { $$ = $1; }
- | varargs_directive { $$ = $1; }
- | typemap_directive { $$ = $1; }
- | types_directive { $$ = $1; }
- | template_directive { $$ = $1; }
- | warn_directive { $$ = $1; }
+swig_directive : extend_directive
+ | apply_directive
+ | clear_directive
+ | constant_directive
+ | echo_directive
+ | fragment_directive
+ | include_directive
+ | inline_directive
+ | insert_directive
+ | module_directive
+ | native_directive
+ | pragma_directive
+ | rename_directive
+ | feature_directive
+ | varargs_directive
+ | typemap_directive
+ | types_directive
+ | template_directive
+ | warn_directive
;
/* ------------------------------------------------------------
@@ -1860,7 +1962,7 @@ extend_directive : EXTEND options classkeyopt idcolon LBRACE {
} else {
/* Previous typedef class definition. Use its symbol table.
Deprecated, just the real name should be used.
- Note that %extend before the class typedef never worked, only %extend after the class typdef. */
+ Note that %extend before the class typedef never worked, only %extend after the class typedef. */
prev_symtab = Swig_symbol_setscope(Getattr(cls, "symtab"));
current_class = cls;
SWIG_WARN_NODE_BEGIN(cls);
@@ -1936,80 +2038,70 @@ clear_directive : CLEAR tm_list SEMI {
/* ------------------------------------------------------------
%constant name = value;
%constant type name = value;
+
+ Note: Source/Preprocessor/cpp.c injects `%constant X = Y;` for
+ each `#define X Y` so that's handled here too.
------------------------------------------------------------ */
constant_directive : CONSTANT identifier EQUAL definetype SEMI {
- if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) {
- SwigType *type = NewSwigType($4.type);
- $$ = new_node("constant");
- Setattr($$,"name",$2);
- Setattr($$,"type",type);
- Setattr($$,"value",$4.val);
- if ($4.rawval) Setattr($$,"rawval", $4.rawval);
- Setattr($$,"storage","%constant");
- SetFlag($$,"feature:immutable");
- add_symbols($$);
- Delete(type);
- } else {
- if ($4.type == T_ERROR) {
- Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line,"Unsupported constant value (ignored)\n");
- }
- $$ = 0;
- }
-
- }
- | CONSTANT type declarator def_args SEMI {
- if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) {
- SwigType_push($2,$3.type);
- /* Sneaky callback function trick */
- if (SwigType_isfunction($2)) {
- SwigType_add_pointer($2);
- }
+ SwigType *type = NewSwigType($4.type);
+ if (Len(type) > 0) {
$$ = new_node("constant");
- Setattr($$,"name",$3.id);
- Setattr($$,"type",$2);
- Setattr($$,"value",$4.val);
- if ($4.rawval) Setattr($$,"rawval", $4.rawval);
- Setattr($$,"storage","%constant");
- SetFlag($$,"feature:immutable");
+ Setattr($$, "name", $2);
+ Setattr($$, "type", type);
+ Setattr($$, "value", $4.val);
+ if ($4.rawval) Setattr($$, "rawval", $4.rawval);
+ Setattr($$, "storage", "%constant");
+ SetFlag($$, "feature:immutable");
add_symbols($$);
+ Delete(type);
} else {
- if ($4.type == T_ERROR) {
- Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line, "Unsupported constant value\n");
- }
+ Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE, cparse_file, cparse_line, "Unsupported constant value (ignored)\n");
$$ = 0;
}
+ }
+ | CONSTANT type declarator def_args SEMI {
+ SwigType_push($2, $3.type);
+ /* Sneaky callback function trick */
+ if (SwigType_isfunction($2)) {
+ SwigType_add_pointer($2);
+ }
+ $$ = new_node("constant");
+ Setattr($$, "name", $3.id);
+ Setattr($$, "type", $2);
+ Setattr($$, "value", $4.val);
+ if ($4.rawval) Setattr($$, "rawval", $4.rawval);
+ Setattr($$, "storage", "%constant");
+ SetFlag($$, "feature:immutable");
+ add_symbols($$);
}
/* Member function pointers with qualifiers. eg.
%constant short (Funcs::*pmf)(bool) const = &Funcs::F; */
| CONSTANT type direct_declarator LPAREN parms RPAREN cv_ref_qualifier def_args SEMI {
- if (($8.type != T_ERROR) && ($8.type != T_SYMBOL)) {
- SwigType_add_function($2, $5);
- SwigType_push($2, $7.qualifier);
- SwigType_push($2, $3.type);
- /* Sneaky callback function trick */
- if (SwigType_isfunction($2)) {
- SwigType_add_pointer($2);
- }
- $$ = new_node("constant");
- Setattr($$, "name", $3.id);
- Setattr($$, "type", $2);
- Setattr($$, "value", $8.val);
- if ($8.rawval) Setattr($$, "rawval", $8.rawval);
- Setattr($$, "storage", "%constant");
- SetFlag($$, "feature:immutable");
- add_symbols($$);
- } else {
- if ($8.type == T_ERROR) {
- Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line, "Unsupported constant value\n");
- }
- $$ = 0;
+ SwigType_add_function($2, $5);
+ SwigType_push($2, $7.qualifier);
+ SwigType_push($2, $3.type);
+ /* Sneaky callback function trick */
+ if (SwigType_isfunction($2)) {
+ SwigType_add_pointer($2);
}
+ $$ = new_node("constant");
+ Setattr($$, "name", $3.id);
+ Setattr($$, "type", $2);
+ Setattr($$, "value", $8.val);
+ if ($8.rawval) Setattr($$, "rawval", $8.rawval);
+ Setattr($$, "storage", "%constant");
+ SetFlag($$, "feature:immutable");
+ add_symbols($$);
}
| CONSTANT error SEMI {
Swig_warning(WARN_PARSE_BAD_VALUE,cparse_file,cparse_line,"Bad constant value (ignored).\n");
$$ = 0;
}
+ | CONSTANT error END {
+ Swig_error(cparse_file,cparse_line,"Missing semicolon (';') after %%constant.\n");
+ Exit(EXIT_FAILURE);
+ }
;
/* ------------------------------------------------------------
@@ -2038,36 +2130,6 @@ echo_directive : ECHO HBLOCK {
}
;
-/* ------------------------------------------------------------
- %except(lang) { ... }
- %except { ... }
- %except(lang);
- %except;
- ------------------------------------------------------------ */
-
-except_directive : EXCEPT LPAREN identifier RPAREN LBRACE {
- skip_balanced('{','}');
- $$ = 0;
- Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
- }
-
- | EXCEPT LBRACE {
- skip_balanced('{','}');
- $$ = 0;
- Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
- }
-
- | EXCEPT LPAREN identifier RPAREN SEMI {
- $$ = 0;
- Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
- }
-
- | EXCEPT SEMI {
- $$ = 0;
- Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
- }
- ;
-
/* fragment keyword arguments */
stringtype : string LBRACE parm RBRACE {
$$ = NewHash();
@@ -2080,9 +2142,7 @@ fname : string {
$$ = NewHash();
Setattr($$,"value",$1);
}
- | stringtype {
- $$ = $1;
- }
+ | stringtype
;
/* ------------------------------------------------------------
@@ -2105,7 +2165,7 @@ fragment_directive: FRAGMENT LPAREN fname COMMA kwargs RPAREN HBLOCK {
| FRAGMENT LPAREN fname COMMA kwargs RPAREN LBRACE {
Hash *p = $5;
String *code;
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$ = new_node("fragment");
Setattr($$,"value",Getattr($3,"value"));
Setattr($$,"type",Getattr($3,"type"));
@@ -2130,9 +2190,9 @@ fragment_directive: FRAGMENT LPAREN fname COMMA kwargs RPAREN HBLOCK {
%importfile(option1="xyz", ...) "filename" [ declarations ]
------------------------------------------------------------ */
-include_directive: includetype options string BEGINFILE {
- $1.filename = Copy(cparse_file);
- $1.line = cparse_line;
+include_directive: includetype options string BEGINFILE <loc>{
+ $$.filename = Copy(cparse_file);
+ $$.line = cparse_line;
scanner_set_location($3,1);
if ($2) {
String *maininput = Getattr($2, "maininput");
@@ -2142,7 +2202,7 @@ include_directive: includetype options string BEGINFILE {
} interface ENDOFFILE {
String *mname = 0;
$$ = $6;
- scanner_set_location($1.filename,$1.line+1);
+ scanner_set_location($5.filename, $5.line + 1);
if (strcmp($1.type,"include") == 0) set_nodeType($$,"include");
if (strcmp($1.type,"import") == 0) {
mname = $2 ? Getattr($2,"module") : 0;
@@ -2216,10 +2276,11 @@ inline_directive : INLINE HBLOCK {
| INLINE LBRACE {
String *cpps;
int start_line = cparse_line;
- skip_balanced('{','}');
if (Namespaceprefix) {
Swig_error(cparse_file, cparse_start_line, "%%inline directive inside a namespace is disallowed.\n");
-
+ }
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ if (Namespaceprefix) {
$$ = 0;
} else {
String *code;
@@ -2265,7 +2326,7 @@ insert_directive : HBLOCK {
}
| INSERT LPAREN idstring RPAREN LBRACE {
String *code;
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$ = new_node("insert");
Setattr($$,"section",$3);
Delitem(scanner_ccode,0);
@@ -2320,25 +2381,6 @@ module_directive: MODULE options idstring {
;
/* ------------------------------------------------------------
- %name(newname) declaration
- %name("newname") declaration
- ------------------------------------------------------------ */
-
-name_directive : NAME LPAREN idstring RPAREN {
- Swig_warning(WARN_DEPRECATED_NAME,cparse_file,cparse_line, "%%name is deprecated. Use %%rename instead.\n");
- Delete(yyrename);
- yyrename = NewString($3);
- $$ = 0;
- }
- | NAME LPAREN RPAREN {
- Swig_warning(WARN_DEPRECATED_NAME,cparse_file,cparse_line, "%%name is deprecated. Use %%rename instead.\n");
- $$ = 0;
- Swig_error(cparse_file,cparse_line,"Missing argument to %%name directive.\n");
- }
- ;
-
-
-/* ------------------------------------------------------------
%native(scriptname) name;
%native(scriptname) type name (parms);
------------------------------------------------------------ */
@@ -2347,6 +2389,7 @@ native_directive : NATIVE LPAREN identifier RPAREN storage_class identifier SEMI
$$ = new_node("native");
Setattr($$,"name",$3);
Setattr($$,"wrap:name",$6);
+ Delete($5);
add_symbols($$);
}
| NATIVE LPAREN identifier RPAREN storage_class type declarator SEMI {
@@ -2364,6 +2407,7 @@ native_directive : NATIVE LPAREN identifier RPAREN storage_class identifier SEMI
Setattr($$,"parms",$7.parms);
Setattr($$,"decl",$7.type);
}
+ Delete($5);
add_symbols($$);
}
;
@@ -2388,12 +2432,12 @@ pragma_directive : PRAGMA pragma_lang identifier EQUAL pragma_arg {
}
;
-pragma_arg : string { $$ = $1; }
- | HBLOCK { $$ = $1; }
+pragma_arg : string
+ | HBLOCK
;
pragma_lang : LPAREN identifier RPAREN { $$ = $2; }
- | empty { $$ = (char *) "swig"; }
+ | %empty { $$ = "swig"; }
;
/* ------------------------------------------------------------
@@ -2585,7 +2629,7 @@ feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbr
}
;
-stringbracesemi : stringbrace { $$ = $1; }
+stringbracesemi : stringbrace
| SEMI { $$ = 0; }
| PARMS LPAREN parms RPAREN SEMI { $$ = $3; }
;
@@ -2641,7 +2685,7 @@ varargs_directive : VARARGS LPAREN varargs_parms RPAREN declarator cpp_const SEM
$$ = 0;
};
-varargs_parms : parms { $$ = $1; }
+varargs_parms : parms
| NUM_INT COMMA parm {
int i;
int n;
@@ -2716,26 +2760,23 @@ typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace {
/* typemap method type (lang,method) or (method) */
typemap_type : kwargs {
- Hash *p;
- String *name;
- p = nextSibling($1);
- if (p && (!Getattr(p,"value"))) {
- /* this is the deprecated two argument typemap form */
- Swig_warning(WARN_DEPRECATED_TYPEMAP_LANG,cparse_file, cparse_line,
- "Specifying the language name in %%typemap is deprecated - use #ifdef SWIG<LANG> instead.\n");
- /* two argument typemap form */
- name = Getattr($1,"name");
- if (!name || (Strcmp(name,typemap_lang))) {
- $$.method = 0;
- $$.kwargs = 0;
- } else {
- $$.method = Getattr(p,"name");
- $$.kwargs = nextSibling(p);
+ String *name = Getattr($1, "name");
+ Hash *p = nextSibling($1);
+ $$.method = name;
+ $$.kwargs = p;
+ if (Getattr($1, "value")) {
+ Swig_error(cparse_file, cparse_line,
+ "%%typemap method shouldn't have a value specified.\n");
+ }
+ while (p) {
+ if (!Getattr(p, "value")) {
+ Swig_error(cparse_file, cparse_line,
+ "%%typemap attribute '%s' is missing its value. If this is specifying the target language, that's no longer supported: use #ifdef SWIG<LANG> instead.\n",
+ Getattr(p, "name"));
+ /* Set to empty value to avoid segfaults later. */
+ Setattr(p, "value", NewStringEmpty());
}
- } else {
- /* one-argument typemap-form */
- $$.method = Getattr($1,"name");
- $$.kwargs = p;
+ p = nextSibling(p);
}
}
;
@@ -2750,7 +2791,7 @@ tm_tail : COMMA typemap_parm tm_tail {
$$ = $2;
set_nextSibling($$,$3);
}
- | empty { $$ = 0;}
+ | %empty { $$ = 0;}
;
typemap_parm : type plain_declarator {
@@ -2795,32 +2836,34 @@ types_directive : TYPES LPAREN parms RPAREN stringbracesemi {
------------------------------------------------------------ */
template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI {
- Parm *p, *tp;
- Node *n;
+ Parm *p;
+ Node *n = 0;
Node *outer_class = currentOuterClass;
Symtab *tscope = 0;
- int specialized = 0;
- int variadic = 0;
+ String *symname = $3 ? NewString($3) : 0;
+ int errored_flag = 0;
+ String *idcolonnt;
$$ = 0;
tscope = Swig_symbol_current(); /* Get the current scope */
/* If the class name is qualified, we need to create or lookup namespace entries */
- $5 = resolve_create_node_scope($5, 0);
+ idcolonnt = resolve_create_node_scope($5, 0, &errored_flag);
- if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) {
- outer_class = nscope_inner;
- }
+ if (!errored_flag) {
+ if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0)
+ outer_class = nscope_inner;
- /*
- We use the new namespace entry 'nscope' only to
- emit the template node. The template parameters are
- resolved in the current 'tscope'.
+ /*
+ We use the new namespace entry 'nscope' only to
+ emit the template node. The template parameters are
+ resolved in the current 'tscope'.
- This is closer to the C++ (typedef) behavior.
- */
- n = Swig_cparse_template_locate($5,$7,tscope);
+ This is closer to the C++ (typedef) behavior.
+ */
+ n = Swig_cparse_template_locate(idcolonnt, $7, symname, tscope);
+ }
/* Patch the argument types to respect namespaces */
p = $7;
@@ -2856,83 +2899,17 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Node *linkliststart = 0;
while (nn) {
Node *templnode = 0;
- if (Strcmp(nodeType(nn),"template") == 0) {
- int nnisclass = (Strcmp(Getattr(nn,"templatetype"),"class") == 0); /* if not a templated class it is a templated function */
- Parm *tparms = Getattr(nn,"templateparms");
- if (!tparms) {
- specialized = 1;
- } else if (Getattr(tparms,"variadic") && strncmp(Char(Getattr(tparms,"variadic")), "1", 1)==0) {
- variadic = 1;
- }
- if (nnisclass && !variadic && !specialized && (ParmList_len($7) > ParmList_len(tparms))) {
- Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparms));
- } else if (nnisclass && !specialized && ((ParmList_len($7) < (ParmList_numrequired(tparms) - (variadic?1:0))))) { /* Variadic parameter is optional */
- Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", (ParmList_numrequired(tparms)-(variadic?1:0)) );
- } else if (!nnisclass && ((ParmList_len($7) != ParmList_len(tparms)))) {
- /* must be an overloaded templated method - ignore it as it is overloaded with a different number of template parameters */
- nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions */
- continue;
- } else {
- String *tname = Copy($5);
- int def_supplied = 0;
- /* Expand the template */
- Node *templ = Swig_symbol_clookup($5,0);
- Parm *targs = templ ? Getattr(templ,"templateparms") : 0;
-
- ParmList *temparms;
- if (specialized) temparms = CopyParmList($7);
- else temparms = CopyParmList(tparms);
-
- /* Create typedef's and arguments */
- p = $7;
- tp = temparms;
- if (!p && ParmList_len(p) != ParmList_len(temparms)) {
- /* we have no template parameters supplied in %template for a template that has default args*/
- p = tp;
- def_supplied = 1;
- }
-
- while (p) {
- String *value = Getattr(p,"value");
- if (def_supplied) {
- Setattr(p,"default","1");
- }
- if (value) {
- Setattr(tp,"value",value);
- } else {
- SwigType *ty = Getattr(p,"type");
- if (ty) {
- Setattr(tp,"type",ty);
- }
- Delattr(tp,"value");
- }
- /* fix default arg values */
- if (targs) {
- Parm *pi = temparms;
- Parm *ti = targs;
- String *tv = Getattr(tp,"value");
- if (!tv) tv = Getattr(tp,"type");
- while(pi != tp && ti && pi) {
- String *name = Getattr(ti,"name");
- String *value = Getattr(pi,"value");
- if (!value) value = Getattr(pi,"type");
- Replaceid(tv, name, value);
- pi = nextSibling(pi);
- ti = nextSibling(ti);
- }
- }
- p = nextSibling(p);
- tp = nextSibling(tp);
- if (!p && tp) {
- p = tp;
- def_supplied = 1;
- } else if (p && !tp) { /* Variadic template - tp < p */
- SWIG_WARN_NODE_BEGIN(nn);
- Swig_warning(WARN_CPP11_VARIADIC_TEMPLATE,cparse_file, cparse_line,"Only the first variadic template argument is currently supported.\n");
- SWIG_WARN_NODE_END(nn);
- break;
- }
- }
+ if (GetFlag(nn, "instantiate")) {
+ Delattr(nn, "instantiate");
+ {
+ int nnisclass = (Strcmp(Getattr(nn, "templatetype"), "class") == 0); /* if not a class template it is a function template */
+ Parm *tparms = Getattr(nn, "templateparms");
+ int specialized = !tparms; /* fully specialized (an explicit specialization) */
+ String *tname = Copy(idcolonnt);
+ Node *primary_template = Swig_symbol_clookup(tname, 0);
+
+ /* Expand the template */
+ ParmList *temparms = Swig_cparse_template_parms_expand($7, primary_template, nn);
templnode = copy_node(nn);
update_nested_classes(templnode); /* update classes nested within template */
@@ -2945,7 +2922,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Setattr(templnode,"sym:typename","1");
}
/* for now, nested %template is allowed only in the same scope as the template declaration */
- if ($3 && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer")))
+ if (symname && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer")))
||(extendmode && current_class && (current_class != Getattr(nn, "nested:outer")))))) {
/*
Comment this out for 1.3.28. We need to
@@ -2953,19 +2930,19 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
move %ignore from using %rename to use
%feature(ignore).
- String *symname = Swig_name_make(templnode,0,$3,0,0);
+ String *symname = Swig_name_make(templnode, 0, symname, 0, 0);
*/
- String *symname = NewString($3);
- Swig_cparse_template_expand(templnode,symname,temparms,tscope);
- Setattr(templnode,"sym:name",symname);
+ Swig_cparse_template_expand(templnode, symname, temparms, tscope);
+ Setattr(templnode, "sym:name", symname);
} else {
static int cnt = 0;
String *nname = NewStringf("__dummy_%d__", cnt++);
Swig_cparse_template_expand(templnode,nname,temparms,tscope);
Setattr(templnode,"sym:name",nname);
+ SetFlag(templnode,"hidden");
Delete(nname);
Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment,apply");
- if ($3) {
+ if (symname) {
Swig_warning(WARN_PARSE_NESTED_TEMPLATE, cparse_file, cparse_line, "Named nested template instantiations not supported. Processing as if no name was given to %%template().\n");
}
}
@@ -3055,7 +3032,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
}
}
- /* all the overloaded templated functions are added into a linked list */
+ /* all the overloaded function templates are added into a linked list */
if (!linkliststart)
linkliststart = templnode;
if (nscope_inner) {
@@ -3076,7 +3053,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
linklistend = templnode;
}
}
- nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions. If a templated class there will never be a sibling. */
+ nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded function templates. If a class template there will never be a sibling. */
}
update_defaultargs(linkliststart);
update_abstracts(linkliststart);
@@ -3084,6 +3061,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Swig_symbol_setscope(tscope);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ Delete(symname);
}
;
@@ -3109,8 +3087,8 @@ c_declaration : c_decl {
default_arguments($$);
}
}
- | c_enum_decl { $$ = $1; }
- | c_enum_forward_decl { $$ = $1; }
+ | c_enum_decl
+ | c_enum_forward_decl
/* An extern C type declaration, disable cparse_cplusplus if needed. */
@@ -3126,14 +3104,22 @@ c_declaration : c_decl {
Setattr($$,"name",$2);
appendChild($$,n);
while (n) {
- SwigType *decl = Getattr(n,"decl");
- if (SwigType_isfunction(decl) && !Equal(Getattr(n, "storage"), "typedef")) {
+ String *s = Getattr(n, "storage");
+ if (s) {
+ if (Strstr(s, "thread_local")) {
+ Insert(s,0,"externc ");
+ } else if (!Equal(s, "typedef")) {
+ Setattr(n,"storage","externc");
+ }
+ } else {
Setattr(n,"storage","externc");
}
n = nextSibling(n);
}
} else {
- Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $2);
+ if (!Equal($2,"C++")) {
+ Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $2);
+ }
$$ = new_node("extern");
Setattr($$,"name",$2);
appendChild($$,firstChild($5));
@@ -3167,9 +3153,7 @@ c_declaration : c_decl {
SetFlag($$,"aliastemplate");
add_symbols($$);
}
- | cpp_static_assert {
- $$ = $1;
- }
+ | cpp_static_assert
;
/* ------------------------------------------------------------
@@ -3195,10 +3179,13 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
if ($5.val && $5.type) {
/* store initializer type as it might be different to the declared type */
SwigType *valuetype = NewSwigType($5.type);
- if (Len(valuetype) > 0)
- Setattr($$,"valuetype",valuetype);
- else
- Delete(valuetype);
+ if (Len(valuetype) > 0) {
+ Setattr($$, "valuetype", valuetype);
+ } else {
+ /* If we can't determine the initializer type use the declared type. */
+ Setattr($$, "valuetype", $2);
+ }
+ Delete(valuetype);
}
if (!$6) {
if (Len(scanner_ccode)) {
@@ -3222,27 +3209,26 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
}
if ($3.id) {
- /* Look for "::" declarations (ignored) */
- if (Strstr($3.id, "::")) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($3.id);
+ if (p) {
/* This is a special case. If the scope name of the declaration exactly
matches that of the declaration, then we will allow it. Otherwise, delete. */
- String *p = Swig_scopename_prefix($3.id);
- if (p) {
- if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
- (Classprefix && Strcmp(p, Classprefix) == 0)) {
- String *lstr = Swig_scopename_last($3.id);
- Setattr($$, "name", lstr);
- Delete(lstr);
- set_nextSibling($$, $6);
- } else {
- Delete($$);
- $$ = $6;
- }
- Delete(p);
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($3.id);
+ Setattr($$, "name", lstr);
+ Delete(lstr);
+ set_nextSibling($$, $6);
} else {
Delete($$);
$$ = $6;
}
+ Delete(p);
+ } else if (Strncmp($3.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = $6;
} else {
set_nextSibling($$, $6);
}
@@ -3254,6 +3240,51 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
if ($4.qualifier && $1 && Strstr($1, "static"))
Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
}
+ | storage_class type declarator cpp_const EQUAL error SEMI {
+ String *decl = $3.type;
+ $$ = new_node("cdecl");
+ if ($4.qualifier)
+ decl = add_qualifier_to_declarator($3.type, $4.qualifier);
+ Setattr($$, "refqualifier", $4.refqualifier);
+ Setattr($$, "type", $2);
+ Setattr($$, "storage", $1);
+ Setattr($$, "name", $3.id);
+ Setattr($$, "decl", decl);
+ Setattr($$, "parms", $3.parms);
+
+ /* Set dummy value to avoid adding in code for handling missing value in later stages */
+ Setattr($$, "value", "*parse error*");
+ SetFlag($$, "valueignored");
+
+ Setattr($$, "throws", $4.throws);
+ Setattr($$, "throw", $4.throwf);
+ Setattr($$, "noexcept", $4.nexcept);
+ Setattr($$, "final", $4.final);
+
+ if ($3.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($3.id);
+ if (p) {
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($3.id);
+ Setattr($$, "name", lstr);
+ Delete(lstr);
+ } else {
+ Delete($$);
+ $$ = 0;
+ }
+ Delete(p);
+ } else if (Strncmp($3.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = 0;
+ }
+ }
+
+ if ($4.qualifier && $1 && Strstr($1, "static"))
+ Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
+ }
/* Alternate function syntax introduced in C++11:
auto funcName(int x, int y) -> int; */
| storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype virt_specifier_seq_opt initializer c_decl_tail {
@@ -3265,7 +3296,6 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
Setattr($$,"name",$3.id);
Setattr($$,"decl",$3.type);
Setattr($$,"parms",$3.parms);
- Setattr($$,"value",$4.val);
Setattr($$,"throws",$4.throws);
Setattr($$,"throw",$4.throwf);
Setattr($$,"noexcept",$4.nexcept);
@@ -3286,12 +3316,10 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
Delete(type);
}
}
- if ($4.bitfield) {
- Setattr($$,"bitfield", $4.bitfield);
- }
- if (Strstr($3.id,"::")) {
- String *p = Swig_scopename_prefix($3.id);
+ if ($3.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($3.id);
if (p) {
if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
(Classprefix && Strcmp(p, Classprefix) == 0)) {
@@ -3304,7 +3332,8 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
$$ = $9;
}
Delete(p);
- } else {
+ } else if (Strncmp($3.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
Delete($$);
$$ = $9;
}
@@ -3315,7 +3344,67 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
if ($4.qualifier && $1 && Strstr($1, "static"))
Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
}
- ;
+ /* C++14 allows the trailing return type to be omitted. It's
+ * probably not feasible for SWIG to deduce it but we should
+ * at least support parsing this so that the rest of an API
+ * can be wrapped. This also means you can provide declaration
+ * with an explicit return type in the interface file for SWIG
+ * to wrap.
+ */
+ | storage_class AUTO declarator cpp_const LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+
+ $$ = new_node("cdecl");
+ if ($4.qualifier) SwigType_push($3.type, $4.qualifier);
+ Setattr($$, "refqualifier", $4.refqualifier);
+ Setattr($$, "type", NewString("auto"));
+ Setattr($$, "storage", $1);
+ Setattr($$, "name", $3.id);
+ Setattr($$, "decl", $3.type);
+ Setattr($$, "parms", $3.parms);
+ Setattr($$, "throws", $4.throws);
+ Setattr($$, "throw", $4.throwf);
+ Setattr($$, "noexcept", $4.nexcept);
+ Setattr($$, "final", $4.final);
+
+ if ($3.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($3.id);
+ if (p) {
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($3.id);
+ Setattr($$, "name", lstr);
+ Delete(lstr);
+ } else {
+ Delete($$);
+ $$ = 0;
+ }
+ Delete(p);
+ } else if (Strncmp($3.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = 0;
+ }
+ }
+
+ if ($4.qualifier && $1 && Strstr($1, "static"))
+ Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
+ }
+ /* C++11 auto variable declaration. */
+ | storage_class AUTO idcolon EQUAL definetype SEMI {
+ SwigType *type = deduce_type(&$5);
+ if (!type)
+ type = NewString("auto");
+ $$ = new_node("cdecl");
+ Setattr($$, "type", type);
+ Setattr($$, "storage", $1);
+ Setattr($$, "name", $3);
+ Setattr($$, "decl", NewStringEmpty());
+ Setattr($$, "value", $5.val);
+ Setattr($$, "valuetype", type);
+ }
+ ;
/* Allow lists of variables and functions to be built up */
@@ -3349,34 +3438,33 @@ c_decl_tail : SEMI {
}
}
| LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$ = 0;
}
| error {
$$ = 0;
if (yychar == RPAREN) {
- Swig_error(cparse_file, cparse_line, "Unexpected ')'.\n");
+ Swig_error(cparse_file, cparse_line, "Unexpected closing parenthesis (')').\n");
} else {
- Swig_error(cparse_file, cparse_line, "Syntax error - possibly a missing semicolon.\n");
+ Swig_error(cparse_file, cparse_line, "Syntax error - possibly a missing semicolon (';').\n");
}
- SWIG_exit(EXIT_FAILURE);
+ Exit(EXIT_FAILURE);
}
;
-initializer : def_args {
- $$ = $1;
- }
+initializer : def_args
;
-cpp_alternate_rettype : primitive_type { $$ = $1; }
- | TYPE_BOOL { $$ = $1; }
- | TYPE_VOID { $$ = $1; }
-/*
- | TYPE_TYPEDEF template_decl { $$ = NewStringf("%s%s",$1,$2); }
-*/
- | TYPE_RAW { $$ = $1; }
+cpp_alternate_rettype : primitive_type
+ | TYPE_BOOL
+ | TYPE_VOID
+ | TYPE_RAW
| idcolon { $$ = $1; }
- | decltype { $$ = $1; }
+ | idcolon AND {
+ $$ = $1;
+ SwigType_add_reference($$);
+ }
+ | decltype
;
/* ------------------------------------------------------------
@@ -3387,31 +3475,41 @@ cpp_alternate_rettype : primitive_type { $$ = $1; }
auto myFunc = [](int x, int y) throw() -> int { return x+y; };
auto six = [](int x, int y) { return x+y; }(4, 2);
------------------------------------------------------------ */
-cpp_lambda_decl : storage_class AUTO idcolon EQUAL lambda_introducer LPAREN parms RPAREN cpp_const lambda_body lambda_tail {
+cpp_lambda_decl : storage_class AUTO idcolon EQUAL lambda_introducer lambda_template LPAREN parms RPAREN cpp_const lambda_body lambda_tail {
$$ = new_node("lambda");
Setattr($$,"name",$3);
+ Delete($1);
add_symbols($$);
}
- | storage_class AUTO idcolon EQUAL lambda_introducer LPAREN parms RPAREN cpp_const ARROW type lambda_body lambda_tail {
+ | storage_class AUTO idcolon EQUAL lambda_introducer lambda_template LPAREN parms RPAREN cpp_const ARROW type lambda_body lambda_tail {
$$ = new_node("lambda");
Setattr($$,"name",$3);
+ Delete($1);
add_symbols($$);
}
- | storage_class AUTO idcolon EQUAL lambda_introducer lambda_body lambda_tail {
+ | storage_class AUTO idcolon EQUAL lambda_introducer lambda_template lambda_body lambda_tail {
$$ = new_node("lambda");
Setattr($$,"name",$3);
+ Delete($1);
add_symbols($$);
}
;
lambda_introducer : LBRACKET {
- skip_balanced('[',']');
+ if (skip_balanced('[',']') < 0) Exit(EXIT_FAILURE);
$$ = 0;
}
;
+lambda_template : LESSTHAN {
+ if (skip_balanced('<','>') < 0) Exit(EXIT_FAILURE);
+ $$ = 0;
+ }
+ | %empty { $$ = 0; }
+ ;
+
lambda_body : LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$ = 0;
}
@@ -3419,7 +3517,7 @@ lambda_tail : SEMI {
$$ = 0;
}
| LPAREN {
- skip_balanced('(',')');
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
} SEMI {
$$ = 0;
}
@@ -3432,13 +3530,13 @@ lambda_tail : SEMI {
------------------------------------------------------------ */
c_enum_key : ENUM {
- $$ = (char *)"enum";
+ $$ = "enum";
}
| ENUM CLASS {
- $$ = (char *)"enum class";
+ $$ = "enum class";
}
| ENUM STRUCT {
- $$ = (char *)"enum struct";
+ $$ = "enum struct";
}
;
@@ -3449,7 +3547,7 @@ c_enum_key : ENUM {
c_enum_inherit : COLON type_right {
$$ = $2;
}
- | empty { $$ = 0; }
+ | %empty { $$ = 0; }
;
/* ------------------------------------------------------------
enum [class] Name;
@@ -3465,7 +3563,7 @@ c_enum_forward_decl : storage_class c_enum_key ename c_enum_inherit SEMI {
if (scopedenum)
SetFlag($$, "scopedenum");
Setattr($$,"name",$3);
- Setattr($$,"inherit",$4);
+ Setattr($$, "enumbase", $4);
Setattr($$,"type",ty);
Setattr($$,"sym:weak", "1");
add_symbols($$);
@@ -3487,7 +3585,7 @@ c_enum_decl : storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBR
if (scopedenum)
SetFlag($$, "scopedenum");
Setattr($$,"name",$3);
- Setattr($$,"inherit",$4);
+ Setattr($$, "enumbase", $4);
Setattr($$,"type",ty);
appendChild($$,$6);
add_symbols($$); /* Add to tag space */
@@ -3518,7 +3616,7 @@ c_enum_decl : storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBR
Setattr($$,"enumkey",$2);
if (scopedenum)
SetFlag($$, "scopedenum");
- Setattr($$,"inherit",$4);
+ Setattr($$, "enumbase", $4);
if ($3) {
Setattr($$,"name",$3);
ty = NewStringf("enum %s", $3);
@@ -3646,10 +3744,12 @@ c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
Setattr($$,"final",$6.final);
err = 0;
}
+ } else {
+ Delete($1);
}
if (err) {
Swig_error(cparse_file,cparse_line,"Syntax error in input(2).\n");
- SWIG_exit(EXIT_FAILURE);
+ Exit(EXIT_FAILURE);
}
}
;
@@ -3658,72 +3758,75 @@ c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
* C++ Support
* ====================================================================== */
-cpp_declaration : cpp_class_decl { $$ = $1; }
- | cpp_forward_class_decl { $$ = $1; }
- | cpp_template_decl { $$ = $1; }
- | cpp_using_decl { $$ = $1; }
- | cpp_namespace_decl { $$ = $1; }
- | cpp_catch_decl { $$ = 0; }
+cpp_declaration : cpp_class_decl
+ | cpp_forward_class_decl
+ | cpp_template_decl
+ | cpp_using_decl
+ | cpp_namespace_decl
+ | cpp_catch_decl
;
/* A simple class/struct/union definition */
-cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
+
+/* Note that class_virt_specifier_opt for supporting final classes introduces one shift-reduce conflict
+ with C style variable declarations, such as: struct X final; */
+
+cpp_class_decl: storage_class cpptype idcolon class_virt_specifier_opt inherit LBRACE <node>{
String *prefix;
List *bases = 0;
Node *scope = 0;
+ int errored_flag = 0;
String *code;
- $<node>$ = new_node("class");
- Setline($<node>$,cparse_start_line);
- Setattr($<node>$,"kind",$2);
- if ($4) {
- Setattr($<node>$,"baselist", Getattr($4,"public"));
- Setattr($<node>$,"protectedbaselist", Getattr($4,"protected"));
- Setattr($<node>$,"privatebaselist", Getattr($4,"private"));
+ $$ = new_node("class");
+ Setattr($$,"kind",$2);
+ if ($5) {
+ Setattr($$,"baselist", Getattr($5,"public"));
+ Setattr($$,"protectedbaselist", Getattr($5,"protected"));
+ Setattr($$,"privatebaselist", Getattr($5,"private"));
}
- Setattr($<node>$,"allows_typedef","1");
+ Setattr($$,"allows_typedef","1");
/* preserve the current scope */
- Setattr($<node>$,"prev_symtab",Swig_symbol_current());
+ Setattr($$,"prev_symtab",Swig_symbol_current());
/* If the class name is qualified. We need to create or lookup namespace/scope entries */
- scope = resolve_create_node_scope($3, 1);
+ scope = resolve_create_node_scope($3, 1, &errored_flag);
/* save nscope_inner to the class - it may be overwritten in nested classes*/
- Setattr($<node>$, "nested:innerscope", nscope_inner);
- Setattr($<node>$, "nested:nscope", nscope);
+ Setattr($$, "nested:innerscope", nscope_inner);
+ Setattr($$, "nested:nscope", nscope);
Setfile(scope,cparse_file);
Setline(scope,cparse_line);
- $3 = scope;
- Setattr($<node>$,"name",$3);
+ Setattr($$, "name", scope);
if (currentOuterClass) {
- SetFlag($<node>$, "nested");
- Setattr($<node>$, "nested:outer", currentOuterClass);
- set_access_mode($<node>$);
+ SetFlag($$, "nested");
+ Setattr($$, "nested:outer", currentOuterClass);
+ set_access_mode($$);
}
- Swig_features_get(Swig_cparse_features(), Namespaceprefix, Getattr($<node>$, "name"), 0, $<node>$);
+ Swig_features_get(Swig_cparse_features(), Namespaceprefix, Getattr($$, "name"), 0, $$);
/* save yyrename to the class attribute, to be used later in add_symbols()*/
- Setattr($<node>$, "class_rename", make_name($<node>$, $3, 0));
- Setattr($<node>$, "Classprefix", $3);
- Classprefix = NewString($3);
+ Setattr($$, "class_rename", make_name($$, scope, 0));
+ Setattr($$, "Classprefix", scope);
+ Classprefix = NewString(scope);
/* Deal with inheritance */
- if ($4)
- bases = Swig_make_inherit_list($3,Getattr($4,"public"),Namespaceprefix);
- prefix = SwigType_istemplate_templateprefix($3);
+ if ($5)
+ bases = Swig_make_inherit_list(scope, Getattr($5, "public"), Namespaceprefix);
+ prefix = SwigType_istemplate_templateprefix(scope);
if (prefix) {
String *fbase, *tbase;
if (Namespaceprefix) {
- fbase = NewStringf("%s::%s", Namespaceprefix,$3);
+ fbase = NewStringf("%s::%s", Namespaceprefix, scope);
tbase = NewStringf("%s::%s", Namespaceprefix, prefix);
} else {
- fbase = Copy($3);
+ fbase = Copy(scope);
tbase = Copy(prefix);
}
Swig_name_inherit(tbase,fbase);
Delete(fbase);
Delete(tbase);
}
- if (strcmp($2,"class") == 0) {
+ if (Strcmp($2, "class") == 0) {
cplus_mode = CPLUS_PRIVATE;
} else {
cplus_mode = CPLUS_PUBLIC;
@@ -3732,7 +3835,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
set_scope_to_global();
}
Swig_symbol_newscope();
- Swig_symbol_setscopename($3);
+ Swig_symbol_setscopename(scope);
Swig_inherit_base_symbols(bases);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
@@ -3754,11 +3857,11 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
}
Delete(prefix);
inclass = 1;
- currentOuterClass = $<node>$;
+ currentOuterClass = $$;
if (cparse_cplusplusout) {
/* save the structure declaration to declare it in global scope for C++ to see */
code = get_raw_text_balanced('{', '}');
- Setattr($<node>$, "code", code);
+ Setattr($$, "code", code);
Delete(code);
}
} cpp_members RBRACE cpp_opt_declarators {
@@ -3767,20 +3870,19 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Symtab *cscope;
Node *am = 0;
String *scpname = 0;
- (void) $<node>6;
$$ = currentOuterClass;
currentOuterClass = Getattr($$, "nested:outer");
- nscope_inner = Getattr($<node>$, "nested:innerscope");
- nscope = Getattr($<node>$, "nested:nscope");
- Delattr($<node>$, "nested:innerscope");
- Delattr($<node>$, "nested:nscope");
+ nscope_inner = Getattr($$, "nested:innerscope");
+ nscope = Getattr($$, "nested:nscope");
+ Delattr($$, "nested:innerscope");
+ Delattr($$, "nested:nscope");
if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) { /* actual parent class for this class */
- Node* forward_declaration = Swig_symbol_clookup_no_inherit(Getattr($<node>$,"name"), Getattr(nscope_inner, "symtab"));
+ Node* forward_declaration = Swig_symbol_clookup_no_inherit(Getattr($$,"name"), Getattr(nscope_inner, "symtab"));
if (forward_declaration) {
- Setattr($<node>$, "access", Getattr(forward_declaration, "access"));
+ Setattr($$, "access", Getattr(forward_declaration, "access"));
}
- Setattr($<node>$, "nested:outer", nscope_inner);
- SetFlag($<node>$, "nested");
+ Setattr($$, "nested:outer", nscope_inner);
+ SetFlag($$, "nested");
}
if (!currentOuterClass)
inclass = 0;
@@ -3788,7 +3890,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Delattr($$, "prev_symtab");
/* Check for pure-abstract class */
- Setattr($$,"abstracts", pure_abstracts($7));
+ Setattr($$,"abstracts", pure_abstracts($8));
/* This bit of code merges in a previously defined %extend directive (if any) */
{
@@ -3804,12 +3906,12 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
scpname = Swig_symbol_qualifiedscopename(0);
Setattr(classes, scpname, $$);
- appendChild($$, $7);
+ appendChild($$, $8);
if (am)
Swig_extend_append_previous($$, am);
- p = $9;
+ p = $10;
if (p && !nscope_inner) {
if (!cparse_cplusplus && currentOuterClass)
appendChild(currentOuterClass, p);
@@ -3820,21 +3922,20 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
if (nscope_inner) {
ty = NewString(scpname); /* if the class is declared out of scope, let the declarator use fully qualified type*/
} else if (cparse_cplusplus && !cparse_externc) {
- ty = NewString($3);
+ ty = NewString(Getattr($7, "name"));
} else {
- ty = NewStringf("%s %s", $2, $3);
+ ty = NewStringf("%s %s", $2, Getattr($7, "name"));
}
while (p) {
Setattr(p, "storage", $1);
Setattr(p, "type" ,ty);
if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) {
SetFlag(p, "hasconsttype");
- SetFlag(p, "feature:immutable");
}
p = nextSibling(p);
}
- if ($9 && Cmp($1,"typedef") == 0)
- add_typedef_name($$, $9, $3, cscope, scpname);
+ if ($10 && Cmp($1,"typedef") == 0)
+ add_typedef_name($$, $10, Getattr($7, "name"), cscope, scpname);
Delete(scpname);
if (cplus_mode != CPLUS_PUBLIC) {
@@ -3849,38 +3950,38 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
if (currentOuterClass)
restore_access_mode($$);
Setattr($$, "symtab", Swig_symbol_popscope());
- Classprefix = Getattr($<node>$, "Classprefix");
- Delattr($<node>$, "Classprefix");
+ Classprefix = Getattr($$, "Classprefix");
+ Delattr($$, "Classprefix");
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
if (cplus_mode == CPLUS_PRIVATE) {
$$ = 0; /* skip private nested classes */
} else if (cparse_cplusplus && currentOuterClass && ignore_nested_classes && !GetFlag($$, "feature:flatnested")) {
- $$ = nested_forward_declaration($1, $2, $3, Copy($3), $9);
+ $$ = nested_forward_declaration($1, $2, Getattr($7, "name"), Copy(Getattr($7, "name")), $10);
} else if (nscope_inner) {
/* this is tricky */
/* we add the declaration in the original namespace */
if (Strcmp(nodeType(nscope_inner), "class") == 0 && cparse_cplusplus && ignore_nested_classes && !GetFlag($$, "feature:flatnested"))
- $$ = nested_forward_declaration($1, $2, $3, Copy($3), $9);
+ $$ = nested_forward_declaration($1, $2, Getattr($7, "name"), Copy(Getattr($7, "name")), $10);
appendChild(nscope_inner, $$);
Swig_symbol_setscope(Getattr(nscope_inner, "symtab"));
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- yyrename = Copy(Getattr($<node>$, "class_rename"));
+ yyrename = Copy(Getattr($$, "class_rename"));
add_symbols($$);
Delattr($$, "class_rename");
/* but the variable definition in the current scope */
Swig_symbol_setscope(cscope);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- add_symbols($9);
+ add_symbols($10);
if (nscope) {
$$ = nscope; /* here we return recreated namespace tower instead of the class itself */
- if ($9) {
- appendSibling($$, $9);
+ if ($10) {
+ appendSibling($$, $10);
}
} else if (!SwigType_istemplate(ty) && template_parameters == 0) { /* for template we need the class itself */
- $$ = $9;
+ $$ = $10;
}
} else {
Delete(yyrename);
@@ -3891,20 +3992,20 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
outer = Getattr(outer, "nested:outer");
appendSibling(outer, $$);
Swig_symbol_setscope(cscope); /* declaration goes in the parent scope */
- add_symbols($9);
+ add_symbols($10);
set_scope_to_global();
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- yyrename = Copy(Getattr($<node>$, "class_rename"));
+ yyrename = Copy(Getattr($$, "class_rename"));
add_symbols($$);
if (!cparse_cplusplusout)
Delattr($$, "nested:outer");
Delattr($$, "class_rename");
$$ = 0;
} else {
- yyrename = Copy(Getattr($<node>$, "class_rename"));
+ yyrename = Copy(Getattr($$, "class_rename"));
add_symbols($$);
- add_symbols($9);
+ add_symbols($10);
Delattr($$, "class_rename");
}
}
@@ -3917,44 +4018,43 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
/* An unnamed struct, possibly with a typedef */
- | storage_class cpptype inherit LBRACE {
+ | storage_class cpptype inherit LBRACE <node>{
String *unnamed;
String *code;
unnamed = make_unnamed();
- $<node>$ = new_node("class");
- Setline($<node>$,cparse_start_line);
- Setattr($<node>$,"kind",$2);
+ $$ = new_node("class");
+ Setattr($$,"kind",$2);
if ($3) {
- Setattr($<node>$,"baselist", Getattr($3,"public"));
- Setattr($<node>$,"protectedbaselist", Getattr($3,"protected"));
- Setattr($<node>$,"privatebaselist", Getattr($3,"private"));
+ Setattr($$,"baselist", Getattr($3,"public"));
+ Setattr($$,"protectedbaselist", Getattr($3,"protected"));
+ Setattr($$,"privatebaselist", Getattr($3,"private"));
}
- Setattr($<node>$,"storage",$1);
- Setattr($<node>$,"unnamed",unnamed);
- Setattr($<node>$,"allows_typedef","1");
+ Setattr($$,"storage",$1);
+ Setattr($$,"unnamed",unnamed);
+ Setattr($$,"allows_typedef","1");
if (currentOuterClass) {
- SetFlag($<node>$, "nested");
- Setattr($<node>$, "nested:outer", currentOuterClass);
- set_access_mode($<node>$);
+ SetFlag($$, "nested");
+ Setattr($$, "nested:outer", currentOuterClass);
+ set_access_mode($$);
}
- Swig_features_get(Swig_cparse_features(), Namespaceprefix, 0, 0, $<node>$);
+ Swig_features_get(Swig_cparse_features(), Namespaceprefix, 0, 0, $$);
/* save yyrename to the class attribute, to be used later in add_symbols()*/
- Setattr($<node>$, "class_rename", make_name($<node>$,0,0));
- if (strcmp($2,"class") == 0) {
+ Setattr($$, "class_rename", make_name($$,0,0));
+ if (Strcmp($2, "class") == 0) {
cplus_mode = CPLUS_PRIVATE;
} else {
cplus_mode = CPLUS_PUBLIC;
}
Swig_symbol_newscope();
cparse_start_line = cparse_line;
- currentOuterClass = $<node>$;
+ currentOuterClass = $$;
inclass = 1;
Classprefix = 0;
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
/* save the structure declaration to make a typedef for it later*/
code = get_raw_text_balanced('{', '}');
- Setattr($<node>$, "code", code);
+ Setattr($$, "code", code);
Delete(code);
} cpp_members RBRACE cpp_opt_declarators {
String *unnamed;
@@ -3962,7 +4062,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
String *name = 0;
Node *n;
Classprefix = 0;
- (void)$<node>5;
+ (void)$5;
$$ = currentOuterClass;
currentOuterClass = Getattr($$, "nested:outer");
if (!currentOuterClass)
@@ -4006,7 +4106,6 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Setattr(n, "type", ty);
if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) {
SetFlag(n,"hasconsttype");
- SetFlag(n,"feature:immutable");
}
n = nextSibling(n);
}
@@ -4043,7 +4142,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Setattr($$,"symtab",Swig_symbol_popscope());
if (name) {
Delete(yyrename);
- yyrename = Copy(Getattr($<node>$, "class_rename"));
+ yyrename = Copy(Getattr($$, "class_rename"));
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
add_symbols($$);
@@ -4078,7 +4177,7 @@ cpp_opt_declarators : SEMI { $$ = 0; }
------------------------------------------------------------ */
cpp_forward_class_decl : storage_class cpptype idcolon SEMI {
- if ($1 && (Strcmp($1,"friend") == 0)) {
+ if ($1 && Strstr($1, "friend")) {
/* Ignore */
$$ = 0;
} else {
@@ -4088,6 +4187,7 @@ cpp_forward_class_decl : storage_class cpptype idcolon SEMI {
Setattr($$,"sym:weak", "1");
add_symbols($$);
}
+ Delete($1);
}
;
@@ -4119,10 +4219,11 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Swig_symbol_setscope(sti);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- $6 = ni;
+ $$ = ni;
+ } else {
+ $$ = $6;
}
- $$ = $6;
if ($$) tname = Getattr($$,"name");
/* Check if the class is a template specialization */
@@ -4145,120 +4246,42 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Setattr($$,"templatetype",nodeType($$));
set_nodeType($$,"template");
/* Template partial specialization */
- if (tempn && ($3) && ($6)) {
- List *tlist;
- String *targs = SwigType_templateargs(tname);
- tlist = SwigType_parmlist(targs);
- /* Printf(stdout,"targs = '%s' %s\n", targs, tlist); */
+ if (tempn && ($3) && ($$)) {
+ ParmList *primary_templateparms = Getattr(tempn, "templateparms");
+ String *targs = SwigType_templateargs(tname); /* tname contains name and specialized template parameters, for example: X<(p.T,TT)> */
+ List *tlist = SwigType_parmlist(targs);
+ int specialization_parms_len = Len(tlist);
if (!Getattr($$,"sym:weak")) {
Setattr($$,"sym:typename","1");
}
+ Setattr($$, "primarytemplate", tempn);
+ Setattr($$, "templateparms", $3);
+ Delattr($$, "specialization");
+ Setattr($$, "partialspecialization", "1");
- if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) {
- Swig_error(Getfile($$),Getline($$),"Inconsistent argument count in template partial specialization. %d %d\n", Len(tlist), ParmList_len(Getattr(tempn,"templateparms")));
+ if (specialization_parms_len > ParmList_len(primary_templateparms)) {
+ Swig_error(Getfile($$), Getline($$), "Template partial specialization has more arguments than primary template %d %d.\n", specialization_parms_len, ParmList_len(primary_templateparms));
+ } else if (specialization_parms_len < ParmList_numrequired(primary_templateparms)) {
+ Swig_error(Getfile($$), Getline($$), "Template partial specialization has fewer arguments than primary template %d %d.\n", specialization_parms_len, ParmList_len(primary_templateparms));
} else {
-
- /* This code builds the argument list for the partial template
- specialization. This is a little hairy, but the idea is as
- follows:
-
- $3 contains a list of arguments supplied for the template.
- For example template<class T>.
-
- tlist is a list of the specialization arguments--which may be
- different. For example class<int,T>.
-
- tp is a copy of the arguments in the original template definition.
-
- The patching algorithm walks through the list of supplied
- arguments ($3), finds the position in the specialization arguments
- (tlist), and then patches the name in the argument list of the
- original template.
- */
-
- {
- String *pn;
- Parm *p, *p1;
- int i, nargs;
- Parm *tp = CopyParmList(Getattr(tempn,"templateparms"));
- nargs = Len(tlist);
- p = $3;
- while (p) {
- for (i = 0; i < nargs; i++){
- pn = Getattr(p,"name");
- if (Strcmp(pn,SwigType_base(Getitem(tlist,i))) == 0) {
- int j;
- Parm *p1 = tp;
- for (j = 0; j < i; j++) {
- p1 = nextSibling(p1);
- }
- Setattr(p1,"name",pn);
- Setattr(p1,"partialarg","1");
- }
- }
- p = nextSibling(p);
- }
- p1 = tp;
- i = 0;
- while (p1) {
- if (!Getattr(p1,"partialarg")) {
- Delattr(p1,"name");
- Setattr(p1,"type", Getitem(tlist,i));
- }
- i++;
- p1 = nextSibling(p1);
- }
- Setattr($$,"templateparms",tp);
- Delete(tp);
- }
- #if 0
- /* Patch the parameter list */
- if (tempn) {
- Parm *p,*p1;
- ParmList *tp = CopyParmList(Getattr(tempn,"templateparms"));
- p = $3;
- p1 = tp;
- while (p && p1) {
- String *pn = Getattr(p,"name");
- Printf(stdout,"pn = '%s'\n", pn);
- if (pn) Setattr(p1,"name",pn);
- else Delattr(p1,"name");
- pn = Getattr(p,"type");
- if (pn) Setattr(p1,"type",pn);
- p = nextSibling(p);
- p1 = nextSibling(p1);
- }
- Setattr($$,"templateparms",tp);
- Delete(tp);
- } else {
- Setattr($$,"templateparms",$3);
- }
- #endif
- Delattr($$,"specialization");
- Setattr($$,"partialspecialization","1");
- /* Create a specialized name for matching */
- {
+ /* Create a specialized name with template parameters replaced with $ variables, such as, X<(T1,p.T2) => X<($1,p.$2)> */
Parm *p = $3;
- String *fname = NewString(Getattr($$,"name"));
+ String *fname = NewString(tname);
String *ffname = 0;
ParmList *partialparms = 0;
char tmp[32];
- int i, ilen;
+ int i = 0;
while (p) {
- String *n = Getattr(p,"name");
- if (!n) {
+ String *name = Getattr(p,"name");
+ ++i;
+ if (!name) {
p = nextSibling(p);
continue;
}
- ilen = Len(tlist);
- for (i = 0; i < ilen; i++) {
- if (Strstr(Getitem(tlist,i),n)) {
- sprintf(tmp,"$%d",i+1);
- Replaceid(fname,n,tmp);
- }
- }
+ sprintf(tmp, "$%d", i);
+ Replaceid(fname, name, tmp);
p = nextSibling(p);
}
/* Patch argument names with typedef */
@@ -4289,6 +4312,27 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Append(ffname,")>");
}
{
+ /* Replace each primary template parameter's name and value with $ variables, such as, class Y,class T=Y => class $1,class $2=$1 */
+ ParmList *primary_templateparms_copy = CopyParmList(primary_templateparms);
+ p = primary_templateparms_copy;
+ i = 0;
+ while (p) {
+ String *name = Getattr(p, "name");
+ Parm *pp = nextSibling(p);
+ ++i;
+ sprintf(tmp, "$%d", i);
+ while (pp) {
+ Replaceid(Getattr(pp, "value"), name, tmp);
+ pp = nextSibling(pp);
+ }
+ Setattr(p, "name", NewString(tmp));
+ p = nextSibling(p);
+ }
+ /* Modify partialparms by adding in missing default values ($ variables) from primary template parameters */
+ partialparms = Swig_cparse_template_partialargs_expand(partialparms, tempn, primary_templateparms_copy);
+ Delete(primary_templateparms_copy);
+ }
+ {
Node *new_partial = NewHash();
String *partials = Getattr(tempn,"partials");
if (!partials) {
@@ -4304,7 +4348,6 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Setattr($$,"partialargs",ffname);
Swig_symbol_cadd(ffname,$$);
}
- }
Delete(tlist);
Delete(targs);
} else {
@@ -4316,8 +4359,8 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Delete(ty);
Delete(fname);
}
- } else if ($$) {
- Setattr($$,"templatetype",nodeType($6));
+ } else if ($$) {
+ Setattr($$, "templatetype", nodeType($$));
set_nodeType($$,"template");
Setattr($$,"templateparms", $3);
if (!Getattr($$,"sym:weak")) {
@@ -4355,87 +4398,90 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
parsing_template_declaration = 0;
}
- /* Explicit template instantiation */
+ /* Class template explicit instantiation definition */
| TEMPLATE cpptype idcolon {
Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
$$ = 0;
}
- /* Explicit template instantiation without the translation unit */
+ /* Function template explicit instantiation definition */
+ | TEMPLATE cpp_alternate_rettype idcolon LPAREN parms RPAREN {
+ Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
+ $$ = 0;
+ }
+
+ /* Class template explicit instantiation declaration (extern template) */
| EXTERN TEMPLATE cpptype idcolon {
- Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
+ Swig_warning(WARN_PARSE_EXTERN_TEMPLATE, cparse_file, cparse_line, "Extern template ignored.\n");
$$ = 0;
}
- ;
-cpp_template_possible: c_decl {
- $$ = $1;
- }
- | cpp_class_decl {
- $$ = $1;
- }
- | cpp_constructor_decl {
- $$ = $1;
- }
+ /* Function template explicit instantiation declaration (extern template) */
+ | EXTERN TEMPLATE cpp_alternate_rettype idcolon LPAREN parms RPAREN {
+ Swig_warning(WARN_PARSE_EXTERN_TEMPLATE, cparse_file, cparse_line, "Extern template ignored.\n");
+ $$ = 0;
+ }
+ ;
+
+cpp_template_possible: c_decl
+ | cpp_class_decl
+ | cpp_constructor_decl
| cpp_template_decl {
$$ = 0;
}
- | cpp_forward_class_decl {
- $$ = $1;
- }
- | cpp_conversion_operator {
- $$ = $1;
- }
+ | cpp_forward_class_decl
+ | cpp_conversion_operator
;
-template_parms : templateparameters {
- /* Rip out the parameter names */
- Parm *p = $1;
- $$ = $1;
-
- while (p) {
- String *name = Getattr(p,"name");
- if (!name) {
- /* Hmmm. Maybe it's a 'class T' parameter */
- char *type = Char(Getattr(p,"type"));
- /* Template template parameter */
- if (strncmp(type,"template<class> ",16) == 0) {
- type += 16;
- }
- if ((strncmp(type,"class ",6) == 0) || (strncmp(type,"typename ", 9) == 0)) {
- char *t = strchr(type,' ');
- Setattr(p,"name", t+1);
- } else
- /* Variadic template args */
- if ((strncmp(type,"class... ",9) == 0) || (strncmp(type,"typename... ", 12) == 0)) {
- char *t = strchr(type,' ');
- Setattr(p,"name", t+1);
- Setattr(p,"variadic", "1");
- } else {
- /*
- Swig_error(cparse_file, cparse_line, "Missing template parameter name\n");
- $$.rparms = 0;
- $$.parms = 0;
- break; */
- }
- }
- p = nextSibling(p);
- }
- }
- ;
-
-templateparameters : templateparameter templateparameterstail {
+template_parms : templateparameter templateparameterstail {
set_nextSibling($1,$2);
$$ = $1;
}
- | empty { $$ = 0; }
+ | %empty { $$ = 0; }
;
-templateparameter : templcpptype {
- $$ = NewParmWithoutFileLineInfo(NewString($1), 0);
- }
- | parm {
- $$ = $1;
+templateparameter : templcpptype def_args {
+ $$ = NewParmWithoutFileLineInfo($1, 0);
+ Setfile($$, cparse_file);
+ Setline($$, cparse_line);
+ Setattr($$, "value", $2.rawval ? $2.rawval : $2.val);
+ }
+ | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon def_args {
+ $$ = NewParmWithoutFileLineInfo(NewStringf("template< %s > %s %s", ParmList_str_defaultargs($3), $5, $6), $6);
+ Setfile($$, cparse_file);
+ Setline($$, cparse_line);
+ if ($7.val) {
+ Setattr($$, "value", $7.val);
+ }
+ }
+ | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype def_args {
+ $$ = NewParmWithoutFileLineInfo(NewStringf("template< %s > %s", ParmList_str_defaultargs($3), $5), 0);
+ Setfile($$, cparse_file);
+ Setline($$, cparse_line);
+ if ($6.val) {
+ Setattr($$, "value", $6.val);
+ }
+ }
+ | parm {
+ Parm *p = $1;
+ String *name = Getattr(p, "name");
+ $$ = $1;
+
+ /* Correct the 'type name' parameter string, split into the appropriate "name" and "type" attributes */
+ if (!name) {
+ String *type = Getattr(p, "type");
+ if ((Strncmp(type, "class ", 6) == 0) || (Strncmp(type, "typename ", 9) == 0)) {
+ /* A 'class T' parameter */
+ const char *t = Strchr(type, ' ');
+ Setattr(p, "name", t + 1);
+ Setattr(p, "type", NewStringWithSize(type, (int)(t - Char(type))));
+ } else if ((Strncmp(type, "v.class ", 8) == 0) || (Strncmp(type, "v.typename ", 11) == 0)) {
+ /* Variadic template args */
+ const char *t = Strchr(type, ' ');
+ Setattr(p, "name", t + 1);
+ Setattr(p, "type", NewStringWithSize(type, (int)(t - Char(type))));
+ }
+ }
}
;
@@ -4443,13 +4489,14 @@ templateparameterstail : COMMA templateparameter templateparameterstail {
set_nextSibling($2,$3);
$$ = $2;
}
- | empty { $$ = 0; }
+ | %empty { $$ = 0; }
;
/* Namespace support */
cpp_using_decl : USING idcolon SEMI {
String *uname = Swig_symbol_type_qualify($2,0);
+ /* Possible TODO: In testcase using_member_multiple_inherit class Susing3, uname is "Susing1::usingmethod" instead of "Susing2::usingmethod" */
String *name = Swig_scopename_last($2);
$$ = new_node("using");
Setattr($$,"uname",uname);
@@ -4458,10 +4505,20 @@ cpp_using_decl : USING idcolon SEMI {
Delete(name);
add_symbols($$);
}
+ | USING TYPENAME idcolon SEMI {
+ String *uname = Swig_symbol_type_qualify($3,0);
+ String *name = Swig_scopename_last($3);
+ $$ = new_node("using");
+ Setattr($$,"uname",uname);
+ Setattr($$,"name", name);
+ Delete(uname);
+ Delete(name);
+ add_symbols($$);
+ }
| USING NAMESPACE idcolon SEMI {
Node *n = Swig_symbol_clookup($3,0);
if (!n) {
- Swig_error(cparse_file, cparse_line, "Nothing known about namespace '%s'\n", $3);
+ Swig_error(cparse_file, cparse_line, "Nothing known about namespace '%s'\n", SwigType_namestr($3));
$$ = 0;
} else {
@@ -4479,7 +4536,7 @@ cpp_using_decl : USING idcolon SEMI {
Swig_symbol_inherit(symtab);
}
} else {
- Swig_error(cparse_file, cparse_line, "'%s' is not a namespace.\n", $3);
+ Swig_error(cparse_file, cparse_line, "'%s' is not a namespace.\n", SwigType_namestr($3));
$$ = 0;
}
} else {
@@ -4489,7 +4546,7 @@ cpp_using_decl : USING idcolon SEMI {
}
;
-cpp_namespace_decl : NAMESPACE idcolon LBRACE {
+cpp_namespace_decl : NAMESPACE idcolon LBRACE <node>{
Hash *h;
Node *parent_ns = 0;
List *scopes = Swig_scopename_tolist($2);
@@ -4499,13 +4556,13 @@ cpp_namespace_decl : NAMESPACE idcolon LBRACE {
/*
Printf(stdout, "==== Namespace %s creation...\n", $2);
*/
- $<node>$ = 0;
+ $$ = 0;
for (i = 0; i < ilen; i++) {
Node *ns = new_node("namespace");
Symtab *current_symtab = Swig_symbol_current();
String *scopename = Getitem(scopes, i);
Setattr(ns, "name", scopename);
- $<node>$ = ns;
+ $$ = ns;
if (parent_ns)
appendChild(parent_ns, ns);
parent_ns = ns;
@@ -4533,7 +4590,7 @@ Printf(stdout, " Scope %s [creating single scope C++17 style]\n", scopename);
}
Delete(scopes);
} interface RBRACE {
- Node *n = $<node>4;
+ Node *n = $4;
Node *top_ns = 0;
do {
Setattr(n, "symtab", Swig_symbol_popscope());
@@ -4543,13 +4600,13 @@ Printf(stdout, " Scope %s [creating single scope C++17 style]\n", scopename);
top_ns = n;
n = parentNode(n);
} while(n);
- appendChild($<node>4, firstChild($5));
+ appendChild($4, firstChild($5));
Delete($5);
$$ = top_ns;
}
- | NAMESPACE LBRACE {
+ | NAMESPACE LBRACE <node>{
Hash *h;
- $1 = Swig_symbol_current();
+ $$ = Swig_symbol_current();
h = Swig_symbol_clookup(" ",0);
if (h && (Strcmp(nodeType(h),"namespace") == 0)) {
Swig_symbol_setscope(Getattr(h,"symtab"));
@@ -4564,7 +4621,7 @@ Printf(stdout, " Scope %s [creating single scope C++17 style]\n", scopename);
set_nodeType($$,"namespace");
Setattr($$,"unnamed","1");
Setattr($$,"symtab", Swig_symbol_popscope());
- Swig_symbol_setscope($1);
+ Swig_symbol_setscope($3);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
add_symbols($$);
@@ -4577,11 +4634,11 @@ Printf(stdout, " Scope %s [creating single scope C++17 style]\n", scopename);
Setattr($$,"alias",$4);
n = Swig_symbol_clookup($4,0);
if (!n) {
- Swig_error(cparse_file, cparse_line, "Unknown namespace '%s'\n", $4);
+ Swig_error(cparse_file, cparse_line, "Unknown namespace '%s'\n", SwigType_namestr($4));
$$ = 0;
} else {
if (Strcmp(nodeType(n),"namespace") != 0) {
- Swig_error(cparse_file, cparse_line, "'%s' is not a namespace\n",$4);
+ Swig_error(cparse_file, cparse_line, "'%s' is not a namespace\n", SwigType_namestr($4));
$$ = 0;
} else {
while (Getattr(n,"alias")) {
@@ -4612,7 +4669,8 @@ cpp_members : cpp_member cpp_members {
} else {
$$ = $2;
}
- }
+ }
+ | cpp_member DOXYGENSTRING /* Misplaced doxygen string after a member, quietly ignore, like Doxygen does */
| EXTEND LBRACE {
extendmode = 1;
if (cplus_mode != CPLUS_PUBLIC) {
@@ -4626,16 +4684,12 @@ cpp_members : cpp_member cpp_members {
appendChild($$,$4);
set_nextSibling($$,$7);
}
- | include_directive { $$ = $1; }
- | empty { $$ = 0;}
+ | include_directive
+ | %empty { $$ = 0;}
| error {
- int start_line = cparse_line;
- skip_decl();
- Swig_error(cparse_file,start_line,"Syntax error in input(3).\n");
- SWIG_exit(EXIT_FAILURE);
- } cpp_members {
- $$ = $3;
- }
+ Swig_error(cparse_file,cparse_line,"Syntax error in input(3).\n");
+ Exit(EXIT_FAILURE);
+ }
;
/* ======================================================================
@@ -4644,7 +4698,7 @@ cpp_members : cpp_member cpp_members {
/* A class member. May be data or a function. Static or virtual as well */
-cpp_member_no_dox : c_declaration { $$ = $1; }
+cpp_member_no_dox : c_declaration
| cpp_constructor_decl {
$$ = $1;
if (extendmode && current_class) {
@@ -4662,26 +4716,24 @@ cpp_member_no_dox : c_declaration { $$ = $1; }
add_symbols($$);
default_arguments($$);
}
- | cpp_destructor_decl { $$ = $1; }
- | cpp_protection_decl { $$ = $1; }
- | cpp_swig_directive { $$ = $1; }
- | cpp_conversion_operator { $$ = $1; }
- | cpp_forward_class_decl { $$ = $1; }
- | cpp_class_decl { $$ = $1; }
- | storage_class idcolon SEMI { $$ = 0; }
- | cpp_using_decl { $$ = $1; }
- | cpp_template_decl { $$ = $1; }
- | cpp_catch_decl { $$ = 0; }
- | template_directive { $$ = $1; }
- | warn_directive { $$ = $1; }
+ | cpp_destructor_decl
+ | cpp_protection_decl
+ | cpp_swig_directive
+ | cpp_conversion_operator
+ | cpp_forward_class_decl
+ | cpp_class_decl
+ | storage_class idcolon SEMI { $$ = 0; Delete($1); }
+ | cpp_using_decl
+ | cpp_template_decl
+ | cpp_catch_decl
+ | template_directive
+ | warn_directive
| anonymous_bitfield { $$ = 0; }
- | fragment_directive {$$ = $1; }
- | types_directive {$$ = $1; }
+ | fragment_directive
+ | types_directive
| SEMI { $$ = 0; }
-cpp_member : cpp_member_no_dox {
- $$ = $1;
- }
+cpp_member : cpp_member_no_dox
| DOXYGENSTRING cpp_member_no_dox {
$$ = $2;
set_comment($2, $1);
@@ -4699,11 +4751,15 @@ cpp_member : cpp_member_no_dox {
*/
cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
- if (inclass || extendmode) {
+ /* Cannot be a constructor declaration/definition if parsed as a friend destructor/constructor
+ or a badly declared friend function without return type */
+ int isfriend = Strstr($1, "friend") != NULL;
+ if (!isfriend && (inclass || extendmode)) {
+ String *name = SwigType_templateprefix($2); /* A constructor can optionally be declared with template parameters before C++20, strip these off */
SwigType *decl = NewStringEmpty();
$$ = new_node("constructor");
Setattr($$,"storage",$1);
- Setattr($$,"name",$2);
+ Setattr($$, "name", name);
Setattr($$,"parms",$4);
SwigType_add_function(decl,$4);
Setattr($$,"decl",decl);
@@ -4721,71 +4777,49 @@ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
Setattr($$,"value",$6.defarg);
} else {
$$ = 0;
+ Delete($1);
}
}
;
-/* A destructor (hopefully) */
+/* A destructor */
-cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
- String *name = NewStringf("%s",$2);
- if (*(Char(name)) != '~') Insert(name,0,"~");
- $$ = new_node("destructor");
- Setattr($$,"name",name);
+cpp_destructor_decl : storage_class NOT idtemplate LPAREN parms RPAREN cpp_vend {
+ String *name = SwigType_templateprefix($3); /* A destructor can optionally be declared with template parameters before C++20, strip these off */
+ Insert(name, 0, "~");
+ $$ = new_node("destructor");
+ Setattr($$, "storage", $1);
+ Setattr($$, "name", name);
Delete(name);
if (Len(scanner_ccode)) {
String *code = Copy(scanner_ccode);
- Setattr($$,"code",code);
+ Setattr($$, "code", code);
Delete(code);
}
{
String *decl = NewStringEmpty();
- SwigType_add_function(decl,$4);
- Setattr($$,"decl",decl);
+ SwigType_add_function(decl, $5);
+ Setattr($$, "decl", decl);
Delete(decl);
}
- Setattr($$,"throws",$6.throws);
- Setattr($$,"throw",$6.throwf);
- Setattr($$,"noexcept",$6.nexcept);
- Setattr($$,"final",$6.final);
- if ($6.val)
- Setattr($$,"value",$6.val);
- if ($6.qualifier)
- Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($6.qualifier, 0));
+ Setattr($$, "throws", $7.throws);
+ Setattr($$, "throw", $7.throwf);
+ Setattr($$, "noexcept", $7.nexcept);
+ Setattr($$, "final", $7.final);
+ if ($7.val) {
+ if (Equal($7.val, "0")) {
+ if (!Strstr($1, "virtual"))
+ Swig_error(cparse_file, cparse_line, "Destructor %s uses a pure specifier but is not virtual.\n", Swig_name_decl($$));
+ } else if (!(Equal($7.val, "delete") || Equal($7.val, "default"))) {
+ Swig_error(cparse_file, cparse_line, "Destructor %s has an invalid pure specifier, only = 0 is allowed.\n", Swig_name_decl($$));
+ }
+ Setattr($$, "value", $7.val);
+ }
+ /* TODO: check all storage decl-specifiers are valid */
+ if ($7.qualifier)
+ Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($7.qualifier, 0));
add_symbols($$);
}
-
-/* A virtual destructor */
-
- | VIRTUAL NOT idtemplate LPAREN parms RPAREN cpp_vend {
- String *name;
- $$ = new_node("destructor");
- Setattr($$,"storage","virtual");
- name = NewStringf("%s",$3);
- if (*(Char(name)) != '~') Insert(name,0,"~");
- Setattr($$,"name",name);
- Delete(name);
- Setattr($$,"throws",$7.throws);
- Setattr($$,"throw",$7.throwf);
- Setattr($$,"noexcept",$7.nexcept);
- Setattr($$,"final",$7.final);
- if ($7.val)
- Setattr($$,"value",$7.val);
- if (Len(scanner_ccode)) {
- String *code = Copy(scanner_ccode);
- Setattr($$,"code",code);
- Delete(code);
- }
- {
- String *decl = NewStringEmpty();
- SwigType_add_function(decl,$5);
- Setattr($$,"decl",decl);
- Delete(decl);
- }
- if ($7.qualifier)
- Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($7.qualifier, 0));
- add_symbols($$);
- }
;
@@ -4800,6 +4834,9 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
if ($8.qualifier) {
SwigType_push($4,$8.qualifier);
}
+ if ($8.val) {
+ Setattr($$,"value",$8.val);
+ }
Setattr($$,"refqualifier",$8.refqualifier);
Setattr($$,"decl",$4);
Setattr($$,"parms",$6);
@@ -4818,6 +4855,9 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
if ($8.qualifier) {
SwigType_push(decl,$8.qualifier);
}
+ if ($8.val) {
+ Setattr($$,"value",$8.val);
+ }
Setattr($$,"refqualifier",$8.refqualifier);
Setattr($$,"decl",decl);
Setattr($$,"parms",$6);
@@ -4836,6 +4876,9 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
if ($8.qualifier) {
SwigType_push(decl,$8.qualifier);
}
+ if ($8.val) {
+ Setattr($$,"value",$8.val);
+ }
Setattr($$,"refqualifier",$8.refqualifier);
Setattr($$,"decl",decl);
Setattr($$,"parms",$6);
@@ -4856,6 +4899,9 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
if ($9.qualifier) {
SwigType_push(decl,$9.qualifier);
}
+ if ($9.val) {
+ Setattr($$,"value",$9.val);
+ }
Setattr($$,"refqualifier",$9.refqualifier);
Setattr($$,"decl",decl);
Setattr($$,"parms",$7);
@@ -4873,7 +4919,10 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
if ($7.qualifier) {
SwigType_push(t,$7.qualifier);
}
- Setattr($$,"refqualifier",$7.refqualifier);
+ if ($7.val) {
+ Setattr($$,"value",$7.val);
+ }
+ Setattr($$,"refqualifier",$7.refqualifier);
Setattr($$,"decl",t);
Setattr($$,"parms",$5);
Setattr($$,"conversion_operator","1");
@@ -4884,7 +4933,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
/* isolated catch clause. */
cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$ = 0;
}
;
@@ -4892,7 +4941,7 @@ cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE {
/* static_assert(bool, const char*); (C++11)
* static_assert(bool); (C++17) */
cpp_static_assert : STATIC_ASSERT LPAREN {
- skip_balanced('(',')');
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
$$ = 0;
}
;
@@ -4921,61 +4970,21 @@ cpp_protection_decl : PUBLIC COLON {
;
/* These directives can be included inside a class definition */
-cpp_swig_directive: pragma_directive { $$ = $1; }
+cpp_swig_directive: pragma_directive
/* A constant (includes #defines) inside a class */
- | constant_directive { $$ = $1; }
-
-/* This is the new style rename */
-
- | name_directive { $$ = $1; }
-
-/* rename directive */
- | rename_directive { $$ = $1; }
- | feature_directive { $$ = $1; }
- | varargs_directive { $$ = $1; }
- | insert_directive { $$ = $1; }
- | typemap_directive { $$ = $1; }
- | apply_directive { $$ = $1; }
- | clear_directive { $$ = $1; }
- | echo_directive { $$ = $1; }
+ | constant_directive
+
+ | rename_directive
+ | feature_directive
+ | varargs_directive
+ | insert_directive
+ | typemap_directive
+ | apply_directive
+ | clear_directive
+ | echo_directive
;
-cpp_end : cpp_const SEMI {
- Clear(scanner_ccode);
- $$.val = 0;
- $$.qualifier = $1.qualifier;
- $$.refqualifier = $1.refqualifier;
- $$.bitfield = 0;
- $$.throws = $1.throws;
- $$.throwf = $1.throwf;
- $$.nexcept = $1.nexcept;
- $$.final = $1.final;
- }
- | cpp_const EQUAL default_delete SEMI {
- Clear(scanner_ccode);
- $$.val = $3.val;
- $$.qualifier = $1.qualifier;
- $$.refqualifier = $1.refqualifier;
- $$.bitfield = 0;
- $$.throws = $1.throws;
- $$.throwf = $1.throwf;
- $$.nexcept = $1.nexcept;
- $$.final = $1.final;
- }
- | cpp_const LBRACE {
- skip_balanced('{','}');
- $$.val = 0;
- $$.qualifier = $1.qualifier;
- $$.refqualifier = $1.refqualifier;
- $$.bitfield = 0;
- $$.throws = $1.throws;
- $$.throwf = $1.throwf;
- $$.nexcept = $1.nexcept;
- $$.final = $1.final;
- }
- ;
-
cpp_vend : cpp_const SEMI {
Clear(scanner_ccode);
$$.val = 0;
@@ -4999,7 +5008,7 @@ cpp_vend : cpp_const SEMI {
$$.final = $1.final;
}
| cpp_const LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$.val = 0;
$$.qualifier = $1.qualifier;
$$.refqualifier = $1.refqualifier;
@@ -5012,61 +5021,94 @@ cpp_vend : cpp_const SEMI {
;
-anonymous_bitfield : storage_class anon_bitfield_type COLON expr SEMI { };
+anonymous_bitfield : storage_class anon_bitfield_type COLON expr SEMI { Delete($1); };
/* Equals type_right without the ENUM keyword and cpptype (templates etc.): */
-anon_bitfield_type : primitive_type { $$ = $1;
- /* Printf(stdout,"primitive = '%s'\n", $$);*/
- }
- | TYPE_BOOL { $$ = $1; }
- | TYPE_VOID { $$ = $1; }
-/*
- | TYPE_TYPEDEF template_decl { $$ = NewStringf("%s%s",$1,$2); }
-*/
- | TYPE_RAW { $$ = $1; }
+anon_bitfield_type : primitive_type
+ | TYPE_BOOL
+ | TYPE_VOID
+ | TYPE_RAW
- | idcolon {
- $$ = $1;
- }
+ | idcolon { $$ = $1; }
;
/* ======================================================================
* PRIMITIVES
* ====================================================================== */
-extern_string : EXTERN string {
- if (Strcmp($2,"C") == 0) {
- $$ = "externc";
- } else if (Strcmp($2,"C++") == 0) {
- $$ = "extern";
+storage_class : storage_class_list {
+ String *r = NewStringEmpty();
+
+ /* Check for invalid combinations. */
+ if (multiple_bits_set($1 & (SWIG_STORAGE_CLASS_EXTERN |
+ SWIG_STORAGE_CLASS_STATIC))) {
+ Swig_error(cparse_file, cparse_line, "Storage class can't be both 'static' and 'extern'");
+ }
+ if (multiple_bits_set($1 & (SWIG_STORAGE_CLASS_EXTERNC |
+ SWIG_STORAGE_CLASS_EXTERN |
+ SWIG_STORAGE_CLASS_EXTERNCPP))) {
+ Swig_error(cparse_file, cparse_line, "Declaration can only be one of 'extern', 'extern \"C\"' and 'extern \"C++\"'");
+ }
+
+ if ($1 & SWIG_STORAGE_CLASS_TYPEDEF) {
+ Append(r, "typedef ");
+ } else {
+ if ($1 & SWIG_STORAGE_CLASS_EXTERNC)
+ Append(r, "externc ");
+ if ($1 & (SWIG_STORAGE_CLASS_EXTERN|SWIG_STORAGE_CLASS_EXTERNCPP))
+ Append(r, "extern ");
+ if ($1 & SWIG_STORAGE_CLASS_STATIC)
+ Append(r, "static ");
+ }
+ if ($1 & SWIG_STORAGE_CLASS_VIRTUAL)
+ Append(r, "virtual ");
+ if ($1 & SWIG_STORAGE_CLASS_FRIEND)
+ Append(r, "friend ");
+ if ($1 & SWIG_STORAGE_CLASS_EXPLICIT)
+ Append(r, "explicit ");
+ if ($1 & SWIG_STORAGE_CLASS_CONSTEXPR)
+ Append(r, "constexpr ");
+ if ($1 & SWIG_STORAGE_CLASS_THREAD_LOCAL)
+ Append(r, "thread_local ");
+ if (Len(r) == 0) {
+ Delete(r);
+ $$ = 0;
+ } else {
+ Chop(r);
+ $$ = r;
+ }
+ }
+ | %empty { $$ = 0; }
+ ;
+
+storage_class_list: storage_class_raw
+ | storage_class_list storage_class_raw {
+ if ($1 & $2) {
+ Swig_error(cparse_file, cparse_line, "Repeated storage class or type specifier '%s'\n", storage_class_string($2));
+ }
+ $$ = $1 | $2;
+ }
+ ;
+
+storage_class_raw : EXTERN { $$ = SWIG_STORAGE_CLASS_EXTERN; }
+ | EXTERN string {
+ if (Strcmp($2,"C") == 0) {
+ $$ = SWIG_STORAGE_CLASS_EXTERNC;
+ } else if (Strcmp($2,"C++") == 0) {
+ $$ = SWIG_STORAGE_CLASS_EXTERNCPP;
} else {
Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $2);
$$ = 0;
}
- }
+ }
+ | STATIC { $$ = SWIG_STORAGE_CLASS_STATIC; }
+ | TYPEDEF { $$ = SWIG_STORAGE_CLASS_TYPEDEF; }
+ | VIRTUAL { $$ = SWIG_STORAGE_CLASS_VIRTUAL; }
+ | FRIEND { $$ = SWIG_STORAGE_CLASS_FRIEND; }
+ | EXPLICIT { $$ = SWIG_STORAGE_CLASS_EXPLICIT; }
+ | CONSTEXPR { $$ = SWIG_STORAGE_CLASS_CONSTEXPR; }
+ | THREAD_LOCAL { $$ = SWIG_STORAGE_CLASS_THREAD_LOCAL; }
;
-storage_class : EXTERN { $$ = "extern"; }
- | extern_string { $$ = $1; }
- | extern_string THREAD_LOCAL { $$ = "thread_local"; }
- | extern_string TYPEDEF { $$ = "typedef"; }
- | STATIC { $$ = "static"; }
- | TYPEDEF { $$ = "typedef"; }
- | VIRTUAL { $$ = "virtual"; }
- | FRIEND { $$ = "friend"; }
- | EXPLICIT { $$ = "explicit"; }
- | CONSTEXPR { $$ = "constexpr"; }
- | EXPLICIT CONSTEXPR { $$ = "explicit constexpr"; }
- | CONSTEXPR EXPLICIT { $$ = "explicit constexpr"; }
- | STATIC CONSTEXPR { $$ = "static constexpr"; }
- | CONSTEXPR STATIC { $$ = "static constexpr"; }
- | THREAD_LOCAL { $$ = "thread_local"; }
- | THREAD_LOCAL STATIC { $$ = "static thread_local"; }
- | STATIC THREAD_LOCAL { $$ = "static thread_local"; }
- | EXTERN THREAD_LOCAL { $$ = "extern thread_local"; }
- | THREAD_LOCAL EXTERN { $$ = "extern thread_local"; }
- | empty { $$ = 0; }
- ;
-
/* ------------------------------------------------------------------------------
Function parameter lists
------------------------------------------------------------------------------ */
@@ -5082,73 +5124,64 @@ parms : rawparms {
}
;
-rawparms : parm ptail {
- set_nextSibling($1,$2);
- $$ = $1;
+/* rawparms constructs parameter lists and deal with quirks of doxygen post strings (after the parameter's comma */
+rawparms : parm { $$ = $1; }
+ | parm DOXYGENPOSTSTRING {
+ set_comment($1, $2);
+ $$ = $1;
+ }
+ | parm DOXYGENSTRING {
+ /* Misplaced doxygen string, attach it to previous parameter, like Doxygen does */
+ set_comment($1, $2);
+ $$ = $1;
}
- | empty {
+ | parm COMMA parms {
+ if ($3) {
+ set_nextSibling($1, $3);
+ }
+ $$ = $1;
+ }
+ | parm DOXYGENPOSTSTRING COMMA parms {
+ if ($4) {
+ set_nextSibling($1, $4);
+ }
+ set_comment($1, $2);
+ $$ = $1;
+ }
+ | parm COMMA DOXYGENPOSTSTRING parms {
+ if ($4) {
+ set_nextSibling($1, $4);
+ }
+ set_comment($1, $3);
+ $$ = $1;
+ }
+ | %empty {
$$ = 0;
- previousNode = currentNode;
- currentNode=0;
- }
- ;
-
-ptail : COMMA parm ptail {
- set_nextSibling($2,$3);
- $$ = $2;
- }
- | COMMA DOXYGENPOSTSTRING parm ptail {
- set_comment(previousNode, $2);
- set_nextSibling($3, $4);
- $$ = $3;
- }
- | empty { $$ = 0; }
- ;
-
+ }
+ ;
parm_no_dox : rawtype parameter_declarator {
SwigType_push($1,$2.type);
$$ = NewParmWithoutFileLineInfo($1,$2.id);
- previousNode = currentNode;
- currentNode = $$;
Setfile($$,cparse_file);
Setline($$,cparse_line);
if ($2.defarg) {
Setattr($$,"value",$2.defarg);
}
}
-
- | TEMPLATE LESSTHAN cpptype GREATERTHAN cpptype idcolon def_args {
- $$ = NewParmWithoutFileLineInfo(NewStringf("template<class> %s %s", $5,$6), 0);
- previousNode = currentNode;
- currentNode = $$;
- Setfile($$,cparse_file);
- Setline($$,cparse_line);
- if ($7.val) {
- Setattr($$,"value",$7.val);
- }
- }
- | PERIOD PERIOD PERIOD {
+ | ELLIPSIS {
SwigType *t = NewString("v(...)");
$$ = NewParmWithoutFileLineInfo(t, 0);
- previousNode = currentNode;
- currentNode = $$;
Setfile($$,cparse_file);
Setline($$,cparse_line);
}
;
-parm : parm_no_dox {
- $$ = $1;
- }
+parm : parm_no_dox
| DOXYGENSTRING parm_no_dox {
$$ = $2;
set_comment($2, $1);
}
- | parm_no_dox DOXYGENPOSTSTRING {
- $$ = $1;
- set_comment($1, $2);
- }
;
valparms : rawvalparms {
@@ -5168,14 +5201,14 @@ rawvalparms : valparm valptail {
set_nextSibling($1,$2);
$$ = $1;
}
- | empty { $$ = 0; }
+ | %empty { $$ = 0; }
;
valptail : COMMA valparm valptail {
set_nextSibling($2,$3);
$$ = $2;
}
- | empty { $$ = 0; }
+ | %empty { $$ = 0; }
;
@@ -5215,40 +5248,33 @@ valparm : parm {
}
;
+callparms : valexpr callptail {
+ $$ = $1;
+ Printf($$.val, "%s", $2.val);
+ }
+ | %empty { $$.val = NewStringEmpty(); }
+ ;
+
+callptail : COMMA valexpr callptail {
+ $$.val = NewStringf(",%s%s", $2.val, $3.val);
+ $$.type = 0;
+ }
+ | %empty { $$.val = NewStringEmpty(); }
+ ;
+
def_args : EQUAL definetype {
- $$ = $2;
- if ($2.type == T_ERROR) {
- Swig_warning(WARN_PARSE_BAD_DEFAULT,cparse_file, cparse_line, "Can't set default argument (ignored)\n");
- $$.val = 0;
- $$.rawval = 0;
- $$.bitfield = 0;
- $$.throws = 0;
- $$.throwf = 0;
- $$.nexcept = 0;
- $$.final = 0;
- }
+ $$ = $2;
}
| EQUAL definetype LBRACKET expr RBRACKET {
- $$ = $2;
- if ($2.type == T_ERROR) {
- Swig_warning(WARN_PARSE_BAD_DEFAULT,cparse_file, cparse_line, "Can't set default argument (ignored)\n");
- $$ = $2;
- $$.val = 0;
- $$.rawval = 0;
- $$.bitfield = 0;
- $$.throws = 0;
- $$.throwf = 0;
- $$.nexcept = 0;
- $$.final = 0;
- } else {
- $$.val = NewStringf("%s[%s]",$2.val,$4.val);
- }
+ $$ = $2;
+ $$.val = NewStringf("%s[%s]", $2.val, $4.val);
}
| EQUAL LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$.val = NewString(scanner_ccode);
$$.rawval = 0;
- $$.type = T_INT;
+ $$.type = T_UNKNOWN;
+ $$.unary_arg_type = 0;
$$.bitfield = 0;
$$.throws = 0;
$$.throwf = 0;
@@ -5265,10 +5291,11 @@ def_args : EQUAL definetype {
$$.nexcept = 0;
$$.final = 0;
}
- | empty {
+ | %empty {
$$.val = 0;
$$.rawval = 0;
- $$.type = T_INT;
+ $$.type = T_UNKNOWN;
+ $$.unary_arg_type = 0;
$$.bitfield = 0;
$$.throws = 0;
$$.throwf = 0;
@@ -5369,7 +5396,7 @@ plain_declarator : declarator {
$$.type = t;
}
}
- | empty {
+ | %empty {
$$.type = 0;
$$.id = 0;
$$.parms = 0;
@@ -5473,71 +5500,74 @@ declarator : pointer notso_direct_declarator {
/* Variadic versions eg. MyClasses&... myIds */
- | pointer PERIOD PERIOD PERIOD notso_direct_declarator {
- $$ = $5;
+ | pointer ELLIPSIS notso_direct_declarator {
+ $$ = $3;
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
+ SwigType_add_variadic($$.type);
}
- | pointer AND PERIOD PERIOD PERIOD notso_direct_declarator {
- $$ = $6;
+ | pointer AND ELLIPSIS notso_direct_declarator {
+ $$ = $4;
SwigType_add_reference($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
+ SwigType_add_variadic($$.type);
}
- | pointer LAND PERIOD PERIOD PERIOD notso_direct_declarator {
- $$ = $6;
+ | pointer LAND ELLIPSIS notso_direct_declarator {
+ $$ = $4;
SwigType_add_rvalue_reference($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
+ SwigType_add_variadic($$.type);
}
- | PERIOD PERIOD PERIOD direct_declarator {
- $$ = $4;
- if (!$$.type) $$.type = NewStringEmpty();
- }
- | AND PERIOD PERIOD PERIOD notso_direct_declarator {
- $$ = $5;
+ | AND ELLIPSIS notso_direct_declarator {
+ $$ = $3;
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
- if ($5.type) {
- SwigType_push($$.type,$5.type);
- Delete($5.type);
+ SwigType_add_variadic($$.type);
+ if ($3.type) {
+ SwigType_push($$.type,$3.type);
+ Delete($3.type);
}
}
- | LAND PERIOD PERIOD PERIOD notso_direct_declarator {
+ | LAND ELLIPSIS notso_direct_declarator {
/* Introduced in C++11, move operator && */
/* Adds one S/R conflict */
- $$ = $5;
+ $$ = $3;
$$.type = NewStringEmpty();
SwigType_add_rvalue_reference($$.type);
- if ($5.type) {
- SwigType_push($$.type,$5.type);
- Delete($5.type);
+ SwigType_add_variadic($$.type);
+ if ($3.type) {
+ SwigType_push($$.type,$3.type);
+ Delete($3.type);
}
}
- | idcolon DSTAR PERIOD PERIOD PERIOD notso_direct_declarator {
+ | idcolon DSTAR ELLIPSIS notso_direct_declarator {
SwigType *t = NewStringEmpty();
- $$ = $6;
+ $$ = $4;
SwigType_add_memberpointer(t,$1);
+ SwigType_add_variadic(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
}
$$.type = t;
}
- | pointer idcolon DSTAR PERIOD PERIOD PERIOD notso_direct_declarator {
+ | pointer idcolon DSTAR ELLIPSIS notso_direct_declarator {
SwigType *t = NewStringEmpty();
- $$ = $7;
+ $$ = $5;
SwigType_add_memberpointer(t,$2);
+ SwigType_add_variadic(t);
SwigType_push($1,t);
if ($$.type) {
SwigType_push($1,$$.type);
@@ -5546,42 +5576,46 @@ declarator : pointer notso_direct_declarator {
$$.type = $1;
Delete(t);
}
- | pointer idcolon DSTAR AND PERIOD PERIOD PERIOD notso_direct_declarator {
- $$ = $8;
+ | pointer idcolon DSTAR AND ELLIPSIS notso_direct_declarator {
+ $$ = $6;
SwigType_add_memberpointer($1,$2);
SwigType_add_reference($1);
+ SwigType_add_variadic($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
}
- | pointer idcolon DSTAR LAND PERIOD PERIOD PERIOD notso_direct_declarator {
- $$ = $8;
+ | pointer idcolon DSTAR LAND ELLIPSIS notso_direct_declarator {
+ $$ = $6;
SwigType_add_memberpointer($1,$2);
SwigType_add_rvalue_reference($1);
+ SwigType_add_variadic($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
}
- | idcolon DSTAR AND PERIOD PERIOD PERIOD notso_direct_declarator {
+ | idcolon DSTAR AND ELLIPSIS notso_direct_declarator {
SwigType *t = NewStringEmpty();
- $$ = $7;
+ $$ = $5;
SwigType_add_memberpointer(t,$1);
SwigType_add_reference(t);
+ SwigType_add_variadic(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
}
$$.type = t;
}
- | idcolon DSTAR LAND PERIOD PERIOD PERIOD notso_direct_declarator {
+ | idcolon DSTAR LAND ELLIPSIS notso_direct_declarator {
SwigType *t = NewStringEmpty();
- $$ = $7;
+ $$ = $5;
SwigType_add_memberpointer(t,$1);
SwigType_add_rvalue_reference(t);
+ SwigType_add_variadic(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
@@ -5837,11 +5871,12 @@ direct_declarator : idcolon {
}
;
-abstract_declarator : pointer {
+abstract_declarator : pointer variadic_opt {
$$.type = $1;
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
+ if ($2) SwigType_add_variadic($$.type);
}
| pointer direct_abstract_declarator {
$$ = $2;
@@ -5849,19 +5884,21 @@ abstract_declarator : pointer {
$$.type = $1;
Delete($2.type);
}
- | pointer AND {
+ | pointer AND variadic_opt {
$$.type = $1;
SwigType_add_reference($$.type);
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
+ if ($3) SwigType_add_variadic($$.type);
}
- | pointer LAND {
+ | pointer LAND variadic_opt {
$$.type = $1;
SwigType_add_rvalue_reference($$.type);
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
+ if ($3) SwigType_add_variadic($$.type);
}
| pointer AND direct_abstract_declarator {
$$ = $3;
@@ -5881,9 +5918,7 @@ abstract_declarator : pointer {
}
$$.type = $1;
}
- | direct_abstract_declarator {
- $$ = $1;
- }
+ | direct_abstract_declarator
| AND direct_abstract_declarator {
$$ = $2;
$$.type = NewStringEmpty();
@@ -5902,19 +5937,21 @@ abstract_declarator : pointer {
Delete($2.type);
}
}
- | AND {
+ | AND variadic_opt {
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
+ if ($2) SwigType_add_variadic($$.type);
}
- | LAND {
+ | LAND variadic_opt {
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
$$.type = NewStringEmpty();
SwigType_add_rvalue_reference($$.type);
+ if ($2) SwigType_add_variadic($$.type);
}
| idcolon DSTAR {
$$.type = NewStringEmpty();
@@ -6105,7 +6142,7 @@ type_qualifier_raw : CONST_QUAL { $$ = "const"; }
/* Data type must be a built in type or an identifier for user-defined types
This type can be preceded by a modifier. */
-type : rawtype {
+type : rawtype %expect 4 {
$$ = $1;
Replace($$,"typename ","", DOH_REPLACE_ANY);
}
@@ -6115,7 +6152,7 @@ rawtype : type_qualifier type_right {
$$ = $2;
SwigType_push($$,$1);
}
- | type_right { $$ = $1; }
+ | type_right
| type_right type_qualifier {
$$ = $1;
SwigType_push($$,$2);
@@ -6125,49 +6162,69 @@ rawtype : type_qualifier type_right {
SwigType_push($$,$3);
SwigType_push($$,$1);
}
+ | rawtype ELLIPSIS {
+ $$ = $1;
+ SwigType_add_variadic($$);
+ }
;
-type_right : primitive_type { $$ = $1;
- /* Printf(stdout,"primitive = '%s'\n", $$);*/
- }
- | TYPE_BOOL { $$ = $1; }
- | TYPE_VOID { $$ = $1; }
-/*
- | TYPE_TYPEDEF template_decl { $$ = NewStringf("%s%s",$1,$2); }
-*/
+type_right : primitive_type
+ | TYPE_BOOL
+ | TYPE_VOID
| c_enum_key idcolon { $$ = NewStringf("enum %s", $2); }
- | TYPE_RAW { $$ = $1; }
+ | TYPE_RAW
- | idcolon {
+ | idcolon %expect 1 {
$$ = $1;
}
- | cpptype idcolon {
+ | cpptype idcolon %expect 1 {
$$ = NewStringf("%s %s", $1, $2);
}
- | decltype {
- $$ = $1;
- }
+ | decltype
;
-decltype : DECLTYPE LPAREN idcolon RPAREN {
- Node *n = Swig_symbol_clookup($3,0);
- if (!n) {
- Swig_error(cparse_file, cparse_line, "Identifier %s not defined.\n", $3);
- $$ = $3;
- } else {
- $$ = Getattr(n, "type");
- }
- }
- ;
+decltype : DECLTYPE LPAREN <str>{
+ $$ = get_raw_text_balanced('(', ')');
+ } decltypeexpr {
+ String *expr = $3;
+ if ($4) {
+ $$ = $4;
+ } else {
+ $$ = NewStringf("decltype%s", expr);
+ /* expr includes parentheses but don't include them in the warning message. */
+ Delitem(expr, 0);
+ Delitem(expr, DOH_END);
+ Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", expr);
+ }
+ Delete(expr);
+ }
+ ;
+
+decltypeexpr : expr RPAREN {
+ $$ = deduce_type(&$1);
+ }
+ | error RPAREN {
+ /* Avoid a parse error if we can't parse the expression
+ * decltype() is applied to.
+ *
+ * Set $$ to 0 here to trigger the decltype rule above to
+ * issue a warning.
+ */
+ $$ = 0;
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
+ Clear(scanner_ccode);
+ }
+ ;
primitive_type : primitive_type_list {
- if (!$1.type) $1.type = NewString("int");
+ String *type = $1.type;
+ if (!type) type = NewString("int");
if ($1.us) {
- $$ = NewStringf("%s %s", $1.us, $1.type);
+ $$ = NewStringf("%s %s", $1.us, type);
Delete($1.us);
- Delete($1.type);
+ Delete(type);
} else {
- $$ = $1.type;
+ $$ = type;
}
if (Cmp($$,"signed int") == 0) {
Delete($$);
@@ -6185,9 +6242,7 @@ primitive_type : primitive_type_list {
}
;
-primitive_type_list : type_specifier {
- $$ = $1;
- }
+primitive_type_list : type_specifier
| type_specifier primitive_type_list {
if ($1.us && $2.us) {
Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $2.us);
@@ -6217,19 +6272,19 @@ primitive_type_list : type_specifier {
} else if (Cmp($1.type,"double") == 0) {
if (Cmp($2.type,"long") == 0) {
$$.type = NewString("long double");
- } else if (Cmp($2.type,"complex") == 0) {
- $$.type = NewString("double complex");
+ } else if (Cmp($2.type,"_Complex") == 0) {
+ $$.type = NewString("double _Complex");
} else {
err = 1;
}
} else if (Cmp($1.type,"float") == 0) {
- if (Cmp($2.type,"complex") == 0) {
- $$.type = NewString("float complex");
+ if (Cmp($2.type,"_Complex") == 0) {
+ $$.type = NewString("float _Complex");
} else {
err = 1;
}
- } else if (Cmp($1.type,"complex") == 0) {
- $$.type = NewStringf("%s complex", $2.type);
+ } else if (Cmp($1.type,"_Complex") == 0) {
+ $$.type = NewStringf("%s _Complex", $2.type);
} else {
err = 1;
}
@@ -6279,7 +6334,7 @@ type_specifier : TYPE_INT {
$$.type = 0;
}
| TYPE_COMPLEX {
- $$.type = NewString("complex");
+ $$.type = NewString("_Complex");
$$.us = 0;
}
| TYPE_NON_ISO_INT8 {
@@ -6300,8 +6355,8 @@ type_specifier : TYPE_INT {
}
;
-definetype : { /* scanner_check_typedef(); */ } expr {
- $$ = $2;
+definetype : expr {
+ $$ = $1;
if ($$.type == T_STRING) {
$$.rawval = NewStringf("\"%(escape)s\"",$$.val);
} else if ($$.type != T_CHAR && $$.type != T_WSTRING && $$.type != T_WCHAR) {
@@ -6314,19 +6369,12 @@ definetype : { /* scanner_check_typedef(); */ } expr {
$$.throwf = 0;
$$.nexcept = 0;
$$.final = 0;
- scanner_ignore_typedef();
}
- | default_delete {
- $$ = $1;
- }
+ | default_delete
;
-default_delete : deleted_definition {
- $$ = $1;
- }
- | explicit_default {
- $$ = $1;
- }
+default_delete : deleted_definition
+ | explicit_default
;
/* For C++ deleted definition '= delete' */
@@ -6334,6 +6382,7 @@ deleted_definition : DELETE_KW {
$$.val = NewString("delete");
$$.rawval = 0;
$$.type = T_STRING;
+ $$.unary_arg_type = 0;
$$.qualifier = 0;
$$.refqualifier = 0;
$$.bitfield = 0;
@@ -6349,6 +6398,7 @@ explicit_default : DEFAULT {
$$.val = NewString("default");
$$.rawval = 0;
$$.type = T_STRING;
+ $$.unary_arg_type = 0;
$$.qualifier = 0;
$$.refqualifier = 0;
$$.bitfield = 0;
@@ -6361,8 +6411,8 @@ explicit_default : DEFAULT {
/* Some stuff for handling enums */
-ename : identifier { $$ = $1; }
- | empty { $$ = (char *) 0;}
+ename : identifier
+ | %empty { $$ = 0; }
;
constant_directives : constant_directive
@@ -6371,7 +6421,7 @@ constant_directives : constant_directive
optional_ignored_defines
: constant_directives
- | empty
+ | %empty
;
/* Enum lists - any #define macros (constant directives) within the enum list are ignored. Trailing commas accepted. */
@@ -6390,6 +6440,12 @@ enumlist : enumlist_item {
set_comment($1, $2);
$$ = $1;
}
+ | enumlist_item DOXYGENSTRING {
+ Setattr($1, "_last", $1);
+ /* Misplaced doxygen string, attach it to previous parameter, like Doxygen does */
+ set_comment($1, $2);
+ $$ = $1;
+ }
| enumlist_item COMMA enumlist {
if ($3) {
set_nextSibling($1, $3);
@@ -6400,6 +6456,17 @@ enumlist : enumlist_item {
}
$$ = $1;
}
+ | enumlist_item DOXYGENPOSTSTRING COMMA enumlist {
+ if ($4) {
+ set_nextSibling($1, $4);
+ Setattr($1,"_last",Getattr($4,"_last"));
+ Setattr($4,"_last",NULL);
+ } else {
+ Setattr($1,"_last",$1);
+ }
+ set_comment($1, $2);
+ $$ = $1;
+ }
| enumlist_item COMMA DOXYGENPOSTSTRING enumlist {
if ($4) {
set_nextSibling($1, $4);
@@ -6421,9 +6488,7 @@ enumlist_item : optional_ignored_defines edecl_with_dox optional_ignored_defines
}
;
-edecl_with_dox : edecl {
- $$ = $1;
- }
+edecl_with_dox : edecl
| DOXYGENSTRING edecl {
$$ = $2;
set_comment($2, $1);
@@ -6452,12 +6517,15 @@ edecl : identifier {
etype : expr {
$$ = $1;
+ /* We get T_USER here for a typedef - unfortunately we can't
+ * currently resolve typedefs at this stage of parsing. */
if (($$.type != T_INT) && ($$.type != T_UINT) &&
($$.type != T_LONG) && ($$.type != T_ULONG) &&
($$.type != T_LONGLONG) && ($$.type != T_ULONGLONG) &&
($$.type != T_SHORT) && ($$.type != T_USHORT) &&
($$.type != T_SCHAR) && ($$.type != T_UCHAR) &&
- ($$.type != T_CHAR) && ($$.type != T_BOOL)) {
+ ($$.type != T_CHAR) && ($$.type != T_BOOL) &&
+ ($$.type != T_UNKNOWN) && ($$.type != T_USER)) {
Swig_error(cparse_file,cparse_line,"Type error. Expecting an integral type\n");
}
}
@@ -6465,11 +6533,12 @@ etype : expr {
/* Arithmetic expressions. Used for constants, C++ templates, and other cool stuff. */
-expr : valexpr { $$ = $1; }
+expr : valexpr
| type {
Node *n;
$$.val = $1;
- $$.type = T_INT;
+ $$.type = T_UNKNOWN;
+ $$.unary_arg_type = 0;
/* Check if value is in scope */
n = Swig_symbol_clookup($1,0);
if (n) {
@@ -6478,9 +6547,15 @@ expr : valexpr { $$ = $1; }
String *q = Swig_symbol_qualified(n);
if (q) {
$$.val = NewStringf("%s::%s", q, Getattr(n,"name"));
+ $$.type = SwigType_type(Getattr(n, "type"));
Delete(q);
}
- }
+ } else {
+ SwigType *type = Getattr(n, "type");
+ if (type) {
+ $$.type = SwigType_type(type);
+ }
+ }
}
}
;
@@ -6490,47 +6565,82 @@ exprmem : ID ARROW ID {
$$.val = NewStringf("%s->%s", $1, $3);
$$.type = 0;
}
+ | ID ARROW ID LPAREN callparms RPAREN {
+ $$.val = NewStringf("%s->%s(%s)", $1, $3, $5.val);
+ $$.type = 0;
+ }
| exprmem ARROW ID {
$$ = $1;
Printf($$.val, "->%s", $3);
}
-/* This generates a shift-reduce
+ | exprmem ARROW ID LPAREN callparms RPAREN {
+ $$ = $1;
+ Printf($$.val, "->%s(%s)", $3, $5.val);
+ }
| ID PERIOD ID {
$$.val = NewStringf("%s.%s", $1, $3);
$$.type = 0;
}
-*/
+ | ID PERIOD ID LPAREN callparms RPAREN {
+ $$.val = NewStringf("%s.%s(%s)", $1, $3, $5.val);
+ $$.type = 0;
+ }
| exprmem PERIOD ID {
$$ = $1;
Printf($$.val, ".%s", $3);
}
+ | exprmem PERIOD ID LPAREN callparms RPAREN {
+ $$ = $1;
+ Printf($$.val, ".%s(%s)", $3, $5.val);
+ }
;
-valexpr : exprnum {
- $$ = $1;
- }
- | exprmem {
- $$ = $1;
- }
+/* Non-compound expression */
+exprsimple : exprnum
+ | exprmem
| string {
$$.val = $1;
$$.type = T_STRING;
+ $$.unary_arg_type = 0;
}
| SIZEOF LPAREN type parameter_declarator RPAREN {
SwigType_push($3,$4.type);
$$.val = NewStringf("sizeof(%s)",SwigType_str($3,0));
$$.type = T_ULONG;
+ $$.unary_arg_type = 0;
}
- | SIZEOF PERIOD PERIOD PERIOD LPAREN type parameter_declarator RPAREN {
- SwigType_push($6,$7.type);
- $$.val = NewStringf("sizeof...(%s)",SwigType_str($6,0));
+ | SIZEOF ELLIPSIS LPAREN type parameter_declarator RPAREN {
+ SwigType_push($4,$5.type);
+ $$.val = NewStringf("sizeof...(%s)",SwigType_str($4,0));
$$.type = T_ULONG;
+ $$.unary_arg_type = 0;
}
- | exprcompound { $$ = $1; }
+ /* We don't support all valid expressions here currently - e.g.
+ * sizeof(<unaryop> x) doesn't work - but those are unlikely to
+ * be seen in real code.
+ *
+ * Note: sizeof(x) is not handled here, but instead by the rule
+ * for sizeof(<type>) because it matches that syntactically.
+ */
+ | SIZEOF LPAREN exprsimple RPAREN {
+ $$.val = NewStringf("sizeof(%s)", $3.val);
+ $$.type = T_ULONG;
+ $$.unary_arg_type = 0;
+ }
+ /* `sizeof expr` without parentheses is valid for an expression,
+ * but not for a type. This doesn't support `sizeof x` in
+ * addition to the case not supported above.
+ */
+ | SIZEOF exprsimple {
+ $$.val = NewStringf("sizeof(%s)", $2.val);
+ $$.type = T_ULONG;
+ $$.unary_arg_type = 0;
+ }
| wstring {
$$.val = $1;
$$.rawval = NewStringf("L\"%s\"", $$.val);
$$.type = T_WSTRING;
+ $$.unary_arg_type = 0;
}
| CHARCONST {
$$.val = NewString($1);
@@ -6540,6 +6650,7 @@ valexpr : exprnum {
$$.rawval = NewString("'\\0'");
}
$$.type = T_CHAR;
+ $$.unary_arg_type = 0;
$$.bitfield = 0;
$$.throws = 0;
$$.throwf = 0;
@@ -6554,6 +6665,7 @@ valexpr : exprnum {
$$.rawval = NewString("L'\\0'");
}
$$.type = T_WCHAR;
+ $$.unary_arg_type = 0;
$$.bitfield = 0;
$$.throws = 0;
$$.throwf = 0;
@@ -6561,6 +6673,11 @@ valexpr : exprnum {
$$.final = 0;
}
+ ;
+
+valexpr : exprsimple
+ | exprcompound
+
/* grouping */
| LPAREN expr RPAREN %prec CAST {
$$.val = NewStringf("(%s)",$2.val);
@@ -6573,7 +6690,9 @@ valexpr : exprnum {
/* A few common casting operations */
| LPAREN expr RPAREN expr %prec CAST {
- $$ = $4;
+ int cast_type_code = SwigType_type($2.val);
+ $$ = $4;
+ $$.unary_arg_type = 0;
if ($4.type != T_STRING) {
switch ($2.type) {
case T_FLOAT:
@@ -6588,10 +6707,28 @@ valexpr : exprnum {
break;
}
}
- $$.type = promote($2.type, $4.type);
+ /* As well as C-style casts, this grammar rule currently also
+ * matches a binary operator with a LHS in parentheses for
+ * binary operators which also have an unary form, e.g.:
+ *
+ * (6)*7
+ * (6)&7
+ * (6)+7
+ * (6)-7
+ */
+ if (cast_type_code != T_USER && cast_type_code != T_UNKNOWN) {
+ /* $2 is definitely a type so we know this is a cast. */
+ $$.type = cast_type_code;
+ } else if ($4.type == 0 || $4.unary_arg_type == 0) {
+ /* Not one of the cases above, so we know this is a cast. */
+ $$.type = cast_type_code;
+ } else {
+ $$.type = promote($2.type, $4.unary_arg_type);
+ }
}
| LPAREN expr pointer RPAREN expr %prec CAST {
$$ = $5;
+ $$.unary_arg_type = 0;
if ($5.type != T_STRING) {
SwigType_push($2.val,$3);
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
@@ -6599,6 +6736,7 @@ valexpr : exprnum {
}
| LPAREN expr AND RPAREN expr %prec CAST {
$$ = $5;
+ $$.unary_arg_type = 0;
if ($5.type != T_STRING) {
SwigType_add_reference($2.val);
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
@@ -6606,6 +6744,7 @@ valexpr : exprnum {
}
| LPAREN expr LAND RPAREN expr %prec CAST {
$$ = $5;
+ $$.unary_arg_type = 0;
if ($5.type != T_STRING) {
SwigType_add_rvalue_reference($2.val);
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
@@ -6613,6 +6752,7 @@ valexpr : exprnum {
}
| LPAREN expr pointer AND RPAREN expr %prec CAST {
$$ = $6;
+ $$.unary_arg_type = 0;
if ($6.type != T_STRING) {
SwigType_push($2.val,$3);
SwigType_add_reference($2.val);
@@ -6621,6 +6761,7 @@ valexpr : exprnum {
}
| LPAREN expr pointer LAND RPAREN expr %prec CAST {
$$ = $6;
+ $$.unary_arg_type = 0;
if ($6.type != T_STRING) {
SwigType_push($2.val,$3);
SwigType_add_rvalue_reference($2.val);
@@ -6629,26 +6770,56 @@ valexpr : exprnum {
}
| AND expr {
$$ = $2;
- $$.val = NewStringf("&%s",$2.val);
- }
- | LAND expr {
- $$ = $2;
- $$.val = NewStringf("&&%s",$2.val);
+ $$.val = NewStringf("&%s", $2.val);
+ $$.rawval = 0;
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)&7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $2.type;
+ switch ($$.type) {
+ case T_CHAR:
+ $$.type = T_STRING;
+ break;
+ case T_WCHAR:
+ $$.type = T_WSTRING;
+ break;
+ default:
+ $$.type = T_POINTER;
+ }
}
| STAR expr {
$$ = $2;
- $$.val = NewStringf("*%s",$2.val);
+ $$.val = NewStringf("*%s", $2.val);
+ $$.rawval = 0;
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)*7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $2.type;
+ switch ($$.type) {
+ case T_STRING:
+ $$.type = T_CHAR;
+ break;
+ case T_WSTRING:
+ $$.type = T_WCHAR;
+ break;
+ default:
+ $$.type = T_UNKNOWN;
+ }
}
- ;
+ ;
-exprnum : NUM_INT { $$ = $1; }
- | NUM_FLOAT { $$ = $1; }
- | NUM_UNSIGNED { $$ = $1; }
- | NUM_LONG { $$ = $1; }
- | NUM_ULONG { $$ = $1; }
- | NUM_LONGLONG { $$ = $1; }
- | NUM_ULONGLONG { $$ = $1; }
- | NUM_BOOL { $$ = $1; }
+exprnum : NUM_INT
+ | NUM_DOUBLE
+ | NUM_FLOAT
+ | NUM_LONGDOUBLE
+ | NUM_UNSIGNED
+ | NUM_LONG
+ | NUM_ULONG
+ | NUM_LONGLONG
+ | NUM_ULONGLONG
+ | NUM_BOOL
;
exprcompound : expr PLUS expr {
@@ -6707,16 +6878,24 @@ exprcompound : expr PLUS expr {
$$.val = NewStringf("%s!=%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3));
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
}
-/* Sadly this causes 2 reduce-reduce conflicts with templates. FIXME resolve these.
- | expr GREATERTHAN expr {
- $$.val = NewStringf("%s > %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3));
+ /* Trying to parse `>` in the general case results in conflicts
+ * in the parser, but all user-reported cases are actually inside
+ * parentheses and we can handle that case.
+ */
+ | LPAREN expr GREATERTHAN expr RPAREN {
+ $$.val = NewStringf("(%s > %s)", COMPOUND_EXPR_VAL($2), COMPOUND_EXPR_VAL($4));
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
}
- | expr LESSTHAN expr {
- $$.val = NewStringf("%s < %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3));
+
+ /* Similarly for `<` except trying to handle exprcompound on the
+ * left side gives a shift/reduce conflict, so also restrict
+ * handling to non-compound subexpressions there. Again this
+ * covers all user-reported cases.
+ */
+ | LPAREN exprsimple LESSTHAN expr RPAREN {
+ $$.val = NewStringf("(%s < %s)", COMPOUND_EXPR_VAL($2), COMPOUND_EXPR_VAL($4));
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
}
-*/
| expr GREATERTHANOREQUALTO expr {
$$.val = NewStringf("%s >= %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3));
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
@@ -6725,6 +6904,20 @@ exprcompound : expr PLUS expr {
$$.val = NewStringf("%s <= %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3));
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
}
+ | expr LESSEQUALGREATER expr {
+ $$.val = NewStringf("%s <=> %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3));
+ /* `<=>` returns one of `std::strong_ordering`,
+ * `std::partial_ordering` or `std::weak_ordering`. The main
+ * thing to do with the return value in this context is to
+ * compare it with another ordering of the same type or
+ * with a literal 0. We set .type = T_USER here which does
+ * what we want for the comparison operators, and also means
+ * that deduce_type() won't deduce a type for this (which is
+ * better than it deducing the wrong type).
+ */
+ $$.type = T_USER;
+ $$.unary_arg_type = 0;
+ }
| expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK {
$$.val = NewStringf("%s?%s:%s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3), COMPOUND_EXPR_VAL($5));
/* This may not be exactly right, but is probably good enough
@@ -6733,23 +6926,33 @@ exprcompound : expr PLUS expr {
}
| MINUS expr %prec UMINUS {
$$.val = NewStringf("-%s",$2.val);
- $$.type = $2.type;
+ $$.type = promote_type($2.type);
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)-7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $2.type;
}
| PLUS expr %prec UMINUS {
$$.val = NewStringf("+%s",$2.val);
- $$.type = $2.type;
+ $$.type = promote_type($2.type);
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)+7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $2.type;
}
| NOT expr {
$$.val = NewStringf("~%s",$2.val);
- $$.type = $2.type;
+ $$.type = promote_type($2.type);
}
| LNOT expr {
$$.val = NewStringf("!%s",COMPOUND_EXPR_VAL($2));
- $$.type = T_INT;
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
}
| type LPAREN {
String *qty;
- skip_balanced('(',')');
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
qty = Swig_symbol_type_qualify($1,0);
if (SwigType_istemplate(qty)) {
String *nstr = SwigType_namestr(qty);
@@ -6758,31 +6961,34 @@ exprcompound : expr PLUS expr {
}
$$.val = NewStringf("%s%s",qty,scanner_ccode);
Clear(scanner_ccode);
- $$.type = T_INT;
+ /* Try to deduce the type - this could be a C++ "constructor
+ * cast" such as `double(4)` or a function call such as
+ * `some_func()`. In the latter case we get T_USER, but that
+ * is wrong so we map it to T_UNKNOWN until we can actually
+ * deduce the return type of a function call (which is
+ * complicated because the return type can vary between
+ * overloaded forms).
+ */
+ $$.type = SwigType_type(qty);
+ if ($$.type == T_USER) $$.type = T_UNKNOWN;
+ $$.unary_arg_type = 0;
Delete(qty);
}
;
-ellipsis : PERIOD PERIOD PERIOD {
+variadic_opt : ELLIPSIS {
$$ = NewString("...");
}
- ;
-
-variadic : ellipsis {
- $$ = $1;
- }
- | empty {
+ | %empty {
$$ = 0;
}
;
-inherit : raw_inherit {
- $$ = $1;
- }
+inherit : raw_inherit
;
raw_inherit : COLON { inherit_list = 1; } base_list { $$ = $3; inherit_list = 0; }
- | empty { $$ = 0; }
+ | %empty { $$ = 0; }
;
base_list : base_specifier {
@@ -6811,102 +7017,94 @@ base_list : base_specifier {
}
;
-base_specifier : opt_virtual {
- $<intvalue>$ = cparse_line;
- } idcolon variadic {
+base_specifier : opt_virtual <intvalue>{
+ $$ = cparse_line;
+ } idcolon variadic_opt {
$$ = NewHash();
Setfile($$,cparse_file);
- Setline($$,$<intvalue>2);
+ Setline($$,$2);
Setattr($$,"name",$3);
Setfile($3,cparse_file);
- Setline($3,$<intvalue>2);
+ Setline($3,$2);
if (last_cpptype && (Strcmp(last_cpptype,"struct") != 0)) {
Setattr($$,"access","private");
Swig_warning(WARN_PARSE_NO_ACCESS, Getfile($$), Getline($$), "No access specifier given for base class '%s' (ignored).\n", SwigType_namestr($3));
} else {
Setattr($$,"access","public");
}
- if ($4)
- SetFlag($$, "variadic");
+ if ($4) {
+ SwigType_add_variadic(Getattr($$, "name"));
+ }
}
- | opt_virtual access_specifier {
- $<intvalue>$ = cparse_line;
- } opt_virtual idcolon variadic {
+ | opt_virtual access_specifier <intvalue>{
+ $$ = cparse_line;
+ } opt_virtual idcolon variadic_opt {
$$ = NewHash();
Setfile($$,cparse_file);
- Setline($$,$<intvalue>3);
+ Setline($$,$3);
Setattr($$,"name",$5);
Setfile($5,cparse_file);
- Setline($5,$<intvalue>3);
+ Setline($5,$3);
Setattr($$,"access",$2);
if (Strcmp($2,"public") != 0) {
Swig_warning(WARN_PARSE_PRIVATE_INHERIT, Getfile($$), Getline($$), "%s inheritance from base '%s' (ignored).\n", $2, SwigType_namestr($5));
}
- if ($6)
- SetFlag($$, "variadic");
+ if ($6) {
+ SwigType_add_variadic(Getattr($$, "name"));
+ }
}
;
-access_specifier : PUBLIC { $$ = (char*)"public"; }
- | PRIVATE { $$ = (char*)"private"; }
- | PROTECTED { $$ = (char*)"protected"; }
+access_specifier : PUBLIC { $$ = "public"; }
+ | PRIVATE { $$ = "private"; }
+ | PROTECTED { $$ = "protected"; }
;
-templcpptype : CLASS {
- $$ = (char*)"class";
- if (!inherit_list) last_cpptype = $$;
- }
- | TYPENAME {
- $$ = (char *)"typename";
- if (!inherit_list) last_cpptype = $$;
- }
- | CLASS PERIOD PERIOD PERIOD {
- $$ = (char *)"class...";
+templcpptype : CLASS variadic_opt {
+ $$ = NewString("class");
if (!inherit_list) last_cpptype = $$;
+ if ($2) SwigType_add_variadic($$);
}
- | TYPENAME PERIOD PERIOD PERIOD {
- $$ = (char *)"typename...";
+ | TYPENAME variadic_opt {
+ $$ = NewString("typename");
if (!inherit_list) last_cpptype = $$;
+ if ($2) SwigType_add_variadic($$);
}
;
-cpptype : templcpptype {
- $$ = $1;
- }
- | STRUCT {
- $$ = (char*)"struct";
+cpptype : templcpptype
+ | STRUCT {
+ $$ = NewString("struct");
if (!inherit_list) last_cpptype = $$;
}
| UNION {
- $$ = (char*)"union";
+ $$ = NewString("union");
if (!inherit_list) last_cpptype = $$;
}
;
classkey : CLASS {
- $$ = (char*)"class";
+ $$ = NewString("class");
if (!inherit_list) last_cpptype = $$;
}
| STRUCT {
- $$ = (char*)"struct";
+ $$ = NewString("struct");
if (!inherit_list) last_cpptype = $$;
}
| UNION {
- $$ = (char*)"union";
+ $$ = NewString("union");
if (!inherit_list) last_cpptype = $$;
}
;
-classkeyopt : classkey {
- $$ = $1;
- }
- | empty {
+classkeyopt : classkey
+ | %empty {
$$ = 0;
}
;
opt_virtual : VIRTUAL
- | empty
+ | %empty
;
virt_specifier_seq : OVERRIDE {
@@ -6923,10 +7121,16 @@ virt_specifier_seq : OVERRIDE {
}
;
-virt_specifier_seq_opt : virt_specifier_seq {
- $$ = $1;
+virt_specifier_seq_opt : virt_specifier_seq
+ | %empty {
+ $$ = 0;
}
- | empty {
+ ;
+
+class_virt_specifier_opt : FINAL {
+ $$ = NewString("1");
+ }
+ | %empty {
$$ = 0;
}
;
@@ -6989,10 +7193,8 @@ qualifiers_exception_specification : cv_ref_qualifier {
}
;
-cpp_const : qualifiers_exception_specification {
- $$ = $1;
- }
- | empty {
+cpp_const : qualifiers_exception_specification
+ | %empty {
$$.throws = 0;
$$.throwf = 0;
$$.nexcept = 0;
@@ -7014,15 +7216,15 @@ ctor_end : cpp_const ctor_initializer SEMI {
Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
}
| cpp_const ctor_initializer LBRACE {
- skip_balanced('{','}');
+ if ($1.qualifier)
+ Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$.have_parms = 0;
$$.defarg = 0;
$$.throws = $1.throws;
$$.throwf = $1.throwf;
$$.nexcept = $1.nexcept;
$$.final = $1.final;
- if ($1.qualifier)
- Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
}
| LPAREN parms RPAREN SEMI {
Clear(scanner_ccode);
@@ -7035,7 +7237,7 @@ ctor_end : cpp_const ctor_initializer SEMI {
$$.final = 0;
}
| LPAREN parms RPAREN LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$.parms = $2;
$$.have_parms = 1;
$$.defarg = 0;
@@ -7065,17 +7267,17 @@ ctor_end : cpp_const ctor_initializer SEMI {
;
ctor_initializer : COLON mem_initializer_list
- | empty
+ | %empty
;
mem_initializer_list : mem_initializer
| mem_initializer_list COMMA mem_initializer
- | mem_initializer PERIOD PERIOD PERIOD
- | mem_initializer_list COMMA mem_initializer PERIOD PERIOD PERIOD
+ | mem_initializer ELLIPSIS
+ | mem_initializer_list COMMA mem_initializer ELLIPSIS
;
mem_initializer : idcolon LPAREN {
- skip_balanced('(',')');
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
Clear(scanner_ccode);
}
/* Uniform initialization in C++11.
@@ -7087,7 +7289,7 @@ mem_initializer : idcolon LPAREN {
};
*/
| idcolon LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
Clear(scanner_ccode);
}
;
@@ -7101,24 +7303,23 @@ less_valparms_greater : LESSTHAN valparms GREATERTHAN {
;
/* Identifiers including the C++11 identifiers with special meaning */
-identifier : ID { $$ = $1; }
+identifier : ID
| OVERRIDE { $$ = Swig_copy_string("override"); }
| FINAL { $$ = Swig_copy_string("final"); }
;
-idstring : identifier { $$ = $1; }
+idstring : identifier
| default_delete { $$ = Char($1.val); }
| string { $$ = Char($1); }
;
-idstringopt : idstring { $$ = $1; }
- | empty { $$ = 0; }
+idstringopt : idstring
+ | %empty { $$ = 0; }
;
idcolon : idtemplate idcolontail {
- $$ = 0;
- if (!$$) $$ = NewStringf("%s%s", $1,$2);
- Delete($2);
+ $$ = NewStringf("%s%s", $1, $2);
+ Delete($2);
}
| NONID DCOLON idtemplatetemplate idcolontail {
$$ = NewStringf("::%s%s",$3,$4);
@@ -7130,7 +7331,7 @@ idcolon : idtemplate idcolontail {
| NONID DCOLON idtemplatetemplate {
$$ = NewStringf("::%s",$3);
}
- | OPERATOR {
+ | OPERATOR %expect 1 {
$$ = NewStringf("%s", $1);
}
| OPERATOR less_valparms_greater {
@@ -7169,9 +7370,7 @@ idtemplate : identifier {
}
;
-idtemplatetemplate : idtemplate {
- $$ = $1;
- }
+idtemplatetemplate : idtemplate
| TEMPLATE identifier less_valparms_greater {
$$ = NewStringf("%s%s", $2, $3);
}
@@ -7179,9 +7378,8 @@ idtemplatetemplate : idtemplate {
/* Identifier, but no templates */
idcolonnt : identifier idcolontailnt {
- $$ = 0;
- if (!$$) $$ = NewStringf("%s%s", $1,$2);
- Delete($2);
+ $$ = NewStringf("%s%s", $1, $2);
+ Delete($2);
}
| NONID DCOLON identifier idcolontailnt {
$$ = NewStringf("::%s%s",$3,$4);
@@ -7234,16 +7432,12 @@ wstring : wstring WSTRING {
| WSTRING { $$ = NewString($1);}
;
-stringbrace : string {
- $$ = $1;
- }
+stringbrace : string
| LBRACE {
- skip_balanced('{','}');
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
$$ = NewString(scanner_ccode);
}
- | HBLOCK {
- $$ = $1;
- }
+ | HBLOCK
;
options : LPAREN kwargs RPAREN {
@@ -7259,7 +7453,7 @@ options : LPAREN kwargs RPAREN {
n = nextSibling(n);
}
}
- | empty { $$ = 0; };
+ | %empty { $$ = 0; };
/* Keyword arguments */
@@ -7294,42 +7488,38 @@ kwargs : idstring EQUAL stringnum {
}
;
-stringnum : string {
- $$ = $1;
- }
+stringnum : string
| exprnum {
$$ = Char($1.val);
}
;
-empty : ;
-
%%
SwigType *Swig_cparse_type(String *s) {
String *ns;
- ns = NewStringf("%s;",s);
+ ns = NewString(s);
Seek(ns,0,SEEK_SET);
scanner_file(ns);
top = 0;
scanner_next_token(PARSETYPE);
yyparse();
/* Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
- return top;
+ return (SwigType *)top;
}
Parm *Swig_cparse_parm(String *s) {
String *ns;
- ns = NewStringf("%s;",s);
+ ns = NewString(s);
Seek(ns,0,SEEK_SET);
scanner_file(ns);
top = 0;
scanner_next_token(PARSEPARM);
yyparse();
- /* Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
+ /* Printf(stdout,"parmparse: '%s' ---> '%s'\n", s, top); */
Delete(ns);
- return top;
+ return (Parm *)top;
}
@@ -7337,9 +7527,9 @@ ParmList *Swig_cparse_parms(String *s, Node *file_line_node) {
String *ns;
char *cs = Char(s);
if (cs && cs[0] != '(') {
- ns = NewStringf("(%s);",s);
+ ns = NewStringf("(%s)",s);
} else {
- ns = NewStringf("%s;",s);
+ ns = NewString(s);
}
Setfile(ns, Getfile(file_line_node));
Setline(ns, Getline(file_line_node));
@@ -7348,7 +7538,7 @@ ParmList *Swig_cparse_parms(String *s, Node *file_line_node) {
top = 0;
scanner_next_token(PARSEPARMS);
yyparse();
- /* Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
- return top;
+ /* Printf(stdout,"parmsparse: '%s' ---> '%s'\n", s, top); */
+ return (ParmList *)top;
}