Implement tree transformations for DeclarationNames. Among other

things, this means that we can properly cope with member access
expressions such as 

  t->operator T()

where T is a template parameter (or other dependent type).

llvm-svn: 80957
This commit is contained in:
Douglas Gregor 2009-09-03 22:13:48 +00:00
parent d93c668f00
commit f816bd70ce
2 changed files with 64 additions and 5 deletions

View File

@ -247,6 +247,15 @@ public:
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
/// \brief Transform the given declaration name.
///
/// By default, transforms the types of conversion function, constructor,
/// and destructor names and then (if needed) rebuilds the declaration name.
/// Identifiers and selectors are returned unmodified. Sublcasses may
/// override this function to provide alternate behavior.
DeclarationName TransformDeclarationName(DeclarationName Name,
SourceLocation Loc);
/// \brief Transform the given template name.
///
/// By default, transforms the template name by transforming the declarations
@ -1667,6 +1676,39 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
return 0;
}
template<typename Derived>
DeclarationName
TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
SourceLocation Loc) {
if (!Name)
return Name;
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXUsingDirective:
return Name;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
TemporaryBase Rebase(*this, Loc, Name);
QualType T = getDerived().TransformType(Name.getCXXNameType());
if (T.isNull())
return DeclarationName();
return SemaRef.Context.DeclarationNames.getCXXSpecialName(
Name.getNameKind(),
SemaRef.Context.getCanonicalType(T));
}
}
return DeclarationName();
}
template<typename Derived>
TemplateName
TreeTransform<Derived>::TransformTemplateName(TemplateName Name) {
@ -3838,8 +3880,10 @@ TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
if (!NNS)
return SemaRef.ExprError();
// FIXME: Transform the declaration name
DeclarationName Name = E->getDeclName();
DeclarationName Name
= getDerived().TransformDeclarationName(E->getDeclName(), E->getLocation());
if (!Name)
return SemaRef.ExprError();
if (!getDerived().AlwaysRebuild() &&
NNS == E->getQualifier() &&
@ -4078,9 +4122,11 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
return SemaRef.ExprError();
}
// FIXME: Transform the declaration name
DeclarationName Name = E->getMember();
DeclarationName Name
= getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc());
if (!Name)
return SemaRef.ExprError();
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() &&
Qualifier == E->getQualifier() &&

View File

@ -46,3 +46,16 @@ void test_f0_through_typedef2(X0 x0, X1 x1) {
}
struct X2 {
operator int() const;
};
template<typename T, typename U>
T convert(const U& value) {
return value.operator T(); // expected-error{{operator long}}
}
void test_convert(X2 x2) {
convert<int>(x2);
convert<long>(x2); // expected-note{{instantiation}}
}