diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-09-03 22:13:48 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-09-03 22:13:48 +0000 |
| commit | f816bd70ce1ffc8ac9323a5539ca07468c7bc746 (patch) | |
| tree | 6f7b1a8beed76aaa04b03c11f8d83a5a06222838 | |
| parent | d93c668f001508de50a9666e73985c1cf3885de0 (diff) | |
| download | bcm5719-llvm-f816bd70ce1ffc8ac9323a5539ca07468c7bc746.tar.gz bcm5719-llvm-f816bd70ce1ffc8ac9323a5539ca07468c7bc746.zip | |
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
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 56 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/member-access-expr.cpp | 13 |
2 files changed, 64 insertions, 5 deletions
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7babcf76b7a..2faaa44daf9 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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 @@ -1668,6 +1677,39 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, } 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) { if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { @@ -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() && diff --git a/clang/test/SemaTemplate/member-access-expr.cpp b/clang/test/SemaTemplate/member-access-expr.cpp index 408e2bb53c4..40dbffe0cf8 100644 --- a/clang/test/SemaTemplate/member-access-expr.cpp +++ b/clang/test/SemaTemplate/member-access-expr.cpp @@ -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}} +} |

