diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-09 03:31:27 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-09 03:31:27 +0000 |
commit | b23c5e8c3df850177449268c5ca7dbf986157525 (patch) | |
tree | 676dabf23d28ebd62d0f453558f8874ea7eafe29 /clang/lib/AST | |
parent | a438a898b02a93a0179be1dd5ed67fb5b01dcf6b (diff) | |
download | bcm5719-llvm-b23c5e8c3df850177449268c5ca7dbf986157525.tar.gz bcm5719-llvm-b23c5e8c3df850177449268c5ca7dbf986157525.zip |
[c++20] Implement P0846R0: allow (ADL-only) calls to template-ids whose
template name is not visible to unqualified lookup.
In order to support this without a severe degradation in our ability to
diagnose typos in template names, this change significantly restructures
the way we handle template-id-shaped syntax for which lookup of the
template name finds nothing.
Instead of eagerly diagnosing an undeclared template name, we now form a
placeholder template-name representing a name that is known to not find
any templates. When the parser sees such a name, it attempts to
disambiguate whether we have a less-than comparison or a template-id.
Any diagnostics or typo-correction for the name are delayed until its
point of use.
The upshot should be a small improvement of our diagostic quality
overall: we now take more syntactic context into account when trying to
resolve an undeclared identifier on the left hand side of a '<'. In
fact, this works well enough that the backwards-compatible portion (for
an undeclared identifier rather than a lookup that finds functions but
no function templates) is enabled in all language modes.
llvm-svn: 360308
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 15 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ODRHash.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/TemplateName.cpp | 16 |
6 files changed, 46 insertions, 2 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 63488853759..c144e01626e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5226,6 +5226,11 @@ ASTContext::getNameForTemplate(TemplateName Name, return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc); } + case TemplateName::AssumedTemplate: { + AssumedTemplateStorage *Storage = Name.getAsAssumedTemplateName(); + return DeclarationNameInfo(Storage->getDeclName(), NameLoc); + } + case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); DeclarationName DName; @@ -5273,7 +5278,8 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const { } case TemplateName::OverloadedTemplate: - llvm_unreachable("cannot canonicalize overloaded template"); + case TemplateName::AssumedTemplate: + llvm_unreachable("cannot canonicalize unresolved template"); case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); @@ -7620,6 +7626,13 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, return TemplateName(OT); } +/// Retrieve a template name representing an unqualified-id that has been +/// assumed to name a template for ADL purposes. +TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const { + auto *OT = new (*this) AssumedTemplateStorage(Name); + return TemplateName(OT); +} + /// Retrieve the template name that represents a qualified /// template name such as \c std::vector. TemplateName diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 7ce2abee6ce..d10db32e872 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8126,6 +8126,14 @@ Expected<TemplateName> ASTImporter::Import_New(TemplateName From) { ToTemplates.end()); } + case TemplateName::AssumedTemplate: { + AssumedTemplateStorage *FromStorage = From.getAsAssumedTemplateName(); + auto DeclNameOrErr = Import_New(FromStorage->getDeclName()); + if (!DeclNameOrErr) + return DeclNameOrErr.takeError(); + return ToContext.getAssumedTemplateName(*DeclNameOrErr); + } + case TemplateName::QualifiedTemplate: { QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName(); auto QualifierOrErr = Import_New(QTN->getQualifier()); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index bf084e325cc..3eafa3d9508 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -180,6 +180,12 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return I1 == E1 && I2 == E2; } + case TemplateName::AssumedTemplate: { + AssumedTemplateStorage *TN1 = N1.getAsAssumedTemplateName(), + *TN2 = N1.getAsAssumedTemplateName(); + return TN1->getDeclName() == TN2->getDeclName(); + } + case TemplateName::QualifiedTemplate: { QualifiedTemplateName *QN1 = N1.getAsQualifiedTemplateName(), *QN2 = N2.getAsQualifiedTemplateName(); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 1dba7ccc90a..8bc19a34e6f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1891,6 +1891,7 @@ void CXXNameMangler::mangleType(TemplateName TN) { break; case TemplateName::OverloadedTemplate: + case TemplateName::AssumedTemplate: llvm_unreachable("can't mangle an overloaded template name as a <type>"); case TemplateName::DependentTemplate: { @@ -2030,6 +2031,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, } case TemplateName::OverloadedTemplate: + case TemplateName::AssumedTemplate: case TemplateName::DependentTemplate: llvm_unreachable("invalid base for a template specialization type"); diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 9d484bd5de5..ba3b2ee49c5 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -140,6 +140,7 @@ void ODRHash::AddTemplateName(TemplateName Name) { break; // TODO: Support these cases. case TemplateName::OverloadedTemplate: + case TemplateName::AssumedTemplate: case TemplateName::QualifiedTemplate: case TemplateName::DependentTemplate: case TemplateName::SubstTemplateTemplateParm: diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index 2474d6278b2..06e1dcec744 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -66,6 +66,8 @@ TemplateName::TemplateName(void *Ptr) { TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} TemplateName::TemplateName(OverloadedTemplateStorage *Storage) : Storage(Storage) {} +TemplateName::TemplateName(AssumedTemplateStorage *Storage) + : Storage(Storage) {} TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) : Storage(Storage) {} TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) @@ -87,6 +89,8 @@ TemplateName::NameKind TemplateName::getKind() const { = Storage.get<UncommonTemplateNameStorage*>(); if (uncommon->getAsOverloadedStorage()) return OverloadedTemplate; + if (uncommon->getAsAssumedTemplateName()) + return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; return SubstTemplateTemplateParmPack; @@ -113,6 +117,14 @@ OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { return nullptr; } +AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const { + if (UncommonTemplateNameStorage *Uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return Uncommon->getAsAssumedTemplateName(); + + return nullptr; +} + SubstTemplateTemplateParmStorage * TemplateName::getAsSubstTemplateTemplateParm() const { if (UncommonTemplateNameStorage *uncommon = @@ -230,7 +242,9 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, } else if (SubstTemplateTemplateParmPackStorage *SubstPack = getAsSubstTemplateTemplateParmPack()) OS << *SubstPack->getParameterPack(); - else { + else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { + Assumed->getDeclName().print(OS, Policy); + } else { OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); (*OTS->begin())->printName(OS); } |