]> granicus.if.org Git - clang/commitdiff
Fix the recently-added warning about 'typename' and 'template'
authorDouglas Gregor <dgregor@apple.com>
Wed, 16 Jun 2010 22:31:08 +0000 (22:31 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 16 Jun 2010 22:31:08 +0000 (22:31 +0000)
disambiguation keywords outside of templates in C++98/03. Previously,
the warning would fire when the associated nested-name-specifier was
not dependent, but that was a misreading of the C++98/03 standard:
now, we complain only when we're outside of any template.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106161 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Parse/Action.h
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTemplate.cpp
lib/Parse/Parser.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/TreeTransform.h
test/SemaObjCXX/message.mm
test/SemaTemplate/nested-name-spec-template.cpp
test/SemaTemplate/template-id-expr.cpp
test/SemaTemplate/typename-specifier-4.cpp
test/SemaTemplate/typename-specifier.cpp

index 0a9cb8a22ed19e58eb5c7238920aec9bcc665787..ecd95d30d23ac85fcbe9c50935e4f71aa34c61d1 100644 (file)
@@ -1610,9 +1610,8 @@ def note_typename_refers_here : Note<
     "referenced member %0 is declared here">;
 def err_typename_missing : Error<
   "missing 'typename' prior to dependent type name '%0%1'">;
-def ext_typename_nondependent : ExtWarn<
-  "'typename' refers to a non-dependent type name; accepted as a C++0x "
-  "extension">;
+def ext_typename_outside_of_template : ExtWarn<
+  "'typename' occurs outside of a template">;
 
 def err_template_kw_refers_to_non_template : Error<
     "%0 following the 'template' keyword does not refer to a template">;
@@ -1624,9 +1623,8 @@ def note_referenced_class_template : Error<
     "class template declared here">;
 def err_template_kw_missing : Error<
   "missing 'template' keyword prior to dependent template name '%0%1'">;
-def ext_template_nondependent : ExtWarn<
-  "'template' refers to a non-dependent template name; accepted as a C++0x "
-  "extension">;
+def ext_template_outside_of_template : ExtWarn<
+  "'template' keyword outside of a template">;
 
 // C++0x Variadic Templates
 def err_template_param_pack_default_arg : Error<
index 0b07ded05d389ee1457d031ccd2c2d2604e25b81..baca3fb50222e38970294a812269981459d46eca 100644 (file)
@@ -1989,6 +1989,8 @@ public:
   /// SS will be "MetaFun::", \p TemplateKWLoc contains the location
   /// of the "template" keyword, and "apply" is the \p Name.
   ///
+  /// \param S The scope in which the dependent template name was parsed.
+  ///
   /// \param TemplateKWLoc the location of the "template" keyword (if any).
   ///
   /// \param SS the nested-name-specifier that precedes the "template" keyword
@@ -2004,7 +2006,8 @@ public:
   ///
   /// \param EnteringContext whether we are entering the context of this
   /// template.
-  virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
+  virtual TemplateTy ActOnDependentTemplateName(Scope *S, 
+                                                SourceLocation TemplateKWLoc,
                                                 CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
                                                 TypeTy *ObjectType,
@@ -2246,8 +2249,9 @@ public:
   /// \param II the identifier we're retrieving (e.g., 'type' in the example).
   /// \param IdLoc the location of the identifier.
   virtual TypeResult
-  ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-                    const IdentifierInfo &II, SourceLocation IdLoc) {
+  ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                    const CXXScopeSpec &SS, const IdentifierInfo &II, 
+                    SourceLocation IdLoc) {
     return TypeResult();
   }
 
@@ -2260,8 +2264,9 @@ public:
   /// \param TemplateLoc the location of the 'template' keyword, if any.
   /// \param Ty the type that the typename specifier refers to.
   virtual TypeResult
-  ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-                    SourceLocation TemplateLoc, TypeTy *Ty) {
+  ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                    const CXXScopeSpec &SS, SourceLocation TemplateLoc, 
+                    TypeTy *Ty) {
     return TypeResult();
   }
 
index 586dac61599cc29ac89ba65ee5a3c949aa3175aa..843baa2fe7295dd3ae9cb895d01a13b0b4c16784 100644 (file)
@@ -165,7 +165,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
       // Commit to parsing the template-id.
       TPA.Commit();
       TemplateTy Template
-        = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
+        = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
+                                             TemplateName,
                                              ObjectType, EnteringContext);
       if (!Template)
         return true;
@@ -319,7 +320,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
           << II.getName()
           << FixItHint::CreateInsertion(Tok.getLocation(), "template ");
         
