diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-02-27 22:46:49 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-02-27 22:46:49 +0000 |
commit | a02411e4d58b1730bea2a990822858ecc31e8eb1 (patch) | |
tree | e9623d0ae8f36d1f6979e671fbe29e1b64f2973d /lib/Sema/SemaTemplate.cpp | |
parent | 77d2c5f66aac32546c016f57143f2d0f399acbd1 (diff) |
Eliminate a silly little Parse/Sema dance when parsing typename
specifiers such as
typename T::template apply<U>
Previously, we would turn T::template apply<U> into a
TemplateSpecializationType. Then, we'd reprocess that
TemplateSpecializationType and turn it into either a
TemplateSpecializationType wrapped in an ElaboratedType (when we could
resolve "apply" to a template declaration) or a
DependentTemplateSpecializationType. We now produce the same ASTs but
without generating the intermediate TemplateSpecializationType.
The end goal here is to avoid generating TemplateSpecializationTypes
with dependent template-names, ever. We're not there yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126589 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 108 |
1 files changed, 60 insertions, 48 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f02dd25824..625944d797 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5923,75 +5923,87 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, } TypeResult -Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - ParsedType Ty) { +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy TemplateIn, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && !getLangOptions().CPlusPlus0x) Diag(TypenameLoc, diag::ext_typename_outside_of_template) - << FixItHint::CreateRemoval(TypenameLoc); - - TypeSourceInfo *InnerTSI = 0; - QualType T = GetTypeFromParser(Ty, &InnerTSI); - - assert(isa<TemplateSpecializationType>(T) && - "Expected a template specialization type"); - + << FixItHint::CreateRemoval(TypenameLoc); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + TemplateName Template = TemplateIn.get(); + if (computeDeclContext(SS, false)) { // If we can compute a declaration context, then the "typename" // keyword was superfluous. Just build an ElaboratedType to keep // track of the nested-name-specifier. - - // Push the inner type, preserving its source locations if possible. + + QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + if (T.isNull()) + return true; + + // Provide source-location information for the template specialization + // type. TypeLocBuilder Builder; - if (InnerTSI) - Builder.pushFullCopy(InnerTSI->getTypeLoc()); - else - Builder.push<TemplateSpecializationTypeLoc>(T).initialize(Context, - TemplateLoc); - + TemplateSpecializationTypeLoc SpecTL + = Builder.push<TemplateSpecializationTypeLoc>(T); + + // FIXME: No place to set the location of the 'template' keyword! + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + // FIXME: This is a hack. We really want to push the nested-name-specifier + // into TemplateSpecializationType. + /* Note: NNS already embedded in template specialization type T. */ T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T); ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); TL.setKeywordLoc(TypenameLoc); TL.setQualifierRange(SS.getRange()); - + TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); return CreateParsedType(T, TSI); } - - // TODO: it's really silly that we make a template specialization - // type earlier only to drop it again here. - const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); - DependentTemplateName *DTN = - TST->getTemplateName().getAsDependentTemplateName(); + + // Construct a dependent template specialization type. + DependentTemplateName *DTN = Template.getAsDependentTemplateName(); assert(DTN && "dependent template has non-dependent name?"); assert(DTN->getQualifier() == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); - T = Context.getDependentTemplateSpecializationType(ETK_Typename, - DTN->getQualifier(), - DTN->getIdentifier(), - TST->getNumArgs(), - TST->getArgs()); - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentTemplateSpecializationTypeLoc TL = - cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc()); - if (InnerTSI) { - TemplateSpecializationTypeLoc TSTL = - cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc()); - TL.setLAngleLoc(TSTL.getLAngleLoc()); - TL.setRAngleLoc(TSTL.getRAngleLoc()); - for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I) - TL.setArgLocInfo(I, TSTL.getArgLocInfo(I)); - } else { - // FIXME: Poor source-location information here. - TL.initializeLocal(Context, TemplateLoc); - } - TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); - return CreateParsedType(T, TSI); + QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. + TypeLocBuilder Builder; + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(TypenameLoc); + SpecTL.setNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + // FIXME: Nested-name-specifier source locations. + SpecTL.setQualifierRange(SS.getRange()); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } + /// \brief Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType |