[cfe-commits] r142906 - in /cfe/trunk: include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Parse/Parser.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/SemaTemplate/ms-if-exists.cpp
Douglas Gregor
dgregor at apple.com
Mon Oct 24 20:44:56 PDT 2011
Author: dgregor
Date: Mon Oct 24 22:44:56 2011
New Revision: 142906
URL: http://llvm.org/viewvc/llvm-project?rev=142906&view=rev
Log:
Check for unexpanded parameter packs in the name that guards a
Microsoft __if_exists/__if_not_exists statement. Also note that we
weren't traversing DeclarationNameInfo *at all* within the
RecursiveASTVisitor, which would be rather fatal for variadic
templates.
Modified:
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/ms-if-exists.cpp
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Oct 24 22:44:56 2011
@@ -187,6 +187,11 @@
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+ /// \brief Recursively visit a name with its location information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
+
/// \brief Recursively visit a template name and dispatch to the
/// appropriate method.
///
@@ -546,6 +551,31 @@
}
template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
+ DeclarationNameInfo NameInfo) {
+ switch (NameInfo.getName().getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
+ TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
+
+ break;
+
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return true;
+}
+
+template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
@@ -1216,6 +1246,7 @@
DEF_TRAVERSE_DECL(UsingDecl, {
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
})
DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
@@ -1511,6 +1542,7 @@
// Like UnresolvedUsingTypenameDecl, but without the 'typename':
// template <class T> Class A : public Base<T> { using Base<T>::foo; };
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
})
DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
@@ -1548,6 +1580,7 @@
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
// If we're an explicit template specialization, iterate over the
// template args that were explicitly specified. If we were doing
@@ -1737,6 +1770,7 @@
DEF_TRAVERSE_STMT(CXXForRangeStmt, { })
DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
})
DEF_TRAVERSE_STMT(ReturnStmt, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
@@ -1745,6 +1779,7 @@
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
if (S->hasExplicitTemplateArgs()) {
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
@@ -1753,12 +1788,14 @@
DEF_TRAVERSE_STMT(DeclRefExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
})
DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
if (S->hasExplicitTemplateArgs()) {
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getExplicitTemplateArgs().getTemplateArgs(),
@@ -1768,6 +1805,7 @@
DEF_TRAVERSE_STMT(MemberExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
})
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 24 22:44:56 2011
@@ -2573,25 +2573,29 @@
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
- "non-type template parameter type|exception type|partial specialization}0 "
+ "non-type template parameter type|exception type|partial specialization|"
+ "__if_exists name|__if_not_exists name}0 "
"contains an unexpanded parameter pack">;
def err_unexpanded_parameter_pack_1 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
- "non-type template parameter type|exception type|partial specialization}0 "
+ "non-type template parameter type|exception type|partial specialization|"
+ "__if_exists name|__if_not_exists name}0 "
"contains unexpanded parameter pack %1">;
def err_unexpanded_parameter_pack_2 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
- "non-type template parameter type|exception type|partial specialization}0 "
+ "non-type template parameter type|exception type|partial specialization|"
+ "__if_exists name|__if_not_exists name}0 "
"contains unexpanded parameter packs %1 and %2">;
def err_unexpanded_parameter_pack_3_or_more : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
- "non-type template parameter type|exception type|partial specialization}0 "
+ "non-type template parameter type|exception type|partial specialization|"
+ "__if_exists name|__if_not_exists name}0 "
"contains unexpanded parameter packs %1, %2, ...">;
def err_pack_expansion_without_parameter_packs : Error<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 24 22:44:56 2011
@@ -2599,8 +2599,12 @@
/// \brief The symbol does not exist.
IER_DoesNotExist,
- /// \brief The name is a dependent name, so it
- IER_Dependent
+ /// \brief The name is a dependent name, so the results will differ
+ /// from one instantiation to the next.
+ IER_Dependent,
+
+ /// \brief An error occurred.
+ IER_Error
};
IfExistsResult
@@ -2608,7 +2612,9 @@
const DeclarationNameInfo &TargetNameInfo);
IfExistsResult
- CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name);
+ CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name);
StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
bool IsIfExists,
@@ -4235,8 +4241,26 @@
UPPC_ExceptionType,
/// \brief Partial specialization.
- UPPC_PartialSpecialization
- };
+ UPPC_PartialSpecialization,
+
+ /// \brief Microsoft __if_exists.
+ UPPC_IfExists,
+
+ /// \brief Microsoft __if_not_exists.
+ UPPC_IfNotExists
+};
+
+ /// \brief Diagnose unexpanded parameter packs.
+ ///
+ /// \param Loc The location at which we should emit the diagnostic.
+ ///
+ /// \param UPPC The context in which we are diagnosing unexpanded
+ /// parameter packs.
+ ///
+ /// \param Unexpanded the set of unexpanded parameter packs.
+ void DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
+ UnexpandedParameterPackContext UPPC,
+ const SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
/// \brief If the given type contains an unexpanded parameter pack,
/// diagnose the error.
@@ -4335,6 +4359,22 @@
void collectUnexpandedParameterPacks(TypeLoc TL,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// nested-name-specifier.
+ ///
+ /// \param SS The nested-name-specifier that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(CXXScopeSpec &SS,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// name.
+ ///
+ /// \param NameInfo The name that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
/// \brief Invoked when parsing a template argument followed by an
/// ellipsis, which creates a pack expansion.
///
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Oct 24 22:44:56 2011
@@ -1503,7 +1503,8 @@
return true;
// Check if the symbol exists.
- switch (Actions.CheckMicrosoftIfExistsSymbol(getCurScope(), Result.SS,
+ switch (Actions.CheckMicrosoftIfExistsSymbol(getCurScope(), Result.KeywordLoc,
+ Result.IsIfExists, Result.SS,
Result.Name)) {
case Sema::IER_Exists:
Result.Behavior = Result.IsIfExists ? IEB_Parse : IEB_Skip;
@@ -1516,6 +1517,9 @@
case Sema::IER_Dependent:
Result.Behavior = IEB_Dependent;
break;
+
+ case Sema::IER_Error:
+ return true;
}
return false;
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Oct 24 22:44:56 2011
@@ -4700,10 +4700,24 @@
return IER_DoesNotExist;
}
-Sema::IfExistsResult Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name) {
+Sema::IfExistsResult
+Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name) {
DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
+
+ // Check for unexpanded parameter packs.
+ SmallVector<UnexpandedParameterPack, 4> Unexpanded;
+ collectUnexpandedParameterPacks(SS, Unexpanded);
+ collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded);
+ if (!Unexpanded.empty()) {
+ DiagnoseUnexpandedParameterPacks(KeywordLoc,
+ IsIfExists? UPPC_IfExists
+ : UPPC_IfNotExists,
+ Unexpanded);
+ return IER_Error;
+ }
+
return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Oct 24 22:44:56 2011
@@ -1307,7 +1307,7 @@
= cast<TemplateTemplateParmDecl>(*NewParam);
// Check for unexpanded parameter packs, recursively.
- if (DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
+ if (::DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
Invalid = true;
continue;
}
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Oct 24 22:44:56 2011
@@ -155,10 +155,13 @@
/// \brief Diagnose all of the unexpanded parameter packs in the given
/// vector.
-static void
-DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
- Sema::UnexpandedParameterPackContext UPPC,
+void
+Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
+ UnexpandedParameterPackContext UPPC,
const SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ if (Unexpanded.empty())
+ return;
+
SmallVector<SourceLocation, 4> Locations;
SmallVector<IdentifierInfo *, 4> Names;
llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
@@ -179,13 +182,13 @@
}
DiagnosticBuilder DB
- = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
+ = Names.size() == 0? Diag(Loc, diag::err_unexpanded_parameter_pack_0)
<< (int)UPPC
- : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
+ : Names.size() == 1? Diag(Loc, diag::err_unexpanded_parameter_pack_1)
<< (int)UPPC << Names[0]
- : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
+ : Names.size() == 2? Diag(Loc, diag::err_unexpanded_parameter_pack_2)
<< (int)UPPC << Names[0] << Names[1]
- : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
+ : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
<< (int)UPPC << Names[0] << Names[1];
for (unsigned I = 0, N = Locations.size(); I != N; ++I)
@@ -205,7 +208,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
T->getTypeLoc());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
+ DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
return true;
}
@@ -220,7 +223,7 @@
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
+ DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded);
return true;
}
@@ -237,7 +240,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseNestedNameSpecifier(SS.getScopeRep());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
+ DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(),
UPPC, Unexpanded);
return true;
}
@@ -274,7 +277,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseType(NameInfo.getName().getCXXNameType());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
+ DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
return true;
}
@@ -289,7 +292,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateName(Template);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
+ DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
return true;
}
@@ -303,7 +306,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateArgumentLoc(Arg);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(*this, Arg.getLocation(), UPPC, Unexpanded);
+ DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded);
return true;
}
@@ -329,6 +332,24 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
}
+void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ if (!Qualifier)
+ return;
+
+ NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data());
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseNestedNameSpecifierLoc(QualifierLoc);
+}
+
+void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseDeclarationNameInfo(NameInfo);
+}
+
+
ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) {
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct 24 22:44:56 2011
@@ -5805,6 +5805,9 @@
case Sema::IER_Dependent:
Dependent = true;
break;
+
+ case Sema::IER_Error:
+ return StmtError();
}
// We need to continue with the instantiation, so do so now.
Modified: cfe/trunk/test/SemaTemplate/ms-if-exists.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-if-exists.cpp?rev=142906&r1=142905&r2=142906&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/ms-if-exists.cpp (original)
+++ cfe/trunk/test/SemaTemplate/ms-if-exists.cpp Mon Oct 24 22:44:56 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fms-extensions %s -verify
+// RUN: %clang_cc1 -fms-extensions -std=c++11 %s -verify
struct Nontemplate {
typedef int type;
@@ -51,3 +51,12 @@
template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' requested here}}
template void f(HasBar);
+
+template<typename T, typename ...Ts>
+void g(T, Ts...) {
+ __if_exists(T::operator Ts) { // expected-error{{__if_exists name contains unexpanded parameter pack 'Ts'}}
+ }
+
+ __if_not_exists(Ts::operator T) { // expected-error{{__if_not_exists name contains unexpanded parameter pack 'Ts'}}
+ }
+}
More information about the cfe-commits
mailing list