-        Template = Actions.ActOnDependentTemplateName(Tok.getLocation(), SS, 
+        Template = Actions.ActOnDependentTemplateName(CurScope, 
+                                                      Tok.getLocation(), SS, 
                                                       TemplateName, ObjectType,
                                                       EnteringContext);
         if (!Template.get())
@@ -1011,7 +1013,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
   case UnqualifiedId::IK_OperatorFunctionId:
   case UnqualifiedId::IK_LiteralOperatorId:
     if (AssumeTemplateId) {
-      Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, 
+      Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
                                                     Id, ObjectType,
                                                     EnteringContext);
       TNK = TNK_Dependent_template_name;
@@ -1042,8 +1044,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
         Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
           << Name
           << FixItHint::CreateInsertion(Id.StartLocation, "template ");
-        Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, 
-                                                      Id, ObjectType,
+        Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc,
+                                                      SS, Id, ObjectType,
                                                       EnteringContext);
         TNK = TNK_Dependent_template_name;
         if (!Template.get())
@@ -1067,7 +1069,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
     bool MemberOfUnknownSpecialization;
     TemplateName.setIdentifier(Name, NameLoc);
     if (ObjectType) {
-      Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, 
+      Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, 
                                                     TemplateName, ObjectType,
                                                     EnteringContext);
       TNK = TNK_Dependent_template_name;
index 5d248f1d774e5d4f882638ca89d579f401bb4fa2..ec0e31e703c9bedf9302a175117d3d826852a53a 100644 (file)
@@ -916,9 +916,9 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
       // template argument.
       if (isEndOfTemplateArgument(Tok)) {
         TemplateTy Template
-        = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name, 
-                                             /*ObjectType=*/0,
-                                             /*EnteringContext=*/false);
+          = Actions.ActOnDependentTemplateName(CurScope, TemplateLoc, SS, Name, 
+                                               /*ObjectType=*/0,
+                                               /*EnteringContext=*/false);
         if (Template.get())
           return ParsedTemplateArgument(SS, Template, Name.StartLocation);
       }
index 296897080d0f9dacdfe622c941af2ad890214f04..225a793af53a559422ddef33eb491a8502f10d85 100644 (file)
@@ -919,7 +919,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
     TypeResult Ty;
     if (Tok.is(tok::identifier)) {
       // FIXME: check whether the next token is '<', first!
-      Ty = Actions.ActOnTypenameType(TypenameLoc, SS, *Tok.getIdentifierInfo(),
+      Ty = Actions.ActOnTypenameType(CurScope, TypenameLoc, SS, 
+                                     *Tok.getIdentifierInfo(),
                                      Tok.getLocation());
     } else if (Tok.is(tok::annot_template_id)) {
       TemplateIdAnnotation *TemplateId
@@ -934,7 +935,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
       assert(Tok.is(tok::annot_typename) &&
              "AnnotateTemplateIdTokenAsType isn't working properly");
       if (Tok.getAnnotationValue())
-        Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
+        Ty = Actions.ActOnTypenameType(CurScope, TypenameLoc, SS, 
+                                       SourceLocation(),
                                        Tok.getAnnotationValue());
       else
         Ty = true;
index 396f144ddf2d9dd80968957dddad8eb3a0b5648a..c81c12bb86cf4affd21a772cfe05c0b1ece05f66 100644 (file)
@@ -2937,7 +2937,8 @@ public:
                                                 SourceLocation NameLoc,
                                const TemplateArgumentListInfo &TemplateArgs);
 
-  virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
+  virtual TemplateTy ActOnDependentTemplateName(Scope *S,
+                                                SourceLocation TemplateKWLoc,
                                                 CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
                                                 TypeTy *ObjectType,
@@ -3121,25 +3122,29 @@ public:
   /// \brief Called when the parser has parsed a C++ typename
   /// specifier, e.g., "typename T::type".
   ///
+  /// \param S The scope in which this typename type occurs.
   /// \param TypenameLoc the location of the 'typename' keyword
   /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
   /// \param II the identifier we're retrieving (e.g., 'type' in the example).
   /// \param IdLoc the location of the identifier.
   virtual TypeResult
-  ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-                    const IdentifierInfo &II, SourceLocation IdLoc);
+  ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                    const CXXScopeSpec &SS, const IdentifierInfo &II, 
+                    SourceLocation IdLoc);
 
   /// \brief Called when the parser has parsed a C++ typename
   /// specifier that ends in a template-id, e.g.,
   /// "typename MetaFun::template apply<T1, T2>".
   ///
+  /// \param S The scope in which this typename type occurs.
   /// \param TypenameLoc the location of the 'typename' keyword
   /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
   /// \param TemplateLoc the location of the 'template' keyword, if any.
   /// \param Ty the type that the typename specifier refers to.
   virtual TypeResult
-  ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-                    SourceLocation TemplateLoc, TypeTy *Ty);
+  ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                    const CXXScopeSpec &SS, SourceLocation TemplateLoc, 
+                    TypeTy *Ty);
 
   QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
                              NestedNameSpecifier *NNS,
