From f7a1a744eba4b29ceb0f20af8f34515d892fdd64 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 24 Nov 2009 19:00:30 +0000 Subject: [PATCH] Rip out TemplateIdRefExpr and make UnresolvedLookupExpr and DependentScopeDeclRefExpr support storing templateids. Unite the common code paths between ActOnDeclarationNameExpr and ActOnTemplateIdExpr. This gets us to a point where we don't need to store function templates in the AST using TemplateNames, which is critical to ripping out OverloadedFunction. Also resolves a few FIXMEs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89785 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 239 +++++----- include/clang/AST/StmtNodes.def | 1 - include/clang/Basic/DiagnosticSemaKinds.td | 4 + lib/AST/Expr.cpp | 13 - lib/AST/ExprCXX.cpp | 113 ++--- lib/AST/StmtPrinter.cpp | 18 +- lib/AST/StmtProfile.cpp | 15 +- lib/Sema/Lookup.h | 13 +- lib/Sema/Sema.h | 68 +-- lib/Sema/SemaCodeComplete.cpp | 6 +- lib/Sema/SemaDeclAttr.cpp | 7 +- lib/Sema/SemaExpr.cpp | 506 +++++++++++---------- lib/Sema/SemaExprCXX.cpp | 2 +- lib/Sema/SemaLookup.cpp | 6 +- lib/Sema/SemaOverload.cpp | 91 ++-- lib/Sema/SemaTemplate.cpp | 366 +++++++++++---- lib/Sema/SemaTemplateInstantiate.cpp | 48 +- lib/Sema/TreeTransform.h | 196 ++++---- 18 files changed, 928 insertions(+), 784 deletions(-) diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 4823c0bca4..63b153a17e 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1052,26 +1052,48 @@ class UnresolvedLookupExpr : public Expr { /// trivially rederivable if we urgently need to kill this field. bool Overloaded; - UnresolvedLookupExpr(QualType T, + /// True if the name looked up had explicit template arguments. + /// This requires all the results to be function templates. + bool HasExplicitTemplateArgs; + + UnresolvedLookupExpr(QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, - bool RequiresADL, bool Overloaded) - : Expr(UnresolvedLookupExprClass, T, false, false), + bool RequiresADL, bool Overloaded, bool HasTemplateArgs) + : Expr(UnresolvedLookupExprClass, T, Dependent, Dependent), Name(Name), Qualifier(Qualifier), QualifierRange(QRange), - NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded) + NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded), + HasExplicitTemplateArgs(HasTemplateArgs) {} public: static UnresolvedLookupExpr *Create(ASTContext &C, + bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, DeclarationName Name, SourceLocation NameLoc, bool ADL, bool Overloaded) { - return new(C) UnresolvedLookupExpr(C.OverloadTy, Qualifier, QualifierRange, - Name, NameLoc, ADL, Overloaded); + return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + Dependent, Qualifier, QualifierRange, + Name, NameLoc, ADL, Overloaded, false); } + static UnresolvedLookupExpr *Create(ASTContext &C, + bool Dependent, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool ADL, + const TemplateArgumentListInfo &Args); + + /// Computes whether an unresolved lookup on the given declarations + /// and optional template arguments is type- and value-dependent. + static bool ComputeDependence(NamedDecl * const *Begin, + NamedDecl * const *End, + const TemplateArgumentListInfo *Args); + void addDecl(NamedDecl *Decl) { Results.addDecl(Decl); } @@ -1098,11 +1120,47 @@ public: /// Fetches the range of the nested-name qualifier. SourceRange getQualifierRange() const { return QualifierRange; } + + /// Determines whether this lookup had explicit template arguments. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + + // Note that, inconsistently with the explicit-template-argument AST + // nodes, users are *forbidden* from calling these methods on objects + // without explicit template arguments. + + /// Gets a reference to the explicit template argument list. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast(this + 1); + } + + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + getExplicitTemplateArgs().copyInto(List); + } + SourceLocation getLAngleLoc() const { + return getExplicitTemplateArgs().LAngleLoc; + } + + SourceLocation getRAngleLoc() const { + return getExplicitTemplateArgs().RAngleLoc; + } + + TemplateArgumentLoc const *getTemplateArgs() const { + return getExplicitTemplateArgs().getTemplateArgs(); + } + + unsigned getNumTemplateArgs() const { + return getExplicitTemplateArgs().NumTemplateArgs; + } virtual SourceRange getSourceRange() const { - if (Qualifier) return SourceRange(QualifierRange.getBegin(), NameLoc); - return SourceRange(NameLoc, NameLoc); + SourceRange Range(NameLoc); + if (Qualifier) Range.setBegin(QualifierRange.getBegin()); + if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); + return Range; } virtual StmtIterator child_begin(); @@ -1141,19 +1199,30 @@ class DependentScopeDeclRefExpr : public Expr { /// \brief The nested-name-specifier that qualifies this unresolved /// declaration name. - NestedNameSpecifier *NNS; + NestedNameSpecifier *Qualifier; - /// \brief Whether this expr is an address of (&) operand. - /// FIXME: Stash this bit into NNS! - bool IsAddressOfOperand; + /// \brief Whether the name includes explicit template arguments. + bool HasExplicitTemplateArgs; -public: - DependentScopeDeclRefExpr(DeclarationName N, QualType T, SourceLocation L, - SourceRange R, NestedNameSpecifier *NNS, - bool IsAddressOfOperand) + DependentScopeDeclRefExpr(QualType T, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool HasExplicitTemplateArgs) : Expr(DependentScopeDeclRefExprClass, T, true, true), - Name(N), Loc(L), QualifierRange(R), NNS(NNS), - IsAddressOfOperand(IsAddressOfOperand) { } + Name(Name), Loc(NameLoc), + QualifierRange(QualifierRange), Qualifier(Qualifier), + HasExplicitTemplateArgs(HasExplicitTemplateArgs) + {} + +public: + static DependentScopeDeclRefExpr *Create(ASTContext &C, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Retrieve the name that this expression refers to. DeclarationName getDeclName() const { return Name; } @@ -1166,121 +1235,57 @@ public: /// \brief Retrieve the nested-name-specifier that qualifies this /// declaration. - NestedNameSpecifier *getQualifier() const { return NNS; } - - /// \brief Retrieve whether this is an address of (&) operand. - - bool isAddressOfOperand() const { return IsAddressOfOperand; } - virtual SourceRange getSourceRange() const { - return SourceRange(QualifierRange.getBegin(), getLocation()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DependentScopeDeclRefExprClass; - } - static bool classof(const DependentScopeDeclRefExpr *) { return true; } - - virtual StmtIterator child_begin(); - virtual StmtIterator child_end(); -}; - -/// \brief An expression that refers to a C++ template-id, such as -/// @c isa. -class TemplateIdRefExpr : public Expr { - /// \brief If this template-id was qualified-id, e.g., @c std::sort, - /// this nested name specifier contains the @c std::. - NestedNameSpecifier *Qualifier; - - /// \brief If this template-id was a qualified-id, e.g., @c std::sort, - /// 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, - const TemplateArgumentListInfo &TemplateArgs); - - virtual void DoDestroy(ASTContext &Context); - -public: - static TemplateIdRefExpr * - Create(ASTContext &Context, QualType T, - NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - TemplateName Template, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs); - - /// \brief Retrieve the nested name specifier used to qualify the name of - /// this template-id, e.g., the "std::sort" in @c std::sort, 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; - TemplateName getTemplateName() const { return Template; } + /// Determines whether this lookup had explicit template arguments. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } - /// \brief Retrieve the location of the name of the template referenced, e.g., - /// the location of "sort" in @c std::sort. - SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; } + // Note that, inconsistently with the explicit-template-argument AST + // nodes, users are *forbidden* from calling these methods on objects + // without explicit template arguments. - /// \brief Retrieve the location of the left angle bracket following the - /// template name ('<'). - SourceLocation getLAngleLoc() const { return LAngleLoc; } + /// Gets a reference to the explicit template argument list. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast(this + 1); + } - /// \brief Retrieve the template arguments provided as part of this - /// template-id. - const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast(this + 1); + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + getExplicitTemplateArgs().copyInto(List); + } + + SourceLocation getLAngleLoc() const { + return getExplicitTemplateArgs().LAngleLoc; } - /// \brief Retrieve the number of template arguments provided as part of this - /// template-id. - unsigned getNumTemplateArgs() const { return NumTemplateArgs; } + SourceLocation getRAngleLoc() const { + return getExplicitTemplateArgs().RAngleLoc; + } - /// \brief Copies the template-argument information into the given - /// structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &Info) const { - Info.setLAngleLoc(LAngleLoc); - Info.setRAngleLoc(RAngleLoc); - for (unsigned i = 0; i < NumTemplateArgs; ++i) - Info.addArgument(getTemplateArgs()[i]); + TemplateArgumentLoc const *getTemplateArgs() const { + return getExplicitTemplateArgs().getTemplateArgs(); } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { return RAngleLoc; } + unsigned getNumTemplateArgs() const { + return getExplicitTemplateArgs().NumTemplateArgs; + } virtual SourceRange getSourceRange() const { - return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc, - RAngleLoc); + SourceRange Range(QualifierRange.getBegin(), getLocation()); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + return Range; } - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); - static bool classof(const Stmt *T) { - return T->getStmtClass() == TemplateIdRefExprClass; + return T->getStmtClass() == DependentScopeDeclRefExprClass; } - static bool classof(const TemplateIdRefExpr *) { return true; } + static bool classof(const DependentScopeDeclRefExpr *) { return true; } + + virtual StmtIterator child_begin(); + virtual StmtIterator child_end(); }; class CXXExprWithTemporaries : public Expr { diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 31fbae17e3..dd8a685a95 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -128,7 +128,6 @@ EXPR(CXXPseudoDestructorExpr, Expr) EXPR(UnresolvedLookupExpr , Expr) EXPR(UnaryTypeTraitExpr , Expr) EXPR(DependentScopeDeclRefExpr , Expr) -EXPR(TemplateIdRefExpr , Expr) EXPR(CXXConstructExpr , Expr) EXPR(CXXBindTemporaryExpr , Expr) EXPR(CXXExprWithTemporaries , Expr) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4032285f8d..c3b504592f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1214,6 +1214,10 @@ 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_template_kw_refers_to_class_template : Error< + "'%0%1' instantiated to a class template, not a function template">; +def note_referenced_class_template : Error< + "class template declared here">; // C++0x Variadic Templates def err_template_param_pack_default_arg : Error< diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 34790d27d2..9f08271694 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1178,18 +1178,6 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; } - case TemplateIdRefExprClass: { - const TemplateIdRefExpr *TID = cast(this); - TemplateName Template = TID->getTemplateName(); - NamedDecl *ND = Template.getAsTemplateDecl(); - if (!ND) - ND = Template.getAsOverloadedFunctionDecl(); - if (ND && DeclCanBeLvalue(ND, Ctx)) - return LV_Valid; - - break; - } - default: break; } @@ -1534,7 +1522,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXPseudoDestructorExprClass: case Expr::UnresolvedLookupExprClass: case Expr::DependentScopeDeclRefExprClass: - case Expr::TemplateIdRefExprClass: case Expr::CXXConstructExprClass: case Expr::CXXBindTemporaryExprClass: case Expr::CXXExprWithTemporariesClass: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 3f49dc6221..8591a4d8bd 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -122,6 +122,40 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() { } // UnresolvedLookupExpr +UnresolvedLookupExpr * +UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, DeclarationName Name, + SourceLocation NameLoc, bool ADL, + const TemplateArgumentListInfo &Args) +{ + void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + + ExplicitTemplateArgumentList::sizeFor(Args)); + UnresolvedLookupExpr *ULE + = new (Mem) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + Dependent, Qualifier, QualifierRange, + Name, NameLoc, ADL, + /*Overload*/ true, + /*ExplicitTemplateArgs*/ true); + + reinterpret_cast(ULE+1)->initializeFrom(Args); + + return ULE; +} + +bool UnresolvedLookupExpr::ComputeDependence(NamedDecl * const *Begin, + NamedDecl * const *End, + const TemplateArgumentListInfo *Args) { + for (NamedDecl * const *I = Begin; I != End; ++I) + if ((*I)->getDeclContext()->isDependentContext()) + return true; + + if (Args && TemplateSpecializationType::anyDependentTemplateArguments(*Args)) + return true; + + return false; +} + Stmt::child_iterator UnresolvedLookupExpr::child_begin() { return child_iterator(); } @@ -137,6 +171,30 @@ Stmt::child_iterator UnaryTypeTraitExpr::child_end() { } // DependentScopeDeclRefExpr +DependentScopeDeclRefExpr * +DependentScopeDeclRefExpr::Create(ASTContext &C, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *Args) { + std::size_t size = sizeof(DependentScopeDeclRefExpr); + if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args); + void *Mem = C.Allocate(size); + + DependentScopeDeclRefExpr *DRE + = new (Mem) DependentScopeDeclRefExpr(C.DependentTy, + Qualifier, QualifierRange, + Name, NameLoc, + Args != 0); + + if (Args) + reinterpret_cast(DRE+1) + ->initializeFrom(*Args); + + return DRE; +} + StmtIterator DependentScopeDeclRefExpr::child_begin() { return child_iterator(); } @@ -145,61 +203,6 @@ StmtIterator DependentScopeDeclRefExpr::child_end() { return child_iterator(); } -TemplateIdRefExpr::TemplateIdRefExpr(QualType T, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) - : Expr(TemplateIdRefExprClass, T, - (Template.isDependent() || - TemplateSpecializationType - ::anyDependentTemplateArguments(TemplateArgs)), - (Template.isDependent() || - TemplateSpecializationType - ::anyDependentTemplateArguments(TemplateArgs))), - Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template), - TemplateNameLoc(TemplateNameLoc), - LAngleLoc(TemplateArgs.getLAngleLoc()), - RAngleLoc(TemplateArgs.getRAngleLoc()), - NumTemplateArgs(TemplateArgs.size()) { - TemplateArgumentLoc *StoredTemplateArgs - = reinterpret_cast (this+1); - for (unsigned I = 0; I != NumTemplateArgs; ++I) - new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]); -} - -TemplateIdRefExpr * -TemplateIdRefExpr::Create(ASTContext &Context, QualType T, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) { - void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) + - sizeof(TemplateArgumentLoc) * TemplateArgs.size()); - return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template, - TemplateNameLoc, TemplateArgs); -} - -void TemplateIdRefExpr::DoDestroy(ASTContext &Context) { - const TemplateArgumentLoc *TemplateArgs = getTemplateArgs(); - for (unsigned I = 0; I != NumTemplateArgs; ++I) - if (Expr *E = TemplateArgs[I].getArgument().getAsExpr()) - E->Destroy(Context); - this->~TemplateIdRefExpr(); - Context.Deallocate(this); -} - -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(ASTContext& C) 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 34ca798579..a7cfed9788 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -487,20 +487,22 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *Node) { Node->getQualifier()->print(OS, Policy); OS << Node->getDeclName().getAsString(); + if (Node->hasExplicitTemplateArgs()) + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), + Node->getNumTemplateArgs(), + Policy); } void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { - OS << Node->getName().getAsString(); -} - -void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) { if (Node->getQualifier()) Node->getQualifier()->print(OS, Policy); - Node->getTemplateName().print(OS, Policy, true); - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), + OS << Node->getName().getAsString(); + if (Node->hasExplicitTemplateArgs()) + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), Node->getNumTemplateArgs(), - Policy); + Policy); } void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index f238451465..2699cdfc4f 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -517,7 +517,11 @@ void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) { void StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) { VisitExpr(S); + VisitNestedNameSpecifier(S->getQualifier()); VisitName(S->getName()); + ID.AddBoolean(S->hasExplicitTemplateArgs()); + if (S->hasExplicitTemplateArgs()) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) { @@ -531,14 +535,9 @@ StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) { VisitExpr(S); VisitName(S->getDeclName()); VisitNestedNameSpecifier(S->getQualifier()); - ID.AddBoolean(S->isAddressOfOperand()); -} - -void StmtProfiler::VisitTemplateIdRefExpr(TemplateIdRefExpr *S) { - VisitExpr(S); - VisitNestedNameSpecifier(S->getQualifier()); - VisitTemplateName(S->getTemplateName()); - VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); + ID.AddBoolean(S->hasExplicitTemplateArgs()); + if (S->hasExplicitTemplateArgs()) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *S) { diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index b30590661c..c7b574fd66 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -379,14 +379,14 @@ public: class Filter { LookupResult &Results; unsigned I; - bool ErasedAny; + bool Changed; #ifndef NDEBUG bool CalledDone; #endif friend class LookupResult; Filter(LookupResult &Results) - : Results(Results), I(0), ErasedAny(false) + : Results(Results), I(0), Changed(false) #ifndef NDEBUG , CalledDone(false) #endif @@ -413,7 +413,12 @@ public: void erase() { Results.Decls[--I] = Results.Decls.back(); Results.Decls.pop_back(); - ErasedAny = true; + Changed = true; + } + + void replace(NamedDecl *D) { + Results.Decls[I-1] = D; + Changed = true; } void done() { @@ -422,7 +427,7 @@ public: CalledDone = true; #endif - if (ErasedAny) + if (Changed) Results.resolveKindAfterFilter(); } }; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3b3b41ba21..beaccdac2f 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1389,6 +1389,16 @@ public: UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand); + + OwningExprResult LookupInObjCMethod(LookupResult &R, + Scope *S, + IdentifierInfo *II); + + OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + bool CheckForImplicitMember, + const TemplateArgumentListInfo *TemplateArgs); OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, @@ -1400,26 +1410,25 @@ public: FieldDecl *Field, Expr *BaseObjectExpr = 0, SourceLocation OpLoc = SourceLocation()); - OwningExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, - DeclarationName Name, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand = false); - OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, - LookupResult &R); - bool UseArgumentDependentLookup(const CXXScopeSpec *SS, + OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); + bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, - LookupResult &R, bool ADL); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, - SourceLocation Loc, - DeclarationName Name, - bool NeedsADL, - bool IsOverloaded, - NamedDecl * const *Decls, - unsigned NumDecls); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, + + OwningExprResult BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc); + OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs); + + OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool ADL); + OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, SourceLocation Loc, NamedDecl *D); @@ -2110,7 +2119,7 @@ public: FunctionDecl::StorageClass& SC); DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); - bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, + bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D, SourceLocation NameLoc, QualType &ThisType, QualType &MemberType); @@ -2207,6 +2216,9 @@ public: //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // + void LookupTemplateName(LookupResult &R, Scope *S, const CXXScopeSpec &SS, + QualType ObjectType, bool EnteringContext); + virtual TemplateNameKind isTemplateName(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, @@ -2286,18 +2298,14 @@ public: DeclSpec::TST TagSpec, SourceLocation TagLoc); - OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, + OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs); + OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, const TemplateArgumentListInfo &TemplateArgs); - - OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc); virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const CXXScopeSpec &SS, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index a555a64ddf..b4947242bd 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1967,8 +1967,10 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, if (!CDecl && FName->isStr("super")) { // "super" may be the name of a variable, in which case we are // probably calling an instance method. - OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName, - false, 0, false); + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(FName, FNameLoc); + OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), SelIdents, NumSelIdents); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3fa7d9cdde..2405d52890 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -177,9 +177,10 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, // Special case where the argument is a template id. if (Attr.getParameterName()) { - sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(), - Attr.getParameterName(), - false, 0, false).takeAs(); + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs(); } else { // check the attribute arguments. if (Attr.getNumArgs() != 1) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9d7a42172c..50fd5ec9b1 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -617,202 +617,140 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return Owned(Result); } +static void DecomposeTemplateName(LookupResult &R, TemplateName TName) { + if (TemplateDecl *TD = TName.getAsTemplateDecl()) + R.addDecl(TD); + else if (OverloadedFunctionDecl *OD + = TName.getAsOverloadedFunctionDecl()) + for (OverloadIterator I(OD), E; I != E; ++I) + R.addDecl(*I); + + R.resolveKind(); +} + Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, const CXXScopeSpec &SS, - UnqualifiedId &Name, + UnqualifiedId &Id, bool HasTrailingLParen, - bool IsAddressOfOperand) { - assert(!(IsAddressOfOperand && HasTrailingLParen) && + bool isAddressOfOperand) { + assert(!(isAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); - if (Name.getKind() == UnqualifiedId::IK_TemplateId) { + if (SS.isInvalid()) + return ExprError(); + + TemplateArgumentListInfo ExplicitTemplateArgs; + + // Decompose the UnqualifiedId into the following data. + DeclarationName Name; + SourceLocation NameLoc; + const TemplateArgumentListInfo *TemplateArgs; + if (Id.getKind() == UnqualifiedId::IK_TemplateId) { + ExplicitTemplateArgs.setLAngleLoc(Id.TemplateId->LAngleLoc); + ExplicitTemplateArgs.setRAngleLoc(Id.TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(*this, - Name.TemplateId->getTemplateArgs(), - Name.TemplateId->NumArgs); - return ActOnTemplateIdExpr(SS, - TemplateTy::make(Name.TemplateId->Template), - Name.TemplateId->TemplateNameLoc, - Name.TemplateId->LAngleLoc, - TemplateArgsPtr, - Name.TemplateId->RAngleLoc); - } - - // FIXME: We lose a bunch of source information by doing this. Later, - // we'll want to merge ActOnDeclarationNameExpr's logic into - // ActOnIdExpression. - return ActOnDeclarationNameExpr(S, - Name.StartLocation, - GetNameFromUnqualifiedId(Name), - HasTrailingLParen, - &SS, - IsAddressOfOperand); -} + Id.TemplateId->getTemplateArgs(), + Id.TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, ExplicitTemplateArgs); + TemplateArgsPtr.release(); -/// ActOnDeclarationNameExpr - The parser has read some kind of name -/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine -/// performs lookup on that name and returns an expression that refers -/// to that name. This routine isn't directly called from the parser, -/// because the parser doesn't know about DeclarationName. Rather, -/// this routine is called by ActOnIdExpression, which contains a -/// parsed UnqualifiedId. -/// -/// HasTrailingLParen indicates whether this identifier is used in a -/// function call context. LookupCtx is only used for a C++ -/// qualified-id (foo::bar) to indicate the class or namespace that -/// the identifier must be a member of. -/// -/// isAddressOfOperand means that this expression is the direct operand -/// of an address-of operator. This matters because this is the only -/// situation where a qualified name referencing a non-static member may -/// appear outside a member function of this class. -Sema::OwningExprResult -Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, - DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand) { - // Could be enum-constant, value decl, instance variable, etc. - if (SS && SS->isInvalid()) - return ExprError(); + TemplateName TName = + TemplateTy::make(Id.TemplateId->Template).getAsVal(); - // Determine whether this is a member of an unknown specialization. - if (SS && SS->isSet() && !computeDeclContext(*SS, false)) { - return Owned(new (Context) DependentScopeDeclRefExpr(Name, Context.DependentTy, - Loc, SS->getRange(), - static_cast(SS->getScopeRep()), - isAddressOfOperand)); + Name = Context.getNameForTemplate(TName); + NameLoc = Id.TemplateId->TemplateNameLoc; + TemplateArgs = &ExplicitTemplateArgs; + } else { + Name = GetNameFromUnqualifiedId(Id); + NameLoc = Id.StartLocation; + TemplateArgs = 0; } - LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName); - LookupParsedName(Lookup, S, SS, true); + IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (Lookup.isAmbiguous()) - return ExprError(); + // C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains: + // -- a nested-name-specifier that contains a class-name that + // names a dependent type. + // Determine whether this is a member of an unknown specialization; + // we need to handle these differently. + if (SS.isSet() && !computeDeclContext(SS, false)) { + bool CheckForImplicitMember = !isAddressOfOperand; - // If this reference is in an Objective-C method, then ivar lookup happens as - // well. - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (II && getCurMethodDecl()) { - // There are two cases to handle here. 1) scoped lookup could have failed, - // in which case we should look for an ivar. 2) scoped lookup could have - // found a decl, but that decl is outside the current instance method (i.e. - // a global variable). In these two cases, we do a lookup for an ivar with - // this name, if the lookup sucedes, we replace it our current decl. - - // FIXME: we should change lookup to do this. - - // If we're in a class method, we don't normally want to look for - // ivars. But if we don't find anything else, and there's an - // ivar, that's an error. - bool IsClassMethod = getCurMethodDecl()->isClassMethod(); - - bool LookForIvars; - if (Lookup.empty()) - LookForIvars = true; - else if (IsClassMethod) - LookForIvars = false; - else - LookForIvars = (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + return ActOnDependentIdExpression(SS, Name, NameLoc, + CheckForImplicitMember, + TemplateArgs); + } - if (LookForIvars) { - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - // Diagnose using an ivar in a class method. - if (IsClassMethod) - return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) - << IV->getDeclName()); - - // If we're referencing an invalid decl, just return this as a silent - // error node. The error diagnostic was already emitted on the decl. - if (IV->isInvalidDecl()) - return ExprError(); + // Perform the required lookup. + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + if (TemplateArgs) { + TemplateName TName = + TemplateTy::make(Id.TemplateId->Template).getAsVal(); - // Check if referencing a field with __attribute__((deprecated)). - if (DiagnoseUseOfDecl(IV, Loc)) - return ExprError(); + // Just re-use the lookup done by isTemplateName. + DecomposeTemplateName(R, TName); + } else { + LookupParsedName(R, S, &SS, true); - // Diagnose the use of an ivar outside of the declaring class. - if (IV->getAccessControl() == ObjCIvarDecl::Private && - ClassDeclared != IFace) - Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); - - // FIXME: This should use a new expr for a direct reference, don't - // turn this into Self->ivar, just return a BareIVarExpr or something. - IdentifierInfo &II = Context.Idents.get("self"); - UnqualifiedId SelfName; - SelfName.setIdentifier(&II, SourceLocation()); - CXXScopeSpec SelfScopeSpec; - OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, - SelfName, false, false); - MarkDeclarationReferenced(Loc, IV); - return Owned(new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfExpr.takeAs(), true, true)); - } - } else if (getCurMethodDecl()->isInstanceMethod()) { - // We should warn if a local variable hides an ivar. - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - if (IV->getAccessControl() != ObjCIvarDecl::Private || - IFace == ClassDeclared) - Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); - } - } - // Needed to implement property "super.method" notation. - if (Lookup.empty() && II->isStr("super")) { - QualType T; + // If this reference is in an Objective-C method, then we need to do + // some special Objective-C lookup, too. + if (!SS.isSet() && II && getCurMethodDecl()) { + OwningExprResult E(LookupInObjCMethod(R, S, II)); + if (E.isInvalid()) + return ExprError(); - if (getCurMethodDecl()->isInstanceMethod()) - T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( - getCurMethodDecl()->getClassInterface())); - else - T = Context.getObjCClassType(); - return Owned(new (Context) ObjCSuperExpr(Loc, T)); + Expr *Ex = E.takeAs(); + if (Ex) return Owned(Ex); } } + if (R.isAmbiguous()) + return ExprError(); + // Determine whether this name might be a candidate for // argument-dependent lookup. - bool ADL = UseArgumentDependentLookup(SS, Lookup, HasTrailingLParen); + bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); - if (Lookup.empty() && !ADL) { + if (R.empty() && !ADL) { // Otherwise, this could be an implicitly declared function reference (legal - // in C90, extension in C99). - if (HasTrailingLParen && II && - !getLangOptions().CPlusPlus) { // Not in C++. - NamedDecl *D = ImplicitlyDefineFunction(Loc, *II, S); - if (D) Lookup.addDecl(D); - } else { - // If this name wasn't predeclared and if this is not a function call, - // diagnose the problem. - if (SS && !SS->isEmpty()) - return ExprError(Diag(Loc, diag::err_no_member) - << Name << computeDeclContext(*SS, false) - << SS->getRange()); + // in C90, extension in C99, forbidden in C++). + if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) { + NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); + if (D) R.addDecl(D); + } + + // If this name wasn't predeclared and if this is not a function + // call, diagnose the problem. + if (R.empty()) { + if (!SS.isEmpty()) + return ExprError(Diag(NameLoc, diag::err_no_member) + << Name << computeDeclContext(SS, false) + << SS.getRange()); else if (Name.getNameKind() == DeclarationName::CXXOperatorName || Name.getNameKind() == DeclarationName::CXXConversionFunctionName) - return ExprError(Diag(Loc, diag::err_undeclared_use) - << Name.getAsString()); + return ExprError(Diag(NameLoc, diag::err_undeclared_use) + << Name); else - return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name); + return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name); } } - if (VarDecl *Var = Lookup.getAsSingle()) { + // This is guaranteed from this point on. + assert(!R.empty() || ADL); + + if (VarDecl *Var = R.getAsSingle()) { // Warn about constructs like: // if (void *X = foo()) { ... } else { X }. // In the else block, the pointer is always false. - // FIXME: In a template instantiation, we don't have scope - // information to check this property. if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { Scope *CheckS = S; while (CheckS && CheckS->getControlParent()) { if (CheckS->isWithinElse() && CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - ExprError(Diag(Loc, diag::warn_value_always_zero) + ExprError(Diag(NameLoc, diag::warn_value_always_zero) << Var->getDeclName() << (Var->getType()->isPointerType()? 2 : Var->getType()->isBooleanType()? 1 : 0)); @@ -823,21 +761,21 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, CheckS = CheckS->getParent(); } } - } else if (FunctionDecl *Func = Lookup.getAsSingle()) { + } else if (FunctionDecl *Func = R.getAsSingle()) { if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { // C99 DR 316 says that, if a function type comes from a // function definition (without a prototype), that type is only // used for checking compatibility. Therefore, when referencing // the function, we pretend that we don't have the full function // type. - if (DiagnoseUseOfDecl(Func, Loc)) + if (DiagnoseUseOfDecl(Func, NameLoc)) return ExprError(); QualType T = Func->getType(); QualType NoProtoType = T; if (const FunctionProtoType *Proto = T->getAs()) NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); - return BuildDeclRefExpr(Func, NoProtoType, Loc, SS); + return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS); } } @@ -853,19 +791,141 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // calculate them both in one pass if that proves important for // performance. if (!ADL) { - bool isAbstractMemberPointer = - (isAddressOfOperand && SS && !SS->isEmpty()); + bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty()); + + if (!isAbstractMemberPointer && !R.empty() && + isa((*R.begin())->getDeclContext())) { + return BuildImplicitMemberReferenceExpr(SS, R, TemplateArgs); + } + } + + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs); + + return BuildDeclarationNameExpr(SS, R, ADL); +} + +/// ActOnDeclarationNameExpr - Build a C++ qualified declaration name, +/// generally during template instantiation. There's a large number +/// of things which don't need to be done along this path. +Sema::OwningExprResult +Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS)) + return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange(); + return ExprError(); + } + + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); +} + +/// LookupInObjCMethod - The parser has read a name in, and Sema has +/// detected that we're currently inside an ObjC method. Perform some +/// additional lookup. +/// +/// Ideally, most of this would be done by lookup, but there's +/// actually quite a lot of extra work involved. +/// +/// Returns a null sentinel to indicate trivial success. +Sema::OwningExprResult +Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II) { + SourceLocation Loc = Lookup.getNameLoc(); + + // There are two cases to handle here. 1) scoped lookup could have failed, + // in which case we should look for an ivar. 2) scoped lookup could have + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with + // this name, if the lookup sucedes, we replace it our current decl. + + // If we're in a class method, we don't normally want to look for + // ivars. But if we don't find anything else, and there's an + // ivar, that's an error. + bool IsClassMethod = getCurMethodDecl()->isClassMethod(); + + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (IsClassMethod) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + + if (LookForIvars) { + ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + // Diagnose using an ivar in a class method. + if (IsClassMethod) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); + + // If we're referencing an invalid decl, just return this as a silent + // error node. The error diagnostic was already emitted on the decl. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check if referencing a field with __attribute__((deprecated)). + if (DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); - if (!isAbstractMemberPointer && !Lookup.empty() && - isa((*Lookup.begin())->getDeclContext())) { - return BuildImplicitMemberReferenceExpr(SS, Lookup); + // Diagnose the use of an ivar outside of the declaring class. + if (IV->getAccessControl() == ObjCIvarDecl::Private && + ClassDeclared != IFace) + Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); + + // FIXME: This should use a new expr for a direct reference, don't + // turn this into Self->ivar, just return a BareIVarExpr or something. + IdentifierInfo &II = Context.Idents.get("self"); + UnqualifiedId SelfName; + SelfName.setIdentifier(&II, SourceLocation()); + CXXScopeSpec SelfScopeSpec; + OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + SelfName, false, false); + MarkDeclarationReferenced(Loc, IV); + return Owned(new (Context) + ObjCIvarRefExpr(IV, IV->getType(), Loc, + SelfExpr.takeAs(), true, true)); + } + } else if (getCurMethodDecl()->isInstanceMethod()) { + // We should warn if a local variable hides an ivar. + ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + IFace == ClassDeclared) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); } } - assert(Lookup.getResultKind() != LookupResult::FoundUnresolvedValue && - "found UnresolvedUsingValueDecl in non-class scope"); + // Needed to implement property "super.method" notation. + if (Lookup.empty() && II->isStr("super")) { + QualType T; + + if (getCurMethodDecl()->isInstanceMethod()) + T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( + getCurMethodDecl()->getClassInterface())); + else + T = Context.getObjCClassType(); + return Owned(new (Context) ObjCSuperExpr(Loc, T)); + } - return BuildDeclarationNameExpr(SS, Lookup, ADL); + // Sentinel value saying that we didn't do anything special. + return Owned((Expr*) 0); } /// \brief Cast member's object to its own class if necessary. @@ -899,29 +959,35 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { /// \brief Build a MemberExpr AST node. static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, const CXXScopeSpec *SS, NamedDecl *Member, - SourceLocation Loc, QualType Ty) { - if (SS && SS->isSet()) - return MemberExpr::Create(C, Base, isArrow, - (NestedNameSpecifier *)SS->getScopeRep(), - SS->getRange(), Member, Loc, - // FIXME: Explicit template argument lists - 0, Ty); - - return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty); + SourceLocation Loc, QualType Ty, + const TemplateArgumentListInfo *TemplateArgs = 0) { + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + if (SS && SS->isSet()) { + Qualifier = (NestedNameSpecifier *) SS->getScopeRep(); + QualifierRange = SS->getRange(); + } + + return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, + Member, Loc, TemplateArgs, Ty); } /// Builds an implicit member access expression from the given /// unqualified lookup set, which is known to contain only class /// members. Sema::OwningExprResult -Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, - LookupResult &R) { +Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + assert(!R.empty() && !R.isAmbiguous()); + NamedDecl *D = R.getAsSingleDecl(Context); SourceLocation Loc = R.getNameLoc(); // We may have found a field within an anonymous union or struct // (C++ [class.union]). // FIXME: This needs to happen post-isImplicitMemberReference? + // FIXME: template-ids inside anonymous structs? if (FieldDecl *FD = dyn_cast(D)) if (cast(FD->getDeclContext())->isAnonymousStructOrUnion()) return BuildAnonymousStructUnionMemberReference(Loc, FD); @@ -938,13 +1004,14 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, if (CXXMethodDecl *MD = dyn_cast(D)) { // Don't diagnose the use of a virtual member function unless it's // explicitly qualified. - if (MD->isVirtual() && (!SS || !SS->isSet())) + if (MD->isVirtual() && !SS.isSet()) ShouldCheckUse = false; } if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc)) return ExprError(); - return Owned(BuildMemberExpr(Context, This, true, SS, D, Loc, MemberType)); + return Owned(BuildMemberExpr(Context, This, true, &SS, D, Loc, MemberType, + TemplateArgs)); } if (CXXMethodDecl *Method = dyn_cast(D)) { @@ -973,10 +1040,13 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, // We're not in an implicit member-reference context, but the lookup // results might not require an instance. Try to build a non-member // decl reference. + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, /* ADL */ false, *TemplateArgs); + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); } -bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS, +bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen) { // Only when used directly as the postfix-expression of a call. @@ -984,7 +1054,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS, return false; // Never if a scope specifier was provided. - if (SS && SS->isSet()) + if (SS.isSet()) return false; // Only in C++ or ObjC++. @@ -1056,11 +1126,13 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { } Sema::OwningExprResult -Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL) { assert(R.getResultKind() != LookupResult::FoundUnresolvedValue); + // If this isn't an overloaded result and we don't need ADL, just + // build an ordinary singleton decl ref. if (!NeedsADL && !R.isOverloadedResult()) return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl()); @@ -1071,10 +1143,12 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) return ExprError(); + bool Dependent + = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0); UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, - SS ? (NestedNameSpecifier *)SS->getScopeRep() : 0, - SS ? SS->getRange() : SourceRange(), + = UnresolvedLookupExpr::Create(Context, Dependent, + (NestedNameSpecifier*) SS.getScopeRep(), + SS.getRange(), R.getLookupName(), R.getNameLoc(), NeedsADL, R.isOverloadedResult()); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) @@ -1086,7 +1160,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, /// \brief Complete semantic analysis for a reference to the given declaration. Sema::OwningExprResult -Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, SourceLocation Loc, NamedDecl *D) { assert(D && "Cannot refer to a NULL declaration"); assert(!isa(D) && @@ -1134,7 +1208,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. - return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, SS); + return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS); } Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, @@ -2640,14 +2714,10 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, Name = DeclarationName(); Qualifier = 0; QualifierRange = SourceRange(); - ArgumentDependentLookup = getLangOptions().CPlusPlus; + ArgumentDependentLookup = false; Overloaded = false; HasExplicitTemplateArguments = false; - // Most of the explicit tracking of ArgumentDependentLookup in this - // function can disappear when we handle unresolved - // TemplateIdRefExprs properly. - // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. @@ -2655,9 +2725,6 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, if (ImplicitCastExpr *IcExpr = dyn_cast(FnExpr)) FnExpr = IcExpr->getSubExpr(); else if (ParenExpr *PExpr = dyn_cast(FnExpr)) { - // Parentheses around a function disable ADL - // (C++0x [basic.lookup.argdep]p1). - ArgumentDependentLookup = false; FnExpr = PExpr->getSubExpr(); } else if (isa(FnExpr) && cast(FnExpr)->getOpcode() @@ -2677,49 +2744,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, Overloaded = UnresLookup->isOverloaded(); if ((Qualifier = UnresLookup->getQualifier())) QualifierRange = UnresLookup->getQualifierRange(); - break; - } else if (TemplateIdRefExpr *TemplateIdRef - = dyn_cast(FnExpr)) { - if (NamedDecl *Function - = TemplateIdRef->getTemplateName().getAsTemplateDecl()) { - Name = Function->getDeclName(); - Fns.push_back(Function); - } - else { - OverloadedFunctionDecl *Overload - = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); - Name = Overload->getDeclName(); - Fns.append(Overload->function_begin(), Overload->function_end()); - } - Overloaded = true; - HasExplicitTemplateArguments = true; - TemplateIdRef->copyTemplateArgumentsInto(ExplicitTemplateArgs); - - // C++ [temp.arg.explicit]p6: - // [Note: For simple function names, argument dependent lookup (3.4.2) - // applies even when the function name is not visible within the - // scope of the call. This is because the call still has the syntactic - // form of a function call (3.4.1). But when a function template with - // explicit template arguments is used, the call does not have the - // correct syntactic form unless there is a function template with - // that name visible at the point of the call. If no such name is - // visible, the call is not syntactically well-formed and - // argument-dependent lookup does not apply. If some such name is - // visible, argument dependent lookup applies and additional function - // templates may be found in other namespaces. - // - // The summary of this paragraph is that, if we get to this point and the - // template-id was not a qualified name, then argument-dependent lookup - // is still possible. - if ((Qualifier = TemplateIdRef->getQualifier())) { - ArgumentDependentLookup = false; - QualifierRange = TemplateIdRef->getQualifierRange(); + if (UnresLookup->hasExplicitTemplateArgs()) { + HasExplicitTemplateArguments = true; + UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs); } 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). - ArgumentDependentLookup = false; break; } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 4aa928a436..4800a1df4a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2306,7 +2306,7 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { /// \returns true if this is an implicit member reference (in which case /// \p ThisType and \p MemberType will be set), or false if it is not an /// implicit member reference. -bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, +bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D, SourceLocation NameLoc, QualType &ThisType, QualType &MemberType) { // If this isn't a C++ method, then it isn't an implicit member reference. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 08e9dc3c63..8f0982740d 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1544,11 +1544,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, if (UnresolvedLookupExpr *ULE = dyn_cast(Arg)) Functions.append(ULE->decls_begin(), ULE->decls_end()); - else if (TemplateIdRefExpr *TIRE = dyn_cast(Arg)) { - TemplateName TName = TIRE->getTemplateName(); - OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl(); - Functions.append(Ovl->function_begin(), Ovl->function_end()); - } else + else continue; for (llvm::SmallVectorImpl::iterator I = Functions.begin(), diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7366ec978b..49050be8c5 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4345,29 +4345,19 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // Try to dig out the overloaded function. OverloadedFunctionDecl *Ovl = 0; FunctionTemplateDecl *FunctionTemplate = 0; - if (DeclRefExpr *DR = dyn_cast(OvlExpr)) { - assert(!isa(DR->getDecl())); - FunctionTemplate = dyn_cast(DR->getDecl()); - HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList(); - if (HasExplicitTemplateArgs) - DR->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } else if (UnresolvedLookupExpr *UL + if (UnresolvedLookupExpr *UL = dyn_cast(OvlExpr)) { Fns.append(UL->decls_begin(), UL->decls_end()); + if (UL->hasExplicitTemplateArgs()) { + HasExplicitTemplateArgs = true; + UL->copyTemplateArgumentsInto(ExplicitTemplateArgs); + } } else if (MemberExpr *ME = dyn_cast(OvlExpr)) { Ovl = dyn_cast(ME->getMemberDecl()); FunctionTemplate = dyn_cast(ME->getMemberDecl()); HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList(); if (HasExplicitTemplateArgs) ME->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } else if (TemplateIdRefExpr *TIRE = dyn_cast(OvlExpr)) { - TemplateName Name = TIRE->getTemplateName(); - Ovl = Name.getAsOverloadedFunctionDecl(); - FunctionTemplate = - dyn_cast_or_null(Name.getAsTemplateDecl()); - - HasExplicitTemplateArgs = true; - TIRE->copyTemplateArgumentsInto(ExplicitTemplateArgs); } if (Ovl) Fns.append(Ovl->function_begin(), Ovl->function_end()); @@ -4693,7 +4683,8 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, if (Input->isTypeDependent()) { UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + 0, SourceRange(), OpName, OpLoc, /*ADL*/ true, IsOverloaded(Functions)); for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); @@ -4849,7 +4840,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + 0, SourceRange(), OpName, OpLoc, /* ADL */ true, IsOverloaded(Functions)); for (FunctionSet::iterator Func = Functions.begin(), @@ -5014,9 +5006,10 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, LLoc, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + 0, SourceRange(), OpName, LLoc, /*ADL*/ true, /*Overloaded*/ false); - // Can't add an actual overloads yet + // Can't add any actual overloads yet Base.release(); Idx.release(); @@ -5611,10 +5604,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { // Do nothing: static member functions aren't any different // from non-member functions. } else { - // Fix the sub expression, which really has to be one of: - // * a DeclRefExpr holding a member function template - // * a TemplateIdRefExpr, also holding a member function template - // * an UnresolvedLookupExpr holding an overloaded member function + // Fix the sub expression, which really has to be an + // UnresolvedLookupExpr holding an overloaded member function + // or template. Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); if (SubExpr == UnOp->getSubExpr()) return UnOp->Retain(); @@ -5635,9 +5627,6 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, MemPtrType, UnOp->getOperatorLoc()); } - - // FIXME: TemplateIdRefExpr referring to a member function template - // specialization! } Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); if (SubExpr == UnOp->getSubExpr()) @@ -5646,28 +5635,24 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, Context.getPointerType(SubExpr->getType()), UnOp->getOperatorLoc()); - } - - if (DeclRefExpr *DRE = dyn_cast(E)) { - assert((isa(DRE->getDecl()) || - isa(DRE->getDecl())) && - "Expected function or function template"); - // FIXME: avoid copy. - TemplateArgumentListInfo TemplateArgs; - if (DRE->hasExplicitTemplateArgumentList()) - DRE->copyTemplateArgumentsInto(TemplateArgs); - - return DeclRefExpr::Create(Context, - DRE->getQualifier(), - DRE->getQualifierRange(), - Fn, - DRE->getLocation(), - Fn->getType(), - (DRE->hasExplicitTemplateArgumentList() - ? &TemplateArgs : 0)); } if (UnresolvedLookupExpr *ULE = dyn_cast(E)) { + if (ULE->hasExplicitTemplateArgs()) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgs; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TemplateArgs); + + return DeclRefExpr::Create(Context, + ULE->getQualifier(), + ULE->getQualifierRange(), + Fn, + ULE->getNameLoc(), + Fn->getType(), + &TemplateArgs); + } + return DeclRefExpr::Create(Context, ULE->getQualifier(), ULE->getQualifierRange(), @@ -5698,22 +5683,6 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { Fn->getType()); } - if (TemplateIdRefExpr *TID = dyn_cast(E)) { - // FIXME: Don't destroy TID here, since we need its template arguments - // to survive. - // TID->Destroy(Context); - - // FIXME: avoid copy. - TemplateArgumentListInfo TemplateArgs; - TID->copyTemplateArgumentsInto(TemplateArgs); - - return DeclRefExpr::Create(Context, - TID->getQualifier(), TID->getQualifierRange(), - Fn, TID->getTemplateNameLoc(), - Fn->getType(), - &TemplateArgs); - } - assert(false && "Invalid reference to overloaded function"); return E->Retain(); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index a37a73119d..0e680f6438 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -99,6 +99,19 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { return 0; } +static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { + LookupResult::Filter filter = R.makeFilter(); + while (filter.hasNext()) { + NamedDecl *Orig = filter.next(); + NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl()); + if (!Repl) + filter.erase(); + else if (Repl != Orig) + filter.replace(Repl); + } + filter.done(); +} + TemplateNameKind Sema::isTemplateName(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, @@ -120,15 +133,58 @@ TemplateNameKind Sema::isTemplateName(Scope *S, default: return TNK_Non_template; } - + + QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + + LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName); + R.suppressDiagnostics(); + LookupTemplateName(R, S, SS, ObjectType, EnteringContext); + if (R.empty()) + return TNK_Non_template; + + NamedDecl *Template = R.getAsSingleDecl(Context); + + if (SS.isSet() && !SS.isInvalid()) { + NestedNameSpecifier *Qualifier + = static_cast(SS.getScopeRep()); + if (OverloadedFunctionDecl *Ovl + = dyn_cast(Template)) + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, + Ovl)); + else + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, + cast(Template))); + } else if (OverloadedFunctionDecl *Ovl + = dyn_cast(Template)) { + TemplateResult = TemplateTy::make(TemplateName(Ovl)); + } else { + TemplateResult = TemplateTy::make( + TemplateName(cast(Template))); + } + + if (isa(Template) || + isa(Template)) + return TNK_Type_template; + + assert((isa(Template) || + isa(Template)) && + "Unhandled template kind in Sema::isTemplateName"); + return TNK_Function_template; +} + +void Sema::LookupTemplateName(LookupResult &Found, + Scope *S, const CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext) { // Determine where to perform name lookup DeclContext *LookupCtx = 0; bool isDependent = false; - if (ObjectTypePtr) { + if (!ObjectType.isNull()) { // This nested-name-specifier occurs in a member access expression, e.g., // x->B::f, and we are looking into the type of the object. assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); - QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); assert((isDependent || !ObjectType->isIncompleteType()) && @@ -141,10 +197,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // The declaration context must be complete. if (LookupCtx && RequireCompleteDeclContext(SS)) - return TNK_Non_template; + return; } - LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName); bool ObjectTypeSearchedInScope = false; if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we @@ -153,7 +208,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // nested-name-specifier. LookupQualifiedName(Found, LookupCtx); - if (ObjectTypePtr && Found.empty()) { + if (!ObjectType.isNull() && Found.empty()) { // C++ [basic.lookup.classref]p1: // In a class member access expression (5.2.5), if the . or -> token is // immediately followed by an identifier followed by a <, the @@ -166,12 +221,12 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // // FIXME: When we're instantiating a template, do we actually have to // look in the scope of the template? Seems fishy... - LookupName(Found, S); + if (S) LookupName(Found, S); ObjectTypeSearchedInScope = true; } } else if (isDependent) { // We cannot look into a dependent object type or - return TNK_Non_template; + return; } else { // Perform unqualified name lookup in the current scope. LookupName(Found, S); @@ -181,27 +236,26 @@ TemplateNameKind Sema::isTemplateName(Scope *S, assert(!Found.isAmbiguous() && "Cannot handle template name-lookup ambiguities"); - NamedDecl *Template - = isAcceptableTemplateName(Context, Found.getAsSingleDecl(Context)); - if (!Template) - return TNK_Non_template; + FilterAcceptableTemplateNames(Context, Found); + if (Found.empty()) + return; - if (ObjectTypePtr && !ObjectTypeSearchedInScope) { + if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) { // C++ [basic.lookup.classref]p1: // [...] If the lookup in the class of the object expression finds a // template, the name is also looked up in the context of the entire // postfix-expression and [...] // - LookupResult FoundOuter(*this, TName, SourceLocation(), LookupOrdinaryName); + LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), + LookupOrdinaryName); LookupName(FoundOuter, S); + FilterAcceptableTemplateNames(Context, FoundOuter); // FIXME: Handle ambiguities in this lookup better - NamedDecl *OuterTemplate - = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context)); - if (!OuterTemplate) { + if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the // object expression is used, otherwise - } else if (!isa(OuterTemplate)) { + } else if (!FoundOuter.getAsSingle()) { // - if the name is found in the context of the entire // postfix-expression and does not name a class template, the name // found in the class of the object expression is used, otherwise @@ -209,49 +263,158 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // - if the name found is a class template, it must refer to the same // entity as the one found in the class of the object expression, // otherwise the program is ill-formed. - if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) { - Diag(Name.getSourceRange().getBegin(), + if (!Found.isSingleResult() || + Found.getFoundDecl()->getCanonicalDecl() + != FoundOuter.getFoundDecl()->getCanonicalDecl()) { + Diag(Found.getNameLoc(), diag::err_nested_name_member_ref_lookup_ambiguous) - << TName - << Name.getSourceRange(); - Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type) - << QualType::getFromOpaquePtr(ObjectTypePtr); - Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope); + << Found.getLookupName(); + Diag(Found.getRepresentativeDecl()->getLocation(), + diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(FoundOuter.getFoundDecl()->getLocation(), + diag::note_ambig_member_ref_scope); // Recover by taking the template that we found in the object // expression's type. } } } +} - if (SS.isSet() && !SS.isInvalid()) { - NestedNameSpecifier *Qualifier - = static_cast(SS.getScopeRep()); - if (OverloadedFunctionDecl *Ovl - = dyn_cast(Template)) - TemplateResult - = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, - Ovl)); - else - TemplateResult - = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, - cast(Template))); - } else if (OverloadedFunctionDecl *Ovl - = dyn_cast(Template)) { - TemplateResult = TemplateTy::make(TemplateName(Ovl)); - } else { - TemplateResult = TemplateTy::make( - TemplateName(cast(Template))); +/// Constructs a full type for the given nested-name-specifier. +static QualType GetTypeForQualifier(ASTContext &Context, + NestedNameSpecifier *Qualifier) { + // Three possibilities: + + // 1. A namespace (global or not). + assert(!Qualifier->getAsNamespace() && "can't construct type for namespace"); + + // 2. A type (templated or not). + Type *Ty = Qualifier->getAsType(); + if (Ty) return QualType(Ty, 0); + + // 3. A dependent identifier. + assert(Qualifier->getAsIdentifier()); + return Context.getTypenameType(Qualifier->getPrefix(), + Qualifier->getAsIdentifier()); +} + +static bool HasDependentTypeAsBase(ASTContext &Context, + CXXRecordDecl *Record, + CanQualType T) { + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), + E = Record->bases_end(); I != E; ++I) { + CanQualType BaseT = Context.getCanonicalType((*I).getType()); + if (BaseT == T) + return true; + + // We have to recurse here to cover some really bizarre cases. + // Obviously, we can only have the dependent type as an indirect + // base class through a dependent base class, and usually it's + // impossible to know which instantiation a dependent base class + // will have. But! If we're actually *inside* the dependent base + // class, then we know its instantiation and can therefore be + // reasonably expected to look into it. + + // template class A : Base { + // class Inner : A { + // void foo() { + // Base::foo(); // statically known to be an implicit member + // reference + // } + // }; + // }; + + CanQual RT = BaseT->getAs(); + assert(RT && "base is not a record type"); + CXXRecordDecl *BaseRecord = cast(RT->getDecl()); + if (BaseRecord->isDefinition() && + HasDependentTypeAsBase(Context, BaseRecord, T)) + return true; } - if (isa(Template) || - isa(Template)) - return TNK_Type_template; + return false; +} - assert((isa(Template) || - isa(Template)) && - "Unhandled template kind in Sema::isTemplateName"); - return TNK_Function_template; +/// Checks whether the given dependent nested-name specifier +/// introduces an implicit member reference. This is only true if the +/// nested-name specifier names a type identical to one of the current +/// instance method's context's (possibly indirect) base classes. +static bool IsImplicitDependentMemberReference(Sema &SemaRef, + NestedNameSpecifier *Qualifier, + QualType &ThisType) { + // If the context isn't a C++ method, then it isn't an implicit + // member reference. + CXXMethodDecl *MD = dyn_cast(SemaRef.CurContext); + if (!MD || MD->isStatic()) + return false; + + ASTContext &Context = SemaRef.Context; + + // We want to check whether the method's context is known to inherit + // from the type named by the nested name specifier. The trivial + // case here is: + // template class Base { ... }; + // template class Derived : Base { + // void foo() { + // Base::foo(); + // } + // }; + + QualType QT = GetTypeForQualifier(Context, Qualifier); + CanQualType T = Context.getCanonicalType(QT); + + // And now, just walk the non-dependent type hierarchy, trying to + // find the given type as a literal base class. + CXXRecordDecl *Record = cast(MD->getParent()); + if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T) + return true; + + return HasDependentTypeAsBase(Context, Record, T); +} + +/// ActOnDependentIdExpression - Handle a dependent declaration name +/// that was just parsed. +Sema::OwningExprResult +Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + bool CheckForImplicitMember, + const TemplateArgumentListInfo *TemplateArgs) { + NestedNameSpecifier *Qualifier + = static_cast(SS.getScopeRep()); + + QualType ThisType; + if (CheckForImplicitMember && + IsImplicitDependentMemberReference(*this, Qualifier, ThisType)) { + Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); + + // Since the 'this' expression is synthesized, we don't need to + // perform the double-lookup check. + NamedDecl *FirstQualifierInScope = 0; + + return Owned(CXXDependentScopeMemberExpr::Create(Context, This, true, + /*Op*/ SourceLocation(), + Qualifier, SS.getRange(), + FirstQualifierInScope, + Name, NameLoc, + TemplateArgs)); + } + + return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs); +} + +Sema::OwningExprResult +Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs) { + return Owned(DependentScopeDeclRefExpr::Create(Context, + static_cast(SS.getScopeRep()), + SS.getRange(), + Name, NameLoc, + TemplateArgs)); } /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining @@ -1311,56 +1474,72 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, return ElabType.getAsOpaquePtr(); } -Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, +Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, const TemplateArgumentListInfo &TemplateArgs) { // 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. - - // Cope with an implicit member access in a C++ non-static member function. - NamedDecl *D = Template.getAsTemplateDecl(); - if (!D) - D = Template.getAsOverloadedFunctionDecl(); - - CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); - QualType ThisType, MemberType; - if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc, - ThisType, MemberType)) { - Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); - return Owned(MemberExpr::Create(Context, This, true, - Qualifier, QualifierRange, - D, TemplateNameLoc, &TemplateArgs, - Context.OverloadTy)); + + // These should be filtered out by our callers. + assert(!R.empty() && "empty lookup results when building templateid"); + assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); + + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + if (SS.isSet()) { + Qualifier = static_cast(SS.getScopeRep()); + QualifierRange = SS.getRange(); } - return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy, - Qualifier, QualifierRange, - Template, TemplateNameLoc, - TemplateArgs)); + bool Dependent + = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), + &TemplateArgs); + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, Dependent, + Qualifier, QualifierRange, + R.getLookupName(), R.getNameLoc(), + RequiresADL, TemplateArgs); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + ULE->addDecl(*I); + + return Owned(ULE); } -Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc) { - TemplateName Template = TemplateD.getAsVal(); +// We actually only call this from template instantiation. +Sema::OwningExprResult +Sema::BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &TemplateArgs) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS)) + return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameLoc, diag::err_template_kw_refers_to_non_template) + << Name << SS.getRange(); + return ExprError(); + } - // Translate the parser's template argument list in our AST format. - TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); - translateTemplateArguments(TemplateArgsIn, TemplateArgs); - TemplateArgsIn.release(); + if (ClassTemplateDecl *Temp = R.getAsSingle()) { + Diag(NameLoc, diag::err_template_kw_refers_to_class_template) + << (NestedNameSpecifier*) SS.getScopeRep() << Name << SS.getRange(); + Diag(Temp->getLocation(), diag::note_referenced_class_template); + return ExprError(); + } - return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), - SS.getRange(), - Template, TemplateNameLoc, TemplateArgs); + return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs); } /// \brief Form a dependent template name. @@ -1673,12 +1852,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // parsed as a template template argument. However, since we now // know that we need a non-type template argument, convert this // template name into an expression. - Expr *E = new (Context) DependentScopeDeclRefExpr(DTN->getIdentifier(), - Context.DependentTy, - Arg.getTemplateNameLoc(), + Expr *E = DependentScopeDeclRefExpr::Create(Context, + DTN->getQualifier(), Arg.getTemplateQualifierRange(), - DTN->getQualifier(), - /*isAddressOfOperand=*/false); + DTN->getIdentifier(), + Arg.getTemplateNameLoc()); TemplateArgument Result; if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 502c151f4e..dd92218c6b 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -557,9 +557,6 @@ namespace { bool isAddressOfOperand); Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E, bool isAddressOfOperand); - Sema::OwningExprResult TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *E, - bool isAddressOfOperand); Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E, bool isAddressOfOperand); @@ -697,49 +694,6 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E, return getSema().Owned(PE); } -Sema::OwningExprResult -TemplateInstantiator::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, - bool isAddressOfOperand) { - LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), - Sema::LookupOrdinaryName); - - for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), - E = Old->decls_end(); I != E; ++I) { - NamedDecl *InstD = SemaRef.FindInstantiatedDecl(*I, TemplateArgs); - if (!InstD) - return SemaRef.ExprError(); - - // The lookup values can never instantiate to a UsingDecl, because - // only UnresolvedUsingValueDecls do that, and those can never - // appear in UnresolvedLookupExprs (only UnresolvedMemberLookupExprs). - assert(!isa(InstD)); - - // Analogously. - assert(!isa(InstD->getUnderlyingDecl())); - - R.addDecl(InstD); - } - - R.resolveKind(); - - // This shouldn't be possible. - assert(!R.isAmbiguous()); - - CXXScopeSpec SS; - NestedNameSpecifier *Qualifier = 0; - if (Old->getQualifier()) { - Qualifier = TransformNestedNameSpecifier(Old->getQualifier(), - Old->getQualifierRange()); - if (!Qualifier) - return SemaRef.ExprError(); - - SS.setScopeRep(Qualifier); - SS.setRange(Old->getQualifierRange()); - } - - return SemaRef.BuildDeclarationNameExpr(&SS, R, Old->requiresADL()); -} - Sema::OwningExprResult TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, bool isAddressOfOperand) { @@ -847,7 +801,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, SS.setRange(E->getQualifierRange()); } - return SemaRef.BuildDeclarationNameExpr(&SS, E->getLocation(), InstD); + return SemaRef.BuildDeclarationNameExpr(SS, E->getLocation(), InstD); } Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index a7a9cfaca8..e1d0bba4a4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_SEMA_TREETRANSFORM_H #include "Sema.h" +#include "Lookup.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" @@ -581,16 +582,6 @@ public: bool TemplateKW, TemplateDecl *Template); - /// \brief Build a new template name given a nested name specifier, a flag - /// indicating whether the "template" keyword was provided, and a set of - /// overloaded function templates. - /// - /// By default, builds the new template name directly. Subclasses may override - /// this routine to provide different behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, - bool TemplateKW, - OverloadedFunctionDecl *Ovl); - /// \brief Build a new template name given a nested name specifier and the /// name that is referred to as a template. /// @@ -811,6 +802,17 @@ public: return getSema().ActOnCXXTryBlock(TryLoc, move(TryBlock), move(Handlers)); } + /// \brief Build a new expression that references a declaration. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + OwningExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL) { + return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL); + } + + /// \brief Build a new expression that references a declaration. /// /// By default, performs semantic analysis to build the new expression. @@ -1449,29 +1451,27 @@ public: SourceRange QualifierRange, DeclarationName Name, SourceLocation Location, - bool IsAddressOfOperand) { + const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; SS.setRange(QualifierRange); SS.setScopeRep(NNS); - return getSema().ActOnDeclarationNameExpr(/*Scope=*/0, - Location, - Name, - /*Trailing lparen=*/false, - &SS, - IsAddressOfOperand); + + if (TemplateArgs) + return getSema().BuildQualifiedTemplateIdExpr(SS, Name, Location, + *TemplateArgs); + + return getSema().BuildQualifiedDeclarationNameExpr(SS, Name, Location); } /// \brief Build a new template-id expression. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateLoc, + OwningExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, const TemplateArgumentListInfo &TemplateArgs) { - return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange, - Template, TemplateLoc, TemplateArgs); + return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs); } /// \brief Build a new object-construction expression. @@ -1857,20 +1857,8 @@ TreeTransform::TransformTemplateName(TemplateName Name, TransTemplate); } - OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl(); - assert(Ovl && "Not a template name or an overload set?"); - OverloadedFunctionDecl *TransOvl - = cast_or_null(getDerived().TransformDecl(Ovl)); - if (!TransOvl) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - NNS == QTN->getQualifier() && - TransOvl == Ovl) - return Name; - - return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(), - TransOvl); + // These should be getting filtered out before they make it into the AST. + assert(false && "overloaded template name survived to here"); } if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { @@ -1906,18 +1894,9 @@ TreeTransform::TransformTemplateName(TemplateName Name, return TemplateName(TransTemplate); } - OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl(); - assert(Ovl && "Not a template name or an overload set?"); - OverloadedFunctionDecl *TransOvl - = cast_or_null(getDerived().TransformDecl(Ovl)); - if (!TransOvl) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - TransOvl == Ovl) - return Name; - - return TemplateName(TransOvl); + // These should be getting filtered out before they reach the AST. + assert(false && "overloaded function decl survived to here"); + return TemplateName(); } template @@ -4562,10 +4541,65 @@ TreeTransform::TransformCXXPseudoDestructorExpr( template Sema::OwningExprResult TreeTransform::TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *E, + UnresolvedLookupExpr *Old, bool isAddressOfOperand) { - // There is no transformation we can apply to an unresolved lookup. - return SemaRef.Owned(E->Retain()); + TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName()); + + LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), + Sema::LookupOrdinaryName); + + // Transform all the decls. + for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), + E = Old->decls_end(); I != E; ++I) { + NamedDecl *InstD = static_cast(getDerived().TransformDecl(*I)); + if (!InstD) + return SemaRef.ExprError(); + + // Expand using declarations. + if (isa(InstD)) { + UsingDecl *UD = cast(InstD); + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) + R.addDecl(*I); + continue; + } + + R.addDecl(InstD); + } + + // Resolve a kind, but don't do any further analysis. If it's + // ambiguous, the callee needs to deal with it. + R.resolveKind(); + + // Rebuild the nested-name qualifier, if present. + CXXScopeSpec SS; + NestedNameSpecifier *Qualifier = 0; + if (Old->getQualifier()) { + Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), + Old->getQualifierRange()); + if (!Qualifier) + return SemaRef.ExprError(); + + SS.setScopeRep(Qualifier); + SS.setRange(Old->getQualifierRange()); + } + + // If we have no template arguments, it's a normal declaration name. + if (!Old->hasExplicitTemplateArgs()) + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + + // If we have template arguments, rebuild them, then rebuild the + // templateid expression. + TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); + for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I], Loc)) + return SemaRef.ExprError(); + TransArgs.addArgument(Loc); + } + + return getDerived().RebuildTemplateIdExpr(SS, R, Old->requiresADL(), + TransArgs); } template @@ -4609,35 +4643,16 @@ TreeTransform::TransformDependentScopeDeclRefExpr( if (!Name) return SemaRef.ExprError(); - if (!getDerived().AlwaysRebuild() && - NNS == E->getQualifier() && - Name == E->getDeclName()) - return SemaRef.Owned(E->Retain()); - - return getDerived().RebuildDependentScopeDeclRefExpr(NNS, - E->getQualifierRange(), - Name, - E->getLocation(), - isAddressOfOperand); -} - -template -Sema::OwningExprResult -TreeTransform::TransformTemplateIdRefExpr(TemplateIdRefExpr *E, - bool isAddressOfOperand) { - TemporaryBase Rebase(*this, E->getTemplateNameLoc(), DeclarationName()); - - TemplateName Template - = getDerived().TransformTemplateName(E->getTemplateName()); - if (Template.isNull()) - return SemaRef.ExprError(); + if (!E->hasExplicitTemplateArgs()) { + if (!getDerived().AlwaysRebuild() && + NNS == E->getQualifier() && + Name == E->getDeclName()) + return SemaRef.Owned(E->Retain()); - NestedNameSpecifier *Qualifier = 0; - if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!Qualifier) - return SemaRef.ExprError(); + return getDerived().RebuildDependentScopeDeclRefExpr(NNS, + E->getQualifierRange(), + Name, E->getLocation(), + /*TemplateArgs*/ 0); } TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); @@ -4648,15 +4663,10 @@ TreeTransform::TransformTemplateIdRefExpr(TemplateIdRefExpr *E, TransArgs.addArgument(Loc); } - // FIXME: Would like to avoid rebuilding if nothing changed, but we can't - // compare template arguments (yet). - - // FIXME: It's possible that we'll find out now that the template name - // actually refers to a type, in which case the caller is actually dealing - // with a functional cast. Give a reasonable error message! - return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(), - Template, E->getTemplateNameLoc(), - TransArgs); + return getDerived().RebuildDependentScopeDeclRefExpr(NNS, + E->getQualifierRange(), + Name, E->getLocation(), + &TransArgs); } template @@ -5322,14 +5332,6 @@ TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, Template); } -template -TemplateName -TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, - bool TemplateKW, - OverloadedFunctionDecl *Ovl) { - return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl); -} - template TemplateName TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, -- 2.40.0