diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-27 23:10:48 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-27 23:10:48 +0000 |
commit | d57959af02b4af695276f4204443afe6e5d86bd8 (patch) | |
tree | 1c3cfaf8db2cb260e9365d44d7f5b178a836b750 /lib/Sema/SemaTemplate.cpp | |
parent | ced21016cec1f189a695857bed103ecc9e3f3696 (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.cpp | 81 |
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(); +} |