index fbd4ff446acc326d4a3088f0f2acc1f84073627e..9e31a543722250736d7aa9849cda8d6970bcd43b 100644 (file)
@@ -307,7 +307,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
       << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
       << SourceRange(SS->getRange().getBegin(), IILoc)
       << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
-    SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get();
+    SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc).get();
   } else {
     assert(SS && SS->isInvalid() && 
            "Invalid scope specifier has already been diagnosed");
index 5e40bc58bba811e8c2a2f6af51623ccc1ce28b6c..b30d4e3e9c31f908751d75ae8b6579ecb93aedd5 100644 (file)
@@ -1687,11 +1687,16 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
 /// SS will be "MetaFun::", \p TemplateKWLoc contains the location
 /// of the "template" keyword, and "apply" is the \p Name.
 Sema::TemplateTy
-Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
+Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc,
                                  CXXScopeSpec &SS,
                                  UnqualifiedId &Name,
                                  TypeTy *ObjectType,
                                  bool EnteringContext) {
+  if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() &&
+      !getLangOptions().CPlusPlus0x)
+    Diag(TemplateKWLoc, diag::ext_template_outside_of_template)
+      << FixItHint::CreateRemoval(TemplateKWLoc);    
+  
   DeclContext *LookupCtx = 0;
   if (SS.isSet())
     LookupCtx = computeDeclContext(SS, EnteringContext);
@@ -1732,15 +1737,6 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
       return TemplateTy();
     } else {
       // We found something; return it.
-      if (ActiveTemplateInstantiations.empty() &&
-          !getLangOptions().CPlusPlus0x &&
-          !SS.isEmpty() && !isDependentScopeSpecifier(SS))
-        Diag(TemplateKWLoc.isValid()? TemplateKWLoc 
-                                    : Name.getSourceRange().getBegin(), 
-             diag::ext_template_nondependent)
-        << SourceRange(Name.getSourceRange().getBegin())
-        << FixItHint::CreateRemoval(TemplateKWLoc);
-      
       return Template;
     }
   }
@@ -5266,13 +5262,19 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
 }
 
 Sema::TypeResult
-Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-                        const IdentifierInfo &II, SourceLocation IdLoc) {
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                        const CXXScopeSpec &SS, const IdentifierInfo &II, 
+                        SourceLocation IdLoc) {
   NestedNameSpecifier *NNS
     = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
   if (!NNS)
     return true;
 
+  if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
+      !getLangOptions().CPlusPlus0x)
+    Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+      << FixItHint::CreateRemoval(TypenameLoc);    
+  
   QualType T = CheckTypenameType(ETK_Typename, NNS, II,
                                  TypenameLoc, SS.getRange(), IdLoc);
   if (T.isNull())
@@ -5295,8 +5297,14 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
 }
 
 Sema::TypeResult
-Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-                        SourceLocation TemplateLoc, TypeTy *Ty) {
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, 
+                        const CXXScopeSpec &SS, SourceLocation TemplateLoc, 
+                        TypeTy *Ty) {
+  if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
+      !getLangOptions().CPlusPlus0x)
+    Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+      << FixItHint::CreateRemoval(TypenameLoc);    
+  
   TypeSourceInfo *InnerTSI = 0;
   QualType T = GetTypeFromParser(Ty, &InnerTSI);
   NestedNameSpecifier *NNS
@@ -5397,15 +5405,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
     return Context.getDependentNameType(Keyword, NNS, &II);
 
   case LookupResult::Found:
-    if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
-      if (ActiveTemplateInstantiations.empty() &&
-          !getLangOptions().CPlusPlus0x && !SS.isEmpty() &&
-          !isDependentScopeSpecifier(SS))
-        Diag(KeywordLoc.isValid()? KeywordLoc : IILoc, 
-             diag::ext_typename_nondependent)
-          << SourceRange(IILoc)
-          << FixItHint::CreateRemoval(KeywordLoc);
-      
+    if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {      
       // We found a type. Build an ElaboratedType, since the
       // typename-specifier was just sugar.
       return Context.getElaboratedType(ETK_Typename, NNS,
index df01be01f1145334fcd28cdf07163a347d42b11d..86e3a25ea25e9776be7ffac09abdeae75144b86a 100644 (file)
@@ -6495,7 +6495,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
   SS.setScopeRep(Qualifier);
   UnqualifiedId Name;
   Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
-  return getSema().ActOnDependentTemplateName(
+  return getSema().ActOnDependentTemplateName(/*Scope=*/0,
                                       /*FIXME:*/getDerived().getBaseLocation(),
                                               SS,
                                               Name,
@@ -6516,7 +6516,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
   SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
   Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
                              Operator, SymbolLocations);
-  return getSema().ActOnDependentTemplateName(
+  return getSema().ActOnDependentTemplateName(/*Scope=*/0,
                                        /*FIXME:*/getDerived().getBaseLocation(),
                                               SS,
                                               Name,
index 10b886b203f4cdaeb71048f0ed00dab18fadf715..76bde6f57cab5b6277f249b673f1f08996d41ca1 100644 (file)
@@ -62,15 +62,15 @@ struct identity {
   // or typename-specifiers.
   if (false) {
     if (true)
-      return [typename identity<I3>::type method]; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}}
+      return [typename identity<I3>::type method]; // expected-warning{{occurs outside of a template}}
 
     return [::I3 method];
   }
 
   int* ip1 = {[super method]};
   int* ip2 = {[::I3 method]};
-  int* ip3 = {[typename identity<I3>::type method]}; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}}
-  int* ip4 = {[typename identity<I2_holder>::type().get() method]}; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}}
+  int* ip3 = {[typename identity<I3>::type method]}; // expected-warning{{occurs outside of a template}}
+  int* ip4 = {[typename identity<I2_holder>::type().get() method]}; // expected-warning{{occurs outside of a template}}
   int array[5] = {[3] = 2};
   return [super method];
 }
