[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