[cfe-commits] r68128 - in /cfe/trunk: include/clang/AST/TemplateName.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/TemplateName.cpp lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiate-template-template-parm.cpp test/SemaTemplate/metafun-apply.cpp
Douglas Gregor
dgregor at apple.com
Tue Mar 31 11:38:03 PDT 2009
Author: dgregor
Date: Tue Mar 31 13:38:02 2009
New Revision: 68128
URL: http://llvm.org/viewvc/llvm-project?rev=68128&view=rev
Log:
Implement template instantiation for template names, including both
template template parameters and dependent template names. For
example, the oft-mentioned
typename MetaFun::template apply<T1, T2>::type
can now be instantiated, with the appropriate name lookup for "apply".
Added:
cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp
Modified:
cfe/trunk/include/clang/AST/TemplateName.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/TemplateName.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/SemaTemplate/metafun-apply.cpp
Modified: cfe/trunk/include/clang/AST/TemplateName.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateName.h?rev=68128&r1=68127&r2=68128&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateName.h (original)
+++ cfe/trunk/include/clang/AST/TemplateName.h Tue Mar 31 13:38:02 2009
@@ -99,6 +99,10 @@
/// \brief Print the template name.
void Print(llvm::raw_ostream &OS) const;
+ /// \brief Debugging aid that dumps the template name to standard
+ /// error.
+ void Dump() const;
+
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddPointer(Storage.getOpaqueValue());
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=68128&r1=68127&r2=68128&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 31 13:38:02 2009
@@ -701,6 +701,8 @@
def err_template_kw_refers_to_non_template : Error<
"%0 following the 'template' keyword does not refer to a template">;
+def err_template_kw_refers_to_function_template : Error<
+ "%0 following the 'template' keyword refers to a function template">;
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
Modified: cfe/trunk/lib/AST/TemplateName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateName.cpp?rev=68128&r1=68127&r2=68128&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateName.cpp (original)
+++ cfe/trunk/lib/AST/TemplateName.cpp Tue Mar 31 13:38:02 2009
@@ -14,6 +14,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "llvm/Support/raw_ostream.h"
+#include <stdio.h>
using namespace clang;
@@ -52,3 +53,12 @@
OS << DTN->getName()->getName();
}
}
+
+void TemplateName::Dump() const {
+ std::string Result;
+ {
+ llvm::raw_string_ostream OS(Result);
+ Print(OS);
+ }
+ fprintf(stderr, "%s", Result.c_str());
+}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=68128&r1=68127&r2=68128&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 31 13:38:02 2009
@@ -1981,6 +1981,11 @@
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
+ TemplateName
+ InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+
// Simple function for cloning expressions.
template<typename T>
OwningExprResult Clone(T *E) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=68128&r1=68127&r2=68128&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 31 13:38:02 2009
@@ -472,10 +472,13 @@
// FIXME: We're missing the locations of the template name, '<', and
// '>'.
- // FIXME: Need to instantiate into the template name.
- return SemaRef.CheckTemplateIdType(T->getTemplateName(),
- Loc,
- SourceLocation(),
+
+ TemplateName Name = SemaRef.InstantiateTemplateName(T->getTemplateName(),
+ Loc,
+ TemplateArgs,
+ NumTemplateArgs);
+
+ return SemaRef.CheckTemplateIdType(Name, Loc, SourceLocation(),
&InstantiatedTemplateArgs[0],
InstantiatedTemplateArgs.size(),
SourceLocation());
@@ -839,3 +842,72 @@
// Required to silence a GCC warning
return 0;
}
+
+TemplateName
+Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(
+ Name.getAsTemplateDecl())) {
+ assert(TTP->getDepth() == 0 &&
+ "Cannot reduce depth of a template template parameter");
+ assert(TTP->getPosition() < NumTemplateArgs && "Wrong # of template args");
+ assert(dyn_cast_or_null<ClassTemplateDecl>(
+ TemplateArgs[TTP->getPosition()].getAsDecl()) &&
+ "Wrong kind of template template argument");
+ ClassTemplateDecl *ClassTemplate
+ = dyn_cast<ClassTemplateDecl>(
+ TemplateArgs[TTP->getPosition()].getAsDecl());
+
+ if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+ NestedNameSpecifier *NNS
+ = InstantiateNestedNameSpecifier(QTN->getQualifier(),
+ /*FIXME=*/SourceRange(Loc),
+ TemplateArgs, NumTemplateArgs);
+ if (NNS)
+ return Context.getQualifiedTemplateName(NNS,
+ QTN->hasTemplateKeyword(),
+ ClassTemplate);
+ }
+
+ return TemplateName(ClassTemplate);
+ } else if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ NestedNameSpecifier *NNS
+ = InstantiateNestedNameSpecifier(DTN->getQualifier(),
+ /*FIXME=*/SourceRange(Loc),
+ TemplateArgs, NumTemplateArgs);
+
+ if (!NNS) // FIXME: Not the best recovery strategy.
+ return Name;
+
+ if (NNS->isDependent())
+ return Context.getDependentTemplateName(NNS, DTN->getName());
+
+ // Somewhat redundant with ActOnDependentTemplateName.
+ CXXScopeSpec SS;
+ SS.setRange(SourceRange(Loc));
+ SS.setScopeRep(NNS);
+ TemplateTy Template;
+ TemplateNameKind TNK = isTemplateName(*DTN->getName(), 0, Template, &SS);
+ if (TNK == TNK_Non_template) {
+ Diag(Loc, diag::err_template_kw_refers_to_non_template)
+ << DTN->getName();
+ return Name;
+ } else if (TNK == TNK_Function_template) {
+ Diag(Loc, diag::err_template_kw_refers_to_non_template)
+ << DTN->getName();
+ return Name;
+ }
+
+ return Template.getAsVal<TemplateName>();
+ }
+
+
+
+ // FIXME: Even if we're referring to a Decl that isn't a template
+ // template parameter, we may need to instantiate the outer contexts
+ // of that Decl. However, this won't be needed until we implement
+ // member templates.
+ return Name;
+}
Added: cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp?rev=68128&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp Tue Mar 31 13:38:02 2009
@@ -0,0 +1,21 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<template<typename T> class MetaFun, typename Value>
+struct apply {
+ typedef typename MetaFun<Value>::type type;
+};
+
+template<class T>
+struct add_pointer {
+ typedef T* type;
+};
+
+template<class T>
+struct add_reference {
+ typedef T& type;
+};
+
+int i;
+apply<add_pointer, int>::type ip = &i;
+apply<add_reference, int>::type ir = i;
+apply<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}}
Modified: cfe/trunk/test/SemaTemplate/metafun-apply.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/metafun-apply.cpp?rev=68128&r1=68127&r2=68128&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/metafun-apply.cpp (original)
+++ cfe/trunk/test/SemaTemplate/metafun-apply.cpp Tue Mar 31 13:38:02 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only %s
+// RUN: clang-cc -fsyntax-only -verify %s
struct add_pointer {
template<typename T>
@@ -10,20 +10,21 @@
struct add_reference {
template<typename T>
struct apply {
- typedef T& type;
+ typedef T& type; // expected-error{{cannot form a reference to 'void'}}
};
};
template<typename MetaFun, typename T>
struct apply1 {
- typedef typename MetaFun::template apply<T>::type type;
+ typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'struct add_reference::apply<void>' requested here}}
};
-#if 0
-// FIXME: The code below requires template instantiation for dependent
-// template-names that occur within nested-name-specifiers.
int i;
-
apply1<add_pointer, int>::type ip = &i;
apply1<add_reference, int>::type ir = i;
-#endif
+apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}}
+
+void test() {
+ apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \
+ // FIXME: expected-error{{unexpected type name 'type': expected expression}}
+}
More information about the cfe-commits
mailing list