]> granicus.if.org Git - clang/commitdiff
Make explicit specializations at class scope work
authorNico Weber <nicolasweber@gmx.de>
Mon, 25 Jun 2012 17:21:05 +0000 (17:21 +0000)
committerNico Weber <nicolasweber@gmx.de>
Mon, 25 Jun 2012 17:21:05 +0000 (17:21 +0000)
for non-type template parameters in microsoft mode.
PR12709.

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

include/clang/AST/DeclTemplate.h
include/clang/AST/RecursiveASTVisitor.h
lib/AST/DeclTemplate.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/ms-function-specialization-class-scope.cpp

index bafa4788866e27a9436dda481439a47018bec851..7affc7e15f27152fa7ab618dbc9731782beb9cac 100644 (file)
@@ -2086,23 +2086,33 @@ class ClassScopeFunctionSpecializationDecl : public Decl {
   virtual void anchor();
 
   ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc,
-                                       CXXMethodDecl *FD)
+                                       CXXMethodDecl *FD, bool Args,
+                                       TemplateArgumentListInfo TemplArgs)
     : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
-      Specialization(FD) {}
+      Specialization(FD), HasExplicitTemplateArgs(Args),
+      TemplateArgs(TemplArgs) {}
 
   ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
     : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
 
   CXXMethodDecl *Specialization;
+  bool HasExplicitTemplateArgs;
+  TemplateArgumentListInfo TemplateArgs;
 
 public:
   CXXMethodDecl *getSpecialization() const { return Specialization; }
+  bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+  const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; }
 
   static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C,
                                                       DeclContext *DC,
                                                       SourceLocation Loc,
-                                                      CXXMethodDecl *FD) {
-    return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD);
+                                                      CXXMethodDecl *FD,
+                                                   bool HasExplicitTemplateArgs,
+                                        TemplateArgumentListInfo TemplateArgs) {
+    return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD,
+                                                        HasExplicitTemplateArgs,
+                                                        TemplateArgs);
   }
 
   static ClassScopeFunctionSpecializationDecl *
index d751d556e9f0ca45aecc737ee0d15e51020762b3..4ad9da30e10d78f956eba3270e387f5dbfaa0082 100644 (file)
@@ -1283,7 +1283,13 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
   })
 
 DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
-  TRY_TO(TraverseDecl(D->getSpecialization()));
+    TRY_TO(TraverseDecl(D->getSpecialization()));
+
+    if (D->hasExplicitTemplateArgs()) {
+      const TemplateArgumentListInfo& args = D->templateArgs();
+      TRY_TO(TraverseTemplateArgumentLocsHelper(
+          args.getArgumentArray(), args.size()));
+    }
  })
 
 DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
index 9a338e5ee6be4aeb5c6c34f5344f80a65be579f0..5aebc2b764c012a669dac265d74fc28c3dd25f61 100644 (file)
@@ -869,5 +869,6 @@ ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
                                                          unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, 
                 sizeof(ClassScopeFunctionSpecializationDecl));
-  return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0);
+  return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0,
+                                             false, TemplateArgumentListInfo());
 }
index 1b0a0abdb2dd660f5c54277c732481445c7dd9d5..40643896fd3bbaf6c5a4b6a323053eca1d61a672 100644 (file)
@@ -5066,7 +5066,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   FunctionTemplateDecl *FunctionTemplate = 0;
   bool isExplicitSpecialization = false;
   bool isFunctionTemplateSpecialization = false;
+
   bool isDependentClassScopeExplicitSpecialization = false;
+  bool HasExplicitTemplateArgs = false;
+  TemplateArgumentListInfo TemplateArgs;
+
   bool isVirtualOkay = false;
 
   FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC,
@@ -5509,8 +5513,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   } else {
     // If the declarator is a template-id, translate the parser's template 
     // argument list into our AST format.
-    bool HasExplicitTemplateArgs = false;
-    TemplateArgumentListInfo TemplateArgs;
     if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
       TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
       TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
@@ -5814,8 +5816,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   if (isDependentClassScopeExplicitSpecialization) {
     ClassScopeFunctionSpecializationDecl *NewSpec =
                          ClassScopeFunctionSpecializationDecl::Create(
-                                Context, CurContext,  SourceLocation(), 
-                                cast<CXXMethodDecl>(NewFD));
+                                Context, CurContext, SourceLocation(), 
+                                cast<CXXMethodDecl>(NewFD),
+                                HasExplicitTemplateArgs, TemplateArgs);
     CurContext->addDecl(NewSpec);
     AddToScope = false;
   }
index d4b5ffe51701d943d3f047c20b5a2ae26c2fafdf..bbf8f50a3c774b2c53933064a812e355c0420c25 100644 (file)
@@ -1952,13 +1952,22 @@ Decl * TemplateDeclInstantiator
 Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
                                      ClassScopeFunctionSpecializationDecl *Decl) {
   CXXMethodDecl *OldFD = Decl->getSpecialization();
-  CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, 0, true));
+  CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD,
+                                                                0, true));
 
   LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
                         Sema::ForRedeclaration);
 
+  TemplateArgumentListInfo TemplateArgs;
+  TemplateArgumentListInfo* TemplateArgsPtr = 0;
+  if (Decl->hasExplicitTemplateArgs()) {
+    TemplateArgs = Decl->templateArgs();
+    TemplateArgsPtr = &TemplateArgs;
+  }
+
   SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext);
-  if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, 0, Previous)) {
+  if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, TemplateArgsPtr,
+                                                  Previous)) {
     NewFD->setInvalidDecl();
     return NewFD;
   }
index bda87f99c9a15e0910cbd25630db84e0dc284d65..131922bbfbaad1a69292cb7cca21e412f392b6f1 100644 (file)
@@ -69,3 +69,24 @@ void test2()
    b.f(100);
 }
 
+
+namespace PR12709 {
+
+template<class T>
+class TemplateClass {
+  void member_function() {
+    specialized_member_template<false>();
+  }
+
+  template<bool b>
+  void specialized_member_template() {}
+
+  template<>
+  void specialized_member_template<false>() {}  // expected-warning{{explicit specialization of 'specialized_member_template' within class scope is a Microsoft extension}}
+};
+
+void f() {
+  TemplateClass<int> t;
+}
+
+}