aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-02-27 22:46:49 +0000
committerDouglas Gregor <dgregor@apple.com>2011-02-27 22:46:49 +0000
commita02411e4d58b1730bea2a990822858ecc31e8eb1 (patch)
treee9623d0ae8f36d1f6979e671fbe29e1b64f2973d
parent77d2c5f66aac32546c016f57143f2d0f399acbd1 (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
-rw-r--r--include/clang/Sema/Sema.h15
-rw-r--r--lib/Parse/Parser.cpp20
-rw-r--r--lib/Sema/SemaTemplate.cpp108
3 files changed, 83 insertions, 60 deletions
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<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