diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprCXX.cpp | 60 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 12 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 29 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 14 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 26 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 36 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 28 |
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)) { |