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
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 4823c0b..63b153a 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1052,26 +1052,48 @@
/// 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 @@
/// 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<const ExplicitTemplateArgumentList*>(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 @@
/// \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;
+
+ DependentScopeDeclRefExpr(QualType T,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ bool HasExplicitTemplateArgs)
+ : Expr(DependentScopeDeclRefExprClass, T, true, true),
+ Name(Name), Loc(NameLoc),
+ QualifierRange(QualifierRange), Qualifier(Qualifier),
+ HasExplicitTemplateArgs(HasExplicitTemplateArgs)
+ {}
public:
- DependentScopeDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
- SourceRange R, NestedNameSpecifier *NNS,
- bool IsAddressOfOperand)
- : Expr(DependentScopeDeclRefExprClass, T, true, true),
- Name(N), Loc(L), QualifierRange(R), NNS(NNS),
- IsAddressOfOperand(IsAddressOfOperand) { }
+ 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,13 +1235,48 @@
/// \brief Retrieve the nested-name-specifier that qualifies this
/// declaration.
- NestedNameSpecifier *getQualifier() const { return NNS; }
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
- /// \brief Retrieve whether this is an address of (&) operand.
+ /// Determines whether this lookup had explicit template arguments.
+ bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
- bool isAddressOfOperand() const { return IsAddressOfOperand; }
+ // 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<const ExplicitTemplateArgumentList*>(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 {
- return SourceRange(QualifierRange.getBegin(), getLocation());
+ SourceRange Range(QualifierRange.getBegin(), getLocation());
+ if (hasExplicitTemplateArgs())
+ Range.setEnd(getRAngleLoc());
+ return Range;
}
static bool classof(const Stmt *T) {
@@ -1184,105 +1288,6 @@
virtual StmtIterator child_end();
};
-/// \brief An expression that refers to a C++ template-id, such as
-/// @c isa<FunctionDecl>.
-class TemplateIdRefExpr : public Expr {
- /// \brief If this template-id was qualified-id, e.g., @c std::sort<int>,
- /// this nested name specifier contains the @c std::.
- NestedNameSpecifier *Qualifier;
-
- /// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>,
- /// this covers the source code range of the @c std::.
- SourceRange QualifierRange;
-
- /// \brief The actual template to which this template-id refers.
- TemplateName Template;
-
- /// \brief The source location of the template name.
- SourceLocation TemplateNameLoc;
-
- /// \brief The source location of the left angle bracket ('<');
- SourceLocation LAngleLoc;
-
- /// \brief The source location of the right angle bracket ('>');
- SourceLocation RAngleLoc;
-
- /// \brief The number of template arguments in TemplateArgs.
- unsigned NumTemplateArgs;
-
- TemplateIdRefExpr(QualType T,
- NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
- TemplateName Template, SourceLocation TemplateNameLoc,
- 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<int>, or NULL
- /// if this template-id was an unqualified-id.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
-
- /// \brief Retrieve the source range describing the nested name specifier
- /// used to qualified the name of this template-id, if the name was qualified.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
- /// \brief Retrieve the name of the template referenced, e.g., "sort" in
- /// @c std::sort<int>;
- TemplateName getTemplateName() const { return Template; }
-
- /// \brief Retrieve the location of the name of the template referenced, e.g.,
- /// the location of "sort" in @c std::sort<int>.
- SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; }
-
- /// \brief Retrieve the location of the left angle bracket following the
- /// template name ('<').
- SourceLocation getLAngleLoc() const { return LAngleLoc; }
-
- /// \brief Retrieve the template arguments provided as part of this
- /// template-id.
- const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc *>(this + 1);
- }
-
- /// \brief Retrieve the number of template arguments provided as part of this
- /// template-id.
- unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
-
- /// \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]);
- }
-
- /// \brief Retrieve the location of the right angle bracket following the
- /// template arguments ('>').
- SourceLocation getRAngleLoc() const { return RAngleLoc; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc,
- RAngleLoc);
- }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == TemplateIdRefExprClass;
- }
- static bool classof(const TemplateIdRefExpr *) { return true; }
-};
-
class CXXExprWithTemporaries : public Expr {
Stmt *SubExpr;
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 31fbae1..dd8a685 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -128,7 +128,6 @@
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 4032285..c3b5045 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1214,6 +1214,10 @@
"%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 34790d2..9f08271 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1178,18 +1178,6 @@
return LV_Valid;
}
- case TemplateIdRefExprClass: {
- const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(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 @@
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 3f49dc6..8591a4d 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -122,6 +122,40 @@
}
// 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<ExplicitTemplateArgumentList*>(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 @@
}
// 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<ExplicitTemplateArgumentList*>(DRE+1)
+ ->initializeFrom(*Args);
+
+ return DRE;
+}
+
StmtIterator DependentScopeDeclRefExpr::child_begin() {
return child_iterator();
}
@@ -145,61 +203,6 @@
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<TemplateArgumentLoc *> (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 34ca798..a7cfed9 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -487,20 +487,22 @@
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 f238451..2699cdf 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -517,7 +517,11 @@
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 @@
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 b305906..c7b574f 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -379,14 +379,14 @@
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 @@
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 @@
CalledDone = true;
#endif
- if (ErasedAny)
+ if (Changed)
Results.resolveKindAfterFilter();
}
};
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3b3b41b..beaccda 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1389,6 +1389,16 @@
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 @@
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 @@
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 @@
//===--------------------------------------------------------------------===//
// 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 @@
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 ActOnTemplateIdExpr(const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc);
+ OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index a555a64..b494724 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1967,8 +1967,10 @@
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 3fa7d9c..2405d52 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -177,9 +177,10 @@
// Special case where the argument is a template id.
if (Attr.getParameterName()) {
- sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(),
- Attr.getParameterName(),
- false, 0, false).takeAs<Expr>();
+ CXXScopeSpec SS;
+ UnqualifiedId id;
+ id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+ sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
} else {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9d7a421..50fd5ec 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -617,202 +617,140 @@
return Owned(Result);
}
-Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
- const CXXScopeSpec &SS,
- UnqualifiedId &Name,
- bool HasTrailingLParen,
- bool IsAddressOfOperand) {
- assert(!(IsAddressOfOperand && HasTrailingLParen) &&
- "cannot be direct & operand and have a trailing lparen");
+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);
- if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
- 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);
+ R.resolveKind();
}
-/// 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())
+Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Id,
+ bool HasTrailingLParen,
+ bool isAddressOfOperand) {
+ assert(!(isAddressOfOperand && HasTrailingLParen) &&
+ "cannot be direct & operand and have a trailing lparen");
+
+ if (SS.isInvalid())
return ExprError();
- // 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<NestedNameSpecifier *>(SS->getScopeRep()),
- isAddressOfOperand));
+ 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,
+ Id.TemplateId->getTemplateArgs(),
+ Id.TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr, ExplicitTemplateArgs);
+ TemplateArgsPtr.release();
+
+ TemplateName TName =
+ TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
+ 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);
-
- if (Lookup.isAmbiguous())
- return ExprError();
-
- // 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.
+ // 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 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();
+ return ActOnDependentIdExpression(SS, Name, NameLoc,
+ CheckForImplicitMember,
+ TemplateArgs);
+ }
- bool LookForIvars;
- if (Lookup.empty())
- LookForIvars = true;
- else if (IsClassMethod)
- LookForIvars = false;
- else
- LookForIvars = (Lookup.isSingleResult() &&
- Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+ // Perform the required lookup.
+ LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ if (TemplateArgs) {
+ TemplateName TName =
+ TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
- 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());
+ // Just re-use the lookup done by isTemplateName.
+ DecomposeTemplateName(R, TName);
+ } else {
+ LookupParsedName(R, S, &SS, true);
- // 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();
+ // 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();
- // Check if referencing a field with __attribute__((deprecated)).
- if (DiagnoseUseOfDecl(IV, Loc))
- return ExprError();
-
- // 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<Expr>(), 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 (getCurMethodDecl()->isInstanceMethod())
- T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
- getCurMethodDecl()->getClassInterface()));
- else
- T = Context.getObjCClassType();
- return Owned(new (Context) ObjCSuperExpr(Loc, T));
+ Expr *Ex = E.takeAs<Expr>();
+ 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<VarDecl>()) {
+ // This is guaranteed from this point on.
+ assert(!R.empty() || ADL);
+
+ if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
// 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 @@
CheckS = CheckS->getParent();
}
}
- } else if (FunctionDecl *Func = Lookup.getAsSingle<FunctionDecl>()) {
+ } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
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<FunctionProtoType>())
NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
- return BuildDeclRefExpr(Func, NoProtoType, Loc, SS);
+ return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS);
}
}
@@ -853,19 +791,141 @@
// 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 && !Lookup.empty() &&
- isa<CXXRecordDecl>((*Lookup.begin())->getDeclContext())) {
- return BuildImplicitMemberReferenceExpr(SS, Lookup);
+ if (!isAbstractMemberPointer && !R.empty() &&
+ isa<CXXRecordDecl>((*R.begin())->getDeclContext())) {
+ return BuildImplicitMemberReferenceExpr(SS, R, TemplateArgs);
}
}
- assert(Lookup.getResultKind() != LookupResult::FoundUnresolvedValue &&
- "found UnresolvedUsingValueDecl in non-class scope");
+ if (TemplateArgs)
+ return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs);
- return BuildDeclarationNameExpr(SS, Lookup, ADL);
+ 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();
+
+ // 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<Expr>(), 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 (getCurMethodDecl()->isInstanceMethod())
+ T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
+ getCurMethodDecl()->getClassInterface()));
+ else
+ T = Context.getObjCClassType();
+ return Owned(new (Context) ObjCSuperExpr(Loc, T));
+ }
+
+ // 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 @@
/// \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);
+ 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 new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
+ 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<FieldDecl>(D))
if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
return BuildAnonymousStructUnionMemberReference(Loc, FD);
@@ -938,13 +1004,14 @@
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(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<CXXMethodDecl>(D)) {
@@ -973,10 +1040,13 @@
// 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 @@
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 @@
}
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 @@
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 @@
/// \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<FunctionTemplateDecl>(D) &&
@@ -1134,7 +1208,7 @@
// 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 @@
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 @@
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr))
FnExpr = IcExpr->getSubExpr();
else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) {
- // Parentheses around a function disable ADL
- // (C++0x [basic.lookup.argdep]p1).
- ArgumentDependentLookup = false;
FnExpr = PExpr->getSubExpr();
} else if (isa<UnaryOperator>(FnExpr) &&
cast<UnaryOperator>(FnExpr)->getOpcode()
@@ -2677,49 +2744,12 @@
Overloaded = UnresLookup->isOverloaded();
if ((Qualifier = UnresLookup->getQualifier()))
QualifierRange = UnresLookup->getQualifierRange();
- break;
- } else if (TemplateIdRefExpr *TemplateIdRef
- = dyn_cast<TemplateIdRefExpr>(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 4aa928a..4800a1d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2306,7 +2306,7 @@
/// \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 08e9dc3..8f09827 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1544,11 +1544,7 @@
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg))
Functions.append(ULE->decls_begin(), ULE->decls_end());
- else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(Arg)) {
- TemplateName TName = TIRE->getTemplateName();
- OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl();
- Functions.append(Ovl->function_begin(), Ovl->function_end());
- } else
+ else
continue;
for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 7366ec9..49050be 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -4345,29 +4345,19 @@
// Try to dig out the overloaded function.
OverloadedFunctionDecl *Ovl = 0;
FunctionTemplateDecl *FunctionTemplate = 0;
- if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
- assert(!isa<OverloadedFunctionDecl>(DR->getDecl()));
- FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
- HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList();
- if (HasExplicitTemplateArgs)
- DR->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- } else if (UnresolvedLookupExpr *UL
+ if (UnresolvedLookupExpr *UL
= dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
Fns.append(UL->decls_begin(), UL->decls_end());
+ if (UL->hasExplicitTemplateArgs()) {
+ HasExplicitTemplateArgs = true;
+ UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+ }
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
if (HasExplicitTemplateArgs)
ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) {
- TemplateName Name = TIRE->getTemplateName();
- Ovl = Name.getAsOverloadedFunctionDecl();
- FunctionTemplate =
- dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
-
- HasExplicitTemplateArgs = true;
- TIRE->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
if (Ovl) Fns.append(Ovl->function_begin(), Ovl->function_end());
@@ -4693,7 +4683,8 @@
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 @@
}
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 @@
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 @@
// 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 @@
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 @@
return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
Context.getPointerType(SubExpr->getType()),
UnOp->getOperatorLoc());
- }
-
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- assert((isa<FunctionTemplateDecl>(DRE->getDecl()) ||
- isa<FunctionDecl>(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<UnresolvedLookupExpr>(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 @@
Fn->getType());
}
- if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(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 a37a731..0e680f6 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -99,6 +99,19 @@
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,109 +133,16 @@
default:
return TNK_Non_template;
}
-
- // Determine where to perform name lookup
- DeclContext *LookupCtx = 0;
- bool isDependent = false;
- if (ObjectTypePtr) {
- // 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()) &&
- "Caller should have completed object type");
- } else if (SS.isSet()) {
- // This nested-name-specifier occurs after another nested-name-specifier,
- // so long into the context associated with the prior nested-name-specifier.
- LookupCtx = computeDeclContext(SS, EnteringContext);
- isDependent = isDependentScopeSpecifier(SS);
-
- // The declaration context must be complete.
- if (LookupCtx && RequireCompleteDeclContext(SS))
- return TNK_Non_template;
- }
- LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName);
- bool ObjectTypeSearchedInScope = false;
- if (LookupCtx) {
- // Perform "qualified" name lookup into the declaration context we
- // computed, which is either the type of the base of a member access
- // expression or the declaration context associated with a prior
- // nested-name-specifier.
- LookupQualifiedName(Found, LookupCtx);
+ QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
- if (ObjectTypePtr && 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
- // identifier must be looked up to determine whether the < is the
- // beginning of a template argument list (14.2) or a less-than operator.
- // The identifier is first looked up in the class of the object
- // expression. If the identifier is not found, it is then looked up in
- // the context of the entire postfix-expression and shall name a class
- // or function template.
- //
- // FIXME: When we're instantiating a template, do we actually have to
- // look in the scope of the template? Seems fishy...
- LookupName(Found, S);
- ObjectTypeSearchedInScope = true;
- }
- } else if (isDependent) {
- // We cannot look into a dependent object type or
- return TNK_Non_template;
- } else {
- // Perform unqualified name lookup in the current scope.
- LookupName(Found, S);
- }
-
- // FIXME: Cope with ambiguous name-lookup results.
- assert(!Found.isAmbiguous() &&
- "Cannot handle template name-lookup ambiguities");
-
- NamedDecl *Template
- = isAcceptableTemplateName(Context, Found.getAsSingleDecl(Context));
- if (!Template)
+ LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName);
+ R.suppressDiagnostics();
+ LookupTemplateName(R, S, SS, ObjectType, EnteringContext);
+ if (R.empty())
return TNK_Non_template;
- if (ObjectTypePtr && !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);
- LookupName(FoundOuter, S);
- // FIXME: Handle ambiguities in this lookup better
- NamedDecl *OuterTemplate
- = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context));
-
- if (!OuterTemplate) {
- // - if the name is not found, the name found in the class of the
- // object expression is used, otherwise
- } else if (!isa<ClassTemplateDecl>(OuterTemplate)) {
- // - 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
- } else {
- // - 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(),
- 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);
-
- // Recover by taking the template that we found in the object
- // expression's type.
- }
- }
- }
+ NamedDecl *Template = R.getAsSingleDecl(Context);
if (SS.isSet() && !SS.isInvalid()) {
NestedNameSpecifier *Qualifier
@@ -251,7 +171,250 @@
assert((isa<FunctionTemplateDecl>(Template) ||
isa<OverloadedFunctionDecl>(Template)) &&
"Unhandled template kind in Sema::isTemplateName");
- return TNK_Function_template;
+ 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 (!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");
+ LookupCtx = computeDeclContext(ObjectType);
+ isDependent = ObjectType->isDependentType();
+ assert((isDependent || !ObjectType->isIncompleteType()) &&
+ "Caller should have completed object type");
+ } else if (SS.isSet()) {
+ // This nested-name-specifier occurs after another nested-name-specifier,
+ // so long into the context associated with the prior nested-name-specifier.
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(SS);
+
+ // The declaration context must be complete.
+ if (LookupCtx && RequireCompleteDeclContext(SS))
+ return;
+ }
+
+ bool ObjectTypeSearchedInScope = false;
+ if (LookupCtx) {
+ // Perform "qualified" name lookup into the declaration context we
+ // computed, which is either the type of the base of a member access
+ // expression or the declaration context associated with a prior
+ // nested-name-specifier.
+ LookupQualifiedName(Found, LookupCtx);
+
+ 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
+ // identifier must be looked up to determine whether the < is the
+ // beginning of a template argument list (14.2) or a less-than operator.
+ // The identifier is first looked up in the class of the object
+ // expression. If the identifier is not found, it is then looked up in
+ // the context of the entire postfix-expression and shall name a class
+ // or function template.
+ //
+ // FIXME: When we're instantiating a template, do we actually have to
+ // look in the scope of the template? Seems fishy...
+ if (S) LookupName(Found, S);
+ ObjectTypeSearchedInScope = true;
+ }
+ } else if (isDependent) {
+ // We cannot look into a dependent object type or
+ return;
+ } else {
+ // Perform unqualified name lookup in the current scope.
+ LookupName(Found, S);
+ }
+
+ // FIXME: Cope with ambiguous name-lookup results.
+ assert(!Found.isAmbiguous() &&
+ "Cannot handle template name-lookup ambiguities");
+
+ FilterAcceptableTemplateNames(Context, Found);
+ if (Found.empty())
+ return;
+
+ 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, Found.getLookupName(), Found.getNameLoc(),
+ LookupOrdinaryName);
+ LookupName(FoundOuter, S);
+ FilterAcceptableTemplateNames(Context, FoundOuter);
+ // FIXME: Handle ambiguities in this lookup better
+
+ if (FoundOuter.empty()) {
+ // - if the name is not found, the name found in the class of the
+ // object expression is used, otherwise
+ } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) {
+ // - 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
+ } else {
+ // - 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 (!Found.isSingleResult() ||
+ Found.getFoundDecl()->getCanonicalDecl()
+ != FoundOuter.getFoundDecl()->getCanonicalDecl()) {
+ Diag(Found.getNameLoc(),
+ diag::err_nested_name_member_ref_lookup_ambiguous)
+ << 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.
+ }
+ }
+ }
+}
+
+/// 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 T> class A : Base<T> {
+ // class Inner : A<T> {
+ // void foo() {
+ // Base<T>::foo(); // statically known to be an implicit member
+ // reference
+ // }
+ // };
+ // };
+
+ CanQual<RecordType> RT = BaseT->getAs<RecordType>();
+ assert(RT && "base is not a record type");
+ CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
+ if (BaseRecord->isDefinition() &&
+ HasDependentTypeAsBase(Context, BaseRecord, T))
+ return true;
+ }
+
+ return false;
+}
+
+/// 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<CXXMethodDecl>(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 T> class Base { ... };
+ // template <class T> class Derived : Base<T> {
+ // void foo() {
+ // Base<T>::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<CXXRecordDecl>(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<NestedNameSpecifier*>(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<NestedNameSpecifier*>(SS.getScopeRep()),
+ SS.getRange(),
+ Name, NameLoc,
+ TemplateArgs));
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -1311,56 +1474,72 @@
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<NestedNameSpecifier*>(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<TemplateName>();
+// 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);
- // Translate the parser's template argument list in our AST format.
- TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
- translateTemplateArguments(TemplateArgsIn, TemplateArgs);
- TemplateArgsIn.release();
+ LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false);
- return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
- SS.getRange(),
- Template, TemplateNameLoc, TemplateArgs);
+ if (R.isAmbiguous())
+ return ExprError();
+
+ if (R.empty()) {
+ Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
+ << Name << SS.getRange();
+ return ExprError();
+ }
+
+ if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
+ 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(SS, R, /* ADL */ false, TemplateArgs);
}
/// \brief Form a dependent template name.
@@ -1673,12 +1852,11 @@
// 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 502c151..dd92218 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -557,9 +557,6 @@
bool isAddressOfOperand);
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E,
bool isAddressOfOperand);
- Sema::OwningExprResult TransformUnresolvedLookupExpr(
- UnresolvedLookupExpr *E,
- bool isAddressOfOperand);
Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E,
bool isAddressOfOperand);
@@ -698,49 +695,6 @@
}
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<UsingDecl>(InstD));
-
- // Analogously.
- assert(!isa<UnresolvedUsingValueDecl>(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) {
// FIXME: Clean this up a bit
@@ -847,7 +801,7 @@
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 a7a9cfa..e1d0bba 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 @@
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.
///
@@ -815,6 +806,17 @@
///
/// 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.
+ /// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *ND, SourceLocation Loc,
@@ -1449,29 +1451,27 @@
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 @@
TransTemplate);
}
- OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl();
- assert(Ovl && "Not a template name or an overload set?");
- OverloadedFunctionDecl *TransOvl
- = cast_or_null<OverloadedFunctionDecl>(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 @@
return TemplateName(TransTemplate);
}
- OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl();
- assert(Ovl && "Not a template name or an overload set?");
- OverloadedFunctionDecl *TransOvl
- = cast_or_null<OverloadedFunctionDecl>(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<typename Derived>
@@ -4562,10 +4541,65 @@
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::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<NamedDecl*>(getDerived().TransformDecl(*I));
+ if (!InstD)
+ return SemaRef.ExprError();
+
+ // Expand using declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(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<typename Derived>
@@ -4609,35 +4643,16 @@
if (!Name)
return SemaRef.ExprError();
- if (!getDerived().AlwaysRebuild() &&
- NNS == E->getQualifier() &&
- Name == E->getDeclName())
- return SemaRef.Owned(E->Retain());
+ if (!E->hasExplicitTemplateArgs()) {
+ 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<typename Derived>
-Sema::OwningExprResult
-TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E,
- bool isAddressOfOperand) {
- TemporaryBase Rebase(*this, E->getTemplateNameLoc(), DeclarationName());
-
- TemplateName Template
- = getDerived().TransformTemplateName(E->getTemplateName());
- if (Template.isNull())
- return SemaRef.ExprError();
-
- 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 @@
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<typename Derived>
@@ -5325,14 +5335,6 @@
template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
- bool TemplateKW,
- OverloadedFunctionDecl *Ovl) {
- return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl);
-}
-
-template<typename Derived>
-TemplateName
-TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo &II,
QualType ObjectType) {
CXXScopeSpec SS;