[cfe-commits] r97092 - in /cfe/trunk: include/clang/AST/ExprCXX.h lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/TreeTransform.h test/SemaTemplate/destructor-template.cpp test/SemaTemplate/member-access-expr.cpp
Douglas Gregor
dgregor at apple.com
Wed Feb 24 17:56:36 PST 2010
Author: dgregor
Date: Wed Feb 24 19:56:36 2010
New Revision: 97092
URL: http://llvm.org/viewvc/llvm-project?rev=97092&view=rev
Log:
Use CXXPseudoDestructorExpr as the stored representation for dependent
expressions that look like pseudo-destructors, e.g.,
p->T::~T()
where p has dependent type.
At template instantiate time, we determine whether we actually have a
pseudo-destructor or a member access, and funnel down to the
appropriate routine in Sema.
Fixes PR6380.
Modified:
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/destructor-template.cpp
cfe/trunk/test/SemaTemplate/member-access-expr.cpp
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Feb 24 19:56:36 2010
@@ -997,6 +997,35 @@
virtual child_iterator child_end();
};
+/// \brief Structure used to store the type being destroyed by a
+/// pseudo-destructor expression.
+class PseudoDestructorTypeStorage {
+ /// \brief Either the type source information or the name of the type, if
+ /// it couldn't be resolved due to type-dependence.
+ llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;
+
+ /// \brief The starting source location of the pseudo-destructor type.
+ SourceLocation Location;
+
+public:
+ PseudoDestructorTypeStorage() { }
+
+ PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
+ : Type(II), Location(Loc) { }
+
+ PseudoDestructorTypeStorage(TypeSourceInfo *Info);
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return Type.dyn_cast<TypeSourceInfo *>();
+ }
+
+ IdentifierInfo *getIdentifier() const {
+ return Type.dyn_cast<IdentifierInfo *>();
+ }
+
+ SourceLocation getLocation() const { return Location; }
+};
+
/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
///
/// A pseudo-destructor is an expression that looks like a member access to a
@@ -1050,8 +1079,9 @@
/// \brief The location of the '~'.
SourceLocation TildeLoc;
- /// \brief The type being destroyed.
- TypeSourceInfo *DestroyedType;
+ /// \brief The type being destroyed, or its name if we were unable to
+ /// resolve the name.
+ PseudoDestructorTypeStorage DestroyedType;
public:
CXXPseudoDestructorExpr(ASTContext &Context,
@@ -1061,14 +1091,15 @@
TypeSourceInfo *ScopeType,
SourceLocation ColonColonLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType)
+ PseudoDestructorTypeStorage DestroyedType)
: Expr(CXXPseudoDestructorExprClass,
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
false, 0, false,
false, 0, 0, false,
CC_Default)),
/*isTypeDependent=*/(Base->isTypeDependent() ||
- DestroyedType->getType()->isDependentType()),
+ (DestroyedType.getTypeSourceInfo() &&
+ DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
/*isValueDependent=*/Base->isValueDependent()),
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
OperatorLoc(OperatorLoc), Qualifier(Qualifier),
@@ -1120,12 +1151,31 @@
/// \brief Retrieve the location of the '~'.
SourceLocation getTildeLoc() const { return TildeLoc; }
- /// \brief Retrieve the type that is being destroyed.
- QualType getDestroyedType() const { return DestroyedType->getType(); }
-
/// \brief Retrieve the source location information for the type
/// being destroyed.
- TypeSourceInfo *getDestroyedTypeInfo() const { return DestroyedType; }
+ ///
+ /// This type-source information is available for non-dependent
+ /// pseudo-destructor expressions and some dependent pseudo-destructor
+ /// expressions. Returns NULL if we only have the identifier for a
+ /// dependent pseudo-destructor expression.
+ TypeSourceInfo *getDestroyedTypeInfo() const {
+ return DestroyedType.getTypeSourceInfo();
+ }
+
+ /// \brief In a dependent pseudo-destructor expression for which we do not
+ /// have full type information on the destroyed type, provides the name
+ /// of the destroyed type.
+ IdentifierInfo *getDestroyedTypeIdentifier() const {
+ return DestroyedType.getIdentifier();
+ }
+
+ /// \brief Retrieve the type being destroyed.
+ QualType getDestroyedType() const;
+
+ /// \brief Retrieve the starting location of the type being destroyed.
+ SourceLocation getDestroyedTypeLoc() const {
+ return DestroyedType.getLocation();
+ }
virtual SourceRange getSourceRange() const;
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Feb 24 19:56:36 2010
@@ -122,9 +122,24 @@
return &Base + 1;
}
+PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
+ : Type(Info)
+{
+ Location = Info->getTypeLoc().getSourceRange().getBegin();
+}
+
+QualType CXXPseudoDestructorExpr::getDestroyedType() const {
+ if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+ return TInfo->getType();
+
+ return QualType();
+}
+
SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
- return SourceRange(Base->getLocStart(),
- DestroyedType->getTypeLoc().getSourceRange().getEnd());
+ SourceLocation End = DestroyedType.getLocation();
+ if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+ End = TInfo->getTypeLoc().getSourceRange().getEnd();
+ return SourceRange(Base->getLocStart(), End);
}
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Feb 24 19:56:36 2010
@@ -1120,7 +1120,10 @@
E->getQualifier()->print(OS, Policy);
std::string TypeS;
- E->getDestroyedType().getAsStringInternal(TypeS, Policy);
+ if (IdentifierInfo *II = E->getDestroyedTypeIdentifier())
+ OS << II->getName();
+ else
+ E->getDestroyedType().getAsStringInternal(TypeS, Policy);
OS << TypeS;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 24 19:56:36 2010
@@ -95,6 +95,7 @@
class ObjCMethodDecl;
class ObjCPropertyDecl;
class ObjCContainerDecl;
+ class PseudoDestructorTypeStorage;
class FunctionProtoType;
class CXXBasePath;
class CXXBasePaths;
@@ -2188,20 +2189,9 @@
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType,
+ PseudoDestructorTypeStorage DestroyedType,
bool HasTrailingLParen);
-
- OwningExprResult ActOnDependentPseudoDestructorExpr(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen);
-
+
virtual OwningExprResult ActOnPseudoDestructorExpr(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=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 24 19:56:36 2010
@@ -161,7 +161,7 @@
Found.clear();
if (Step == 0 && LookupCtx)
LookupQualifiedName(Found, LookupCtx);
- else if (Step == 1 && LookInScope)
+ else if (Step == 1 && LookInScope && S)
LookupName(Found, S);
else
continue;
@@ -2441,9 +2441,9 @@
TypeSourceInfo *ScopeTypeInfo,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestructedTypeInfo,
+ PseudoDestructorTypeStorage Destructed,
bool HasTrailingLParen) {
- assert(DestructedTypeInfo && "No destructed type in pseudo-destructor expr?");
+ TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
// C++ [expr.pseudo]p2:
// The left-hand side of the dot operator shall be of scalar type. The
@@ -2475,21 +2475,24 @@
// C++ [expr.pseudo]p2:
// [...] The cv-unqualified versions of the object type and of the type
// designated by the pseudo-destructor-name shall be the same type.
- QualType DestructedType = DestructedTypeInfo->getType();
- SourceLocation DestructedTypeStart
- = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
- if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
- !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
- Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
- << ObjectType << DestructedType << BaseE->getSourceRange()
- << DestructedTypeInfo->getTypeLoc().getSourceRange();
-
- // Recover by
- DestructedType = ObjectType;
- DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
- DestructedTypeStart);
+ if (DestructedTypeInfo) {
+ QualType DestructedType = DestructedTypeInfo->getType();
+ SourceLocation DestructedTypeStart
+ = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
+ if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
+ Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
+ << ObjectType << DestructedType << BaseE->getSourceRange()
+ << DestructedTypeInfo->getTypeLoc().getSourceRange();
+
+ // Recover by setting the destructed type to the object type.
+ DestructedType = ObjectType;
+ DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
+ DestructedTypeStart);
+ Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+ }
}
-
+
// C++ [expr.pseudo]p2:
// [...] Furthermore, the two type-names in a pseudo-destructor-name of the
// form
@@ -2522,148 +2525,12 @@
ScopeTypeInfo,
CCLoc,
TildeLoc,
- DestructedTypeInfo));
+ Destructed));
+
if (HasTrailingLParen)
return move(Result);
- return DiagnoseDtorReference(
- DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin(),
- move(Result));
-}
-
-Sema::OwningExprResult
-Sema::ActOnDependentPseudoDestructorExpr(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
- Expr *BaseE = (Expr *)Base.get();
- QualType ObjectType = BaseE->getType();
- assert(ObjectType->isDependentType());
-
- // 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);
-
+ return DiagnoseDtorReference(Destructed.getLocation(), move(Result));
}
Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
@@ -2683,11 +2550,6 @@
"Invalid second type name in pseudo-destructor");
Expr *BaseE = (Expr *)Base.get();
- if (BaseE->isTypeDependent())
- return ActOnDependentPseudoDestructorExpr(S, move(Base), OpLoc, OpKind,
- SS, FirstTypeName, CCLoc,
- TildeLoc, SecondTypeName,
- HasTrailingLParen);
// C++ [expr.pseudo]p2:
// The left-hand side of the dot operator shall be of scalar type. The
@@ -2697,27 +2559,46 @@
if (OpKind == tok::arrow) {
if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
ObjectType = Ptr->getPointeeType();
- } else if (!BaseE->isTypeDependent()) {
+ } else if (!ObjectType->isDependentType()) {
// The user wrote "p->" when she probably meant "p."; fix it.
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << ObjectType << true
- << CodeModificationHint::CreateReplacement(OpLoc, ".");
+ << ObjectType << true
+ << CodeModificationHint::CreateReplacement(OpLoc, ".");
if (isSFINAEContext())
return ExprError();
OpKind = tok::period;
}
}
+
+ // Compute the object type that we should use for name lookup purposes. Only
+ // record types and dependent types matter.
+ void *ObjectTypePtrForLookup = 0;
+ if (!SS.isSet()) {
+ ObjectTypePtrForLookup = (void *)ObjectType->getAs<RecordType>();
+ if (!ObjectTypePtrForLookup && ObjectType->isDependentType())
+ ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr();
+ }
// Convert the name of the type being destructed (following the ~) into a
// type (with source-location information).
QualType DestructedType;
TypeSourceInfo *DestructedTypeInfo = 0;
+ PseudoDestructorTypeStorage Destructed;
if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
TypeTy *T = getTypeName(*SecondTypeName.Identifier,
SecondTypeName.StartLocation,
- S, &SS);
- if (!T) {
+ S, &SS, true, ObjectTypePtrForLookup);
+ if (!T &&
+ ((SS.isSet() && !computeDeclContext(SS, false)) ||
+ (!SS.isSet() && ObjectType->isDependentType()))) {
+ // The name of the type being destroyed is a dependent name, and we
+ // couldn't find anything useful in scope. Just store the identifier and
+ // it's location, and we'll perform (qualified) name lookup again at
+ // template instantiation time.
+ Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier,
+ SecondTypeName.StartLocation);
+ } else if (!T) {
Diag(SecondTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
<< SecondTypeName.Identifier << ObjectType;
@@ -2748,9 +2629,12 @@
// If we've performed some kind of recovery, (re-)build the type source
// information.
- if (!DestructedTypeInfo)
- DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
+ if (!DestructedType.isNull()) {
+ if (!DestructedTypeInfo)
+ DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
SecondTypeName.StartLocation);
+ Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+ }
// Convert the name of the scope type (the type prior to '::') into a type.
TypeSourceInfo *ScopeTypeInfo = 0;
@@ -2760,7 +2644,7 @@
if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
TypeTy *T = getTypeName(*FirstTypeName.Identifier,
FirstTypeName.StartLocation,
- S, &SS);
+ S, &SS, false, ObjectTypePtrForLookup);
if (!T) {
Diag(FirstTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
@@ -2799,7 +2683,7 @@
return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS,
ScopeTypeInfo, CCLoc, TildeLoc,
- DestructedTypeInfo, HasTrailingLParen);
+ Destructed, HasTrailingLParen);
}
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Feb 24 19:56:36 2010
@@ -884,12 +884,12 @@
OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
SourceLocation OperatorLoc,
bool isArrow,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType);
+ PseudoDestructorTypeStorage Destroyed);
/// \brief Build a new unary operator expression.
///
@@ -4671,34 +4671,67 @@
if (Base.isInvalid())
return SemaRef.ExprError();
+ Sema::TypeTy *ObjectTypePtr = 0;
+ bool MayBePseudoDestructor = false;
+ Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
+ E->getOperatorLoc(),
+ E->isArrow()? tok::arrow : tok::period,
+ ObjectTypePtr,
+ MayBePseudoDestructor);
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
NestedNameSpecifier *Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
- true);
+ true,
+ ObjectType);
if (E->getQualifier() && !Qualifier)
return SemaRef.ExprError();
- // FIXME: Object type!
- TypeSourceInfo *DestroyedTypeInfo
- = getDerived().TransformType(E->getDestroyedTypeInfo());
- if (!DestroyedTypeInfo)
- return SemaRef.ExprError();
+ PseudoDestructorTypeStorage Destroyed;
+ if (E->getDestroyedTypeInfo()) {
+ TypeSourceInfo *DestroyedTypeInfo
+ = getDerived().TransformType(E->getDestroyedTypeInfo(), ObjectType);
+ if (!DestroyedTypeInfo)
+ return SemaRef.ExprError();
+ Destroyed = DestroyedTypeInfo;
+ } else if (ObjectType->isDependentType()) {
+ // We aren't likely to be able to resolve the identifier down to a type
+ // now anyway, so just retain the identifier.
+ Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(),
+ E->getDestroyedTypeLoc());
+ } else {
+ // Look for a destructor known with the given name.
+ CXXScopeSpec SS;
+ if (Qualifier) {
+ SS.setScopeRep(Qualifier);
+ SS.setRange(E->getQualifierRange());
+ }
+
+ Sema::TypeTy *T = SemaRef.getDestructorName(E->getTildeLoc(),
+ *E->getDestroyedTypeIdentifier(),
+ E->getDestroyedTypeLoc(),
+ /*Scope=*/0,
+ SS, ObjectTypePtr,
+ false);
+ if (!T)
+ return SemaRef.ExprError();
+
+ Destroyed
+ = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T),
+ E->getDestroyedTypeLoc());
+ }
- // FIXME: Object type!
TypeSourceInfo *ScopeTypeInfo = 0;
if (E->getScopeTypeInfo()) {
- ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
+ ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo(),
+ ObjectType);
if (!ScopeTypeInfo)
return SemaRef.ExprError();
}
- if (!getDerived().AlwaysRebuild() &&
- Base.get() == E->getBase() &&
- Qualifier == E->getQualifier() &&
- ScopeTypeInfo == E->getScopeTypeInfo() &&
- DestroyedTypeInfo == E->getDestroyedTypeInfo())
- return SemaRef.Owned(E->Retain());
-
return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
E->getOperatorLoc(),
E->isArrow(),
@@ -4707,7 +4740,7 @@
ScopeTypeInfo,
E->getColonColonLoc(),
E->getTildeLoc(),
- DestroyedTypeInfo);
+ Destroyed);
}
template<typename Derived>
@@ -5758,7 +5791,7 @@
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType) {
+ PseudoDestructorTypeStorage Destroyed) {
CXXScopeSpec SS;
if (Qualifier) {
SS.setRange(QualifierRange);
@@ -5767,18 +5800,19 @@
Expr *BaseE = (Expr *)Base.get();
QualType BaseType = BaseE->getType();
- if (BaseE->isTypeDependent() ||
+ if (BaseE->isTypeDependent() || Destroyed.getIdentifier() ||
(!isArrow && !BaseType->getAs<RecordType>()) ||
(isArrow && BaseType->getAs<PointerType>() &&
- !BaseType->getAs<PointerType>()->getAs<RecordType>())) {
+ !BaseType->getAs<PointerType>()->getPointeeType()->getAs<RecordType>())){
// This pseudo-destructor expression is still a pseudo-destructor.
return SemaRef.BuildPseudoDestructorExpr(move(Base), OperatorLoc,
isArrow? tok::arrow : tok::period,
SS, ScopeType, CCLoc, TildeLoc,
- DestroyedType,
+ Destroyed,
/*FIXME?*/true);
}
+ TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
DeclarationName Name
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(DestroyedType->getType()));
@@ -5788,8 +5822,7 @@
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
OperatorLoc, isArrow,
SS, /*FIXME: FirstQualifier*/ 0,
- Name,
- DestroyedType->getTypeLoc().getSourceRange().getBegin(),
+ Name, Destroyed.getLocation(),
/*TemplateArgs*/ 0);
}
Modified: cfe/trunk/test/SemaTemplate/destructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/destructor-template.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/destructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/destructor-template.cpp Wed Feb 24 19:56:36 2010
@@ -25,6 +25,8 @@
void X<T>::f() {
Y<T> *y;
y->template Y<T>::~Y();
+ y->template Y<T>::~Y<T>();
+ y->~Y();
}
template struct X<int>;
Modified: cfe/trunk/test/SemaTemplate/member-access-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-access-expr.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/member-access-expr.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-access-expr.cpp Wed Feb 24 19:56:36 2010
@@ -63,11 +63,13 @@
template<typename T>
void destruct(T* ptr) {
ptr->~T();
+ ptr->T::~T();
}
template<typename T>
void destruct_intptr(int *ip) {
ip->~T();
+ ip->T::~T();
}
void test_destruct(X2 *x2p, int *ip) {
More information about the cfe-commits
mailing list