Start processing template-ids as types when the template-name refers
to a class template. For example, the template-id 'vector<int>' now
has a nice, sugary type in the type system. What we can do now:
- Parse template-ids like 'vector<int>' (where 'vector' names a
class template) and form proper types for them in the type system.
- Parse icky template-ids like 'A<5>' and 'A<(5 > 0)>' properly,
using (sadly) a bool in the parser to tell it whether '>' should
be treated as an operator or not.
This is a baby-step, with major problems and limitations:
- There are currently two ways that we handle template arguments
(whether they are types or expressions). These will be merged, and,
most likely, TemplateArg will disappear.
- We don't have any notion of the declaration of class template
specializations or of template instantiations, so all template-ids
are fancy names for 'int' :)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64153 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 6c5f90a..6b6a501 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -25,38 +25,43 @@
/// declaration if II names a template. An optional CXXScope can be
/// passed to indicate the C++ scope in which the identifier will be
/// found.
-Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS) {
- DeclContext *DC = 0;
-
- if (SS) {
- if (SS->isInvalid())
- return 0;
- DC = static_cast<DeclContext*>(SS->getScopeRep());
- }
+Sema::TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S,
+ DeclTy *&Template,
+ const CXXScopeSpec *SS) {
NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
if (IIDecl) {
- // FIXME: We need to represent templates via some kind of
- // TemplateDecl, because what follows is a hack that only works in
- // one specific case.
- if (isa<TemplateDecl>(IIDecl))
- return IIDecl;
+ if (isa<TemplateDecl>(IIDecl)) {
+ Template = IIDecl;
+ if (isa<FunctionTemplateDecl>(IIDecl))
+ return TNK_Function_template;
+ else if (isa<ClassTemplateDecl>(IIDecl))
+ return TNK_Class_template;
+ else if (isa<TemplateTemplateParmDecl>(IIDecl))
+ return TNK_Template_template_parm;
+ else
+ assert(false && "Unknown TemplateDecl");
+ }
+ // FIXME: What follows is a gross hack.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
- if (FD->getType()->isDependentType())
- return FD;
+ if (FD->getType()->isDependentType()) {
+ Template = FD;
+ return TNK_Function_template;
+ }
} else if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(IIDecl)) {
for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
FEnd = Ovl->function_end();
F != FEnd; ++F) {
- if ((*F)->getType()->isDependentType())
- return Ovl;
+ if ((*F)->getType()->isDependentType()) {
+ Template = Ovl;
+ return TNK_Function_template;
+ }
}
}
}
- return 0;
+ return TNK_Non_template;
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -226,6 +231,15 @@
(Decl**)Params, NumParams, RAngleLoc);
}
+Sema::OwningTemplateArgResult Sema::ActOnTypeTemplateArgument(TypeTy *Type) {
+ return Owned(new (Context) TemplateArg(QualType::getFromOpaquePtr(Type)));
+}
+
+Sema::OwningTemplateArgResult
+Sema::ActOnExprTemplateArgument(ExprArg Value) {
+ return Owned(new (Context) TemplateArg(static_cast<Expr *>(Value.release())));
+}
+
Sema::DeclTy *
Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
@@ -351,6 +365,42 @@
return NewTemplate;
}
+Action::TypeTy *
+Sema::ActOnClassTemplateSpecialization(DeclTy *TemplateD,
+ SourceLocation LAngleLoc,
+ MultiTemplateArgsArg TemplateArgsIn,
+ SourceLocation RAngleLoc,
+ const CXXScopeSpec *SS) {
+ TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD));
+
+ // FIXME: Not happy about this. We should teach the parser to pass
+ // us opaque pointers + bools for template argument lists.
+ // FIXME: Also not happy about the fact that we leak these
+ // TemplateArg structures. Fixing the above will fix this, too.
+ llvm::SmallVector<uintptr_t, 16> Args;
+ llvm::SmallVector<bool, 16> ArgIsType;
+ unsigned NumArgs = TemplateArgsIn.size();
+ TemplateArg **TemplateArgs
+ = reinterpret_cast<TemplateArg **>(TemplateArgsIn.release());
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Expr *ExprArg = TemplateArgs[Arg]->getAsExpr()) {
+ Args.push_back(reinterpret_cast<uintptr_t>(ExprArg));
+ ArgIsType.push_back(false);
+ } else {
+ QualType T = TemplateArgs[Arg]->getAsType();
+ Args.push_back(reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()));
+ ArgIsType.push_back(true);
+ }
+ }
+
+ // Yes, all class template specializations are just silly sugar for
+ // 'int'. Gotta problem wit dat?
+ return Context.getClassTemplateSpecializationType(Template, NumArgs,
+ &Args[0], &ArgIsType[0],
+ Context.IntTy)
+ .getAsOpaquePtr();
+}
+
/// \brief Determine whether the given template parameter lists are
/// equivalent.
///