C++, fix direct lookup problem

Also clarify documentation regarding cross-references involving templates.

See also sphinx-doc/sphinx#2057
This commit is contained in:
Jakob Lykke Andersen 2018-08-11 10:30:10 +02:00
parent 0af74a76dc
commit 4397606d03
3 changed files with 48 additions and 27 deletions

View File

@ -172,6 +172,8 @@ Features added
* C++, add support for anonymous entities using names staring with ``@``.
Fixes #3593 and #2683.
* #5147: C++, add support for (most) character literals.
* C++, cross-referencing entities inside primary templates is supported,
and now properly documented.
* #3606: MathJax should be loaded with async attribute
* html: Output ``canonical_url`` metadata if :confval:`html_baseurl` set (refs:
#4193)

View File

@ -1033,19 +1033,25 @@ Assume the following declarations.
Inner
In general the reference must include the template parameter declarations,
e.g., ``template\<typename TOuter> Wrapper::Outer``
(:cpp:class:`template\<typename TOuter> Wrapper::Outer`). Currently the lookup
only succeed if the template parameter identifiers are equal strings. That is,
``template\<typename UOuter> Wrapper::Outer`` will not work.
and template arguments for the prefix of qualified names. For example:
The inner class template cannot be directly referenced, unless the current
namespace is changed or the following shorthand is used. If a template
parameter list is omitted, then the lookup will assume either a template or a
non-template, but not a partial template specialisation. This means the
following references work.
- ``template\<typename TOuter> Wrapper::Outer``
(:cpp:class:`template\<typename TOuter> Wrapper::Outer`)
- ``template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner``
(:cpp:class:`template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner`)
- ``Wrapper::Outer`` (:cpp:class:`Wrapper::Outer`)
- ``Wrapper::Outer::Inner`` (:cpp:class:`Wrapper::Outer::Inner`)
Currently the lookup only succeed if the template parameter identifiers are equal strings.
That is, ``template\<typename UOuter> Wrapper::Outer`` will not work.
As a shorthand notation, if a template parameter list is omitted,
then the lookup will assume either a primary template or a non-template,
but not a partial template specialisation.
This means the following references work as well:
- ``Wrapper::Outer``
(:cpp:class:`Wrapper::Outer`)
- ``Wrapper::Outer::Inner``
(:cpp:class:`Wrapper::Outer::Inner`)
- ``template\<typename TInner> Wrapper::Outer::Inner``
(:cpp:class:`template\<typename TInner> Wrapper::Outer::Inner`)

View File

@ -3634,8 +3634,9 @@ class Symbol(object):
return ASTNestedName(names, templates, rooted=False)
def _find_named_symbol(self, identOrOp, templateParams, templateArgs,
templateShorthand, matchSelf, recurseInAnon):
# type: (Any, Any, Any, Any, bool, bool) -> Symbol
templateShorthand, matchSelf, recurseInAnon,
correctPrimaryTemplateArgs):
# type: (Any, Any, Any, Any, bool, bool, bool) -> Symbol
def isSpecialization():
# the names of the template parameters must be given exactly as args
@ -3658,12 +3659,13 @@ class Symbol(object):
if paramName != argName:
return True
return False
if templateParams is not None and templateArgs is not None:
# If both are given, but it's not a specialization, then do lookup as if
# there is no argument list.
# For example: template<typename T> int A<T>::var;
if not isSpecialization():
templateArgs = None
if correctPrimaryTemplateArgs:
if templateParams is not None and templateArgs is not None:
# If both are given, but it's not a specialization, then do lookup as if
# there is no argument list.
# For example: template<typename T> int A<T>::var;
if not isSpecialization():
templateArgs = None
def matches(s):
if s.identOrOp != identOrOp:
@ -3722,7 +3724,8 @@ class Symbol(object):
templateArgs,
templateShorthand=False,
matchSelf=False,
recurseInAnon=True)
recurseInAnon=True,
correctPrimaryTemplateArgs=True)
if symbol is None:
symbol = Symbol(parent=parentSymbol, identOrOp=identOrOp,
templateParams=templateParams,
@ -3746,7 +3749,8 @@ class Symbol(object):
templateArgs,
templateShorthand=False,
matchSelf=False,
recurseInAnon=True)
recurseInAnon=True,
correctPrimaryTemplateArgs=False)
if symbol:
if not declaration:
# good, just a scope creation
@ -3797,7 +3801,8 @@ class Symbol(object):
templateArgs=otherChild.templateArgs,
templateShorthand=False,
matchSelf=False,
recurseInAnon=False)
recurseInAnon=False,
correctPrimaryTemplateArgs=False)
if ourChild is None:
# TODO: hmm, should we prune by docnames?
self._children.append(otherChild)
@ -3860,7 +3865,8 @@ class Symbol(object):
templateParams, templateArgs,
templateShorthand=False,
matchSelf=False,
recurseInAnon=False)
recurseInAnon=False,
correctPrimaryTemplateArgs=False)
if not s:
return None
return s
@ -3911,7 +3917,8 @@ class Symbol(object):
templateParams, templateArgs,
templateShorthand=templateShorthand,
matchSelf=matchSelf,
recurseInAnon=recurseInAnon)
recurseInAnon=recurseInAnon,
correctPrimaryTemplateArgs=False)
if symbol is not None:
return symbol
# try without template params and args
@ -3919,7 +3926,8 @@ class Symbol(object):
None, None,
templateShorthand=templateShorthand,
matchSelf=matchSelf,
recurseInAnon=recurseInAnon)
recurseInAnon=recurseInAnon,
correctPrimaryTemplateArgs=False)
return symbol
else:
identOrOp = name.identOrOp
@ -3933,9 +3941,13 @@ class Symbol(object):
templateParams, templateArgs,
templateShorthand=templateShorthand,
matchSelf=matchSelf,
recurseInAnon=recurseInAnon)
recurseInAnon=recurseInAnon,
correctPrimaryTemplateArgs=True)
if symbol is None:
# TODO: maybe search without template args
# TODO: Maybe search without template args?
# Though, the correctPrimaryTemplateArgs above does
# that for primary templates.
# Is there another case where it would be good?
return None
# We have now matched part of a nested name, and need to match more
# so even if we should matchSelf before, we definitely shouldn't
@ -6343,6 +6355,7 @@ class CPPDomain(Domain):
if not parentSymbol:
print("Target: ", target)
print("ParentKey: ", parentKey)
print(rootSymbol.dump(1))
assert parentSymbol # should be there
else:
parentSymbol = rootSymbol