Restore pre-r335182 behavior for naming inherited constructors as

members of dependent contexts.

This permits cases where the names before and after the '::' in a
dependent inherited constructor using-declaration do not match, but
where we can nonetheless tell when parsing the template that a
constructor is being named. Under (open) core language DR 2070, such
cases will probably be ill-formed, but r335182 does not quite give
that result and didn't intend to change this, so restore the old
behavior for now.

llvm-svn: 335381
This commit is contained in:
Richard Smith 2018-06-22 19:50:19 +00:00
parent 5421b37893
commit 69bc9aa22f
4 changed files with 31 additions and 4 deletions

View File

@ -4985,7 +4985,8 @@ public:
IdentifierInfo &Name);
ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec &SS);
Scope *S, CXXScopeSpec &SS,
bool EnteringContext);
ParsedType getDestructorName(SourceLocation TildeLoc,
IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec &SS,

View File

@ -2505,7 +2505,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
if (AllowConstructorName &&
Actions.isCurrentClassName(*Id, getCurScope(), &SS)) {
// We have parsed a constructor name.
ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS);
ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS,
EnteringContext);
if (!Ty)
return true;
Result.setConstructorName(Ty, IdLoc, IdLoc);
@ -2555,7 +2556,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
<< FixItHint::CreateRemoval(
SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc));
ParsedType Ty = Actions.getConstructorName(
*TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS);
*TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS,
EnteringContext);
if (!Ty)
return true;
Result.setConstructorName(Ty, TemplateId->TemplateNameLoc,

View File

@ -82,11 +82,20 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
ParsedType Sema::getConstructorName(IdentifierInfo &II,
SourceLocation NameLoc,
Scope *S, CXXScopeSpec &SS) {
Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
CXXRecordDecl *CurClass = getCurrentClass(S, &SS);
assert(CurClass && &II == CurClass->getIdentifier() &&
"not a constructor name");
// When naming a constructor as a member of a dependent context (eg, in a
// friend declaration or an inherited constructor declaration), form an
// unresolved "typename" type.
if (CurClass->isDependentContext() && !EnteringContext) {
QualType T = Context.getDependentNameType(ETK_None, SS.getScopeRep(), &II);
return ParsedType::make(T);
}
if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass))
return ParsedType();

View File

@ -199,5 +199,20 @@ namespace InhCtor {
using T::T; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
};
UsingIntTemplate<int> uit; // expected-note {{here}}
// This case is odd: we don't name the constructor of a dependent base as
// Base::Base, but we still happen to have enough information to identify
// when parsing the template that we're inheriting constructors.
//
// FIXME: Once CWG 2070 is resolved, check whether this case should be
// accepted or not.
namespace DependentCtorName {
template <typename T> struct B { B(int); };
template <typename T> struct A : B<T> {
using X = B<T>;
using X::B;
};
A<int> ab = 0;
}
#endif
}