зеркало из https://github.com/microsoft/clang.git
Finish implementing checking of class template partial specializations
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73260 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6aa75cfbdd
Коммит
16df850bb7
|
@ -743,18 +743,19 @@ def err_template_spec_needs_header : Error<
|
|||
def err_template_spec_extra_headers : Error<
|
||||
"template specialization must have a single 'template<>' header">;
|
||||
def err_template_spec_decl_out_of_scope_global : Error<
|
||||
"class template specialization of %0 must occur in the global scope">;
|
||||
"class template %select{|partial }0specialization of %1 must occur in the "
|
||||
"global scope">;
|
||||
def err_template_spec_decl_out_of_scope : Error<
|
||||
"class template specialization of %0 not in namespace %1">;
|
||||
"class template %select{|partial }0specialization of %1 not in namespace %2">;
|
||||
def err_template_spec_decl_function_scope : Error<
|
||||
"%select{class template specialization|explicit instantiation}0 of %1 "
|
||||
"in function scope">;
|
||||
"%select{class template specialization|class template partial specialization|"
|
||||
"explicit instantiation}0 of %1 in function scope">;
|
||||
def err_template_spec_redecl_out_of_scope : Error<
|
||||
"%select{class template specialization|explicit instantiation}0 of %1 "
|
||||
"not in a namespace enclosing %2">;
|
||||
"%select{class template specialization|class template partial specialization|"
|
||||
"explicit instantiation}0 of %1 not in a namespace enclosing %2">;
|
||||
def err_template_spec_redecl_global_scope : Error<
|
||||
"%select{class template specialization|explicit instantiation}0 of %1 must "
|
||||
"occur at global scope">;
|
||||
"%select{class template specialization|class template partial specialization|"
|
||||
"explicit instantiation}0 of %1 must occur at global scope">;
|
||||
|
||||
// C++ Class Template Partial Specialization
|
||||
def err_default_arg_in_partial_spec : Error<
|
||||
|
|
|
@ -1950,6 +1950,7 @@ public:
|
|||
ClassTemplateSpecializationDecl *PrevDecl,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceRange ScopeSpecifierRange,
|
||||
bool PartialSpecialization,
|
||||
bool ExplicitInstantiation);
|
||||
|
||||
bool CheckClassTemplatePartialSpecializationArgs(
|
||||
|
|
|
@ -1932,6 +1932,7 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
|
|||
ClassTemplateSpecializationDecl *PrevDecl,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceRange ScopeSpecifierRange,
|
||||
bool PartialSpecialization,
|
||||
bool ExplicitInstantiation) {
|
||||
// C++ [temp.expl.spec]p2:
|
||||
// An explicit specialization shall be declared in the namespace
|
||||
|
@ -1947,8 +1948,9 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
|
|||
// that encloses the one in which the explicit specialization was
|
||||
// declared.
|
||||
if (CurContext->getLookupContext()->isFunctionOrMethod()) {
|
||||
int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0;
|
||||
Diag(TemplateNameLoc, diag::err_template_spec_decl_function_scope)
|
||||
<< ExplicitInstantiation << ClassTemplate;
|
||||
<< Kind << ClassTemplate;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1963,11 +1965,12 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
|
|||
if (DC != TemplateContext) {
|
||||
if (isa<TranslationUnitDecl>(TemplateContext))
|
||||
Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope_global)
|
||||
<< PartialSpecialization
|
||||
<< ClassTemplate << ScopeSpecifierRange;
|
||||
else if (isa<NamespaceDecl>(TemplateContext))
|
||||
Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope)
|
||||
<< ClassTemplate << cast<NamedDecl>(TemplateContext)
|
||||
<< ScopeSpecifierRange;
|
||||
<< PartialSpecialization << ClassTemplate
|
||||
<< cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange;
|
||||
|
||||
Diag(ClassTemplate->getLocation(), diag::note_template_decl_here);
|
||||
}
|
||||
|
@ -1981,16 +1984,17 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
|
|||
// FIXME: In C++98, we would like to turn these errors into warnings,
|
||||
// dependent on a -Wc++0x flag.
|
||||
bool SuppressedDiag = false;
|
||||
int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0;
|
||||
if (isa<TranslationUnitDecl>(TemplateContext)) {
|
||||
if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x)
|
||||
Diag(TemplateNameLoc, diag::err_template_spec_redecl_global_scope)
|
||||
<< ExplicitInstantiation << ClassTemplate << ScopeSpecifierRange;
|
||||
<< Kind << ClassTemplate << ScopeSpecifierRange;
|
||||
else
|
||||
SuppressedDiag = true;
|
||||
} else if (isa<NamespaceDecl>(TemplateContext)) {
|
||||
if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x)
|
||||
Diag(TemplateNameLoc, diag::err_template_spec_redecl_out_of_scope)
|
||||
<< ExplicitInstantiation << ClassTemplate
|
||||
<< Kind << ClassTemplate
|
||||
<< cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange;
|
||||
else
|
||||
SuppressedDiag = true;
|
||||
|
@ -2285,6 +2289,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
|
||||
TemplateNameLoc,
|
||||
SS.getRange(),
|
||||
isPartialSpecialization,
|
||||
/*ExplicitInstantiation=*/false))
|
||||
return true;
|
||||
|
||||
|
@ -2440,6 +2445,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
|
|||
if (CheckClassTemplateSpecializationScope(ClassTemplate, 0,
|
||||
TemplateNameLoc,
|
||||
SS.getRange(),
|
||||
/*PartialSpecialization=*/false,
|
||||
/*ExplicitInstantiation=*/true))
|
||||
return true;
|
||||
|
||||
|
|
|
@ -854,8 +854,11 @@ Sema::InstantiateClassTemplateSpecialization(
|
|||
const TemplateArgumentList *TemplateArgs
|
||||
= &ClassTemplateSpec->getTemplateArgs();
|
||||
|
||||
// Determine whether any class template partial specializations
|
||||
// match the given template arguments.
|
||||
// C++ [temp.class.spec]p7:
|
||||
// Partial specialization declarations themselves are not found by
|
||||
// name lookup. Rather, when the primary template name is used,
|
||||
// any previously declared partial specializations of the primary
|
||||
// template are also considered.
|
||||
typedef std::pair<ClassTemplatePartialSpecializationDecl *,
|
||||
TemplateArgumentList *> MatchResult;
|
||||
llvm::SmallVector<MatchResult, 4> Matched;
|
||||
|
|
|
@ -255,3 +255,10 @@ int is_nested_value_type_identity1[
|
|||
//int is_nested_value_type_identity2[
|
||||
// is_nested_value_type_identity<NoValueType>::value? -1 : 1];
|
||||
|
||||
|
||||
// C++ [temp.class.spec]p4:
|
||||
template<class T1, class T2, int I> class A { }; //#1
|
||||
template<class T, int I> class A<T, T*, I> { }; //#2
|
||||
template<class T1, class T2, int I> class A<T1*, T2, I> { }; //#3
|
||||
template<class T> class A<int, T*, 5> { }; //#4
|
||||
template<class T1, class T2, int I> class A<T1, T2*, I> { }; //#5
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
template<typename T> struct vector;
|
||||
|
||||
// C++ [temp.class.spec]p9
|
||||
// C++ [temp.class.spec]p6:
|
||||
namespace N {
|
||||
namespace M {
|
||||
template<typename T> struct A; // expected-note{{here}}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct N::M::A<T*> { }; // expected-error{{not in namespace}}
|
||||
|
||||
// C++ [temp.class.spec]p9
|
||||
// bullet 1
|
||||
template <int I, int J> struct A {};
|
||||
template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}}
|
||||
|
|
|
@ -1887,7 +1887,7 @@ welcome!</p>
|
|||
<td> 14.5.4 [temp.class.spec]</td>
|
||||
<td class="complete" align="center"></td>
|
||||
<td class="complete" align="center"></td>
|
||||
<td class="medium" align="center"></td>
|
||||
<td class="complete" align="center"></td>
|
||||
<td class="na" align="center">N/A</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
|
Загрузка…
Ссылка в новой задаче