[cfe-commits] r74563 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/AST/StmtNodes.def include/clang/Parse/Action.h lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp
Douglas Gregor
dgregor at apple.com
Tue Jun 30 15:34:41 PDT 2009
Author: dgregor
Date: Tue Jun 30 17:34:41 2009
New Revision: 74563
URL: http://llvm.org/viewvc/llvm-project?rev=74563&view=rev
Log:
Preliminary parsing and ASTs for template-ids that refer to function
templates, such as make<int&>. These template-ids are only barely
functional for function calls; much more to come.
Added:
cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp
Modified:
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/AST/StmtNodes.def
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Jun 30 17:34:41 2009
@@ -1017,6 +1017,100 @@
virtual StmtIterator child_end();
};
+/// \brief An expression that refers to a C++ template-id, such as
+/// @c isa<FunctionDecl>.
+class TemplateIdRefExpr : public Expr {
+ /// \brief If this template-id was qualified-id, e.g., @c std::sort<int>,
+ /// this nested name specifier contains the @c std::.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>,
+ /// this covers the source code range of the @c std::.
+ SourceRange QualifierRange;
+
+ /// \brief The actual template to which this template-id refers.
+ TemplateName Template;
+
+ /// \brief The source location of the template name.
+ SourceLocation TemplateNameLoc;
+
+ /// \brief The source location of the left angle bracket ('<');
+ SourceLocation LAngleLoc;
+
+ /// \brief The source location of the right angle bracket ('>');
+ SourceLocation RAngleLoc;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
+
+ TemplateIdRefExpr(QualType T,
+ NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ TemplateName Template, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc);
+
+public:
+ static TemplateIdRefExpr *
+ Create(ASTContext &Context, QualType T,
+ NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ TemplateName Template, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, SourceLocation RAngleLoc);
+
+ void Destroy(ASTContext &Context);
+
+ /// \brief Retrieve the nested name specifier used to qualify the name of
+ /// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL
+ /// if this template-id was an unqualified-id.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Retrieve the source range describing the nested name specifier
+ /// used to qualified the name of this template-id, if the name was qualified.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the name of the template referenced, e.g., "sort" in
+ /// @c std::sort<int>;
+ TemplateName getTemplateName() const { return Template; }
+
+ /// \brief Retrieve the location of the name of the template referenced, e.g.,
+ /// the location of "sort" in @c std::sort<int>.
+ SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// template name ('<').
+ SourceLocation getLAngleLoc() const { return LAngleLoc; }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgument *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgument *>(this + 1);
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc,
+ RAngleLoc);
+ }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TemplateIdRefExprClass;
+ }
+ static bool classof(const TemplateIdRefExpr *) { return true; }
+};
+
class CXXExprWithTemporaries : public Expr {
Stmt *SubExpr;
Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Tue Jun 30 17:34:41 2009
@@ -9,7 +9,7 @@
//
// This file defines the AST Node info database.
//
-//===----------------------------------------------------------------------===//
+//===---------------------------------------------------------------------===//
#ifndef FIRST_STMT
#define FIRST_STMT(CLASS)
@@ -123,6 +123,7 @@
EXPR(UnaryTypeTraitExpr , Expr)
EXPR(QualifiedDeclRefExpr , DeclRefExpr)
EXPR(UnresolvedDeclRefExpr , Expr)
+EXPR(TemplateIdRefExpr , Expr)
EXPR(CXXConstructExpr , Expr)
EXPR(CXXBindTemporaryExpr , Expr)
EXPR(CXXExprWithTemporaries , Expr)
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Jun 30 17:34:41 2009
@@ -1379,6 +1379,24 @@
return TypeResult();
};
+ /// \brief Form a reference to a template-id (that will refer to a function)
+ /// from a template and a list of template arguments.
+ ///
+ /// This action forms an expression that references the given template-id,
+ /// possibly checking well-formedness of the template arguments. It does not
+ /// imply the declaration of any entity.
+ ///
+ /// \param Template A template whose specialization results in a
+ /// function or a dependent template.
+ virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc) {
+ return ExprError();
+ }
+
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Jun 30 17:34:41 2009
@@ -13,6 +13,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
using namespace clang;
@@ -153,6 +154,65 @@
return child_iterator();
}
+TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc)
+ : Expr(TemplateIdRefExprClass, T,
+ (Template.isDependent() ||
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs, NumTemplateArgs)),
+ (Template.isDependent() ||
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs, NumTemplateArgs))),
+ Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template),
+ TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc),
+ RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs)
+
+{
+ TemplateArgument *StoredTemplateArgs
+ = reinterpret_cast<TemplateArgument *> (this+1);
+ for (unsigned I = 0; I != NumTemplateArgs; ++I)
+ new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
+}
+
+TemplateIdRefExpr *
+TemplateIdRefExpr::Create(ASTContext &Context, QualType T,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, SourceLocation RAngleLoc) {
+ void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
+ sizeof(TemplateArgument) * NumTemplateArgs);
+ return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
+ TemplateNameLoc, LAngleLoc, TemplateArgs,
+ NumTemplateArgs, RAngleLoc);
+}
+
+void TemplateIdRefExpr::Destroy(ASTContext &Context) {
+ const TemplateArgument *TemplateArgs = getTemplateArgs();
+ for (unsigned I = 0; I != NumTemplateArgs; ++I)
+ if (Expr *E = TemplateArgs[I].getAsExpr())
+ E->Destroy(Context);
+}
+
+Stmt::child_iterator TemplateIdRefExpr::child_begin() {
+ // FIXME: Walk the expressions in the template arguments (?)
+ return Stmt::child_iterator();
+}
+
+Stmt::child_iterator TemplateIdRefExpr::child_end() {
+ // FIXME: Walk the expressions in the template arguments (?)
+ return Stmt::child_iterator();
+}
+
bool UnaryTypeTraitExpr::EvaluateTrait() const {
switch(UTT) {
default: assert(false && "Unknown type trait or not implemented");
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Jun 30 17:34:41 2009
@@ -490,6 +490,18 @@
OS << Node->getDeclName().getAsString();
}
+void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) {
+ if (Node->getQualifier())
+ Node->getQualifier()->print(OS, Policy);
+ Node->getTemplateName().print(OS, Policy, true);
+ OS << '<';
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+ OS << '>';
+}
+
void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
if (Node->getBase()) {
PrintExpr(Node->getBase());
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Jun 30 17:34:41 2009
@@ -777,7 +777,7 @@
case tok::annot_cxxscope: // [C++] id-expression: qualified-id
case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
- // template-id
+ case tok::annot_template_id: // [C++] template-id
Res = ParseCXXIdExpression(isAddressOfOperand);
return ParsePostfixExpressionSuffix(move(Res));
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Jun 30 17:34:41 2009
@@ -207,13 +207,13 @@
/// operator-function-id
/// conversion-function-id [TODO]
/// '~' class-name [TODO]
-/// template-id [TODO]
+/// template-id
///
/// qualified-id:
/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
/// '::' identifier
/// '::' operator-function-id
-/// '::' template-id [TODO]
+/// '::' template-id
///
/// nested-name-specifier:
/// type-name '::'
@@ -264,7 +264,7 @@
// operator-function-id
// conversion-function-id
// '~' class-name [TODO]
- // template-id [TODO]
+ // template-id
//
switch (Tok.getKind()) {
default:
@@ -294,6 +294,29 @@
return ExprError();
}
+ case tok::annot_template_id: {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ assert((TemplateId->Kind == TNK_Function_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) &&
+ "A template type name is not an ID expression");
+
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ TemplateId->getTemplateArgs(),
+ TemplateId->getTemplateArgIsType(),
+ TemplateId->NumArgs);
+
+ OwningExprResult Result
+ = Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->getTemplateArgLocations(),
+ TemplateId->RAngleLoc);
+ ConsumeToken(); // Consume the template-id token
+ return move(Result);
+ }
+
} // switch.
assert(0 && "The switch was supposed to take care everything.");
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jun 30 17:34:41 2009
@@ -2075,6 +2075,20 @@
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
+ OwningExprResult BuildTemplateIdExpr(TemplateName Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc);
+
+ virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc);
+
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
SourceLocation NameLoc,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 30 17:34:41 2009
@@ -2635,7 +2635,6 @@
}
// If we're directly calling a function, get the appropriate declaration.
- DeclRefExpr *DRExpr = NULL;
Expr *FnExpr = Fn;
bool ADL = true;
while (true) {
@@ -2650,14 +2649,19 @@
cast<UnaryOperator>(FnExpr)->getOpcode()
== UnaryOperator::AddrOf) {
FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr();
- } else if ((DRExpr = dyn_cast<DeclRefExpr>(FnExpr))) {
+ } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) {
// Qualified names disable ADL (C++0x [basic.lookup.argdep]p1).
ADL &= !isa<QualifiedDeclRefExpr>(DRExpr);
+ NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl());
break;
} else if (UnresolvedFunctionNameExpr *DepName
= dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) {
UnqualifiedName = DepName->getName();
break;
+ } else if (TemplateIdRefExpr *TemplateIdRef
+ = dyn_cast<TemplateIdRefExpr>(FnExpr)) {
+ NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl();
+ break;
} else {
// Any kind of name that does not refer to a declaration (or
// set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3).
@@ -2668,14 +2672,13 @@
OverloadedFunctionDecl *Ovl = 0;
FunctionTemplateDecl *FunctionTemplate = 0;
- if (DRExpr) {
- FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
- if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DRExpr->getDecl())))
+ if (NDecl) {
+ FDecl = dyn_cast<FunctionDecl>(NDecl);
+ if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(NDecl)))
FDecl = FunctionTemplate->getTemplatedDecl();
else
- FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
- Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl());
- NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl());
+ FDecl = dyn_cast<FunctionDecl>(NDecl);
+ Ovl = dyn_cast<OverloadedFunctionDecl>(NDecl);
}
if (Ovl || FunctionTemplate ||
@@ -2689,16 +2692,15 @@
ADL = false;
if (Ovl || FunctionTemplate || ADL) {
- FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0,
- UnqualifiedName, LParenLoc, Args,
- NumArgs, CommaLocs, RParenLoc, ADL);
+ FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, LParenLoc,
+ Args, NumArgs, CommaLocs, RParenLoc, ADL);
if (!FDecl)
return ExprError();
// Update Fn to refer to the actual function selected.
Expr *NewFn = 0;
if (QualifiedDeclRefExpr *QDRExpr
- = dyn_cast_or_null<QualifiedDeclRefExpr>(DRExpr))
+ = dyn_cast<QualifiedDeclRefExpr>(FnExpr))
NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(),
QDRExpr->getLocation(),
false, false,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jun 30 17:34:41 2009
@@ -933,6 +933,42 @@
return Result.getAsOpaquePtr();
}
+Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc) {
+ // FIXME: Can we do any checking at this point? I guess we could check the
+ // template arguments that we have against the template name, if the template
+ // name refers to a single template. That's not a terribly common case,
+ // though.
+ return Owned(TemplateIdRefExpr::Create(Context,
+ /*FIXME: New type?*/Context.OverloadTy,
+ /*FIXME: Necessary?*/0,
+ /*FIXME: Necessary?*/SourceRange(),
+ Template, TemplateNameLoc, LAngleLoc,
+ TemplateArgs,
+ NumTemplateArgs, RAngleLoc));
+}
+
+Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc) {
+ TemplateName Template = TemplateD.getAsVal<TemplateName>();
+
+ // Translate the parser's template argument list in our AST format.
+ llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+
+ return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc,
+ TemplateArgs.data(), TemplateArgs.size(),
+ RAngleLoc);
+}
+
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=74563&r1=74562&r2=74563&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Tue Jun 30 17:34:41 2009
@@ -107,6 +107,34 @@
}
Sema::OwningExprResult
+TemplateExprInstantiator::VisitTemplateIdRefExpr(TemplateIdRefExpr *E) {
+ TemplateName Template
+ = SemaRef.InstantiateTemplateName(E->getTemplateName(), E->getTemplateNameLoc(),
+ TemplateArgs);
+ // FIXME: Can InstantiateTemplateName report an error?
+
+ llvm::SmallVector<TemplateArgument, 4> InstantiatedArgs;
+ for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+ TemplateArgument InstArg = SemaRef.Instantiate(E->getTemplateArgs()[I],
+ TemplateArgs);
+ if (InstArg.isNull())
+ return SemaRef.ExprError();
+
+ InstantiatedArgs.push_back(InstArg);
+ }
+
+ // FIXME: It's possible that we'll find out now that the template name
+ // actually refers to a type, in which case this is a functional cast.
+ // Implement this!
+
+ return SemaRef.BuildTemplateIdExpr(Template, E->getTemplateNameLoc(),
+ E->getLAngleLoc(),
+ InstantiatedArgs.data(),
+ InstantiatedArgs.size(),
+ E->getRAngleLoc());
+}
+
+Sema::OwningExprResult
TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp?rev=74563&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp Tue Jun 30 17:34:41 2009
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T> struct A { };
+
+template<typename T> T make(A<T>);
+
+void test_make() {
+ int& ir0 = make<int&>(A<int&>());
+ A<int> a0 = make< A<int> >(A<A<int> >());
+}
+
More information about the cfe-commits
mailing list