]> granicus.if.org Git - python/commitdiff
Issue #25555: Fix parser and AST: fill lineno and col_offset of "arg" node when
authorVictor Stinner <victor.stinner@gmail.com>
Fri, 6 Nov 2015 16:01:48 +0000 (17:01 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Fri, 6 Nov 2015 16:01:48 +0000 (17:01 +0100)
compiling AST from Python objects.

Include/Python-ast.h
Misc/NEWS
Parser/asdl_c.py
Python/Python-ast.c
Python/ast.c

index 3bc015fe78bc228dd7f5c25dd4830fb42fedbc07..2d3eacb9c3b93452930f53a6faace869f7273af2 100644 (file)
@@ -585,8 +585,9 @@ excepthandler_ty _Py_ExceptHandler(expr_ty type, identifier name, asdl_seq *
 arguments_ty _Py_arguments(asdl_seq * args, arg_ty vararg, asdl_seq *
                            kwonlyargs, asdl_seq * kw_defaults, arg_ty kwarg,
                            asdl_seq * defaults, PyArena *arena);
-#define arg(a0, a1, a2) _Py_arg(a0, a1, a2)
-arg_ty _Py_arg(identifier arg, expr_ty annotation, PyArena *arena);
+#define arg(a0, a1, a2, a3, a4) _Py_arg(a0, a1, a2, a3, a4)
+arg_ty _Py_arg(identifier arg, expr_ty annotation, int lineno, int col_offset,
+               PyArena *arena);
 #define keyword(a0, a1, a2) _Py_keyword(a0, a1, a2)
 keyword_ty _Py_keyword(identifier arg, expr_ty value, PyArena *arena);
 #define alias(a0, a1, a2) _Py_alias(a0, a1, a2)
index fef42a0ed4fb7cc0dc74eb3e6f3468d1266faebc..029a55fe6fcf30dba732c9b305fb2c474a235622 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -11,6 +11,9 @@ Release date: TBA
 Core and Builtins
 -----------------
 
+- Issue #25555: Fix parser and AST: fill lineno and col_offset of "arg" node
+  when compiling AST from Python objects.
+
 - Issue #24802: Avoid buffer overreads when int(), float(), compile(), exec()
   and eval() are passed bytes-like objects.  These objects are not
   necessarily terminated by a null byte, but the functions assumed they were.
index 79e834b3dc89a598857860835bb3ac9e7d82a275..f38c25358b17432036d1a07d83628c1546cf6fdd 100755 (executable)
@@ -275,7 +275,9 @@ class PrototypeVisitor(EmitVisitor):
 
     def visitProduct(self, prod, name):
         self.emit_function(name, get_c_type(name),
-                           self.get_args(prod.fields), [], union=False)
+                           self.get_args(prod.fields),
+                           self.get_args(prod.attributes),
+                           union=False)
 
 
 class FunctionVisitor(PrototypeVisitor):
@@ -329,7 +331,8 @@ class FunctionVisitor(PrototypeVisitor):
             self.emit(s, depth, reflow)
         for argtype, argname, opt in args:
             emit("p->%s = %s;" % (argname, argname), 1)
-        assert not attrs
+        for argtype, argname, opt in attrs:
+            emit("p->%s = %s;" % (argname, argname), 1)
 
 
 class PickleVisitor(EmitVisitor):
@@ -452,10 +455,15 @@ class Obj2ModVisitor(PickleVisitor):
         self.emit("PyObject* tmp = NULL;", 1)
         for f in prod.fields:
             self.visitFieldDeclaration(f, name, prod=prod, depth=1)
+        for a in prod.attributes:
+            self.visitFieldDeclaration(a, name, prod=prod, depth=1)
         self.emit("", 0)
         for f in prod.fields:
             self.visitField(f, name, prod=prod, depth=1)
+        for a in prod.attributes:
+            self.visitField(a, name, prod=prod, depth=1)
         args = [f.name for f in prod.fields]
+        args.extend([a.name for a in prod.attributes])
         self.emit("*out = %s(%s);" % (name, self.buildArgs(args)), 1)
         self.emit("return 0;", 1)
         self.emit("failed:", 0)
index 8a2dc7cc54dc3e09ab608be38d038bcc47427007..edfcbad1341ca50dbd65b3c878b8b17eb6f2cbb3 100644 (file)
@@ -2372,7 +2372,8 @@ arguments(asdl_seq * args, arg_ty vararg, asdl_seq * kwonlyargs, asdl_seq *
 }
 
 arg_ty
-arg(identifier arg, expr_ty annotation, PyArena *arena)
+arg(identifier arg, expr_ty annotation, int lineno, int col_offset, PyArena
+    *arena)
 {
     arg_ty p;
     if (!arg) {
@@ -2385,6 +2386,8 @@ arg(identifier arg, expr_ty annotation, PyArena *arena)
         return NULL;
     p->arg = arg;
     p->annotation = annotation;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
     return p;
 }
 
@@ -7086,6 +7089,8 @@ obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena)
     PyObject* tmp = NULL;
     identifier arg;
     expr_ty annotation;
+    int lineno;
+    int col_offset;
 
     if (_PyObject_HasAttrId(obj, &PyId_arg)) {
         int res;
@@ -7108,7 +7113,29 @@ obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena)
     } else {
         annotation = NULL;
     }
-    *out = arg(arg, annotation, arena);
+    if (_PyObject_HasAttrId(obj, &PyId_lineno)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_lineno);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &lineno, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from arg");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_col_offset)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_col_offset);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &col_offset, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from arg");
+        return 1;
+    }
+    *out = arg(arg, annotation, lineno, col_offset, arena);
     return 0;
 failed:
     Py_XDECREF(tmp);
index dd5187a165cffb019d7fe331a02f839f7894a9ec..7743c31c1fbdf7a35b6feb0457faba13316ab197 100644 (file)
@@ -1173,11 +1173,9 @@ ast_for_arg(struct compiling *c, const node *n)
             return NULL;
     }
 
-    ret = arg(name, annotation, c->c_arena);
+    ret = arg(name, annotation, LINENO(n), n->n_col_offset, c->c_arena);
     if (!ret)
         return NULL;
-    ret->lineno = LINENO(n);
-    ret->col_offset = n->n_col_offset;
     return ret;
 }
 
@@ -1233,11 +1231,10 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
                     goto error;
                 if (forbidden_name(c, argname, ch, 0))
                     goto error;
-                arg = arg(argname, annotation, c->c_arena);
+                arg = arg(argname, annotation, LINENO(ch), ch->n_col_offset,
+                          c->c_arena);
                 if (!arg)
                     goto error;
-                arg->lineno = LINENO(ch);
-                arg->col_offset = ch->n_col_offset;
                 asdl_seq_SET(kwonlyargs, j++, arg);
                 i += 2; /* the name and the comma */
                 break;