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
This commit is contained in:
Douglas Gregor 2009-02-25 22:18:32 +00:00
Родитель 88b7094185
Коммит 6bc9f7e286
2 изменённых файлов: 23 добавлений и 6 удалений

Просмотреть файл

@ -687,8 +687,9 @@ Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc,
ConvertedTemplateArgs.size(), ConvertedTemplateArgs.size(),
0); 0);
ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
Decl->setLexicalDeclContext(CurContext);
} }
// Build the fully-sugared type for this class template // Build the fully-sugared type for this class template
// specialization, which refers back to the class template // specialization, which refers back to the class template
// specialization we created or found. // 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 // Check the validity of the template headers that introduce this
// template. // 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) { if (TemplateParameterLists.size() == 0) {
// FIXME: It would be very nifty if we could introduce some kind // FIXME: It would be very nifty if we could introduce some kind
// of "code insertion hint" that could show the code that needs to // 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 // arguments was referenced but not declared, reuse that
// declaration node as our own, updating its source location to // declaration node as our own, updating its source location to
// reflect our new declaration. // reflect our new declaration.
// FIXME: update source locations
Specialization = PrevDecl; Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
PrevDecl = 0; PrevDecl = 0;
} else { } else {
// Create a new class template specialization declaration node for // 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 // FIXME: We want to create a nicely sugared type to use as the
// type for this explicit specialization? // type of this explicit specialization.
// Set the lexical context. If the tag has a C++ scope specifier, // C++ [temp.expl.spec]p9:
// the lexical context will be different from the semantic context. // 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); Specialization->setLexicalDeclContext(CurContext);
// We may be starting the definition of this specialization. // We may be starting the definition of this specialization.

Просмотреть файл

@ -52,8 +52,11 @@ template<> struct ::A<double>;
namespace N { namespace N {
template<typename T> struct B; // expected-note 2{{template is declared here}} 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<short>; // okay
template<> struct ::N::B<int>; // okay template<> struct ::N::B<int>; // okay
int f(int);
} }
template<> struct N::B<int> { }; // okay 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 ::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); }
};