]> granicus.if.org Git - clang/commitdiff
Cope with extraneous "template" keyword when providing an out-of-line
authorDouglas Gregor <dgregor@apple.com>
Fri, 20 Nov 2009 23:39:24 +0000 (23:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 20 Nov 2009 23:39:24 +0000 (23:39 +0000)
definition of a member template (or a member thereof). Fixes PR5566.

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

include/clang/Parse/Action.h
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTemplate.cpp
lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/TreeTransform.h
test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp
test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp

index 018cc1454038ea5030184a16036909a1c4566ba8..abe50d05bcc51285e6ec5b4812f5ab97d4933310 100644 (file)
@@ -1685,10 +1685,14 @@ public:
   /// \param ObjectType if this dependent template name occurs in the
   /// context of a member access expression, the type of the object being
   /// accessed.
+  ///
+  /// \param EnteringContext whether we are entering the context of this
+  /// template.
   virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
                                                 const CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
-                                                TypeTy *ObjectType) {
+                                                TypeTy *ObjectType,
+                                                bool EnteringContext) {
     return TemplateTy();
   }
 
index 145c8616eb855620b55197efa721d47c47cd5431..992211dad759bced71133d97f747db2313a3c6c2 100644 (file)
@@ -148,7 +148,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
       TPA.Commit();
       TemplateTy Template
         = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
-                                             ObjectType);
+                                             ObjectType, EnteringContext);
       if (!Template)
         break;
       if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
@@ -774,7 +774,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
     TemplateName.setIdentifier(Name, NameLoc);
     if (ObjectType) {
       Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, 
-                                                    TemplateName, ObjectType);
+                                                    TemplateName, ObjectType,
+                                                    EnteringContext);
       TNK = TNK_Dependent_template_name;
       if (!Template.get())
         return true;
index 16b1c800800f1cb29bd67c5adf77b08916bf876f..5be4ca82f7284f942074474076cc31fdab0972f0 100644 (file)
@@ -851,7 +851,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
       if (isEndOfTemplateArgument(Tok)) {
         TemplateTy Template
         = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name, 
-                                             /*ObjectType=*/0);
+                                             /*ObjectType=*/0,
+                                             /*EnteringContext=*/false);
         if (Template.get())
           return ParsedTemplateArgument(SS, Template, Name.StartLocation);
       }
index 6e74f9277a1a7ffa77debc9bcb694b8947b26d9a..2d3f9fc8cb207881f31689cab0bef48c03a22011 100644 (file)
@@ -2293,7 +2293,8 @@ public:
   virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
                                                 const CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
-                                                TypeTy *ObjectType);
+                                                TypeTy *ObjectType,
+                                                bool EnteringContext);
 
   bool CheckClassTemplatePartialSpecializationArgs(
                                         TemplateParameterList *TemplateParams,
index 8d77b1ff9b8518b6b795bf8f8dff1649a71f5aab..f013343894179b6b65ecfd223e1a53de56bbeb64 100644 (file)
@@ -1381,10 +1381,11 @@ Sema::TemplateTy
 Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
                                  const CXXScopeSpec &SS,
                                  UnqualifiedId &Name,
-                                 TypeTy *ObjectType) {
+                                 TypeTy *ObjectType,
+                                 bool EnteringContext) {
   if ((ObjectType &&
        computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
-      (SS.isSet() && computeDeclContext(SS, false))) {
+      (SS.isSet() && computeDeclContext(SS, EnteringContext))) {
     // C++0x [temp.names]p5:
     //   If a name prefixed by the keyword template is not the name of
     //   a template, the program is ill-formed. [Note: the keyword
@@ -1403,7 +1404,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
     // rules, even in C++03 mode, retroactively applying the DR.
     TemplateTy Template;
     TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
-                                          false, Template);
+                                          EnteringContext, Template);
     if (TNK == TNK_Non_template) {
       Diag(Name.getSourceRange().getBegin(), 
            diag::err_template_kw_refers_to_non_template)
index 579937ead7695a13ef4e9993ea37a912de842fad..5018b1544e40cd243528c2432241e32915c3e091 100644 (file)
@@ -5349,7 +5349,8 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
                                       /*FIXME:*/getDerived().getBaseLocation(),
                                               SS,
                                               Name,
-                                              ObjectType.getAsOpaquePtr())
+                                              ObjectType.getAsOpaquePtr(),
+                                              /*EnteringContext=*/false)
            .template getAsVal<TemplateName>();
 }
 
@@ -5369,7 +5370,8 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
                                        /*FIXME:*/getDerived().getBaseLocation(),
                                               SS,
                                               Name,
-                                              ObjectType.getAsOpaquePtr())
+                                              ObjectType.getAsOpaquePtr(),
+                                              /*EnteringContext=*/false)
            .template getAsVal<TemplateName>();
 }
   
index b63c56c40fe8d028d6efd45dc51679fff56939ab..90bb16256c5b03e929f3ecf9c834ac9655ebc8ed 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 template<typename T, int N>
 struct A;
 
index 725b61c271624807a5750d3efb6dec9888f02edb..2d52994dc97e7eabe893cbaf7903359e22ff9eda 100644 (file)
@@ -66,3 +66,14 @@ X0<T, U>::operator T*() const {
 
 namespace N { template <class X> class A {void a();}; }
 namespace N { template <class X> void A<X>::a() {} }
+
+// PR5566
+template<typename T>
+struct X1 { 
+  template<typename U>
+  struct B { void f(); };
+};
+
+template<typename T>
+template<typename U>
+void X1<T>::template B<U>::f() { }