From: Douglas Gregor Date: Sun, 27 Feb 2011 22:46:49 +0000 (+0000) Subject: Eliminate a silly little Parse/Sema dance when parsing typename X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a02411e4d58b1730bea2a990822858ecc31e8eb1;p=clang Eliminate a silly little Parse/Sema dance when parsing typename specifiers such as typename T::template apply Previously, we would turn T::template apply 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 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 7a1a9f6b09..b124bbe475 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3384,11 +3384,20 @@ public: /// \param TypenameLoc the location of the 'typename' keyword /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). /// \param TemplateLoc the location of the 'template' keyword, if any. - /// \param Ty the type that the typename specifier refers to. + /// \param TemplateName The template name. + /// \param TemplateNameLoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). TypeResult ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - ParsedType Ty); + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc); QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 07e592cdb0..69d1853c0f 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1051,15 +1051,17 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { return true; } - AnnotateTemplateIdTokenAsType(0); - assert(Tok.is(tok::annot_typename) && - "AnnotateTemplateIdTokenAsType isn't working properly"); - if (Tok.getAnnotationValue()) - Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, - SourceLocation(), - getTypeAnnotation(Tok)); - else - Ty = true; + ASTTemplateArgsPtr TemplateArgsPtr(Actions, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + + Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, + /*FIXME:*/SourceLocation(), + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); } else { Diag(Tok, diag::err_expected_type_name_after_typename) << SS.getRange(); 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(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(T).initialize(Context, - TemplateLoc); - + TemplateSpecializationTypeLoc SpecTL + = Builder.push(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(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(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(SS.getScopeRep())); - T = Context.getDependentTemplateSpecializationType(ETK_Typename, - DTN->getQualifier(), - DTN->getIdentifier(), - TST->getNumArgs(), - TST->getArgs()); - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentTemplateSpecializationTypeLoc TL = - cast(TSI->getTypeLoc()); - if (InnerTSI) { - TemplateSpecializationTypeLoc TSTL = - cast(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(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