aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-27 23:10:48 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-27 23:10:48 +0000
commitd57959af02b4af695276f4204443afe6e5d86bd8 (patch)
tree1c3cfaf8db2cb260e9365d44d7f5b178a836b750 /lib/Sema/SemaTemplate.cpp
parentced21016cec1f189a695857bed103ecc9e3f3696 (diff)
Initial implementation of parsing, semantic analysis, and template
instantiation for C++ typename-specifiers such as typename T::type The parsing of typename-specifiers is relatively easy thanks to annotation tokens. When we see the "typename", we parse the typename-specifier and produce a typename annotation token. There are only a few places where we need to handle this. We currently parse the typename-specifier form that terminates in an identifier, but not the simple-template-id form, e.g., typename T::template apply<U, V> Parsing of nested-name-specifiers has a similar problem, since at this point we don't have any representation of a class template specialization whose template-name is unknown. Semantic analysis is only partially complete, with some support for template instantiation that works for simple examples. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67875 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp81
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 697582c82c..69946975cd 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1964,3 +1964,84 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
CurContext->addDecl(Specialization);
return Specialization;
}
+
+Sema::TypeResult
+Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+ const IdentifierInfo &II, SourceLocation IdLoc) {
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (!NNS)
+ return true;
+
+ QualType T = CheckTypenameType(NNS, II, SourceRange(TypenameLoc, IdLoc));
+ if (T.isNull())
+ return 0;
+
+ return T.getAsOpaquePtr();
+}
+
+/// \brief Build the type that describes a C++ typename specifier,
+/// e.g., "typename T::type".
+QualType
+Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
+ SourceRange Range) {
+ if (NNS->isDependent()) // FIXME: member of the current instantiation!
+ return Context.getTypenameType(NNS, &II);
+
+ CXXScopeSpec SS;
+ SS.setScopeRep(NNS);
+ SS.setRange(Range);
+ if (RequireCompleteDeclContext(SS))
+ return QualType();
+
+ DeclContext *Ctx = computeDeclContext(SS);
+ assert(Ctx && "No declaration context?");
+
+ DeclarationName Name(&II);
+ LookupResult Result = LookupQualifiedName(Ctx, Name, LookupOrdinaryName,
+ false);
+ unsigned DiagID = 0;
+ Decl *Referenced = 0;
+ switch (Result.getKind()) {
+ case LookupResult::NotFound:
+ if (Ctx->isTranslationUnit())
+ DiagID = diag::err_typename_nested_not_found_global;
+ else
+ DiagID = diag::err_typename_nested_not_found;
+ break;
+
+ case LookupResult::Found:
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getAsDecl())) {
+ // We found a type. Build a QualifiedNameType, since the
+ // typename-specifier was just sugar. FIXME: Tell
+ // QualifiedNameType that it has a "typename" prefix.
+ return Context.getQualifiedNameType(NNS, Context.getTypeDeclType(Type));
+ }
+
+ DiagID = diag::err_typename_nested_not_type;
+ Referenced = Result.getAsDecl();
+ break;
+
+ case LookupResult::FoundOverloaded:
+ DiagID = diag::err_typename_nested_not_type;
+ Referenced = *Result.begin();
+ break;
+
+ case LookupResult::AmbiguousBaseSubobjectTypes:
+ case LookupResult::AmbiguousBaseSubobjects:
+ case LookupResult::AmbiguousReference:
+ DiagnoseAmbiguousLookup(Result, Name, Range.getEnd(), Range);
+ return QualType();
+ }
+
+ // If we get here, it's because name lookup did not find a
+ // type. Emit an appropriate diagnostic and return an error.
+ if (NamedDecl *NamedCtx = dyn_cast<NamedDecl>(Ctx))
+ Diag(Range.getEnd(), DiagID) << Range << Name << NamedCtx;
+ else
+ Diag(Range.getEnd(), DiagID) << Range << Name;
+ if (Referenced)
+ Diag(Referenced->getLocation(), diag::note_typename_refers_here)
+ << Name;
+ return QualType();
+}