Changeset View
Changeset View
Standalone View
Standalone View
lib/Sema/SemaTemplate.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 6,947 Lines • ▼ Show 20 Lines | if (Complain) | ||||
TemplateArgLoc); | TemplateArgLoc); | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/// \brief Check whether a template is declared with "C" language linkage. | |||||
/// | |||||
/// If a template or a template specialization is declared with "C" language | |||||
/// linkage, issues a diagnostic and returns true. Otherwise, returns false. | |||||
static bool | |||||
CheckTemplateLanguageLinkage(Sema &S, DeclContext *Ctx, SourceRange Rng) { | |||||
if (Ctx && Ctx->isExternCContext()) { | |||||
S.Diag(Rng.getBegin(), diag::err_template_linkage) << Rng; | |||||
if (const LinkageSpecDecl *LSD = Ctx->getExternCContext()) | |||||
S.Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
/// \brief Check whether a template can be declared within this scope. | /// \brief Check whether a template can be declared within this scope. | ||||
/// | /// | ||||
/// If the template declaration is valid in this scope, returns | /// If the template declaration is valid in this scope, returns | ||||
/// false. Otherwise, issues a diagnostic and returns true. | /// false. Otherwise, issues a diagnostic and returns true. | ||||
bool | bool | ||||
Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { | Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { | ||||
if (!S) | if (!S) | ||||
return false; | return false; | ||||
// Find the nearest enclosing declaration scope. | // Find the nearest enclosing declaration scope. | ||||
while ((S->getFlags() & Scope::DeclScope) == 0 || | while ((S->getFlags() & Scope::DeclScope) == 0 || | ||||
(S->getFlags() & Scope::TemplateParamScope) != 0) | (S->getFlags() & Scope::TemplateParamScope) != 0) | ||||
S = S->getParent(); | S = S->getParent(); | ||||
// C++ [temp]p4: | // C++ [temp]p4: | ||||
// A template [...] shall not have C linkage. | // A template [...] shall not have C linkage. | ||||
DeclContext *Ctx = S->getEntity(); | DeclContext *Ctx = S->getEntity(); | ||||
if (Ctx && Ctx->isExternCContext()) { | if (CheckTemplateLanguageLinkage(*this, Ctx, | ||||
Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) | TemplateParams->getSourceRange())) | ||||
<< TemplateParams->getSourceRange(); | |||||
if (const LinkageSpecDecl *LSD = Ctx->getExternCContext()) | |||||
Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); | |||||
return true; | return true; | ||||
} | |||||
Ctx = Ctx->getRedeclContext(); | Ctx = Ctx->getRedeclContext(); | ||||
// C++ [temp]p2: | // C++ [temp]p2: | ||||
// A template-declaration can appear only as a namespace scope or | // A template-declaration can appear only as a namespace scope or | ||||
// class scope declaration. | // class scope declaration. | ||||
if (Ctx) { | if (Ctx) { | ||||
if (Ctx->isFileContext()) | if (Ctx->isFileContext()) | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11) | ||||
EntityKind = 8; | EntityKind = 8; | ||||
else { | else { | ||||
S.Diag(Loc, diag::err_template_spec_unknown_kind) | S.Diag(Loc, diag::err_template_spec_unknown_kind) | ||||
<< S.getLangOpts().CPlusPlus11; | << S.getLangOpts().CPlusPlus11; | ||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity); | S.Diag(Specialized->getLocation(), diag::note_specialized_entity); | ||||
return true; | return true; | ||||
} | } | ||||
// C++ [temp]p6: | |||||
// A template, a template explicit specialization, and a class template | |||||
rogfer01: Can you add a test for a partial specialization? Your test for the class case only includes an… | |||||
Not Done ReplyInline ActionsCurrently the location used for template specialization-related diagnostics is on the next line, e.g.: /work/llvm/src/tools/clang/test/SemaTemplate/class-template-spec.cpp:242:10: error: templates must have C++ linkage struct C<T*> {}; ^ Do we want to use a different location for this particular diagnostic? miyuki: Currently the location used for template specialization-related diagnostics is on the next line… | |||||
Not Done ReplyInline ActionsOh sorry, I was not precise when I put that example. I don't think it should be different in this case. rogfer01: Oh sorry, I was not precise when I put that example. I don't think it should be different in… | |||||
// partial specialization shall not have C linkage. | |||||
if (CheckTemplateLanguageLinkage(S, S.CurContext, Loc)) | |||||
return true; | |||||
// C++ [temp.expl.spec]p2: | // C++ [temp.expl.spec]p2: | ||||
// An explicit specialization shall be declared in the namespace | // An explicit specialization shall be declared in the namespace | ||||
// of which the template is a member, or, for member templates, in | // of which the template is a member, or, for member templates, in | ||||
// the namespace of which the enclosing class or enclosing class | // the namespace of which the enclosing class or enclosing class | ||||
What do you think about factoring this out into a separate function that is then called both from here and CheckTemplateDeclScope (since it is exactly the same code?) faisalv: What do you think about factoring this out into a separate function that is then called both… | |||||
// template is a member. An explicit specialization of a member | // template is a member. An explicit specialization of a member | ||||
// function, member class or static data member of a class | // function, member class or static data member of a class | ||||
// template shall be declared in the namespace of which the class | // template shall be declared in the namespace of which the class | ||||
// template is a member. Such a declaration may also be a | // template is a member. Such a declaration may also be a | ||||
// definition. If the declaration is not a definition, the | // definition. If the declaration is not a definition, the | ||||
// specialization may be defined later in the name- space in which | // specialization may be defined later in the name- space in which | ||||
// the explicit specialization was declared, or in a namespace | // the explicit specialization was declared, or in a namespace | ||||
// that encloses the one in which the explicit specialization was | // that encloses the one in which the explicit specialization was | ||||
▲ Show 20 Lines • Show All 2,954 Lines • Show Last 20 Lines |
Can you add a test for a partial specialization? Your test for the class case only includes an explicit specialization.