[cfe-commits] r96367 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/SemaCXX/destructor.cpp test/SemaCXX/invalid-member-expr.cpp test/SemaCXX/pseudo-destructors.cpp test/SemaTemplate/destructor-template.cpp
Douglas Gregor
dgregor at apple.com
Tue Feb 16 11:10:00 PST 2010
Author: dgregor
Date: Tue Feb 16 13:09:40 2010
New Revision: 96367
URL: http://llvm.org/viewvc/llvm-project?rev=96367&view=rev
Log:
Improve parsing and instantiation of destructor names, so that we can
now cope with the destruction of types named as dependent templates,
e.g.,
y->template Y<T>::~Y()
Nominally, we implement C++0x [basic.lookup.qual]p6. However, we don't
follow the letter of the standard here because that would fail to
parse
template<typename T, typename U>
X0<T, U>::~X0() { }
properly. The problem is captured in core issue 339, which gives some
(but not enough!) guidance. I expect to revisit this code when the
resolution of 339 is clear, and/or we start capturing better source
information for DeclarationNames.
Fixes PR6152.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaCXX/destructor.cpp
cfe/trunk/test/SemaCXX/invalid-member-expr.cpp
cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
cfe/trunk/test/SemaTemplate/destructor-template.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Feb 16 13:09:40 2010
@@ -146,8 +146,6 @@
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_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">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 16 13:09:40 2010
@@ -557,6 +557,10 @@
"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<
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Feb 16 13:09:40 2010
@@ -1075,7 +1075,7 @@
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 @@
//===------------------------- 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,
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Feb 16 13:09:40 2010
@@ -1387,8 +1387,7 @@
//===--------------------------------------------------------------------===//
// 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(),
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Feb 16 13:09:40 2010
@@ -464,8 +464,7 @@
/// 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 @@
// 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;
}
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Feb 16 13:09:40 2010
@@ -846,13 +846,8 @@
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 @@
// 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 @@
}
// 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;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Feb 16 13:09:40 2010
@@ -2056,6 +2056,12 @@
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,
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Feb 16 13:09:40 2010
@@ -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,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Feb 16 13:09:40 2010
@@ -4911,18 +4911,21 @@
/// \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();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Feb 16 13:09:40 2010
@@ -570,7 +570,8 @@
/// \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 @@
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
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Feb 16 13:09:40 2010
@@ -191,7 +191,7 @@
/// 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 @@
/// 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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
//===----------------------------------------------------------------------===//
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 nested
@@ -2468,7 +2483,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
- VectorTypeLoc TL) {
+ VectorTypeLoc TL,
+ QualType ObjectType) {
VectorType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(T->getElementType());
if (ElementType.isNull())
@@ -2491,7 +2507,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
- ExtVectorTypeLoc TL) {
+ ExtVectorTypeLoc TL,
+ QualType ObjectType) {
VectorType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(T->getElementType());
if (ElementType.isNull())
@@ -2516,7 +2533,8 @@
template<typename Derived>
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL) {
+ FunctionProtoTypeLoc TL,
+ QualType ObjectType) {
FunctionProtoType *T = TL.getTypePtr();
QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
if (ResultType.isNull())
@@ -2592,7 +2610,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
TypeLocBuilder &TLB,
- FunctionNoProtoTypeLoc TL) {
+ FunctionNoProtoTypeLoc TL,
+ QualType ObjectType) {
FunctionNoProtoType *T = TL.getTypePtr();
QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
if (ResultType.isNull())
@@ -2612,7 +2631,8 @@
template<typename Derived> QualType
TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
- UnresolvedUsingTypeLoc TL) {
+ UnresolvedUsingTypeLoc TL,
+ QualType ObjectType) {
UnresolvedUsingType *T = TL.getTypePtr();
Decl *D = getDerived().TransformDecl(T->getDecl());
if (!D)
@@ -2635,7 +2655,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
- TypedefTypeLoc TL) {
+ TypedefTypeLoc TL,
+ QualType ObjectType) {
TypedefType *T = TL.getTypePtr();
TypedefDecl *Typedef
= cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
@@ -2658,7 +2679,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
- TypeOfExprTypeLoc TL) {
+ TypeOfExprTypeLoc TL,
+ QualType ObjectType) {
// typeof expressions are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
@@ -2685,7 +2707,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
- TypeOfTypeLoc TL) {
+ TypeOfTypeLoc TL,
+ QualType ObjectType) {
TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
if (!New_Under_TI)
@@ -2709,7 +2732,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
- DecltypeTypeLoc TL) {
+ DecltypeTypeLoc TL,
+ QualType ObjectType) {
DecltypeType *T = TL.getTypePtr();
// decltype expressions are not potentially evaluated contexts
@@ -2736,7 +2760,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
- RecordTypeLoc TL) {
+ RecordTypeLoc TL,
+ QualType ObjectType) {
RecordType *T = TL.getTypePtr();
RecordDecl *Record
= cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
@@ -2759,7 +2784,8 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
- EnumTypeLoc TL) {
+ EnumTypeLoc TL,
+ QualType ObjectType) {
EnumType *T = TL.getTypePtr();
EnumDecl *Enum
= cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
@@ -2782,7 +2808,8 @@
template <typename Derived>
QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
- ElaboratedTypeLoc TL) {
+ ElaboratedTypeLoc TL,
+ QualType ObjectType) {
ElaboratedType *T = TL.getTypePtr();
// FIXME: this should be a nested type.
@@ -2808,26 +2835,20 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL) {
+ TemplateTypeParmTypeLoc TL,
+ QualType ObjectType) {
return TransformTypeSpecType(TLB, TL);
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
TypeLocBuilder &TLB,
- SubstTemplateTypeParmTypeLoc TL) {
+ SubstTemplateTypeParmTypeLoc TL,
+ QualType ObjectType) {
return TransformTypeSpecType(TLB, TL);
}
template<typename Derived>
-inline QualType
-TreeTransform<Derived>::TransformTemplateSpecializationType(
- TypeLocBuilder &TLB,
- TemplateSpecializationTypeLoc TL) {
- return TransformTemplateSpecializationType(TLB, TL, QualType());
-}
-
-template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
const TemplateSpecializationType *TST,
QualType ObjectType) {
@@ -2901,11 +2922,13 @@
template<typename Derived>
QualType
TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB,
- QualifiedNameTypeLoc TL) {
+ QualifiedNameTypeLoc TL,
+ QualType ObjectType) {
QualifiedNameType *T = TL.getTypePtr();
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(),
- SourceRange());
+ SourceRange(),
+ ObjectType);
if (!NNS)
return QualType();
@@ -2930,14 +2953,16 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
- TypenameTypeLoc TL) {
+ TypenameTypeLoc TL,
+ QualType ObjectType) {
TypenameType *T = TL.getTypePtr();
/* FIXME: preserve source information better than this */
SourceRange SR(TL.getNameLoc());
NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR);
+ = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR,
+ ObjectType);
if (!NNS)
return QualType();
@@ -2970,7 +2995,8 @@
template<typename Derived>
QualType
TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
- ObjCInterfaceTypeLoc TL) {
+ ObjCInterfaceTypeLoc TL,
+ QualType ObjectType) {
assert(false && "TransformObjCInterfaceType unimplemented");
return QualType();
}
@@ -2978,7 +3004,8 @@
template<typename Derived>
QualType
TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
- ObjCObjectPointerTypeLoc TL) {
+ ObjCObjectPointerTypeLoc TL,
+ QualType ObjectType) {
assert(false && "TransformObjCObjectPointerType unimplemented");
return QualType();
}
Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Tue Feb 16 13:09:40 2010
@@ -40,9 +40,9 @@
~F(); // expected-error {{destructor cannot be redeclared}}
};
-~; // expected-error {{expected the class name after '~' to name a destructor}}
+~; // expected-error {{expected a class name after '~' to name a destructor}}
~undef(); // expected-error {{expected the class name after '~' to name a destructor}}
-~operator+(int, int); // expected-error {{expected the class name after '~' to name a destructor}}
+~operator+(int, int); // expected-error {{expected a class name after '~' to name a destructor}}
~F(){} // expected-error {{destructor must be a non-static member function}}
struct G {
Modified: cfe/trunk/test/SemaCXX/invalid-member-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/invalid-member-expr.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/invalid-member-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/invalid-member-expr.cpp Tue Feb 16 13:09:40 2010
@@ -6,7 +6,7 @@
X x;
x.int; // expected-error{{expected unqualified-id}}
- x.~int(); // expected-error{{expected the class name}}
+ x.~int(); // expected-error{{expected a class name}}
x.operator; // expected-error{{missing type specifier after 'operator'}}
x.operator typedef; // expected-error{{missing type specifier after 'operator'}}
}
@@ -15,7 +15,7 @@
X *x;
x->int; // expected-error{{expected unqualified-id}}
- x->~int(); // expected-error{{expected the class name}}
+ x->~int(); // expected-error{{expected a class name}}
x->operator; // expected-error{{missing type specifier after 'operator'}}
x->operator typedef; // expected-error{{missing type specifier after 'operator'}}
}
Modified: cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pseudo-destructors.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/pseudo-destructors.cpp (original)
+++ cfe/trunk/test/SemaCXX/pseudo-destructors.cpp Tue Feb 16 13:09:40 2010
@@ -18,8 +18,8 @@
a->~foo(); // expected-error{{identifier 'foo' in pseudo-destructor expression does not name a type}}
- // FIXME: the type printed below isn't wonderful
- a->~Bar(); // expected-error{{no member named}}
+ // FIXME: the diagnostic below isn't wonderful
+ a->~Bar(); // expected-error{{does not name a type}}
f->~Bar();
f->~Foo();
@@ -28,7 +28,7 @@
g().~Bar(); // expected-error{{non-scalar}}
f->::~Bar();
- f->N::~Wibble();
+ f->N::~Wibble(); // expected-error{{expected the class name after '~' to name a destructor}}
f->::~Bar(17, 42); // expected-error{{cannot have any arguments}}
}
Modified: cfe/trunk/test/SemaTemplate/destructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/destructor-template.cpp?rev=96367&r1=96366&r2=96367&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/destructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/destructor-template.cpp Tue Feb 16 13:09:40 2010
@@ -17,3 +17,16 @@
}
template void destroy_me(Incomplete*);
+
+namespace PR6152 {
+ template<typename T> struct X { void f(); };
+ template<typename T> struct Y { };
+ template<typename T>
+ void X<T>::f() {
+ Y<T> *y;
+ y->template Y<T>::~Y();
+ }
+
+ template struct X<int>;
+}
+
More information about the cfe-commits
mailing list