aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--include/clang/Parse/Action.h14
-rw-r--r--include/clang/Parse/Parser.h3
-rw-r--r--lib/Parse/ParseDeclCXX.cpp6
-rw-r--r--lib/Parse/ParseExprCXX.cpp27
-rw-r--r--lib/Sema/Sema.h6
-rw-r--r--lib/Sema/SemaExprCXX.cpp226
-rw-r--r--lib/Sema/SemaTemplate.cpp9
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp6
-rw-r--r--lib/Sema/TreeTransform.h171
-rw-r--r--test/SemaCXX/destructor.cpp4
-rw-r--r--test/SemaCXX/invalid-member-expr.cpp4
-rw-r--r--test/SemaCXX/pseudo-destructors.cpp6
-rw-r--r--test/SemaTemplate/destructor-template.cpp13
15 files changed, 394 insertions, 113 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index bc26c3b0da..4b8ed44783 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -146,8 +146,6 @@ def err_missing_comma_before_ellipsis : Error<
def err_unexpected_typedef_ident : Error<
"unexpected type name %0: expected identifier">;
def err_expected_class_name : Error<"expected class name">;
-def err_destructor_class_name : Error<
- "expected the class name after '~' to name a destructor">;
def err_unspecified_vla_size_with_static : Error<
"'static' may not be used with an unspecified variable length array size">;
@@ -247,8 +245,10 @@ def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
def err_using_namespace_in_class : Error<
"'using namespace' is not allowed in classes">;
-def err_ident_in_pseudo_dtor_not_a_type : Error<
- "identifier %0 in pseudo-destructor expression does not name a type">;
+def err_destructor_tilde_identifier : Error<
+ "expected a class name after '~' to name a destructor">;
+def err_destructor_template_id : Error<
+ "destructor name %0 does not refer to a template">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 19b242e86b..bc834a8478 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -557,6 +557,10 @@ def err_destructor_typedef_name : Error<
"destructor cannot be declared using a typedef %0 of the class name">;
def err_destructor_name : Error<
"expected the class name after '~' to name the enclosing class">;
+def err_destructor_class_name : Error<
+ "expected the class name after '~' to name a destructor">;
+def err_ident_in_pseudo_dtor_not_a_type : Error<
+ "identifier %0 in pseudo-destructor expression does not name a type">;
// C++ initialization
def err_init_conversion_failed : Error<
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index ec542f08c3..882e5d15f5 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -1075,7 +1075,7 @@ public:
SourceLocation RLoc) {
return ExprEmpty();
}
-
+
/// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
/// of the form \c x.m or \c p->m.
///
@@ -1473,6 +1473,18 @@ public:
//===------------------------- C++ Expressions --------------------------===//
+ /// \brief Parsed a destructor name or pseudo-destructor name.
+ ///
+ /// \returns the type being destructed.
+ virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, const CXXScopeSpec &SS,
+ TypeTy *ObjectType,
+ bool EnteringContext) {
+ return getTypeName(II, NameLoc, S, &SS, false, ObjectType);
+ }
+
+
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
tok::TokenKind Kind,
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index f4d3d3e54d..f491fa895b 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1387,8 +1387,7 @@ private:
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
TypeResult ParseClassName(SourceLocation &EndLocation,
- const CXXScopeSpec *SS = 0,
- bool DestrExpected = false);
+ const CXXScopeSpec *SS = 0);
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 51ee6a4434..225ce256b1 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -464,8 +464,7 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
/// simple-template-id
///
Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
- const CXXScopeSpec *SS,
- bool DestrExpected) {
+ const CXXScopeSpec *SS) {
// Check whether we have a template-id that names a type.
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
@@ -536,8 +535,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
// We have an identifier; check whether it is actually a type.
TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
if (!Type) {
- Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
- : diag::err_expected_class_name);
+ Diag(IdLoc, diag::err_expected_class_name);
return true;
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 0dbe1ea838..932d6ebf97 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -846,13 +846,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
EnteringContext, Template);
if (TNK == TNK_Non_template && Id.DestructorName == 0) {
- // The identifier following the destructor did not refer to a template
- // or to a type. Complain.
- if (ObjectType)
- Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << Name;
- else
- Diag(NameLoc, diag::err_destructor_class_name);
+ Diag(NameLoc, diag::err_destructor_template_id)
+ << Name << SS.getRange();
return true;
}
}
@@ -1258,7 +1253,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
// Parse the class-name.
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_destructor_class_name);
+ Diag(Tok, diag::err_destructor_tilde_identifier);
return true;
}
@@ -1273,17 +1268,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// Note that this is a destructor name.
- Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
- CurScope, &SS, false, ObjectType);
- if (!Ty) {
- if (ObjectType)
- Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << ClassName;
- else
- Diag(ClassNameLoc, diag::err_destructor_class_name);
+ Action::TypeTy *Ty = Actions.getDestructorName(TildeLoc, *ClassName,
+ ClassNameLoc, CurScope,
+ SS, ObjectType,
+ EnteringContext);
+ if (!Ty)
return true;
- }
-
+
Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
return false;
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3c0adbe6b0..25ca3d1144 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2056,6 +2056,12 @@ public:
SourceLocation Loc,
ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs);
+ virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, const CXXScopeSpec &SS,
+ TypeTy *ObjectType,
+ bool EnteringContext);
+
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
tok::TokenKind Kind,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 9eeda54299..4098d0f2cf 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -24,6 +24,232 @@
#include "llvm/ADT/STLExtras.h"
using namespace clang;
+Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II,
+ SourceLocation NameLoc,
+ Scope *S, const CXXScopeSpec &SS,
+ TypeTy *ObjectTypePtr,
+ bool EnteringContext) {
+ // Determine where to perform name lookup.
+
+ // FIXME: This area of the standard is very messy, and the current
+ // wording is rather unclear about which scopes we search for the
+ // destructor name; see core issues 399 and 555. Issue 399 in
+ // particular shows where the current description of destructor name
+ // lookup is completely out of line with existing practice, e.g.,
+ // this appears to be ill-formed:
+ //
+ // namespace N {
+ // template <typename T> struct S {
+ // ~S();
+ // };
+ // }
+ //
+ // void f(N::S<int>* s) {
+ // s->N::S<int>::~S();
+ // }
+ //
+ //
+ QualType SearchType;
+ DeclContext *LookupCtx = 0;
+ bool isDependent = false;
+ bool LookInScope = false;
+
+ // If we have an object type, it's because we are in a
+ // pseudo-destructor-expression or a member access expression, and
+ // we know what type we're looking for.
+ if (ObjectTypePtr)
+ SearchType = GetTypeFromParser(ObjectTypePtr);
+
+ if (SS.isSet()) {
+ // C++ [basic.lookup.qual]p6:
+ // If a pseudo-destructor-name (5.2.4) contains a
+ // nested-name-specifier, the type-names are looked up as types
+ // in the scope designated by the nested-name-specifier. Similarly, in
+ // a qualified-id of theform:
+ //
+ // :: [opt] nested-name-specifier[opt] class-name :: ~class-name
+ //
+ // the second class-name is looked up in the same scope as the first.
+ //
+ // To implement this, we look at the prefix of the
+ // nested-name-specifier we were given, and determine the lookup
+ // context from that.
+ NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ if (NestedNameSpecifier *Prefix = NNS->getPrefix()) {
+ CXXScopeSpec PrefixSS;
+ PrefixSS.setScopeRep(Prefix);
+ LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(PrefixSS);
+ } else if (ObjectTypePtr) {
+ LookupCtx = computeDeclContext(SearchType);
+ isDependent = SearchType->isDependentType();
+ } else {
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ if (LookupCtx && !LookupCtx->isTranslationUnit()) {
+ LookupCtx = LookupCtx->getParent();
+ isDependent = LookupCtx->isDependentContext();
+ } else {
+ isDependent = false;
+ }
+ }
+
+ LookInScope = false;
+ } else if (ObjectTypePtr) {
+ // C++ [basic.lookup.classref]p3:
+ // If the unqualified-id is ~type-name, the type-name is looked up
+ // in the context of the entire postfix-expression. If the type T
+ // of the object expression is of a class type C, the type-name is
+ // also looked up in the scope of class C. At least one of the
+ // lookups shall find a name that refers to (possibly
+ // cv-qualified) T.
+ LookupCtx = computeDeclContext(SearchType);
+ isDependent = SearchType->isDependentType();
+ assert((isDependent || !SearchType->isIncompleteType()) &&
+ "Caller should have completed object type");
+
+ LookInScope = true;
+ } else {
+ // Perform lookup into the current scope (only).
+ LookInScope = true;
+ }
+
+ LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
+ for (unsigned Step = 0; Step != 2; ++Step) {
+ // Look for the name first in the computed lookup context (if we
+ // have one) and, if that fails to find a match, in the sope (if
+ // we're allowed to look there).
+ Found.clear();
+ if (Step == 0 && LookupCtx)
+ LookupQualifiedName(Found, LookupCtx);
+ else if (Step == 1 && LookInScope)
+ LookupName(Found, S);
+ else
+ continue;
+
+ // FIXME: Should we be suppressing ambiguities here?
+ if (Found.isAmbiguous())
+ return 0;
+
+ if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
+ QualType T = Context.getTypeDeclType(Type);
+ // If we found the injected-class-name of a class template, retrieve the
+ // type of that template.
+ // FIXME: We really shouldn't need to do this.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Type))
+ if (Record->isInjectedClassName())
+ if (Record->getDescribedClassTemplate())
+ T = Record->getDescribedClassTemplate()
+ ->getInjectedClassNameType(Context);
+
+ if (SearchType.isNull() || SearchType->isDependentType() ||
+ Context.hasSameUnqualifiedType(T, SearchType)) {
+ // We found our type!
+
+ return T.getAsOpaquePtr();
+ }
+ }
+
+ // If the name that we found is a class template name, and it is
+ // the same name as the template name in the last part of the
+ // nested-name-specifier (if present) or the object type, then
+ // this is the destructor for that class.
+ // FIXME: This is a workaround until we get real drafting for core
+ // issue 399, for which there isn't even an obvious direction.
+ if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) {
+ QualType MemberOfType;
+ if (SS.isSet()) {
+ if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) {
+ // Figure out the type of the context, if it has one.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Ctx))
+ MemberOfType = Context.getTypeDeclType(Spec);
+ else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (Record->getDescribedClassTemplate())
+ MemberOfType = Record->getDescribedClassTemplate()
+ ->getInjectedClassNameType(Context);
+ else
+ MemberOfType = Context.getTypeDeclType(Record);
+ }
+ }
+ }
+ if (MemberOfType.isNull())
+ MemberOfType = SearchType;
+
+ if (MemberOfType.isNull())
+ continue;
+
+ // We're referring into a class template specialization. If the
+ // class template we found is the same as the template being
+ // specialized, we found what we are looking for.
+ if (const RecordType *Record = MemberOfType->getAs<RecordType>()) {
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+ if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
+ Template->getCanonicalDecl())
+ return MemberOfType.getAsOpaquePtr();
+ }
+
+ continue;
+ }
+
+ // We're referring to an unresolved class template
+ // specialization. Determine whether we class template we found
+ // is the same as the template being specialized or, if we don't
+ // know which template is being specialized, that it at least
+ // has the same name.
+ if (const TemplateSpecializationType *SpecType
+ = MemberOfType->getAs<TemplateSpecializationType>()) {
+ TemplateName SpecName = SpecType->getTemplateName();
+
+ // The class template we found is the same template being
+ // specialized.
+ if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
+ if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
+ return MemberOfType.getAsOpaquePtr();
+
+ continue;
+ }
+
+ // The class template we found has the same name as the
+ // (dependent) template name being specialized.
+ if (DependentTemplateName *DepTemplate
+ = SpecName.getAsDependentTemplateName()) {
+ if (DepTemplate->isIdentifier() &&
+ DepTemplate->getIdentifier() == Template->getIdentifier())
+ return MemberOfType.getAsOpaquePtr();
+
+ continue;
+ }
+ }
+ }
+ }
+
+ if (isDependent) {
+ // We didn't find our type, but that's okay: it's dependent
+ // anyway.
+ NestedNameSpecifier *NNS = 0;
+ SourceRange Range;
+ if (SS.isSet()) {
+ NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ Range = SourceRange(SS.getRange().getBegin(), NameLoc);
+ } else {
+ NNS = NestedNameSpecifier::Create(Context, &II);
+ Range = SourceRange(NameLoc);
+ }
+
+ return CheckTypenameType(NNS, II, Range).getAsOpaquePtr();
+ }
+
+ if (ObjectTypePtr)
+ Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << &II;
+ else
+ Diag(NameLoc, diag::err_destructor_class_name);
+
+ return 0;
+}
+
/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
Action::OwningExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 10e411f582..c98f88f86a 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4911,18 +4911,21 @@ namespace {
/// \brief Transforms a typename type by determining whether the type now
/// refers to a member of the current instantiation, and then
/// type-checking and building a QualifiedNameType (when possible).
- QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
+ QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL,
+ QualType ObjectType);
};
}
QualType
CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
- TypenameTypeLoc TL) {
+ TypenameTypeLoc TL,
+ QualType ObjectType) {
TypenameType *T = TL.getTypePtr();
NestedNameSpecifier *NNS
= TransformNestedNameSpecifier(T->getQualifier(),
- /*FIXME:*/SourceRange(getBaseLocation()));
+ /*FIXME:*/SourceRange(getBaseLocation()),
+ ObjectType);
if (!NNS)
return QualType();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 51e17fe472..f12c559ec1 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -570,7 +570,8 @@ namespace {
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL);
+ TemplateTypeParmTypeLoc TL,
+ QualType ObjectType);
};
}
@@ -859,7 +860,8 @@ Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
QualType
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL) {
+ TemplateTypeParmTypeLoc TL,
+ QualType ObjectType) {
TemplateTypeParmType *T = TL.getTypePtr();
if (T->getDepth() < TemplateArgs.getNumLevels()) {
// Replace the template type parameter with its corresponding
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index fc069f7ba3..a59608661c 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -191,7 +191,7 @@ public:
/// switched to storing TypeSourceInfos.
///
/// \returns the transformed type.
- QualType TransformType(QualType T);
+ QualType TransformType(QualType T, QualType ObjectType = QualType());
/// \brief Transforms the given type-with-location into a new
/// type-with-location.
@@ -201,13 +201,15 @@ public:
/// may override this function (to take over all type
/// transformations) or some set of the TransformXXXType functions
/// to alter the transformation.
- TypeSourceInfo *TransformType(TypeSourceInfo *DI);
+ TypeSourceInfo *TransformType(TypeSourceInfo *DI,
+ QualType ObjectType = QualType());
/// \brief Transform the given type-with-location into a new
/// type, collecting location information in the given builder
/// as necessary.
///
- QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
+ QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL,
+ QualType ObjectType = QualType());
/// \brief Transform the given statement.
///
@@ -307,20 +309,17 @@ public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+ QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T, \
+ QualType ObjectType = QualType());
#include "clang/AST/TypeLocNodes.def"
- QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+ QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL,
+ QualType ObjectType);
QualType
TransformTemplateSpecializationType(const TemplateSpecializationType *T,
QualType ObjectType);
- QualType
- TransformTemplateSpecializationType(TypeLocBuilder &TLB,
- TemplateSpecializationTypeLoc TL,
- QualType ObjectType);
-
OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
#define STMT(Node, Parent) \
@@ -1779,7 +1778,8 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName());
- QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+ QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0),
+ ObjectType);
if (T.isNull())
return 0;
@@ -1820,14 +1820,8 @@ TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
TemporaryBase Rebase(*this, Loc, Name);
- QualType T;
- if (!ObjectType.isNull() &&
- isa<TemplateSpecializationType>(Name.getCXXNameType())) {
- TemplateSpecializationType *SpecType
- = cast<TemplateSpecializationType>(Name.getCXXNameType());
- T = TransformTemplateSpecializationType(SpecType, ObjectType);
- } else
- T = getDerived().TransformType(Name.getCXXNameType());
+ QualType T = getDerived().TransformType(Name.getCXXNameType(),
+ ObjectType);
if (T.isNull())
return DeclarationName();
@@ -1847,7 +1841,8 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
- /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+ /*FIXME:*/SourceRange(getDerived().getBaseLocation()),
+ ObjectType);
if (!NNS)
return TemplateName();
@@ -1873,7 +1868,8 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
- /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+ /*FIXME:*/SourceRange(getDerived().getBaseLocation()),
+ ObjectType);
if (!NNS && DTN->getQualifier())
return TemplateName();
@@ -2055,7 +2051,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
//===----------------------------------------------------------------------===//
template<typename Derived>
-QualType TreeTransform<Derived>::TransformType(QualType T) {
+QualType TreeTransform<Derived>::TransformType(QualType T,
+ QualType ObjectType) {
if (getDerived().AlreadyTransformed(T))
return T;
@@ -2064,7 +2061,7 @@ QualType TreeTransform<Derived>::TransformType(QualType T) {
TypeSourceInfo *DI = getSema().Context.CreateTypeSourceInfo(T);
DI->getTypeLoc().initialize(getDerived().getBaseLocation());
- TypeSourceInfo *NewDI = getDerived().TransformType(DI);
+ TypeSourceInfo *NewDI = getDerived().TransformType(DI, ObjectType);
if (!NewDI)
return QualType();
@@ -2073,7 +2070,8 @@ QualType TreeTransform<Derived>::TransformType(QualType T) {
}
template<typename Derived>
-TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
+TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI,
+ QualType ObjectType) {
if (getDerived().AlreadyTransformed(DI->getType()))
return DI;
@@ -2082,7 +2080,7 @@ TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
TypeLoc TL = DI->getTypeLoc();
TLB.reserve(TL.getFullDataSize());
- QualType Result = getDerived().TransformType(TLB, TL);
+ QualType Result = getDerived().TransformType(TLB, TL, ObjectType);
if (Result.isNull())
return 0;
@@ -2091,12 +2089,14 @@ TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T,
+ QualType ObjectType) {
switch (T.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
case TypeLoc::CLASS: \
- return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+ return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T), \
+ ObjectType);
#include "clang/AST/TypeLocNodes.def"
}
@@ -2112,10 +2112,12 @@ TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
template<typename Derived>
QualType
TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
- QualifiedTypeLoc T) {
+ QualifiedTypeLoc T,
+ QualType ObjectType) {
Qualifiers Quals = T.getType().getLocalQualifiers();
- QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+ QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc(),
+ ObjectType);
if (Result.isNull())
return QualType();
@@ -2166,7 +2168,8 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
template<typename Derived>
QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
- BuiltinTypeLoc T) {
+ BuiltinTypeLoc T,
+ QualType ObjectType) {
BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType());
NewT.setBuiltinLoc(T.getBuiltinLoc());
if (T.needsExtraLocalData())
@@ -2176,21 +2179,24 @@ QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
template<typename Derived>
QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
- ComplexTypeLoc T) {
+ ComplexTypeLoc T,
+ QualType ObjectType) {
// FIXME: recurse?
return TransformTypeSpecType(TLB, T);
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
- PointerTypeLoc TL) {
+ PointerTypeLoc TL,
+ QualType ObjectType) {
TransformPointerLikeType(PointerType);
}
template<typename Derived>
QualType
TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
- BlockPointerTypeLoc TL) {
+ BlockPointerTypeLoc TL,
+ QualType ObjectType) {
TransformPointerLikeType(BlockPointerType);
}
@@ -2201,7 +2207,8 @@ TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
template<typename Derived>
QualType
TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
- ReferenceTypeLoc TL) {
+ ReferenceTypeLoc TL,
+ QualType ObjectType) {
const ReferenceType *T = TL.getTypePtr();
// Note that this works with the pointee-as-written.
@@ -2233,21 +2240,24 @@ TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
template<typename Derived>
QualType
TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
- LValueReferenceTypeLoc TL) {
- return TransformReferenceType(TLB, TL);
+ LValueReferenceTypeLoc TL,
+ QualType ObjectType) {
+ return TransformReferenceType(TLB, TL, ObjectType);
}
template<typename Derived>
QualType
TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
- RValueReferenceTypeLoc TL) {
- return TransformReferenceType(TLB, TL);
+ RValueReferenceTypeLoc TL,
+ QualType ObjectType) {
+ return TransformReferenceType(TLB, TL, ObjectType);
}
template<typename Derived>
QualType
TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
- MemberPointerTypeLoc TL) {
+ MemberPointerTypeLoc TL,
+ QualType ObjectType) {
MemberPointerType *T = TL.getTypePtr();
QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
@@ -2279,7 +2289,8 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
template<typename Derived>
QualType
TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
- ConstantArrayTypeLoc TL) {
+ ConstantArrayTypeLoc TL,
+ QualType ObjectType) {
ConstantArrayType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
@@ -2314,7 +2325,8 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
template<typename Derived>
QualType TreeTransform<Derived>::TransformIncompleteArrayType(
TypeLocBuilder &TLB,
- IncompleteArrayTypeLoc TL) {
+ IncompleteArrayTypeLoc TL,
+ QualType ObjectType) {
IncompleteArrayType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
@@ -2342,7 +2354,8 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType(
template<typename Derived>
QualType
TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
- VariableArrayTypeLoc TL) {
+ VariableArrayTypeLoc TL,
+ QualType ObjectType) {
VariableArrayType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
@@ -2383,7 +2396,8 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
template<typename Derived>
QualType
TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
- DependentSizedArrayTypeLoc TL) {
+ DependentSizedArrayTypeLoc TL,
+ QualType ObjectType) {
DependentSizedArrayType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
@@ -2426,7 +2440,8 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
template<typename Derived>
QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
TypeLocBuilder &TLB,
- DependentSizedExtVectorTypeLoc TL) {
+ DependentSizedExtVectorTypeLoc TL,
+ QualType ObjectType) {
DependentSizedExtVectorType *T = TL.getTypePtr();
// FIXME: ext vector locs should be nest