mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++ fixes
- Hyperlinks for declarations involving east cv-qualifiers. - Duplicate declaration error on function templates with constraints in the return type. Fixes sphinx-doc/sphinx#5755
This commit is contained in:
parent
3a83f29f86
commit
8eb4ab0681
3
CHANGES
3
CHANGES
@ -20,6 +20,9 @@ Bugs fixed
|
||||
be searched.
|
||||
* #5889: LaTeX: user ``numfig_format`` is stripped of spaces and may cause
|
||||
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.
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
@ -364,8 +364,8 @@ _keywords = [
|
||||
'while', 'xor', 'xor_eq'
|
||||
]
|
||||
|
||||
_max_id = 3
|
||||
_id_prefix = [None, '', '_CPPv2', '_CPPv3']
|
||||
_max_id = 4
|
||||
_id_prefix = [None, '', '_CPPv2', '_CPPv3', '_CPPv4']
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Id v1 constants
|
||||
@ -895,7 +895,7 @@ class ASTFoldExpr(ASTBase):
|
||||
|
||||
def get_id(self, version):
|
||||
assert version >= 3
|
||||
if version == 3:
|
||||
if version == 3 or version == 4:
|
||||
return text_type(self)
|
||||
# TODO: find the right mangling scheme
|
||||
assert False
|
||||
@ -2537,11 +2537,12 @@ class ASTDeclSpecs(ASTBase):
|
||||
res.append('C')
|
||||
return u''.join(res)
|
||||
res = []
|
||||
if self.leftSpecs.volatile or self.rightSpecs.volatile:
|
||||
if self.allSpecs.volatile:
|
||||
res.append('V')
|
||||
if self.leftSpecs.const or self.rightSpecs.volatile:
|
||||
if self.allSpecs.const:
|
||||
res.append('K')
|
||||
res.append(self.trailingTypeSpec.get_id(version))
|
||||
if self.trailingTypeSpec is not None:
|
||||
res.append(self.trailingTypeSpec.get_id(version))
|
||||
return u''.join(res)
|
||||
|
||||
def _stringify(self, transform):
|
||||
@ -3177,6 +3178,14 @@ class ASTType(ASTBase):
|
||||
if objectType == 'function': # also modifiers
|
||||
modifiers = self.decl.get_modifiers_id(version)
|
||||
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))
|
||||
elif objectType == 'type': # just the name
|
||||
res.append(symbol.get_full_nested_name().get_id(version))
|
||||
@ -6354,7 +6363,7 @@ class CPPObject(ObjectDescription):
|
||||
# Assume we are actually in the old symbol,
|
||||
# instead of the newly created duplicate.
|
||||
self.env.temp_data['cpp:last_symbol'] = e.symbol
|
||||
self.warn("Duplicate declaration.")
|
||||
self.warn("Duplicate declaration, %s" % sig)
|
||||
|
||||
if ast.objectType == 'enumerator':
|
||||
self._add_enumerator_to_parent(ast)
|
||||
|
@ -244,7 +244,7 @@ def test_expressions():
|
||||
# a < expression that starts with something that could be a template
|
||||
exprCheck('A < 42', 'lt1AL42E')
|
||||
check('function', 'template<> void f(A<B, 2> &v)',
|
||||
{2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE"})
|
||||
{2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE", 4: "IE1fvR1AI1BXL2EEE"})
|
||||
exprCheck('A<1>::value', 'N1AIXL1EEE5valueE')
|
||||
check('class', "template<int T = 42> A", {2: "I_iE1A"})
|
||||
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
||||
@ -428,7 +428,7 @@ def test_function_definitions():
|
||||
check('function', 'virtual void f()', {1: "f", 2: "1fv"})
|
||||
# test for ::nestedName, from issue 1738
|
||||
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"})
|
||||
# tests derived from issue #1753 (skip to keep sanity)
|
||||
check("function", "f(int (&array)[10])", {2: "1fRA10_i", 3: "1fRAL10E_i"})
|
||||
@ -479,6 +479,10 @@ def test_function_definitions():
|
||||
check('function', 'int C::* f(int, double)', {2: '1fid'})
|
||||
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():
|
||||
check('function', 'void operator new [ ] ()',
|
||||
@ -558,7 +562,7 @@ def test_templates():
|
||||
check('class', "A<T>", {2: "IE1AI1TE"}, output="template<> A<T>")
|
||||
# first just check which objects support templating
|
||||
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('type', "template<> a = A", {2: "IE1a"})
|
||||
with pytest.raises(DefinitionError):
|
||||
@ -596,6 +600,10 @@ def test_templates():
|
||||
"std::basic_ostream<Char, Traits> &os, "
|
||||
"const c_string_view_base<const Char, Traits> &str)",
|
||||
{2: "I00ElsRNSt13basic_ostreamI4Char6TraitsEE"
|
||||
"RK18c_string_view_baseIK4Char6TraitsE",
|
||||
4: "I00Els"
|
||||
"RNSt13basic_ostreamI4Char6TraitsEE"
|
||||
"RNSt13basic_ostreamI4Char6TraitsEE"
|
||||
"RK18c_string_view_baseIK4Char6TraitsE"})
|
||||
|
||||
# template introductions
|
||||
@ -619,9 +627,11 @@ def test_templates():
|
||||
check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux',
|
||||
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
||||
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()',
|
||||
{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',
|
||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
||||
check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
|
||||
@ -648,7 +658,8 @@ def test_template_args():
|
||||
"template<typename F> "
|
||||
"void allow(F *f, typename func<F, B, G != 1>::type tt)",
|
||||
{2: "I0E5allowP1FN4funcI1F1BXG != 1EE4typeE",
|
||||
3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE"})
|
||||
3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE",
|
||||
4: "I0E5allowvP1FN4funcI1F1BXne1GL1EEE4typeE"})
|
||||
# from #3542
|
||||
check('type', "template<typename T> "
|
||||
"enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>",
|
||||
|
Loading…
Reference in New Issue
Block a user