Improve template instantiation for member access expressions that
involve qualified names, e.g., x->Base::f. We now maintain enough
information in the AST to compare the results of the name lookup of
"Base" in the scope of the postfix-expression (determined at template
definition time) and in the type of the object expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80953 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 20259a7..7babcf7 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -15,6 +15,7 @@
#include "Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -243,7 +244,8 @@
/// alternate behavior.
NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
- QualType ObjectType = QualType());
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = 0);
/// \brief Transform the given template name.
///
@@ -499,7 +501,8 @@
NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
IdentifierInfo &II,
- QualType ObjectType);
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope);
/// \brief Build a new nested-name-specifier given the prefix and the
/// namespace named in the next step in the nested-name-specifier.
@@ -1454,7 +1457,8 @@
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Name,
- SourceLocation MemberLoc) {
+ SourceLocation MemberLoc,
+ NamedDecl *FirstQualifierInScope) {
OwningExprResult Base = move(BaseE);
tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
@@ -1467,7 +1471,8 @@
MemberLoc,
Name,
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
- &SS);
+ &SS,
+ FirstQualifierInScope);
return move(Base);
}
@@ -1591,7 +1596,8 @@
NestedNameSpecifier *
TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
- QualType ObjectType) {
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
if (!NNS)
return 0;
@@ -1599,13 +1605,15 @@
NestedNameSpecifier *Prefix = NNS->getPrefix();
if (Prefix) {
Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range,
- ObjectType);
+ ObjectType,
+ FirstQualifierInScope);
if (!Prefix)
return 0;
- // Clear out the object type; it only applies to the first element in
- // the nested-name-specifier.
+ // Clear out the object type and the first qualifier in scope; they only
+ // apply to the first element in the nested-name-specifier.
ObjectType = QualType();
+ FirstQualifierInScope = 0;
}
switch (NNS->getKind()) {
@@ -1618,7 +1626,8 @@
return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
*NNS->getAsIdentifier(),
- ObjectType);
+ ObjectType,
+ FirstQualifierInScope);
case NestedNameSpecifier::Namespace: {
NamespaceDecl *NS
@@ -4055,22 +4064,28 @@
if (Base.isInvalid())
return SemaRef.ExprError();
+ NamedDecl *FirstQualifierInScope
+ = cast_or_null<NamedDecl>(
+ getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
+
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
- QualType::getFromOpaquePtr(ObjectType));
+ QualType::getFromOpaquePtr(ObjectType),
+ FirstQualifierInScope);
if (!Qualifier)
return SemaRef.ExprError();
}
// FIXME: Transform the declaration name
DeclarationName Name = E->getMember();
-
+
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() &&
Qualifier == E->getQualifier() &&
- Name == E->getMember())
+ Name == E->getMember() &&
+ FirstQualifierInScope == E->getFirstQualifierFoundInScope())
return SemaRef.Owned(E->Retain());
return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base),
@@ -4079,7 +4094,8 @@
Qualifier,
E->getQualifierRange(),
Name,
- E->getMemberLoc());
+ E->getMemberLoc(),
+ FirstQualifierInScope);
}
template<typename Derived>
@@ -4435,15 +4451,17 @@
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
IdentifierInfo &II,
- QualType ObjectType) {
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
// FIXME: The source location information is all wrong.
SS.setRange(Range);
SS.setScopeRep(Prefix);
return static_cast<NestedNameSpecifier *>(
- SemaRef.ActOnCXXNestedNameSpecifier(0, SS, Range.getEnd(),
+ SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
Range.getEnd(), II,
- ObjectType.getAsOpaquePtr(),
+ ObjectType,
+ FirstQualifierInScope,
false));
}