[cfe-commits] r84545 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseExpr.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/TreeTransform.h test/SemaTemplate/member-template-access-expr.cpp
Douglas Gregor
dgregor at apple.com
Mon Oct 19 15:04:39 PDT 2009
Author: dgregor
Date: Mon Oct 19 17:04:39 2009
New Revision: 84545
URL: http://llvm.org/viewvc/llvm-project?rev=84545&view=rev
Log:
Parse a simple-template-id following a '~' when calling a destructor, e.g.,
t->~T<A0, A1>()
Fixes PR5213.
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=84545&r1=84544&r2=84545&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Oct 19 17:04:39 2009
@@ -1390,6 +1390,34 @@
return ExprEmpty();
}
+ /// \brief Parsed a C++ destructor reference that refers to a type.
+ ///
+ /// This action is used when parsing a destructor reference that uses a
+ /// template-id, e.g.,
+ ///
+ /// \code
+ /// t->~Tmpl<T1, T2>
+ /// \endcode
+ ///
+ /// \param S the scope in which the destructor reference occurs.
+ /// \param Base the base object of the destructor reference expression.
+ /// \param OpLoc the location of the operator ('.' or '->').
+ /// \param OpKind the kind of the destructor reference operator ('.' or '->').
+ /// \param TypeRange the source range that covers the destructor type.
+ /// \param Type the type that is being destroyed.
+ /// \param SS the scope specifier that precedes the destructor name.
+ /// \param HasTrailingLParen whether the destructor name is followed by a '('.
+ virtual OwningExprResult
+ ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceRange TypeRange,
+ TypeTy *Type,
+ const CXXScopeSpec &SS,
+ bool HasTrailingLParen) {
+ return ExprEmpty();
+ }
+
/// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
/// reference, for example:
///
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=84545&r1=84544&r2=84545&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Oct 19 17:04:39 2009
@@ -972,13 +972,41 @@
return ExprError();
}
- if (!LHS.isInvalid())
- LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind,
- Tok.getLocation(),
- Tok.getIdentifierInfo(),
- SS,
- NextToken().is(tok::l_paren));
+ if (NextToken().is(tok::less)) {
+ // class-name:
+ // ~ simple-template-id
+ TemplateTy Template
+ = Actions.ActOnDependentTemplateName(SourceLocation(),
+ *Tok.getIdentifierInfo(),
+ Tok.getLocation(),
+ SS,
+ ObjectType);
+ if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS,
+ SourceLocation(), true))
+ return ExprError();
+
+ assert(Tok.is(tok::annot_typename) &&
+ "AnnotateTemplateIdToken didn't work?");
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+ OpLoc, OpKind,
+ Tok.getAnnotationRange(),
+ Tok.getAnnotationValue(),
+ SS,
+ NextToken().is(tok::l_paren));
+ } else {
+ // class-name:
+ // ~ identifier
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+ OpLoc, OpKind,
+ Tok.getLocation(),
+ Tok.getIdentifierInfo(),
+ SS,
+ NextToken().is(tok::l_paren));
+ }
+
+ // Consume the identifier or template-id token.
ConsumeToken();
} else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
// We have a reference to a member operator, e.g., t.operator int or
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=84545&r1=84544&r2=84545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Oct 19 17:04:39 2009
@@ -2108,6 +2108,15 @@
bool HasTrailingLParen);
virtual OwningExprResult
+ ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceRange TypeRange,
+ TypeTy *Type,
+ const CXXScopeSpec &SS,
+ bool HasTrailingLParen);
+
+ virtual OwningExprResult
ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=84545&r1=84544&r2=84545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Oct 19 17:04:39 2009
@@ -2099,6 +2099,8 @@
ClassName);
else {
TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS);
+
+ // FIXME: If Base is dependent, we might not be able to resolve it here.
if (!BaseTy) {
Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
<< ClassName;
@@ -2108,25 +2110,41 @@
BaseType = GetTypeFromParser(BaseTy);
}
- CanQualType CanBaseType = Context.getCanonicalType(BaseType);
- DeclarationName DtorName =
- Context.DeclarationNames.getCXXDestructorName(CanBaseType);
+ return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind,
+ SourceRange(ClassNameLoc),
+ BaseType.getAsOpaquePtr(),
+ SS, HasTrailingLParen);
+}
+Sema::OwningExprResult
+Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceRange TypeRange,
+ TypeTy *T,
+ const CXXScopeSpec &SS,
+ bool HasTrailingLParen) {
+ QualType Type = QualType::getFromOpaquePtr(T);
+ CanQualType CanType = Context.getCanonicalType(Type);
+ DeclarationName DtorName =
+ Context.DeclarationNames.getCXXDestructorName(CanType);
+
OwningExprResult Result
- = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
- DtorName, DeclPtrTy(), &SS);
+ = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
+ TypeRange.getBegin(), DtorName, DeclPtrTy(),
+ &SS);
if (Result.isInvalid() || HasTrailingLParen)
return move(Result);
-
+
// The only way a reference to a destructor can be used is to
// immediately call them. Since the next token is not a '(', produce a
// diagnostic and build the call now.
Expr *E = (Expr *)Result.get();
- SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(E->getLocEnd());
+ SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());
Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
<< isa<CXXPseudoDestructorExpr>(E)
<< CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
-
+
return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=84545&r1=84544&r2=84545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct 19 17:04:39 2009
@@ -253,7 +253,8 @@
/// Identifiers and selectors are returned unmodified. Sublcasses may
/// override this function to provide alternate behavior.
DeclarationName TransformDeclarationName(DeclarationName Name,
- SourceLocation Loc);
+ SourceLocation Loc,
+ QualType ObjectType = QualType());
/// \brief Transform the given template name.
///
@@ -276,6 +277,10 @@
QualType Transform##CLASS##Type(const CLASS##Type *T);
#include "clang/AST/TypeNodes.def"
+ QualType
+ TransformTemplateSpecializationType(const TemplateSpecializationType *T,
+ QualType ObjectType);
+
OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
#define STMT(Node, Parent) \
@@ -1734,7 +1739,8 @@
template<typename Derived>
DeclarationName
TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc,
+ QualType ObjectType) {
if (!Name)
return Name;
@@ -1751,7 +1757,14 @@
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
TemporaryBase Rebase(*this, Loc, Name);
- QualType T = getDerived().TransformType(Name.getCXXNameType());
+ 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());
if (T.isNull())
return DeclarationName();
@@ -1814,7 +1827,8 @@
return TemplateName();
if (!getDerived().AlwaysRebuild() &&
- NNS == DTN->getQualifier())
+ NNS == DTN->getQualifier() &&
+ ObjectType.isNull())
return Name;
return getDerived().RebuildTemplateName(NNS, *DTN->getName(), ObjectType);
@@ -2336,10 +2350,18 @@
}
template<typename Derived>
+inline QualType
+TreeTransform<Derived>::TransformTemplateSpecializationType(
+ const TemplateSpecializationType *T) {
+ return TransformTemplateSpecializationType(T, QualType());
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
- const TemplateSpecializationType *T) {
+ const TemplateSpecializationType *T,
+ QualType ObjectType) {
TemplateName Template
- = getDerived().TransformTemplateName(T->getTemplateName());
+ = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);
if (Template.isNull())
return QualType();
@@ -4186,7 +4208,7 @@
// refer to a built-in type!).
NamedDecl *FirstQualifierInScope
= cast_or_null<NamedDecl>(
- getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
+ getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
@@ -4199,7 +4221,8 @@
}
DeclarationName Name
- = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc());
+ = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc(),
+ QualType::getFromOpaquePtr(ObjectType));
if (!Name)
return SemaRef.ExprError();
Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=84545&r1=84544&r2=84545&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Mon Oct 19 17:04:39 2009
@@ -28,3 +28,26 @@
// int &ir = f1<X>(xd);
}
+// PR5213
+template <class T>
+struct A {};
+
+template<class T>
+class B
+{
+ A<T> a_;
+
+public:
+ void destroy();
+};
+
+template<class T>
+void
+B<T>::destroy()
+{
+ a_.~A<T>();
+}
+
+void do_destroy_B(B<int> b) {
+ b.destroy();
+}
More information about the cfe-commits
mailing list