Eliminate QualifiedDeclRefExpr, which captured the notion of a
qualified reference to a declaration that is not a non-static data
member or non-static member function, e.g.,
namespace N { int i; }
int j = N::i;
Instead, extend DeclRefExpr to optionally store the qualifier. Most
clients won't see or care about the difference (since
QualifierDeclRefExpr inherited DeclRefExpr). However, this reduces the
number of top-level expression types that clients need to cope with,
brings the implementation of DeclRefExpr into line with MemberExpr,
and simplifies and unifies our handling of declaration references.
Extended DeclRefExpr to (optionally) store explicitly-specified
template arguments. This occurs when naming a declaration via a
template-id (which will be stored in a TemplateIdRefExpr) that,
following template argument deduction and (possibly) overload
resolution, is replaced with a DeclRefExpr that refers to a template
specialization but maintains the template arguments as written.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84962 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 589b0c6..b7ccede 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1420,8 +1420,7 @@
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass: {
+ case Stmt::DeclRefExprClass: {
// DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking
// at code that refers to a variable's name. We check if it has local
// storage within the function, and if so, return the expression.
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 3811513..b877b1c 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1171,8 +1171,7 @@
// At the XXX, our completions are TagDecl::TK_union,
// TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
// TK_struct, and TK_class.
- if (QualifiedDeclRefExpr *QDRE = dyn_cast<QualifiedDeclRefExpr>(DRE))
- Qualifier = QDRE->getQualifier();
+ Qualifier = DRE->getQualifier();
}
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ae45429..accdc7e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -446,9 +446,7 @@
isAddressOfOperand);
}
-/// BuildDeclRefExpr - Build either a DeclRefExpr or a
-/// QualifiedDeclRefExpr based on whether or not SS is a
-/// nested-name-specifier.
+/// BuildDeclRefExpr - Build a DeclRefExpr.
Sema::OwningExprResult
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
@@ -476,15 +474,11 @@
MarkDeclarationReferenced(Loc, D);
- Expr *E;
- if (SS && !SS->isEmpty()) {
- E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
- ValueDependent, SS->getRange(),
- static_cast<NestedNameSpecifier *>(SS->getScopeRep()));
- } else
- E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
-
- return Owned(E);
+ return Owned(DeclRefExpr::Create(Context,
+ SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
+ SS? SS->getRange() : SourceRange(),
+ D, Loc,
+ Ty, TypeDependent, ValueDependent));
}
/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
@@ -2738,16 +2732,12 @@
cast<UnaryOperator>(FnExpr)->getOpcode()
== UnaryOperator::AddrOf) {
FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr();
- } else if (QualifiedDeclRefExpr *QDRExpr
- = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) {
- // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1).
- ArgumentDependentLookup = false;
- Qualifier = QDRExpr->getQualifier();
- QualifierRange = QDRExpr->getQualifierRange();
- Function = dyn_cast<NamedDecl>(QDRExpr->getDecl());
- break;
} else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) {
Function = dyn_cast<NamedDecl>(DRExpr->getDecl());
+ if ((Qualifier = DRExpr->getQualifier())) {
+ ArgumentDependentLookup = false;
+ QualifierRange = DRExpr->getQualifierRange();
+ }
break;
} else if (UnresolvedFunctionNameExpr *DepName
= dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) {
@@ -2933,16 +2923,10 @@
return ExprError();
// Update Fn to refer to the actual function selected.
- Expr *NewFn = 0;
- if (Qualifier)
- NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(),
- Fn->getLocStart(),
- false, false,
- QualifierRange,
- Qualifier);
- else
- NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(),
- Fn->getLocStart());
+ // FIXME: Use FixOverloadedFunctionReference?
+ Expr *NewFn = DeclRefExpr::Create(Context, Qualifier, QualifierRange, FDecl,
+ Fn->getLocStart(), FDecl->getType(), false,
+ false);
Fn->Destroy(Context);
Fn = NewFn;
}
@@ -5083,7 +5067,6 @@
static NamedDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
return cast<DeclRefExpr>(E)->getDecl();
case Stmt::MemberExprClass:
// If this is an arrow operator, the address is an offset from
@@ -5199,7 +5182,7 @@
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
// scope qualifier for the class.
- if (isa<QualifiedDeclRefExpr>(op)) {
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (FD->getType()->isReferenceType()) {
@@ -5216,7 +5199,8 @@
} else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) {
// Okay: we can take the address of a function.
// As above.
- if (isa<QualifiedDeclRefExpr>(op) && MD->isInstance())
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
+ MD->isInstance())
return Context.getMemberPointerType(op->getType(),
Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (!isa<FunctionDecl>(dcl))
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index ebcf3ad..9e79b99 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5370,18 +5370,19 @@
if (Method->isStatic()) {
// Do nothing: static member functions aren't any different
// from non-member functions.
- } else if (QualifiedDeclRefExpr *DRE
- = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr())) {
- // We have taken the address of a pointer to member
- // function. Perform the computation here so that we get the
- // appropriate pointer to member type.
- DRE->setDecl(Fn);
- DRE->setType(Fn->getType());
- QualType ClassType
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- E->setType(Context.getMemberPointerType(Fn->getType(),
- ClassType.getTypePtr()));
- return E;
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) {
+ if (DRE->getQualifier()) {
+ // We have taken the address of a pointer to member
+ // function. Perform the computation here so that we get the
+ // appropriate pointer to member type.
+ DRE->setDecl(Fn);
+ DRE->setType(Fn->getType());
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+ E->setType(Context.getMemberPointerType(Fn->getType(),
+ ClassType.getTypePtr()));
+ return E;
+ }
}
// FIXME: TemplateIdRefExpr referring to a member function template
// specialization!
@@ -5401,18 +5402,20 @@
MemExpr->setMemberDecl(Fn);
E->setType(Fn->getType());
} else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
- // FIXME: We should capture the template arguments here.
- if (NestedNameSpecifier *Qualifier = TID->getQualifier())
- E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(),
- TID->getTemplateNameLoc(),
- /*FIXME?*/false, /*FIXME?*/false,
- TID->getQualifierRange(),
- Qualifier);
- else
- E = new (Context) DeclRefExpr(Fn, Fn->getType(),
- TID->getTemplateNameLoc());
+ E = DeclRefExpr::Create(Context,
+ TID->getQualifier(), TID->getQualifierRange(),
+ Fn, TID->getTemplateNameLoc(),
+ true,
+ TID->getLAngleLoc(),
+ TID->getTemplateArgs(),
+ TID->getNumTemplateArgs(),
+ TID->getRAngleLoc(),
+ Fn->getType(),
+ /*FIXME?*/false, /*FIXME?*/false);
- TID->Destroy(Context);
+ // FIXME: Don't destroy TID here, since we need its template arguments
+ // to survive.
+ // TID->Destroy(Context);
} else {
assert(false && "Invalid reference to overloaded function");
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 0f22320..2bb790d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1845,7 +1845,7 @@
// template-parameter shall be one of: [...]
//
// -- a pointer to member expressed as described in 5.3.1.
- QualifiedDeclRefExpr *DRE = 0;
+ DeclRefExpr *DRE = 0;
// Ignore (and complain about) any excess parentheses.
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
@@ -1860,8 +1860,11 @@
}
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg))
- if (UnOp->getOpcode() == UnaryOperator::AddrOf)
- DRE = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr());
+ if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
+ DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+ if (DRE && !DRE->getQualifier())
+ DRE = 0;
+ }
if (!DRE)
return Diag(Arg->getSourceRange().getBegin(),
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 53d1580..1790d27 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -618,10 +618,21 @@
// FIXME: Is this correct? Maybe FindInstantiatedDecl should do this?
InstD = InstD->getUnderlyingDecl();
- // FIXME: nested-name-specifier for QualifiedDeclRefExpr
+ CXXScopeSpec SS;
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+
+ SS.setScopeRep(Qualifier);
+ SS.setRange(E->getQualifierRange());
+ }
+
return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD,
/*FIXME:*/false,
- /*FIXME:*/0,
+ &SS,
/*FIXME:*/false);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index dec9499..94a0e11 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -781,10 +781,15 @@
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildDeclRefExpr(NamedDecl *ND, SourceLocation Loc) {
+ OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *ND, SourceLocation Loc) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(QualifierRange);
return getSema().BuildDeclarationNameExpr(Loc, ND,
/*FIXME:*/false,
- /*SS=*/0,
+ &SS,
/*FIXME:*/false);
}
@@ -1392,26 +1397,6 @@
T.getAsOpaquePtr(), RParenLoc);
}
- /// \brief Build a new qualified declaration reference expression.
- ///
- /// By default, performs semantic analysis to build the new expression.
- /// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildQualifiedDeclRefExpr(NestedNameSpecifier *NNS,
- SourceRange QualifierRange,
- NamedDecl *ND,
- SourceLocation Location,
- bool IsAddressOfOperand) {
- CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(NNS);
- return getSema().ActOnDeclarationNameExpr(/*Scope=*/0,
- Location,
- ND->getDeclName(),
- /*Trailing lparen=*/false,
- &SS,
- IsAddressOfOperand);
- }
-
/// \brief Build a new (previously unresolved) declaration reference
/// expression.
///
@@ -3276,15 +3261,40 @@
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+ }
+
NamedDecl *ND
= dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl()));
if (!ND)
return SemaRef.ExprError();
- if (!getDerived().AlwaysRebuild() && ND == E->getDecl())
+ if (!getDerived().AlwaysRebuild() &&
+ Qualifier == E->getQualifier() &&
+ ND == E->getDecl() &&
+ !E->hasExplicitTemplateArgumentList())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildDeclRefExpr(ND, E->getLocation());
+ // FIXME: We're losing the explicit template arguments in this transformation.
+
+ llvm::SmallVector<TemplateArgument, 4> TransArgs;
+ for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+ TemplateArgument TransArg
+ = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
+ if (TransArg.isNull())
+ return SemaRef.ExprError();
+
+ TransArgs.push_back(TransArg);
+ }
+
+ // FIXME: Pass the qualifier/qualifier range along.
+ return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(),
+ ND, E->getLocation());
}
template<typename Derived>
@@ -4301,32 +4311,6 @@
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) {
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
- if (!NNS)
- return SemaRef.ExprError();
-
- NamedDecl *ND
- = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl()));
- if (!ND)
- return SemaRef.ExprError();
-
- if (!getDerived().AlwaysRebuild() &&
- NNS == E->getQualifier() &&
- ND == E->getDecl())
- return SemaRef.Owned(E->Retain());
-
- return getDerived().RebuildQualifiedDeclRefExpr(NNS,
- E->getQualifierRange(),
- ND,
- E->getLocation(),
- /*FIXME:*/false);
-}
-
-template<typename Derived>
-Sema::OwningExprResult
TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
UnresolvedDeclRefExpr *E) {
NestedNameSpecifier *NNS