summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-03 22:13:48 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-03 22:13:48 +0000
commitf816bd70ce1ffc8ac9323a5539ca07468c7bc746 (patch)
tree6f7b1a8beed76aaa04b03c11f8d83a5a06222838
parentd93c668f001508de50a9666e73985c1cf3885de0 (diff)
downloadbcm5719-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.h56
-rw-r--r--clang/test/SemaTemplate/member-access-expr.cpp13
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}}
+}
OpenPOWER on IntegriCloud