mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '1.8'
This commit is contained in:
commit
ae60ed5b0b
5
CHANGES
5
CHANGES
@ -202,6 +202,11 @@ Bugs fixed
|
|||||||
be searched.
|
be searched.
|
||||||
* #5889: LaTeX: user ``numfig_format`` is stripped of spaces and may cause
|
* #5889: LaTeX: user ``numfig_format`` is stripped of spaces and may cause
|
||||||
build failure
|
build failure
|
||||||
|
* C++, fix hyperlinks for declarations involving east cv-qualifiers.
|
||||||
|
* #5755: C++, fix duplicate declaration error on function templates with constraints
|
||||||
|
in the return type.
|
||||||
|
* C++, parse unary right fold expressions and binary fold expressions.
|
||||||
|
* #5928: KeyError: 'DOCUTILSCONFIG' when running build
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -365,8 +365,8 @@ _keywords = [
|
|||||||
'while', 'xor', 'xor_eq'
|
'while', 'xor', 'xor_eq'
|
||||||
]
|
]
|
||||||
|
|
||||||
_max_id = 3
|
_max_id = 4
|
||||||
_id_prefix = [None, '', '_CPPv2', '_CPPv3']
|
_id_prefix = [None, '', '_CPPv2', '_CPPv3', '_CPPv4']
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Id v1 constants
|
# Id v1 constants
|
||||||
@ -892,6 +892,7 @@ class ASTParenExpr(ASTBase):
|
|||||||
|
|
||||||
class ASTFoldExpr(ASTBase):
|
class ASTFoldExpr(ASTBase):
|
||||||
def __init__(self, leftExpr, op, rightExpr):
|
def __init__(self, leftExpr, op, rightExpr):
|
||||||
|
# type: (Any, str, Any) -> None
|
||||||
assert leftExpr is not None or rightExpr is not None
|
assert leftExpr is not None or rightExpr is not None
|
||||||
self.leftExpr = leftExpr
|
self.leftExpr = leftExpr
|
||||||
self.op = op
|
self.op = op
|
||||||
@ -918,9 +919,23 @@ class ASTFoldExpr(ASTBase):
|
|||||||
# type: (int) -> str
|
# type: (int) -> str
|
||||||
assert version >= 3
|
assert version >= 3
|
||||||
if version == 3:
|
if version == 3:
|
||||||
return str(self)
|
return text_type(self)
|
||||||
# TODO: find the right mangling scheme
|
# https://github.com/itanium-cxx-abi/cxx-abi/pull/67
|
||||||
assert False
|
res = []
|
||||||
|
if self.leftExpr is None: # (... op expr)
|
||||||
|
res.append('fl')
|
||||||
|
elif self.rightExpr is None: # (expr op ...)
|
||||||
|
res.append('fr')
|
||||||
|
else: # (expr op ... op expr)
|
||||||
|
# we don't check where the parameter pack is,
|
||||||
|
# we just always call this a binary left fold
|
||||||
|
res.append('fL')
|
||||||
|
res.append(_id_operator_v2[self.op])
|
||||||
|
if self.leftExpr:
|
||||||
|
res.append(self.leftExpr.get_id(version))
|
||||||
|
if self.rightExpr:
|
||||||
|
res.append(self.rightExpr.get_id(version))
|
||||||
|
return ''.join(res)
|
||||||
|
|
||||||
def describe_signature(self, signode, mode, env, symbol):
|
def describe_signature(self, signode, mode, env, symbol):
|
||||||
signode.append(nodes.Text('('))
|
signode.append(nodes.Text('('))
|
||||||
@ -2635,11 +2650,12 @@ class ASTDeclSpecs(ASTBase):
|
|||||||
res.append('C')
|
res.append('C')
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
res = []
|
res = []
|
||||||
if self.leftSpecs.volatile or self.rightSpecs.volatile:
|
if self.allSpecs.volatile:
|
||||||
res.append('V')
|
res.append('V')
|
||||||
if self.leftSpecs.const or self.rightSpecs.volatile:
|
if self.allSpecs.const:
|
||||||
res.append('K')
|
res.append('K')
|
||||||
res.append(self.trailingTypeSpec.get_id(version))
|
if self.trailingTypeSpec is not None:
|
||||||
|
res.append(self.trailingTypeSpec.get_id(version))
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def _stringify(self, transform):
|
def _stringify(self, transform):
|
||||||
@ -3286,6 +3302,14 @@ class ASTType(ASTBase):
|
|||||||
if objectType == 'function': # also modifiers
|
if objectType == 'function': # also modifiers
|
||||||
modifiers = self.decl.get_modifiers_id(version)
|
modifiers = self.decl.get_modifiers_id(version)
|
||||||
res.append(symbol.get_full_nested_name().get_id(version, modifiers))
|
res.append(symbol.get_full_nested_name().get_id(version, modifiers))
|
||||||
|
if version >= 4:
|
||||||
|
# with templates we need to mangle the return type in as well
|
||||||
|
templ = symbol.declaration.templatePrefix
|
||||||
|
if templ is not None:
|
||||||
|
typeId = self.decl.get_ptr_suffix_id(version)
|
||||||
|
returnTypeId = self.declSpecs.get_id(version)
|
||||||
|
res.append(typeId)
|
||||||
|
res.append(returnTypeId)
|
||||||
res.append(self.decl.get_param_id(version))
|
res.append(self.decl.get_param_id(version))
|
||||||
elif objectType == 'type': # just the name
|
elif objectType == 'type': # just the name
|
||||||
res.append(symbol.get_full_nested_name().get_id(version))
|
res.append(symbol.get_full_nested_name().get_id(version))
|
||||||
@ -4753,13 +4777,45 @@ class DefinitionParser:
|
|||||||
if not self.skip_string(')'):
|
if not self.skip_string(')'):
|
||||||
self.fail("Expected ')' in end of fold expression.")
|
self.fail("Expected ')' in end of fold expression.")
|
||||||
return ASTFoldExpr(None, op, rightExpr)
|
return ASTFoldExpr(None, op, rightExpr)
|
||||||
# TODO: actually try to parse fold expression
|
# try first parsing a unary right fold, or a binary fold
|
||||||
# fall back to a paren expression
|
pos = self.pos
|
||||||
res = self._parse_expression(inTemplate=False)
|
try:
|
||||||
|
self.skip_ws()
|
||||||
|
leftExpr = self._parse_cast_expression()
|
||||||
|
self.skip_ws()
|
||||||
|
if not self.match(_fold_operator_re):
|
||||||
|
self.fail("Expected fold operator after left expression in fold expression.")
|
||||||
|
op = self.matched_text
|
||||||
|
self.skip_ws()
|
||||||
|
if not self.skip_string_and_ws('...'):
|
||||||
|
self.fail("Expected '...' after fold operator in fold expression.")
|
||||||
|
except DefinitionError as eFold:
|
||||||
|
self.pos = pos
|
||||||
|
# fall back to a paren expression
|
||||||
|
try:
|
||||||
|
res = self._parse_expression(inTemplate=False)
|
||||||
|
self.skip_ws()
|
||||||
|
if not self.skip_string(')'):
|
||||||
|
self.fail("Expected ')' in end of parenthesized expression.")
|
||||||
|
except DefinitionError as eExpr:
|
||||||
|
raise self._make_multi_error([
|
||||||
|
(eFold, "If fold expression"),
|
||||||
|
(eExpr, "If parenthesized expression")
|
||||||
|
], "Error in fold expression or parenthesized expression.")
|
||||||
|
return ASTParenExpr(res)
|
||||||
|
# now it definitely is a fold expression
|
||||||
|
if self.skip_string(')'):
|
||||||
|
return ASTFoldExpr(leftExpr, op, None)
|
||||||
|
if not self.match(_fold_operator_re):
|
||||||
|
self.fail("Expected fold operator or ')' after '...' in fold expression.")
|
||||||
|
if op != self.matched_text:
|
||||||
|
self.fail("Operators are different in binary fold: '%s' and '%s'."
|
||||||
|
% (op, self.matched_text))
|
||||||
|
rightExpr = self._parse_cast_expression()
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if not self.skip_string(')'):
|
if not self.skip_string(')'):
|
||||||
self.fail("Expected ')' in end of fold expression or parenthesized expression.")
|
self.fail("Expected ')' to end binary fold expression.")
|
||||||
return ASTParenExpr(res)
|
return ASTFoldExpr(leftExpr, op, rightExpr)
|
||||||
|
|
||||||
def _parse_primary_expression(self):
|
def _parse_primary_expression(self):
|
||||||
# literal
|
# literal
|
||||||
@ -5068,7 +5124,7 @@ class DefinitionParser:
|
|||||||
try:
|
try:
|
||||||
typ = self._parse_type(False)
|
typ = self._parse_type(False)
|
||||||
if not self.skip_string(')'):
|
if not self.skip_string(')'):
|
||||||
raise DefinitionError("Expected ')' in cast expression.")
|
self.fail("Expected ')' in cast expression.")
|
||||||
expr = self._parse_cast_expression()
|
expr = self._parse_cast_expression()
|
||||||
return ASTCastExpr(typ, expr)
|
return ASTCastExpr(typ, expr)
|
||||||
except DefinitionError as exCast:
|
except DefinitionError as exCast:
|
||||||
@ -6488,7 +6544,7 @@ class CPPObject(ObjectDescription):
|
|||||||
# Assume we are actually in the old symbol,
|
# Assume we are actually in the old symbol,
|
||||||
# instead of the newly created duplicate.
|
# instead of the newly created duplicate.
|
||||||
self.env.temp_data['cpp:last_symbol'] = e.symbol
|
self.env.temp_data['cpp:last_symbol'] = e.symbol
|
||||||
self.warn("Duplicate declaration.")
|
self.warn("Duplicate declaration, %s" % sig)
|
||||||
|
|
||||||
if ast.objectType == 'enumerator':
|
if ast.objectType == 'enumerator':
|
||||||
self._add_enumerator_to_parent(ast)
|
self._add_enumerator_to_parent(ast)
|
||||||
|
@ -170,7 +170,7 @@ def using_user_docutils_conf(confdir):
|
|||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
if docutilsconfig is None:
|
if docutilsconfig is None:
|
||||||
os.environ.pop('DOCUTILSCONFIG')
|
os.environ.pop('DOCUTILSCONFIG', None)
|
||||||
else:
|
else:
|
||||||
os.environ['DOCUTILSCONFIG'] = docutilsconfig
|
os.environ['DOCUTILSCONFIG'] = docutilsconfig
|
||||||
|
|
||||||
|
@ -104,9 +104,12 @@ def test_fundamental_types():
|
|||||||
|
|
||||||
|
|
||||||
def test_expressions():
|
def test_expressions():
|
||||||
def exprCheck(expr, id):
|
def exprCheck(expr, id, id4=None):
|
||||||
ids = 'IE1CIA%s_1aE'
|
ids = 'IE1CIA%s_1aE'
|
||||||
check('class', 'template<> C<a[%s]>' % expr, {2: ids % expr, 3: ids % id})
|
idDict = {2: ids % expr, 3: ids % id}
|
||||||
|
if id4 is not None:
|
||||||
|
idDict[4] = ids % id4
|
||||||
|
check('class', 'template<> C<a[%s]>' % expr, idDict)
|
||||||
# primary
|
# primary
|
||||||
exprCheck('nullptr', 'LDnE')
|
exprCheck('nullptr', 'LDnE')
|
||||||
exprCheck('true', 'L1E')
|
exprCheck('true', 'L1E')
|
||||||
@ -153,7 +156,9 @@ def test_expressions():
|
|||||||
exprCheck(p + "'\\U0001F34C'", t + "127820")
|
exprCheck(p + "'\\U0001F34C'", t + "127820")
|
||||||
|
|
||||||
# TODO: user-defined lit
|
# TODO: user-defined lit
|
||||||
exprCheck('(... + Ns)', '(... + Ns)')
|
exprCheck('(... + Ns)', '(... + Ns)', id4='flpl2Ns')
|
||||||
|
exprCheck('(Ns + ...)', '(Ns + ...)', id4='frpl2Ns')
|
||||||
|
exprCheck('(Ns + ... + 0)', '(Ns + ... + 0)', id4='fLpl2NsL0E')
|
||||||
exprCheck('(5)', 'L5E')
|
exprCheck('(5)', 'L5E')
|
||||||
exprCheck('C', '1C')
|
exprCheck('C', '1C')
|
||||||
# postfix
|
# postfix
|
||||||
@ -242,7 +247,7 @@ def test_expressions():
|
|||||||
# a < expression that starts with something that could be a template
|
# a < expression that starts with something that could be a template
|
||||||
exprCheck('A < 42', 'lt1AL42E')
|
exprCheck('A < 42', 'lt1AL42E')
|
||||||
check('function', 'template<> void f(A<B, 2> &v)',
|
check('function', 'template<> void f(A<B, 2> &v)',
|
||||||
{2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE"})
|
{2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE", 4: "IE1fvR1AI1BXL2EEE"})
|
||||||
exprCheck('A<1>::value', 'N1AIXL1EEE5valueE')
|
exprCheck('A<1>::value', 'N1AIXL1EEE5valueE')
|
||||||
check('class', "template<int T = 42> A", {2: "I_iE1A"})
|
check('class', "template<int T = 42> A", {2: "I_iE1A"})
|
||||||
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
||||||
@ -426,7 +431,7 @@ def test_function_definitions():
|
|||||||
check('function', 'virtual void f()', {1: "f", 2: "1fv"})
|
check('function', 'virtual void f()', {1: "f", 2: "1fv"})
|
||||||
# test for ::nestedName, from issue 1738
|
# test for ::nestedName, from issue 1738
|
||||||
check("function", "result(int val, ::std::error_category const &cat)",
|
check("function", "result(int val, ::std::error_category const &cat)",
|
||||||
{1: "result__i.std::error_categoryCR", 2: "6resultiRNSt14error_categoryE"})
|
{1: "result__i.std::error_categoryCR", 2: "6resultiRKNSt14error_categoryE"})
|
||||||
check("function", "int *f()", {1: "f", 2: "1fv"})
|
check("function", "int *f()", {1: "f", 2: "1fv"})
|
||||||
# tests derived from issue #1753 (skip to keep sanity)
|
# tests derived from issue #1753 (skip to keep sanity)
|
||||||
check("function", "f(int (&array)[10])", {2: "1fRA10_i", 3: "1fRAL10E_i"})
|
check("function", "f(int (&array)[10])", {2: "1fRA10_i", 3: "1fRAL10E_i"})
|
||||||
@ -477,6 +482,10 @@ def test_function_definitions():
|
|||||||
check('function', 'int C::* f(int, double)', {2: '1fid'})
|
check('function', 'int C::* f(int, double)', {2: '1fid'})
|
||||||
check('function', 'void f(int C::* *)', {2: '1fPM1Ci'})
|
check('function', 'void f(int C::* *)', {2: '1fPM1Ci'})
|
||||||
|
|
||||||
|
# exceptions from return type mangling
|
||||||
|
check('function', 'template<typename T> C()', {2: 'I0E1Cv'})
|
||||||
|
check('function', 'template<typename T> operator int()', {1: None, 2: 'I0Ecviv'})
|
||||||
|
|
||||||
|
|
||||||
def test_operators():
|
def test_operators():
|
||||||
check('function', 'void operator new [ ] ()',
|
check('function', 'void operator new [ ] ()',
|
||||||
@ -556,7 +565,7 @@ def test_templates():
|
|||||||
check('class', "A<T>", {2: "IE1AI1TE"}, output="template<> A<T>")
|
check('class', "A<T>", {2: "IE1AI1TE"}, output="template<> A<T>")
|
||||||
# first just check which objects support templating
|
# first just check which objects support templating
|
||||||
check('class', "template<> A", {2: "IE1A"})
|
check('class', "template<> A", {2: "IE1A"})
|
||||||
check('function', "template<> void A()", {2: "IE1Av"})
|
check('function', "template<> void A()", {2: "IE1Av", 4: "IE1Avv"})
|
||||||
check('member', "template<> A a", {2: "IE1a"})
|
check('member', "template<> A a", {2: "IE1a"})
|
||||||
check('type', "template<> a = A", {2: "IE1a"})
|
check('type', "template<> a = A", {2: "IE1a"})
|
||||||
with pytest.raises(DefinitionError):
|
with pytest.raises(DefinitionError):
|
||||||
@ -594,6 +603,10 @@ def test_templates():
|
|||||||
"std::basic_ostream<Char, Traits> &os, "
|
"std::basic_ostream<Char, Traits> &os, "
|
||||||
"const c_string_view_base<const Char, Traits> &str)",
|
"const c_string_view_base<const Char, Traits> &str)",
|
||||||
{2: "I00ElsRNSt13basic_ostreamI4Char6TraitsEE"
|
{2: "I00ElsRNSt13basic_ostreamI4Char6TraitsEE"
|
||||||
|
"RK18c_string_view_baseIK4Char6TraitsE",
|
||||||
|
4: "I00Els"
|
||||||
|
"RNSt13basic_ostreamI4Char6TraitsEE"
|
||||||
|
"RNSt13basic_ostreamI4Char6TraitsEE"
|
||||||
"RK18c_string_view_baseIK4Char6TraitsE"})
|
"RK18c_string_view_baseIK4Char6TraitsE"})
|
||||||
|
|
||||||
# template introductions
|
# template introductions
|
||||||
@ -617,9 +630,11 @@ def test_templates():
|
|||||||
check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux',
|
check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux',
|
||||||
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
||||||
check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()',
|
check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()',
|
||||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv'})
|
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv',
|
||||||
|
4: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEvv'})
|
||||||
check('function', 'abc::ns::foo{id_0, id_1, ...id_2} void xyz::bar()',
|
check('function', 'abc::ns::foo{id_0, id_1, ...id_2} void xyz::bar()',
|
||||||
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv'})
|
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv',
|
||||||
|
4: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEvv'})
|
||||||
check('member', 'abc::ns::foo{id_0, id_1, id_2} ghi::qux xyz::bar',
|
check('member', 'abc::ns::foo{id_0, id_1, id_2} ghi::qux xyz::bar',
|
||||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
||||||
check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
|
check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
|
||||||
@ -646,7 +661,8 @@ def test_template_args():
|
|||||||
"template<typename F> "
|
"template<typename F> "
|
||||||
"void allow(F *f, typename func<F, B, G != 1>::type tt)",
|
"void allow(F *f, typename func<F, B, G != 1>::type tt)",
|
||||||
{2: "I0E5allowP1FN4funcI1F1BXG != 1EE4typeE",
|
{2: "I0E5allowP1FN4funcI1F1BXG != 1EE4typeE",
|
||||||
3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE"})
|
3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE",
|
||||||
|
4: "I0E5allowvP1FN4funcI1F1BXne1GL1EEE4typeE"})
|
||||||
# from #3542
|
# from #3542
|
||||||
check('type', "template<typename T> "
|
check('type', "template<typename T> "
|
||||||
"enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>",
|
"enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>",
|
||||||
|
Loading…
Reference in New Issue
Block a user