forked from OSchip/llvm-project
Don't claim template names that name non-templates are undeclared.
This commit is contained in:
parent
00c76f3496
commit
a5458bb0d6
|
@ -4916,7 +4916,8 @@ def note_using_value_decl_missing_typename : Note<
|
|||
"add 'typename' to treat this using declaration as a type">;
|
||||
|
||||
def err_template_kw_refers_to_non_template : Error<
|
||||
"%0 following the 'template' keyword does not refer to a template">;
|
||||
"%0%select{| following the 'template' keyword}1 "
|
||||
"does not refer to a template">;
|
||||
def note_template_kw_refers_to_non_template : Note<
|
||||
"declared as a non-template here">;
|
||||
def err_template_kw_refers_to_dependent_non_template : Error<
|
||||
|
|
|
@ -6999,6 +6999,27 @@ public:
|
|||
bool AllowFunctionTemplates = true,
|
||||
bool AllowDependent = true);
|
||||
|
||||
enum TemplateNameIsRequiredTag { TemplateNameIsRequired };
|
||||
/// Whether and why a template name is required in this lookup.
|
||||
class RequiredTemplateKind {
|
||||
public:
|
||||
/// Template name is required if TemplateKWLoc is valid.
|
||||
RequiredTemplateKind(SourceLocation TemplateKWLoc = SourceLocation())
|
||||
: TemplateKW(TemplateKWLoc) {}
|
||||
/// Template name is unconditionally required.
|
||||
RequiredTemplateKind(TemplateNameIsRequiredTag) : TemplateKW() {}
|
||||
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
return TemplateKW.getValueOr(SourceLocation());
|
||||
}
|
||||
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
|
||||
bool isRequired() const { return TemplateKW != SourceLocation(); }
|
||||
explicit operator bool() const { return isRequired(); }
|
||||
|
||||
private:
|
||||
llvm::Optional<SourceLocation> TemplateKW;
|
||||
};
|
||||
|
||||
enum class AssumedTemplateKind {
|
||||
/// This is not assumed to be a template name.
|
||||
None,
|
||||
|
@ -7008,12 +7029,11 @@ public:
|
|||
/// functions (but no function templates).
|
||||
FoundFunctions,
|
||||
};
|
||||
bool LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
|
||||
QualType ObjectType, bool EnteringContext,
|
||||
bool &MemberOfUnknownSpecialization,
|
||||
SourceLocation TemplateKWLoc = SourceLocation(),
|
||||
AssumedTemplateKind *ATK = nullptr,
|
||||
bool Disambiguation = false);
|
||||
bool LookupTemplateName(
|
||||
LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
|
||||
bool EnteringContext, bool &MemberOfUnknownSpecialization,
|
||||
RequiredTemplateKind RequiredTemplate = SourceLocation(),
|
||||
AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
|
||||
|
||||
TemplateNameKind isTemplateName(Scope *S,
|
||||
CXXScopeSpec &SS,
|
||||
|
|
|
@ -205,7 +205,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
|
|||
LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName);
|
||||
if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
|
||||
MemberOfUnknownSpecialization, SourceLocation(),
|
||||
&AssumedTemplate, Disambiguation))
|
||||
&AssumedTemplate,
|
||||
/*AllowTypoCorrection=*/!Disambiguation))
|
||||
return TNK_Non_template;
|
||||
|
||||
if (AssumedTemplate != AssumedTemplateKind::None) {
|
||||
|
@ -371,9 +372,9 @@ bool Sema::LookupTemplateName(LookupResult &Found,
|
|||
QualType ObjectType,
|
||||
bool EnteringContext,
|
||||
bool &MemberOfUnknownSpecialization,
|
||||
SourceLocation TemplateKWLoc,
|
||||
RequiredTemplateKind RequiredTemplate,
|
||||
AssumedTemplateKind *ATK,
|
||||
bool Disambiguation) {
|
||||
bool AllowTypoCorrection) {
|
||||
if (ATK)
|
||||
*ATK = AssumedTemplateKind::None;
|
||||
|
||||
|
@ -473,7 +474,8 @@ bool Sema::LookupTemplateName(LookupResult &Found,
|
|||
if (Found.isAmbiguous())
|
||||
return false;
|
||||
|
||||
if (ATK && SS.isEmpty() && ObjectType.isNull() && TemplateKWLoc.isInvalid()) {
|
||||
if (ATK && SS.isEmpty() && ObjectType.isNull() &&
|
||||
!RequiredTemplate.hasTemplateKeyword()) {
|
||||
// C++2a [temp.names]p2:
|
||||
// A name is also considered to refer to a template if it is an
|
||||
// unqualified-id followed by a < and name lookup finds either one or more
|
||||
|
@ -499,7 +501,7 @@ bool Sema::LookupTemplateName(LookupResult &Found,
|
|||
}
|
||||
}
|
||||
|
||||
if (Found.empty() && !IsDependent && !Disambiguation) {
|
||||
if (Found.empty() && !IsDependent && AllowTypoCorrection) {
|
||||
// If we did not find any names, and this is not a disambiguation, attempt
|
||||
// to correct any typos.
|
||||
DeclarationName Name = Found.getLookupName();
|
||||
|
@ -545,9 +547,11 @@ bool Sema::LookupTemplateName(LookupResult &Found,
|
|||
|
||||
// If a 'template' keyword was used, a lookup that finds only non-template
|
||||
// names is an error.
|
||||
if (ExampleLookupResult && TemplateKWLoc.isValid()) {
|
||||
if (ExampleLookupResult && RequiredTemplate) {
|
||||
Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)
|
||||
<< Found.getLookupName() << SS.getRange();
|
||||
<< Found.getLookupName() << SS.getRange()
|
||||
<< RequiredTemplate.hasTemplateKeyword()
|
||||
<< RequiredTemplate.getTemplateKeywordLoc();
|
||||
Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(),
|
||||
diag::note_template_kw_refers_to_non_template)
|
||||
<< Found.getLookupName();
|
||||
|
@ -4722,10 +4726,14 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
|
|||
LookupResult R(*this, DNI.getName(), Name.getBeginLoc(),
|
||||
LookupOrdinaryName);
|
||||
bool MOUS;
|
||||
// FIXME: If LookupTemplateName fails here, we'll have produced its
|
||||
// diagnostics twice.
|
||||
if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext,
|
||||
MOUS, TemplateKWLoc) && !R.isAmbiguous()) {
|
||||
// Tell LookupTemplateName that we require a template so that it diagnoses
|
||||
// cases where it finds a non-template.
|
||||
RequiredTemplateKind RTK = TemplateKWLoc.isValid()
|
||||
? RequiredTemplateKind(TemplateKWLoc)
|
||||
: TemplateNameIsRequired;
|
||||
if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, MOUS,
|
||||
RTK, nullptr, /*AllowTypoCorrection=*/false) &&
|
||||
!R.isAmbiguous()) {
|
||||
if (LookupCtx)
|
||||
Diag(Name.getBeginLoc(), diag::err_no_member)
|
||||
<< DNI.getName() << LookupCtx << SS.getRange();
|
||||
|
|
|
@ -169,4 +169,17 @@ namespace TwoPhaseLookup {
|
|||
void h3(N::G<int> *p) { p->~G<int>(); }
|
||||
void h4(N::G<int> *p) { f(p); }
|
||||
}
|
||||
|
||||
namespace TemplateNamesNonTemplate {
|
||||
int A; // expected-note 2{{non-template here}}
|
||||
template<typename> int B; // expected-note 2{{variable template 'B' declared here}} expected-warning {{extension}}
|
||||
using C = int; // expected-note 2{{non-template here}}
|
||||
|
||||
template<typename T> void f1(int *p) { p->~A<int>(); } // expected-error {{'A' does not refer to a template}}
|
||||
template<typename T> void f2(int *p) { p->~B<int>(); } // expected-error {{template name refers to non-type template 'B'}}
|
||||
template<typename T> void f3(int *p) { p->~C<int>(); } // expected-error {{'C' does not refer to a template}}
|
||||
template<typename T> void f4(int *p) { p->TemplateNamesNonTemplate::C::~A<int>(); } // expected-error {{'A' does not refer to a template}}
|
||||
template<typename T> void f5(int *p) { p->TemplateNamesNonTemplate::C::~B<int>(); } // expected-error {{template name refers to non-type template 'TemplateNamesNonTemplate::B'}}
|
||||
template<typename T> void f6(int *p) { p->TemplateNamesNonTemplate::C::~C<int>(); } // expected-error {{'C' does not refer to a template}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue