From: Douglas Gregor Date: Thu, 25 Feb 2010 01:56:36 +0000 (+0000) Subject: Use CXXPseudoDestructorExpr as the stored representation for dependent X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2e7dd2f4a50d835351153aee568d35ccc986310;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97092 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 6a06554b60..d1351b8b14 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -997,6 +997,35 @@ public: 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 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(); + } + + IdentifierInfo *getIdentifier() const { + return Type.dyn_cast(); + } + + 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 @@ class CXXPseudoDestructorExpr : public Expr { /// \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 @@ public: 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(Base)), IsArrow(isArrow), OperatorLoc(OperatorLoc), Qualifier(Qualifier), @@ -1120,12 +1151,31 @@ public: /// \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; diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 28d07f1df2..b9a4ee6e4d 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -122,9 +122,24 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() { 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); } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 3ae306d3c7..da43878628 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1120,7 +1120,10 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { 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; } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index abc775e06b..1bc084c5db 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -95,6 +95,7 @@ namespace clang { class ObjCMethodDecl; class ObjCPropertyDecl; class ObjCContainerDecl; + class PseudoDestructorTypeStorage; class FunctionProtoType; class CXXBasePath; class CXXBasePaths; @@ -2188,20 +2189,9 @@ public: 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, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 025f2ad49e..64f2ef204e 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -161,7 +161,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, 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 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, 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 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, // 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 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, 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 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, "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 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, if (OpKind == tok::arrow) { if (const PointerType *Ptr = ObjectType->getAs()) { 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(); + 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 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, // 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 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, 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 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS, ScopeTypeInfo, CCLoc, TildeLoc, - DestructedTypeInfo, HasTrailingLParen); + Destructed, HasTrailingLParen); } CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 922c041393..416f480e57 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -884,12 +884,12 @@ public: 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 @@ TreeTransform::TransformCXXPseudoDestructorExpr( 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 @@ TreeTransform::TransformCXXPseudoDestructorExpr( ScopeTypeInfo, E->getColonColonLoc(), E->getTildeLoc(), - DestroyedTypeInfo); + Destroyed); } template @@ -5758,7 +5791,7 @@ TreeTransform::RebuildCXXPseudoDestructorExpr(ExprArg Base, TypeSourceInfo *ScopeType, SourceLocation CCLoc, SourceLocation TildeLoc, - TypeSourceInfo *DestroyedType) { + PseudoDestructorTypeStorage Destroyed) { CXXScopeSpec SS; if (Qualifier) { SS.setRange(QualifierRange); @@ -5767,18 +5800,19 @@ TreeTransform::RebuildCXXPseudoDestructorExpr(ExprArg Base, Expr *BaseE = (Expr *)Base.get(); QualType BaseType = BaseE->getType(); - if (BaseE->isTypeDependent() || + if (BaseE->isTypeDependent() || Destroyed.getIdentifier() || (!isArrow && !BaseType->getAs()) || (isArrow && BaseType->getAs() && - !BaseType->getAs()->getAs())) { + !BaseType->getAs()->getPointeeType()->getAs())){ // 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 @@ TreeTransform::RebuildCXXPseudoDestructorExpr(ExprArg Base, return getSema().BuildMemberReferenceExpr(move(Base), BaseType, OperatorLoc, isArrow, SS, /*FIXME: FirstQualifier*/ 0, - Name, - DestroyedType->getTypeLoc().getSourceRange().getBegin(), + Name, Destroyed.getLocation(), /*TemplateArgs*/ 0); } diff --git a/test/SemaTemplate/destructor-template.cpp b/test/SemaTemplate/destructor-template.cpp index 7dd429b796..83b1beeea9 100644 --- a/test/SemaTemplate/destructor-template.cpp +++ b/test/SemaTemplate/destructor-template.cpp @@ -25,6 +25,8 @@ namespace PR6152 { void X::f() { Y *y; y->template Y::~Y(); + y->template Y::~Y(); + y->~Y(); } template struct X; diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp index 116e8377b3..24db791e01 100644 --- a/test/SemaTemplate/member-access-expr.cpp +++ b/test/SemaTemplate/member-access-expr.cpp @@ -63,11 +63,13 @@ void test_convert(X2 x2) { template void destruct(T* ptr) { ptr->~T(); + ptr->T::~T(); } template void destruct_intptr(int *ip) { ip->~T(); + ip->T::~T(); } void test_destruct(X2 *x2p, int *ip) {