r292545 - Finish implementation of C++ DR1310 (http://wg21.link/cwg1310).
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 19 16:20:39 PST 2017
Author: rsmith
Date: Thu Jan 19 18:20:39 2017
New Revision: 292545
URL: http://llvm.org/viewvc/llvm-project?rev=292545&view=rev
Log:
Finish implementation of C++ DR1310 (http://wg21.link/cwg1310).
Diagnose the case when a dependent template name instantiates to an
injected-class-name outside a nested-name-specifier.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
cfe/trunk/test/CXX/drs/dr10xx.cpp
cfe/trunk/test/CXX/drs/dr13xx.cpp
cfe/trunk/www/cxx_dr_status.html
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jan 19 18:20:39 2017
@@ -5984,13 +5984,10 @@ public:
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- TemplateNameKind ActOnDependentTemplateName(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- UnqualifiedId &Name,
- ParsedType ObjectType,
- bool EnteringContext,
- TemplateTy &Template);
+ TemplateNameKind ActOnDependentTemplateName(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
+ TemplateTy &Template, bool AllowInjectedClassName = false);
DeclResult
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Jan 19 18:20:39 2017
@@ -310,11 +310,9 @@ bool Parser::ParseOptionalCXXScopeSpecif
// Commit to parsing the template-id.
TPA.Commit();
TemplateTy Template;
- if (TemplateNameKind TNK
- = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, TemplateKWLoc, TemplateName,
- ObjectType, EnteringContext,
- Template)) {
+ if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true)) {
if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc,
TemplateName, false))
return true;
@@ -509,12 +507,10 @@ bool Parser::ParseOptionalCXXScopeSpecif
Diag(Tok.getLocation(), DiagID)
<< II.getName()
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
-
- if (TemplateNameKind TNK
- = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, SourceLocation(),
- TemplateName, ObjectType,
- EnteringContext, Template)) {
+
+ if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, SourceLocation(), TemplateName, ObjectType,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true)) {
// Consume the identifier.
ConsumeToken();
if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
@@ -2020,9 +2016,11 @@ bool Parser::ParseUnqualifiedIdTemplateI
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
if (AssumeTemplateId) {
- TNK = Actions.ActOnDependentTemplateName(getCurScope(), SS, TemplateKWLoc,
- Id, ObjectType, EnteringContext,
- Template);
+ // We defer the injected-class-name checks until we've found whether
+ // this template-id is used to form a nested-name-specifier or not.
+ TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
+ Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
return true;
} else {
@@ -2051,10 +2049,9 @@ bool Parser::ParseUnqualifiedIdTemplateI
Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
<< Name
<< FixItHint::CreateInsertion(Id.StartLocation, "template ");
- TNK = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, TemplateKWLoc, Id,
- ObjectType, EnteringContext,
- Template);
+ TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
+ Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
return true;
}
@@ -2077,10 +2074,9 @@ bool Parser::ParseUnqualifiedIdTemplateI
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
if (ObjectType) {
- TNK = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, TemplateKWLoc, TemplateName,
- ObjectType, EnteringContext,
- Template);
+ TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
return true;
} else {
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jan 19 18:20:39 2017
@@ -3241,7 +3241,8 @@ TemplateNameKind Sema::ActOnDependentTem
UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
- TemplateTy &Result) {
+ TemplateTy &Result,
+ bool AllowInjectedClassName) {
if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TemplateKWLoc,
getLangOpts().CPlusPlus11 ?
@@ -3289,6 +3290,24 @@ TemplateNameKind Sema::ActOnDependentTem
return TNK_Non_template;
} else {
// We found something; return it.
+ auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx);
+ if (!AllowInjectedClassName && SS.isSet() && LookupRD &&
+ Name.getKind() == UnqualifiedId::IK_Identifier && Name.Identifier &&
+ LookupRD->getIdentifier() == Name.Identifier) {
+ // C++14 [class.qual]p2:
+ // In a lookup in which function names are not ignored and the
+ // nested-name-specifier nominates a class C, if the name specified
+ // [...] is the injected-class-name of C, [...] the name is instead
+ // considered to name the constructor
+ //
+ // We don't get here if naming the constructor would be valid, so we
+ // just reject immediately and recover by treating the
+ // injected-class-name as naming the template.
+ Diag(Name.getLocStart(),
+ diag::ext_out_of_line_qualified_id_type_names_constructor)
+ << Name.Identifier << 0 /*injected-class-name used as template name*/
+ << 1 /*'template' keyword was used*/;
+ }
return TNK;
}
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jan 19 18:20:39 2017
@@ -806,7 +806,8 @@ namespace {
TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr);
+ NamedDecl *FirstQualifierInScope = nullptr,
+ bool AllowInjectedClassName = false);
const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
@@ -1040,11 +1041,10 @@ TemplateInstantiator::RebuildElaboratedT
T);
}
-TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
+TemplateName TemplateInstantiator::TransformTemplateName(
+ CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
+ QualType ObjectType, NamedDecl *FirstQualifierInScope,
+ bool AllowInjectedClassName) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -1095,9 +1095,10 @@ TemplateName TemplateInstantiator::Trans
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
return Arg.getAsTemplate();
}
-
- return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
- FirstQualifierInScope);
+
+ return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
+ FirstQualifierInScope,
+ AllowInjectedClassName);
}
ExprResult
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jan 19 18:20:39 2017
@@ -505,7 +505,8 @@ public:
TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr);
+ NamedDecl *FirstQualifierInScope = nullptr,
+ bool AllowInjectedClassName = false);
/// \brief Transform the given template argument.
///
@@ -916,14 +917,15 @@ public:
NestedNameSpecifierLoc QualifierLoc,
const IdentifierInfo *Name,
SourceLocation NameLoc,
- TemplateArgumentListInfo &Args) {
+ TemplateArgumentListInfo &Args,
+ bool AllowInjectedClassName) {
// Rebuild the template name.
// TODO: avoid TemplateName abstraction
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
TemplateName InstName
= getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(),
- nullptr);
+ nullptr, AllowInjectedClassName);
if (InstName.isNull())
return QualType();
@@ -1088,7 +1090,8 @@ public:
const IdentifierInfo &Name,
SourceLocation NameLoc,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope);
+ NamedDecl *FirstQualifierInScope,
+ bool AllowInjectedClassName);
/// \brief Build a new template name given a nested name specifier and the
/// overloaded operator name that is referred to as a template.
@@ -1100,7 +1103,8 @@ public:
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
OverloadedOperatorKind Operator,
SourceLocation NameLoc,
- QualType ObjectType);
+ QualType ObjectType,
+ bool AllowInjectedClassName);
/// \brief Build a new template name given a template template parameter pack
/// and the
@@ -3601,7 +3605,8 @@ TreeTransform<Derived>::TransformTemplat
TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
+ NamedDecl *FirstQualifierInScope,
+ bool AllowInjectedClassName) {
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
TemplateDecl *Template = QTN->getTemplateDecl();
assert(Template && "qualified template name must refer to a template");
@@ -3638,11 +3643,12 @@ TreeTransform<Derived>::TransformTemplat
*DTN->getIdentifier(),
NameLoc,
ObjectType,
- FirstQualifierInScope);
+ FirstQualifierInScope,
+ AllowInjectedClassName);
}
return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc,
- ObjectType);
+ ObjectType, AllowInjectedClassName);
}
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
@@ -4152,11 +4158,9 @@ TypeSourceInfo *TreeTransform<Derived>::
TemplateSpecializationTypeLoc SpecTL =
TL.castAs<TemplateSpecializationTypeLoc>();
- TemplateName Template
- = getDerived().TransformTemplateName(SS,
- SpecTL.getTypePtr()->getTemplateName(),
- SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup);
+ TemplateName Template = getDerived().TransformTemplateName(
+ SS, SpecTL.getTypePtr()->getTemplateName(), SpecTL.getTemplateNameLoc(),
+ ObjectType, UnqualLookup, /*AllowInjectedClassName*/true);
if (Template.isNull())
return nullptr;
@@ -4170,7 +4174,8 @@ TypeSourceInfo *TreeTransform<Derived>::
= getDerived().RebuildTemplateName(SS,
*SpecTL.getTypePtr()->getIdentifier(),
SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup);
+ ObjectType, UnqualLookup,
+ /*AllowInjectedClassName*/true);
if (Template.isNull())
return nullptr;
@@ -5878,12 +5883,10 @@ TransformDependentTemplateSpecialization
NewTemplateArgs))
return QualType();
- QualType Result
- = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(),
- QualifierLoc,
- T->getIdentifier(),
- TL.getTemplateNameLoc(),
- NewTemplateArgs);
+ QualType Result = getDerived().RebuildDependentTemplateSpecializationType(
+ T->getKeyword(), QualifierLoc, T->getIdentifier(),
+ TL.getTemplateNameLoc(), NewTemplateArgs,
+ /*AllowInjectedClassName*/ false);
if (Result.isNull())
return QualType();
@@ -12015,7 +12018,8 @@ TreeTransform<Derived>::RebuildTemplateN
const IdentifierInfo &Name,
SourceLocation NameLoc,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
+ NamedDecl *FirstQualifierInScope,
+ bool AllowInjectedClassName) {
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
@@ -12024,7 +12028,7 @@ TreeTransform<Derived>::RebuildTemplateN
SS, TemplateKWLoc, TemplateName,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
- Template);
+ Template, AllowInjectedClassName);
return Template.get();
}
@@ -12033,7 +12037,8 @@ TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
OverloadedOperatorKind Operator,
SourceLocation NameLoc,
- QualType ObjectType) {
+ QualType ObjectType,
+ bool AllowInjectedClassName) {
UnqualifiedId Name;
// FIXME: Bogus location information.
SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc };
@@ -12044,7 +12049,7 @@ TreeTransform<Derived>::RebuildTemplateN
SS, TemplateKWLoc, Name,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
- Template);
+ Template, AllowInjectedClassName);
return Template.get();
}
Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp Thu Jan 19 18:20:39 2017
@@ -81,9 +81,7 @@ template void in_instantiation_x0<X0>();
template<typename T> void in_instantiation_x1() {
typename T::X1 x1; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a type in this context}}
- // FIXME: Matching the behavior of other compilers, we do not treat this case
- // as naming the constructor.
- typename T::template X1<int> x1i;
+ typename T::template X1<int> x1i; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a template name in this context}}
typename T::X0 x0;
}
template void in_instantiation_x1<X1<int> >(); // expected-note {{instantiation of}}
Modified: cfe/trunk/test/CXX/drs/dr10xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr10xx.cpp?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr10xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr10xx.cpp Thu Jan 19 18:20:39 2017
@@ -29,10 +29,11 @@ namespace dr1004 { // dr1004: 5
}
};
- // FIXME: Is this example (from the standard) really OK, or does name lookup
- // of "T::template A" name the constructor?
- template<class T, template<class> class U = T::template A> struct Third { };
- Third<A<int> > t;
+ // This example (from the standard) is actually ill-formed, because
+ // name lookup of "T::template A" names the constructor.
+ // FIXME: Only issue one diagnostic for this case.
+ template<class T, template<class> class U = T::template A> struct Third { }; // expected-error 2{{is a constructor name}}
+ Third<A<int> > t; // expected-note {{in instantiation of}} expected-note {{while substituting}} expected-note {{while checking}}
}
namespace dr1048 { // dr1048: 3.6
Modified: cfe/trunk/test/CXX/drs/dr13xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr13xx.cpp?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr13xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr13xx.cpp Thu Jan 19 18:20:39 2017
@@ -13,7 +13,7 @@ namespace std {
};
}
-namespace dr1310 { // dr1310: partial
+namespace dr1310 { // dr1310: 5
struct S {} * sp = new S::S; // expected-error {{qualified reference to 'S' is a constructor name}}
void f() {
S::S(a); // expected-error {{qualified reference to 'S' is a constructor name}}
@@ -36,34 +36,61 @@ namespace dr1310 { // dr1310: partial
template struct VT<T>;
template<template<typename> class> class TT {};
+ template<typename> class TTy {};
- template<typename T> struct W {};
+ template<typename T> struct WBase {};
+ template<typename T> struct W : WBase<T> { typedef int X; int n; };
void w_test() {
W<int>::W w1a; // expected-error {{qualified reference to 'W' is a constructor name}}
+ W<int>::W::X w1ax;
W<int>::W<int> w1b; // expected-error {{qualified reference to 'W' is a constructor name}}
- typename W<int>::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{typename}}
- typename W<int>::W<int> w2b; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{typename}}
- W<int>::template W<int> w3; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{template}}
- typename W<int>::template W<int> w4; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{typename}} expected-error 0-1{{template}}
- TT<W<int>::W> tt1; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{template}}
- // FIXME: It's inconsistent for us to reject the above 'template' cases but
- // not this one; per the standard, they are all ill-formed.
- TT<W<int>::template W> tt2; // expected-error 0-1{{template}}
+ W<int>::W<int>::X w1bx;
+ typename W<int>::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}}
+ typename W<int>::W::X w2ax; // expected-error 0-1{{outside of a template}}
+ typename W<int>::W<int> w2b; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}}
+ typename W<int>::W<int>::X w2bx; // expected-error 0-1{{outside of a template}}
+ W<int>::template W<int> w3; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}}
+ W<int>::template W<int>::X w3x; // expected-error 0-1{{outside of a template}}
+ typename W<int>::template W<int> w4; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-2{{outside of a template}}
+ typename W<int>::template W<int>::X w4x; // expected-error 0-2{{outside of a template}}
+
+ TT<W<int>::W> tt1; // expected-error {{qualified reference to 'W' is a constructor name}}
+ TTy<W<int>::W> tt1a; // expected-error {{qualified reference to 'W' is a constructor name}}
+ TT<W<int>::template W> tt2; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}}
+ TT<W<int>::WBase> tt3;
+ TTy<W<int>::WBase> tt3a;
+ TT<W<int>::template WBase> tt4; // expected-error 0-1{{outside of a template}}
+
+ W<int> w;
+ (void)w.W::W::n;
+ (void)w.W<int>::W::n;
+ (void)w.W<int>::W<int>::n;
+ (void)w.W<int>::template W<int>::n; // expected-error 0-1{{outside of a template}}
}
template<typename W>
void wt_test() {
- typename W::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{typename}}
- // FIXME: We reject the non-dependent form of this, and this case appears
- // to be ill-formed too. However, our behavior here matches that of other
- // implementations.
- typename W::template W<int> w4; // expected-error 0-1{{typename}} expected-error 0-1{{template}}
- // FIXME: We reject the non-dependent form of this one, too.
- TT<W::W> tt1; // expected-error 0-1{{template}}
- TT<W::template W> tt2; // expected-error 0-1{{template}}
+ typename W::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}}
+ typename W::template W<int> w4; // expected-error {{qualified reference to 'W' is a constructor name}}
+ TTy<typename W::W> tt2; // expected-error {{qualified reference to 'W' is a constructor name}}
+ TT<W::template W> tt3; // expected-error {{qualified reference to 'W' is a constructor name}}
+ }
+ template<typename W>
+ void wt_test_good() {
+ typename W::W::X w2ax;
+ typename W::template W<int>::X w4x;
+ TTy<typename W::WBase> tt4;
+ TT<W::template WBase> tt5;
+
+ W w;
+ (void)w.W::W::n;
+ (void)w.W::template W<int>::n;
+ (void)w.template W<int>::W::n;
+ (void)w.template W<int>::template W<int>::n;
}
template void wt_test<W<int> >(); // expected-note {{instantiation of}}
+ template void wt_test_good<W<int> >();
}
namespace dr1315 { // dr1315: partial
Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=292545&r1=292544&r2=292545&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Thu Jan 19 18:20:39 2017
@@ -1949,7 +1949,7 @@ of class templates</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#318">318</a></td>
<td>CD1</td>
<td><TT>struct A::A</TT> should not name the constructor of <TT>A</TT></td>
- <td class="partial" align="center">Superseded by <a href="#1310">1310</a></td>
+ <td class="svn" align="center">Superseded by <a href="#1310">1310</a></td>
</tr>
<tr id="319">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#319">319</a></td>
@@ -7675,7 +7675,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1310">1310</a></td>
<td>CD3</td>
<td>What is an “acceptable lookup result?”</td>
- <td class="partial" align="center">Partial</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1311">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1311">1311</a></td>
More information about the cfe-commits
mailing list