From: Douglas Gregor Date: Wed, 24 Feb 2010 21:52:20 +0000 (+0000) Subject: Retain source information for the "type-name ::" in a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e0601ea1220348957dacec5f3dd0707837365290;p=clang Retain source information for the "type-name ::" in a pseudo-destructor expression such as p->T::~T() git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97060 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 0861ff1b76..ccec7ef330 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -999,19 +999,28 @@ public: /// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). /// -/// Example: +/// A pseudo-destructor is an expression that looks like a member access to a +/// destructor of a scalar type, except that scalar types don't have +/// destructors. For example: +/// +/// \code +/// typedef int T; +/// void f(int *p) { +/// p->T::~T(); +/// } +/// \endcode /// +/// Pseudo-destructors typically occur when instantiating templates such as: +/// /// \code /// template /// void destroy(T* ptr) { -/// ptr->~T(); +/// ptr->T::~T(); /// } /// \endcode /// -/// When the template is parsed, the expression \c ptr->~T will be stored as -/// a member reference expression. If it then instantiated with a scalar type -/// as a template argument for T, the resulting expression will be a -/// pseudo-destructor expression. +/// for scalar types. A pseudo-destructor expression has no run-time semantics +/// beyond evaluating the base expression. class CXXPseudoDestructorExpr : public Expr { /// \brief The base expression (that is being destroyed). Stmt *Base; @@ -1030,6 +1039,14 @@ class CXXPseudoDestructorExpr : public Expr { /// present. SourceRange QualifierRange; + /// \brief The type that precedes the '::' in a qualified pseudo-destructor + /// expression. + TypeSourceInfo *ScopeType; + + /// \brief The location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation ColonColonLoc; + /// \brief The type being destroyed. QualType DestroyedType; @@ -1041,6 +1058,8 @@ public: Expr *Base, bool isArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + TypeSourceInfo *ScopeType, + SourceLocation ColonColonLoc, QualType DestroyedType, SourceLocation DestroyedTypeLoc) : Expr(CXXPseudoDestructorExprClass, @@ -1052,8 +1071,9 @@ public: /*isValueDependent=*/Base->isValueDependent()), Base(static_cast(Base)), IsArrow(isArrow), OperatorLoc(OperatorLoc), Qualifier(Qualifier), - QualifierRange(QualifierRange), DestroyedType(DestroyedType), - DestroyedTypeLoc(DestroyedTypeLoc) { } + QualifierRange(QualifierRange), + ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), + DestroyedType(DestroyedType), DestroyedTypeLoc(DestroyedTypeLoc) { } void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast(Base); } @@ -1081,6 +1101,21 @@ public: /// \brief Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } + /// \brief Retrieve the scope type in a qualified pseudo-destructor + /// expression. + /// + /// Pseudo-destructor expressions can have extra qualification within them + /// that is not part of the nested-name-specifier, e.g., \c p->T::~T(). + /// Here, if the object type of the expression is (or may be) a scalar type, + /// \p T may also be a scalar type and, therefore, cannot be part of a + /// nested-name-specifier. It is stored as the "scope type" of the pseudo- + /// destructor expression. + TypeSourceInfo *getScopeTypeLoc() const { return ScopeType; } + + /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation getColonColonLoc() const { return ColonColonLoc; } + /// \brief Retrieve the type that is being destroyed. QualType getDestroyedType() const { return DestroyedType; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c3116a3885..5ced625f61 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2936,6 +2936,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, IsArrow, OpLoc, (NestedNameSpecifier *) SS.getScopeRep(), SS.getRange(), + 0, SourceLocation(), MemberName.getCXXNameType(), MemberLoc)); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 9172956b51..53b3ab070f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2664,7 +2664,8 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, // // ::[opt] nested-name-specifier[opt] type-name :: ~ type-name // - // shall designate the same scalar type. + // shall designate the same scalar type. + TypeSourceInfo *ScopeTypeLoc; QualType ScopeType; if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.Identifier) { @@ -2680,7 +2681,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, return ExprError(); } else { // FIXME: Drops source-location information. - ScopeType = GetTypeFromParser(T); + ScopeType = GetTypeFromParser(T, &ScopeTypeLoc); if (!ScopeType->isDependentType() && !Context.hasSameUnqualifiedType(DestructedType, ScopeType)) { @@ -2690,6 +2691,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, << ObjectType << ScopeType << BaseE->getSourceRange(); ScopeType = QualType(); + ScopeTypeLoc = 0; } } } else { @@ -2707,7 +2709,6 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, } } - // FIXME: Drops the scope type. OwningExprResult Result = Owned(new (Context) CXXPseudoDestructorExpr(Context, Base.takeAs(), @@ -2715,6 +2716,8 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, OpLoc, (NestedNameSpecifier *) SS.getScopeRep(), SS.getRange(), + ScopeTypeLoc, + CCLoc, DestructedType, SecondTypeName.StartLocation)); if (HasTrailingLParen)