diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 66 | ||||
| -rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 16 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 224 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 81 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/destructor-template.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/member-access-expr.cpp | 2 | 
8 files changed, 197 insertions, 218 deletions
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 6a06554b603..d1351b8b144 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/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<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 @@ 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<Stmt *>(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/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 28d07f1df2c..b9a4ee6e4d2 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 3ae306d3c7a..da43878628f 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index abc775e06bc..1bc084c5db3 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 025f2ad49e9..64f2ef204e7 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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<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 @@ 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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 922c041393f..416f480e577 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/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<Derived>::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<Derived>::TransformCXXPseudoDestructorExpr(                                                       ScopeTypeInfo,                                                       E->getColonColonLoc(),                                                       E->getTildeLoc(), -                                                     DestroyedTypeInfo); +                                                     Destroyed);  }  template<typename Derived> @@ -5758,7 +5791,7 @@ TreeTransform<Derived>::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<Derived>::RebuildCXXPseudoDestructorExpr(ExprArg Base,    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 @@ TreeTransform<Derived>::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/clang/test/SemaTemplate/destructor-template.cpp b/clang/test/SemaTemplate/destructor-template.cpp index 7dd429b796f..83b1beeea99 100644 --- a/clang/test/SemaTemplate/destructor-template.cpp +++ b/clang/test/SemaTemplate/destructor-template.cpp @@ -25,6 +25,8 @@ namespace PR6152 {    void X<T>::f() {      Y<T> *y;      y->template Y<T>::~Y(); +    y->template Y<T>::~Y<T>(); +    y->~Y();    }    template struct X<int>; diff --git a/clang/test/SemaTemplate/member-access-expr.cpp b/clang/test/SemaTemplate/member-access-expr.cpp index 116e8377b36..24db791e011 100644 --- a/clang/test/SemaTemplate/member-access-expr.cpp +++ b/clang/test/SemaTemplate/member-access-expr.cpp @@ -63,11 +63,13 @@ void test_convert(X2 x2) {  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) {  | 

