aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ExprCXX.cpp60
-rw-r--r--lib/AST/StmtPrinter.cpp12
-rw-r--r--lib/Parse/ParseExpr.cpp2
-rw-r--r--lib/Parse/ParseExprCXX.cpp29
-rw-r--r--lib/Sema/Sema.h14
-rw-r--r--lib/Sema/SemaExpr.cpp26
-rw-r--r--lib/Sema/SemaTemplate.cpp36
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp28
8 files changed, 191 insertions, 16 deletions
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 18c0f77ab2..399c30255a 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -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 @@ StmtIterator UnresolvedDeclRefExpr::child_end() {
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");
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 825a873d06..fec17fb223 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -490,6 +490,18 @@ void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {
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());
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index ee2f209fff..cd7618f665 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -777,7 +777,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
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));
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index d89f1e172f..1220b2d27b 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -207,13 +207,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
/// 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 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
// operator-function-id
// conversion-function-id
// '~' class-name [TODO]
- // template-id [TODO]
+ // template-id
//
switch (Tok.getKind()) {
default:
@@ -294,6 +294,29 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
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.");
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 308a78c80c..65b5f25029 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2075,6 +2075,20 @@ public:
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,
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index d66b002578..2ee3c992b6 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2635,7 +2635,6 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
}
// 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 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
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 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
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 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
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,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index e2f6d33827..d72fcf8adc 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -933,6 +933,42 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
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
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 719a9eda47..58896d48fa 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -107,6 +107,34 @@ TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
}
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)) {