diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-25 22:18:32 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-25 22:18:32 +0000 |
commit | 6bc9f7e286913fb1df95fa3fdcac7aab2628eaeb (patch) | |
tree | 198d3d72dd7d6095b3dec9c7c9cab83d5d9022a0 | |
parent | 88b7094185b9d4fe9820c731b6936d8d37f6143e (diff) |
Improve location information on "reused" class template specialization
decls. Test and document the semantic location of class template
specialization definitions that occur within a scope enclosing the
scope of the class template.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65478 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 22 | ||||
-rw-r--r-- | test/SemaTemplate/class-template-spec.cpp | 7 |
2 files changed, 23 insertions, 6 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index db582edba2..0c60520142 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -687,8 +687,9 @@ Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc, ConvertedTemplateArgs.size(), 0); ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); + Decl->setLexicalDeclContext(CurContext); } - + // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. @@ -1611,6 +1612,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // Check the validity of the template headers that introduce this // template. + // FIXME: Once we have member templates, we'll need to check + // C++ [temp.expl.spec]p17-18, where we could have multiple levels of + // template<> headers. if (TemplateParameterLists.size() == 0) { // FIXME: It would be very nifty if we could introduce some kind // of "code insertion hint" that could show the code that needs to @@ -1684,8 +1688,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // arguments was referenced but not declared, reuse that // declaration node as our own, updating its source location to // reflect our new declaration. - // FIXME: update source locations Specialization = PrevDecl; + Specialization->setLocation(TemplateNameLoc); PrevDecl = 0; } else { // Create a new class template specialization declaration node for @@ -1725,11 +1729,17 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, } } - // FIXME: Do we want to create a nicely sugared type to use as the - // type for this explicit specialization? + // FIXME: We want to create a nicely sugared type to use as the + // type of this explicit specialization. - // Set the lexical context. If the tag has a C++ scope specifier, - // the lexical context will be different from the semantic context. + // C++ [temp.expl.spec]p9: + // A template explicit specialization is in the scope of the + // namespace in which the template was defined. + // + // We actually implement this paragraph where we set the semantic + // context (in the creation of the ClassTemplateSpecializationDecl), + // but we also maintain the lexical context where the actual + // definition occurs. Specialization->setLexicalDeclContext(CurContext); // We may be starting the definition of this specialization. diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp index 4ae1b9bdc9..15c797a5da 100644 --- a/test/SemaTemplate/class-template-spec.cpp +++ b/test/SemaTemplate/class-template-spec.cpp @@ -52,8 +52,11 @@ template<> struct ::A<double>; namespace N { template<typename T> struct B; // expected-note 2{{template is declared here}} + template<> struct ::N::B<char>; // okay template<> struct ::N::B<short>; // okay template<> struct ::N::B<int>; // okay + + int f(int); } template<> struct N::B<int> { }; // okay @@ -65,3 +68,7 @@ namespace M { template<> struct ::A<long double>; // expected-error{{class template specialization of 'A' must occur in the global scope}} } + +template<> struct N::B<char> { + int testf(int x) { return f(x); } +}; |