[cfe-commits] r97045 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/TreeTransform.h
Douglas Gregor
dgregor at apple.com
Wed Feb 24 10:44:31 PST 2010
Author: dgregor
Date: Wed Feb 24 12:44:31 2010
New Revision: 97045
URL: http://llvm.org/viewvc/llvm-project?rev=97045&view=rev
Log:
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/TreeTransform.h
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Feb 24 12:44:31 2010
@@ -1614,12 +1614,66 @@
/// with the type into which name lookup should look to find the member in
/// the member access expression.
///
+ /// \param MayBePseudoDestructor Originally false. The action should
+ /// set this true if the expression may end up being a
+ /// pseudo-destructor expression, indicating to the parser that it
+ /// shoudl be parsed as a pseudo-destructor rather than as a member
+ /// access expression. Note that this should apply both when the
+ /// object type is a scalar and when the object type is dependent.
+ ///
/// \returns the (possibly modified) \p Base expression
virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S,
ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
- TypeTy *&ObjectType) {
+ TypeTy *&ObjectType,
+ bool &MayBePseudoDestructor) {
+ return ExprEmpty();
+ }
+
+ /// \brief Parsed a C++ pseudo-destructor expression or a dependent
+ /// member access expression that has the same syntactic form as a
+ /// pseudo-destructor expression.
+ ///
+ /// \param S The scope in which the member access expression occurs.
+ ///
+ /// \param Base The expression in which a member is being accessed, e.g., the
+ /// "x" in "x.f".
+ ///
+ /// \param OpLoc The location of the member access operator ("." or "->")
+ ///
+ /// \param OpKind The kind of member access operator ("." or "->")
+ ///
+ /// \param SS The nested-name-specifier that precedes the type names
+ /// in the grammar. Note that this nested-name-specifier will not
+ /// cover the last "type-name ::" in the grammar, because it isn't
+ /// necessarily a nested-name-specifier.
+ ///
+ /// \param FirstTypeName The type name that follows the optional
+ /// nested-name-specifier but precedes the '::', e.g., the first
+ /// type-name in "type-name :: type-name". This type name may be
+ /// empty. This will be either an identifier or a template-id.
+ ///
+ /// \param CCLoc The location of the '::' in "type-name ::
+ /// typename". May be invalid, if there is no \p FirstTypeName.
+ ///
+ /// \param TildeLoc The location of the '~'.
+ ///
+ /// \param SecondTypeName The type-name following the '~', which is
+ /// the name of the type being destroyed. This will be either an
+ /// identifier or a template-id.
+ ///
+ /// \param HasTrailingLParen Whether the next token in the stream is
+ /// a left parentheses.
+ virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen) {
return ExprEmpty();
}
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Feb 24 12:44:31 2010
@@ -964,7 +964,7 @@
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TypeTy *ObjectType,
bool EnteringContext,
- bool InMemberAccessExpr = false);
+ bool *MayBePseudoDestructor = 0);
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
@@ -975,6 +975,13 @@
OwningExprResult ParseCXXTypeid();
//===--------------------------------------------------------------------===//
+ // C++ 5.2.4: C++ Pseudo-Destructor Expressions
+ OwningExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ Action::TypeTy *ObjectType);
+
+ //===--------------------------------------------------------------------===//
// C++ 9.3.2: C++ 'this' pointer
OwningExprResult ParseCXXThis();
@@ -1415,7 +1422,8 @@
SourceLocation NameLoc,
bool EnteringContext,
TypeTy *ObjectType,
- UnqualifiedId &Id);
+ UnqualifiedId &Id,
+ bool AssumeTemplateId = false);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
TypeTy *ObjectType,
UnqualifiedId &Result);
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Feb 24 12:44:31 2010
@@ -996,12 +996,16 @@
CXXScopeSpec SS;
Action::TypeTy *ObjectType = 0;
+ bool MayBePseudoDestructor = false;
if (getLang().CPlusPlus && !LHS.isInvalid()) {
LHS = Actions.ActOnStartCXXMemberReference(CurScope, move(LHS),
- OpLoc, OpKind, ObjectType);
+ OpLoc, OpKind, ObjectType,
+ MayBePseudoDestructor);
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType, false, true);
+
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
+ &MayBePseudoDestructor);
}
if (Tok.is(tok::code_completion)) {
@@ -1012,6 +1016,17 @@
ConsumeToken();
}
+ if (MayBePseudoDestructor) {
+ LHS = ParseCXXPseudoDestructor(move(LHS), OpLoc, OpKind, SS,
+ ObjectType);
+ break;
+ }
+
+ // Either the action has told is that this cannot be a
+ // pseudo-destructor expression (based on the type of base
+ // expression), or we didn't see a '~' in the right place. We
+ // can still parse a destructor name here, but in that case it
+ // names a real destructor.
UnqualifiedId Name;
if (ParseUnqualifiedId(SS,
/*EnteringContext=*/false,
@@ -1022,10 +1037,9 @@
return ExprError();
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
- SS, Name, ObjCImpDecl,
+ LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc,
+ OpKind, SS, Name, ObjCImpDecl,
Tok.is(tok::l_paren));
-
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Feb 24 12:44:31 2010
@@ -45,14 +45,21 @@
/// \param EnteringContext whether we will be entering into the context of
/// the nested-name-specifier after parsing it.
///
-/// \param InMemberAccessExpr Whether this scope specifier is within a
+/// \param MayBePseudoDestructor When non-NULL, points to a flag that
+/// indicates whether this nested-name-specifier may be part of a
+/// pseudo-destructor name. In this case, the flag will be set false
+/// if we don't actually end up parsing a destructor name. Moreorover,
+/// if we do end up determining that we are parsing a destructor name,
+/// the last component of the nested-name-specifier is not parsed as
+/// part of the scope specifier.
+
/// member access expression, e.g., the \p T:: in \p p->T::m.
///
/// \returns true if a scope specifier was parsed.
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Action::TypeTy *ObjectType,
bool EnteringContext,
- bool InMemberAccessExpr) {
+ bool *MayBePseudoDestructor) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -79,6 +86,12 @@
HasScopeSpecifier = true;
}
+ bool CheckForDestructor = false;
+ if (MayBePseudoDestructor && *MayBePseudoDestructor) {
+ CheckForDestructor = true;
+ *MayBePseudoDestructor = false;
+ }
+
while (true) {
if (HasScopeSpecifier) {
// C++ [basic.lookup.classref]p5:
@@ -173,8 +186,11 @@
// convert it into a type within the nested-name-specifier.
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- bool MayBePseudoDestructor
- = InMemberAccessExpr && GetLookAheadToken(2).is(tok::tilde);
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
+ *MayBePseudoDestructor = true;
+ return HasScopeSpecifier;
+ }
+
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
AnnotateTemplateIdTokenAsType(&SS);
@@ -197,7 +213,7 @@
TypeToken.getAnnotationValue(),
TypeToken.getAnnotationRange(),
CCLoc,
- MayBePseudoDestructor));
+ false));
else
SS.setScopeRep(0);
SS.setEndLoc(CCLoc);
@@ -224,11 +240,13 @@
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
// and emit a fixit hint for it.
if (Next.is(tok::colon) && !ColonIsSacred) {
- bool MayBePseudoDestructor
- = InMemberAccessExpr && GetLookAheadToken(2).is(tok::tilde);
-
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
+ *MayBePseudoDestructor = true;
+ return HasScopeSpecifier;
+ }
+
if (Actions.IsInvalidUnlessNestedName(CurScope, SS, II,
- MayBePseudoDestructor, ObjectType,
+ false, ObjectType,
EnteringContext) &&
// If the token after the colon isn't an identifier, it's still an
// error, but they probably meant something else strange so don't
@@ -243,6 +261,11 @@
}
if (Next.is(tok::coloncolon)) {
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
+ *MayBePseudoDestructor = true;
+ return HasScopeSpecifier;
+ }
+
// We have an identifier followed by a '::'. Lookup this name
// as the name in a nested-name-specifier.
SourceLocation IdLoc = ConsumeToken();
@@ -258,11 +281,9 @@
if (SS.isInvalid())
continue;
- bool MayBePseudoDestructor = InMemberAccessExpr && Tok.is(tok::tilde);
-
SS.setScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
- MayBePseudoDestructor, ObjectType,
+ false, ObjectType,
EnteringContext));
SS.setEndLoc(CCLoc);
continue;
@@ -298,6 +319,12 @@
break;
}
+ // Even if we didn't see any pieces of a nested-name-specifier, we
+ // still check whether there is a tilde in this position, which
+ // indicates a potential pseudo-destructor.
+ if (CheckForDestructor && Tok.is(tok::tilde))
+ *MayBePseudoDestructor = true;
+
return HasScopeSpecifier;
}
@@ -493,6 +520,77 @@
return move(Result);
}
+/// \brief Parse a C++ pseudo-destructor expression after the base,
+/// . or -> operator, and nested-name-specifier have already been
+/// parsed.
+///
+/// postfix-expression: [C++ 5.2]
+/// postfix-expression . pseudo-destructor-name
+/// postfix-expression -> pseudo-destructor-name
+///
+/// pseudo-destructor-name:
+/// ::[opt] nested-name-specifier[opt] type-name :: ~type-name
+/// ::[opt] nested-name-specifier template simple-template-id ::
+/// ~type-name
+/// ::[opt] nested-name-specifier[opt] ~type-name
+///
+Parser::OwningExprResult
+Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ Action::TypeTy *ObjectType) {
+ // We're parsing either a pseudo-destructor-name or a dependent
+ // member access that has the same form as a
+ // pseudo-destructor-name. We parse both in the same way and let
+ // the action model sort them out.
+ //
+ // Note that the ::[opt] nested-name-specifier[opt] has already
+ // been parsed, and if there was a simple-template-id, it has
+ // been coalesced into a template-id annotation token.
+ UnqualifiedId FirstTypeName;
+ SourceLocation CCLoc;
+ if (Tok.is(tok::identifier)) {
+ FirstTypeName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
+ CCLoc = ConsumeToken();
+ } else if (Tok.is(tok::annot_template_id)) {
+ FirstTypeName.setTemplateId(
+ (TemplateIdAnnotation *)Tok.getAnnotationValue());
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
+ CCLoc = ConsumeToken();
+ } else {
+ FirstTypeName.setIdentifier(0, SourceLocation());
+ }
+
+ // Parse the tilde.
+ assert(Tok.is(tok::tilde) && "ParseOptionalCXXScopeSpecifier fail");
+ SourceLocation TildeLoc = ConsumeToken();
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_destructor_tilde_identifier);
+ return ExprError();
+ }
+
+ // Parse the second type.
+ UnqualifiedId SecondTypeName;
+ IdentifierInfo *Name = Tok.getIdentifierInfo();
+ SourceLocation NameLoc = ConsumeToken();
+ SecondTypeName.setIdentifier(Name, NameLoc);
+
+ // If there is a '<', the second type name is a template-id. Parse
+ // it as such.
+ if (Tok.is(tok::less) &&
+ ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType,
+ SecondTypeName, /*AssumeTemplateName=*/true))
+ return ExprError();
+
+ return Actions.ActOnPseudoDestructorExpr(CurScope, move(Base), OpLoc, OpKind,
+ SS, FirstTypeName, CCLoc,
+ TildeLoc, SecondTypeName,
+ Tok.is(tok::l_paren));
+}
+
/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
///
/// boolean-literal: [C++ 2.13.5]
@@ -818,13 +916,17 @@
/// that precedes the '<'. If template arguments were parsed successfully,
/// will be updated with the template-id.
///
+/// \param AssumeTemplateId When true, this routine will assume that the name
+/// refers to a template without performing name lookup to verify.
+///
/// \returns true if a parse error occurred, false otherwise.
bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
TypeTy *ObjectType,
- UnqualifiedId &Id) {
+ UnqualifiedId &Id,
+ bool AssumeTemplateId) {
assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
TemplateTy Template;
@@ -833,8 +935,16 @@
case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
- TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext,
- Template);
+ if (AssumeTemplateId) {
+ Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
+ Id, ObjectType,
+ EnteringContext);
+ TNK = TNK_Dependent_template_name;
+ if (!Template.get())
+ return true;
+ } else
+ TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType,
+ EnteringContext, Template);
break;
case UnqualifiedId::IK_ConstructorName: {
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 24 12:44:31 2010
@@ -2175,7 +2175,18 @@
ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
- TypeTy *&ObjectType);
+ TypeTy *&ObjectType,
+ bool &MayBePseudoDestructor);
+
+ virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen);
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 24 12:44:31 2010
@@ -21,6 +21,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
@@ -2325,7 +2326,8 @@
Sema::OwningExprResult
Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, TypeTy *&ObjectType) {
+ tok::TokenKind OpKind, TypeTy *&ObjectType,
+ bool &MayBePseudoDestructor) {
// Since this might be a postfix expression, get rid of ParenListExprs.
Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
@@ -2333,6 +2335,7 @@
assert(BaseExpr && "no record expansion");
QualType BaseType = BaseExpr->getType();
+ MayBePseudoDestructor = false;
if (BaseType->isDependentType()) {
// If we have a pointer to a dependent type and are using the -> operator,
// the object type is the type that the pointer points to. We might still
@@ -2342,6 +2345,7 @@
BaseType = Ptr->getPointeeType();
ObjectType = BaseType.getAsOpaquePtr();
+ MayBePseudoDestructor = true;
return move(Base);
}
@@ -2383,7 +2387,11 @@
// [...] If the type of the object expression is of pointer to scalar
// type, the unqualified-id is looked up in the context of the complete
// postfix-expression.
+ //
+ // This also indicates that we should be parsing a
+ // pseudo-destructor-name.
ObjectType = 0;
+ MayBePseudoDestructor = true;
return move(Base);
}
@@ -2399,10 +2407,149 @@
// type C (or of pointer to a class type C), the unqualified-id is looked
// up in the scope of class C. [...]
ObjectType = BaseType.getAsOpaquePtr();
-
return move(Base);
}
+Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen) {
+ assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ "Invalid first type name in pseudo-destructor");
+ assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ "Invalid second type name in pseudo-destructor");
+
+ Expr *BaseE = (Expr *)Base.get();
+ QualType ObjectType;
+ if (BaseE->isTypeDependent())
+ ObjectType = Context.DependentTy;
+
+ // The nested-name-specifier provided by the parser, then extended
+ // by the "type-name ::" in the pseudo-destructor-name, if present.
+ CXXScopeSpec ExtendedSS = SS;
+
+ if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ FirstTypeName.Identifier) {
+ // We have a pseudo-destructor with a "type-name ::".
+ // FIXME: As a temporary hack, we go ahead and resolve this to part of
+ // a nested-name-specifier.
+ if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ // Resolve the identifier to a nested-name-specifier.
+ CXXScopeTy *FinalScope
+ = ActOnCXXNestedNameSpecifier(S, SS,
+ FirstTypeName.StartLocation,
+ CCLoc,
+ *FirstTypeName.Identifier,
+ true,
+ ObjectType.getAsOpaquePtr(),
+ false);
+ if (SS.getBeginLoc().isInvalid())
+ ExtendedSS.setBeginLoc(FirstTypeName.StartLocation);
+ ExtendedSS.setEndLoc(CCLoc);
+ ExtendedSS.setScopeRep(FinalScope);
+ } else {
+ // Resolve the template-id to a type, and that to a
+ // nested-name-specifier.
+ TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc);
+ if (!T.isInvalid()) {
+ CXXScopeTy *FinalScope
+ = ActOnCXXNestedNameSpecifier(S, SS, T.get(),
+ SourceRange(TemplateId->TemplateNameLoc,
+ TemplateId->RAngleLoc),
+ CCLoc,
+ true);
+ if (SS.getBeginLoc().isInvalid())
+ ExtendedSS.setBeginLoc(TemplateId->TemplateNameLoc);
+ ExtendedSS.setEndLoc(CCLoc);
+ ExtendedSS.setScopeRep(FinalScope);
+ }
+ }
+ }
+
+ // Produce a destructor name based on the second type-name (which
+ // follows the tilde).
+ TypeTy *DestructedType;
+ SourceLocation EndLoc;
+ if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ const CXXScopeSpec *LookupSS = &SS;
+ bool isDependent = isDependentScopeSpecifier(ExtendedSS);
+ if (isDependent || computeDeclContext(ExtendedSS))
+ LookupSS = &ExtendedSS;
+
+ DestructedType = getTypeName(*SecondTypeName.Identifier,
+ SecondTypeName.StartLocation,
+ S, LookupSS, true, ObjectType.getTypePtr());
+ if (!DestructedType && isDependent) {
+ // We didn't find our type, but that's okay: it's dependent
+ // anyway.
+ // FIXME: We should not be building a typename type here!
+ NestedNameSpecifier *NNS = 0;
+ SourceRange Range;
+ if (SS.isSet()) {
+ NNS = (NestedNameSpecifier *)ExtendedSS.getScopeRep();
+ Range = SourceRange(ExtendedSS.getRange().getBegin(),
+ SecondTypeName.StartLocation);
+ } else {
+ NNS = NestedNameSpecifier::Create(Context, SecondTypeName.Identifier);
+ Range = SourceRange(SecondTypeName.StartLocation);
+ }
+
+ DestructedType = CheckTypenameType(NNS, *SecondTypeName.Identifier,
+ Range).getAsOpaquePtr();
+ if (!DestructedType)
+ return ExprError();
+ }
+
+ if (!DestructedType) {
+ // FIXME: Crummy diagnostic.
+ Diag(SecondTypeName.StartLocation, diag::err_destructor_class_name);
+ return ExprError();
+ }
+
+ EndLoc = SecondTypeName.EndLocation;
+ } else {
+ // Resolve the template-id to a type, and that to a
+ // nested-name-specifier.
+ TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ EndLoc = TemplateId->RAngleLoc;
+ TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc);
+ if (T.isInvalid() || !T.get())
+ return ExprError();
+
+ DestructedType = T.get();
+ }
+
+ // Form a (possibly fake) destructor name and let the member access
+ // expression code deal with this.
+ // FIXME: Don't do this! It's totally broken!
+ UnqualifiedId Destructor;
+ Destructor.setDestructorName(TildeLoc, DestructedType, EndLoc);
+ return ActOnMemberAccessExpr(S, move(Base), OpLoc, OpKind, ExtendedSS,
+ Destructor, DeclPtrTy(), HasTrailingLParen);
+}
+
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
CXXMethodDecl *Method) {
if (PerformObjectArgumentInitialization(Exp, Method))
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=97045&r1=97044&r2=97045&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Feb 24 12:44:31 2010
@@ -5041,10 +5041,12 @@
// Start the member reference and compute the object's type.
Sema::TypeTy *ObjectTy = 0;
+ bool MayBePseudoDestructor = false;
Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
- ObjectTy);
+ ObjectTy,
+ MayBePseudoDestructor);
if (Base.isInvalid())
return SemaRef.ExprError();
More information about the cfe-commits
mailing list