index e542507a2f7767a9251a1ed23fdaa11e142570fd..0251894f35ad62267416713502c31915f647ae90 100644 (file)
@@ -21,7 +21,7 @@ namespace N {
   }
 
   M::Promote<int>::type *ret_intptr3(int* ip) { return ip; }
-  M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' refers to a non-dependent template name; accepted as a C++0x extension}}
+  M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' keyword outside of a template}}
 }
 
 N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; }
index e8974211b60bb713304a3ac83842b38d131c5232..de8d7f6c91a4aa52e735b8ab9a1c6f44c403e262 100644 (file)
@@ -62,12 +62,12 @@ struct Y0 {
 
   template<typename U>
   void f() {
-    Y0::template f1<U>(0); // expected-warning{{'template' refers to a non-dependent template name}}
-    Y0::template f1(0); // expected-warning{{'template' refers to a non-dependent template name}}
+    Y0::template f1<U>(0);
+    Y0::template f1(0);
     this->template f1(0);
 
-    Y0::template f2<U>(0); // expected-warning{{'template' refers to a non-dependent template name}}
-    Y0::template f2(0);// expected-warning{{'template' refers to a non-dependent template name}}
+    Y0::template f2<U>(0);
+    Y0::template f2(0);
 
     Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
     Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
@@ -75,8 +75,7 @@ struct Y0 {
     int x;
     x = Y0::f4(0);
     x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
-    x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} \
-    // expected-warning{{'template' refers to a non-dependent template name}}
+    x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
 
     x = this->f4(0);
     x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
index da11119e5b276a93ad639466d3ad22316f432108..5a313bf2256a2ddef03fd53b7d56c81dead1ab1e 100644 (file)
@@ -27,7 +27,8 @@ struct make_pair {
 int a0[is_same<metafun_apply2<make_pair, int, float>::type, 
                pair<int, float> >::value? 1 : -1];
 int a1[is_same<
-         typename make_pair::template apply<int, float>, // expected-warning{{'template' refers to a non-dependent template name}}
+         typename make_pair::template apply<int, float>, // expected-warning{{'template' keyword outside of a template}} \
+       // expected-warning{{'typename' occurs outside of a template}}
          make_pair::apply<int, float>
        >::value? 1 : -1];
 
index e066475be99e9635669439bda34461634039e2f0..4c788f6a8a3cdad18b2f27c1a38375bb1a534b4d 100644 (file)
@@ -15,20 +15,22 @@ namespace N {
 
 int i;
 
-typename N::A::type *ip1 = &i; // expected-warning{{'typename' refers to a non-dependent type name}}
-typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}}
-typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}}
+typename N::A::type *ip1 = &i; // expected-warning{{'typename' occurs outside of a template}}
+typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}} \
+// expected-warning{{'typename' occurs outside of a template}}
+typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} \
+// expected-warning{{'typename' occurs outside of a template}}
 
 void test(double d) {
   typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}} \
-  // expected-warning 2{{'typename' refers to a non-dependent type name}}
+  // expected-warning 2{{'typename' occurs outside of a template}}
   int five = f(5);
   
   using namespace N;
-  for (typename A::type i = 0; i < 10; ++i) // expected-warning{{'typename' refers to a non-dependent type name}}
+  for (typename A::type i = 0; i < 10; ++i) // expected-warning{{'typename' occurs outside of a template}}
     five += 1;
 
-  const typename N::A::type f2(d); // expected-warning{{'typename' refers to a non-dependent type name}}
+  const typename N::A::type f2(d); // expected-warning{{'typename' occurs outside of a template}}
 }
 
 namespace N {