forked from OSchip/llvm-project
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. llvm-svn: 126589
This commit is contained in:
parent
99847d2bf1
commit
b09518c551
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue