summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-05-09 03:31:27 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-05-09 03:31:27 +0000
commitb23c5e8c3df850177449268c5ca7dbf986157525 (patch)
tree676dabf23d28ebd62d0f453558f8874ea7eafe29 /clang/lib/AST
parenta438a898b02a93a0179be1dd5ed67fb5b01dcf6b (diff)
downloadbcm5719-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.cpp15
-rw-r--r--clang/lib/AST/ASTImporter.cpp8
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp6
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp2
-rw-r--r--clang/lib/AST/ODRHash.cpp1
-rw-r--r--clang/lib/AST/TemplateName.cpp16
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);
}
OpenPOWER on IntegriCloud