Retain complete source information for the type after the '~' in a

CXXPseudoDestructorExpr. 

Update template instantiation for pseudo-destructor expressions to use
this source information and to make use of
Sema::BuildPseudoDestructorExpr when the base expression is dependent
or refers to a scalar type.

llvm-svn: 97079
This commit is contained in:
Douglas Gregor 2010-02-24 23:40:28 +00:00
parent 88fdcd323d
commit 651fe5ec20
5 changed files with 98 additions and 59 deletions

View File

@ -1048,10 +1048,7 @@ class CXXPseudoDestructorExpr : public Expr {
SourceLocation ColonColonLoc; SourceLocation ColonColonLoc;
/// \brief The type being destroyed. /// \brief The type being destroyed.
QualType DestroyedType; TypeSourceInfo *DestroyedType;
/// \brief The location of the type after the '~'.
SourceLocation DestroyedTypeLoc;
public: public:
CXXPseudoDestructorExpr(ASTContext &Context, CXXPseudoDestructorExpr(ASTContext &Context,
@ -1060,20 +1057,20 @@ public:
SourceRange QualifierRange, SourceRange QualifierRange,
TypeSourceInfo *ScopeType, TypeSourceInfo *ScopeType,
SourceLocation ColonColonLoc, SourceLocation ColonColonLoc,
QualType DestroyedType, TypeSourceInfo *DestroyedType)
SourceLocation DestroyedTypeLoc)
: Expr(CXXPseudoDestructorExprClass, : Expr(CXXPseudoDestructorExprClass,
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
false, 0, false, false, 0, false,
false, 0, 0, false, false, 0, 0, false,
CC_Default)), CC_Default)),
/*isTypeDependent=*/false, /*isTypeDependent=*/(Base->isTypeDependent() ||
DestroyedType->getType()->isDependentType()),
/*isValueDependent=*/Base->isValueDependent()), /*isValueDependent=*/Base->isValueDependent()),
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
OperatorLoc(OperatorLoc), Qualifier(Qualifier), OperatorLoc(OperatorLoc), Qualifier(Qualifier),
QualifierRange(QualifierRange), QualifierRange(QualifierRange),
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), ScopeType(ScopeType), ColonColonLoc(ColonColonLoc),
DestroyedType(DestroyedType), DestroyedTypeLoc(DestroyedTypeLoc) { } DestroyedType(DestroyedType) { }
void setBase(Expr *E) { Base = E; } void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); } Expr *getBase() const { return cast<Expr>(Base); }
@ -1110,21 +1107,20 @@ public:
/// \p T may also be a scalar type and, therefore, cannot be part of a /// \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- /// nested-name-specifier. It is stored as the "scope type" of the pseudo-
/// destructor expression. /// destructor expression.
TypeSourceInfo *getScopeTypeLoc() const { return ScopeType; } TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }
/// \brief Retrieve the location of the '::' in a qualified pseudo-destructor /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
/// expression. /// expression.
SourceLocation getColonColonLoc() const { return ColonColonLoc; } SourceLocation getColonColonLoc() const { return ColonColonLoc; }
/// \brief Retrieve the type that is being destroyed. /// \brief Retrieve the type that is being destroyed.
QualType getDestroyedType() const { return DestroyedType; } QualType getDestroyedType() const { return DestroyedType->getType(); }
/// \brief Retrieve the location of the type being destroyed. /// \brief Retrieve the source location information for the type
SourceLocation getDestroyedTypeLoc() const { return DestroyedTypeLoc; } /// being destroyed.
TypeSourceInfo *getDestroyedTypeInfo() const { return DestroyedType; }
virtual SourceRange getSourceRange() const { virtual SourceRange getSourceRange() const;
return SourceRange(Base->getLocStart(), DestroyedTypeLoc);
}
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXPseudoDestructorExprClass; return T->getStmtClass() == CXXPseudoDestructorExprClass;

View File

@ -15,6 +15,7 @@
#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
using namespace clang; using namespace clang;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -121,6 +122,12 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() {
return &Base + 1; return &Base + 1;
} }
SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
return SourceRange(Base->getLocStart(),
DestroyedType->getTypeLoc().getSourceRange().getEnd());
}
// UnresolvedLookupExpr // UnresolvedLookupExpr
UnresolvedLookupExpr * UnresolvedLookupExpr *
UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,

View File

@ -2932,13 +2932,15 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// FIXME: We've lost the precise spelling of the type by going through // FIXME: We've lost the precise spelling of the type by going through
// DeclarationName. Can we do better? // DeclarationName. Can we do better?
TypeSourceInfo *DestroyedTypeInfo
= Context.getTrivialTypeSourceInfo(MemberName.getCXXNameType(),
MemberLoc);
return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr, return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
IsArrow, OpLoc, IsArrow, OpLoc,
(NestedNameSpecifier *) SS.getScopeRep(), (NestedNameSpecifier *) SS.getScopeRep(),
SS.getRange(), SS.getRange(),
0, SourceLocation(), 0, SourceLocation(),
MemberName.getCXXNameType(), DestroyedTypeInfo));
MemberLoc));
} }
// Handle access to Objective-C instance variables, such as "Obj->ivar" and // Handle access to Objective-C instance variables, such as "Obj->ivar" and

View File

@ -2431,11 +2431,11 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
SourceLocation OpLoc, SourceLocation OpLoc,
tok::TokenKind OpKind, tok::TokenKind OpKind,
const CXXScopeSpec &SS, const CXXScopeSpec &SS,
TypeSourceInfo *ScopeTypeInfo, TypeSourceInfo *ScopeTypeInfo,
SourceLocation CCLoc, SourceLocation CCLoc,
TypeSourceInfo *DestructedTypeLoc, TypeSourceInfo *DestructedTypeInfo,
bool HasTrailingLParen) { bool HasTrailingLParen) {
assert(DestructedTypeLoc && "No destructed type in pseudo-destructor expr?"); assert(DestructedTypeInfo && "No destructed type in pseudo-destructor expr?");
// C++ [expr.pseudo]p2: // C++ [expr.pseudo]p2:
// The left-hand side of the dot operator shall be of scalar type. The // The left-hand side of the dot operator shall be of scalar type. The
@ -2467,18 +2467,18 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
// C++ [expr.pseudo]p2: // C++ [expr.pseudo]p2:
// [...] The cv-unqualified versions of the object type and of the type // [...] The cv-unqualified versions of the object type and of the type
// designated by the pseudo-destructor-name shall be the same type. // designated by the pseudo-destructor-name shall be the same type.
QualType DestructedType = DestructedTypeLoc->getType(); QualType DestructedType = DestructedTypeInfo->getType();
SourceLocation DestructedTypeStart SourceLocation DestructedTypeStart
= DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin(); = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
if (!DestructedType->isDependentType() && !ObjectType->isDependentType() && if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
<< ObjectType << DestructedType << BaseE->getSourceRange() << ObjectType << DestructedType << BaseE->getSourceRange()
<< DestructedTypeLoc->getTypeLoc().getSourceRange(); << DestructedTypeInfo->getTypeLoc().getSourceRange();
// Recover by // Recover by
DestructedType = ObjectType; DestructedType = ObjectType;
DestructedTypeLoc = Context.getTrivialTypeSourceInfo(ObjectType, DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
DestructedTypeStart); DestructedTypeStart);
} }
@ -2513,13 +2513,12 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
SS.getRange(), SS.getRange(),
ScopeTypeInfo, ScopeTypeInfo,
CCLoc, CCLoc,
DestructedType, DestructedTypeInfo));
DestructedTypeStart));
if (HasTrailingLParen) if (HasTrailingLParen)
return move(Result); return move(Result);
return DiagnoseDtorReference( return DiagnoseDtorReference(
DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin(), DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin(),
move(Result)); move(Result));
} }

View File

@ -884,28 +884,11 @@ public:
OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base, OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
SourceLocation OperatorLoc, SourceLocation OperatorLoc,
bool isArrow, bool isArrow,
SourceLocation DestroyedTypeLoc, NestedNameSpecifier *Qualifier,
QualType DestroyedType, SourceRange QualifierRange,
NestedNameSpecifier *Qualifier, TypeSourceInfo *ScopeType,
SourceRange QualifierRange) { SourceLocation CCLoc,
CXXScopeSpec SS; TypeSourceInfo *DestroyedType);
if (Qualifier) {
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
}
QualType BaseType = ((Expr*) Base.get())->getType();
DeclarationName Name
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(DestroyedType));
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
OperatorLoc, isArrow,
SS, /*FIXME: FirstQualifier*/ 0,
Name, DestroyedTypeLoc,
/*TemplateArgs*/ 0);
}
/// \brief Build a new unary operator expression. /// \brief Build a new unary operator expression.
/// ///
@ -4694,27 +4677,35 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
if (E->getQualifier() && !Qualifier) if (E->getQualifier() && !Qualifier)
return SemaRef.ExprError(); return SemaRef.ExprError();
QualType DestroyedType; // FIXME: Object type!
{ TypeSourceInfo *DestroyedTypeInfo
TemporaryBase Rebase(*this, E->getDestroyedTypeLoc(), DeclarationName()); = getDerived().TransformType(E->getDestroyedTypeInfo());
DestroyedType = getDerived().TransformType(E->getDestroyedType()); if (!DestroyedTypeInfo)
if (DestroyedType.isNull()) return SemaRef.ExprError();
// FIXME: Object type!
TypeSourceInfo *ScopeTypeInfo = 0;
if (E->getScopeTypeInfo()) {
ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
if (!ScopeTypeInfo)
return SemaRef.ExprError(); return SemaRef.ExprError();
} }
if (!getDerived().AlwaysRebuild() && if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() && Base.get() == E->getBase() &&
Qualifier == E->getQualifier() && Qualifier == E->getQualifier() &&
DestroyedType == E->getDestroyedType()) ScopeTypeInfo == E->getScopeTypeInfo() &&
DestroyedTypeInfo == E->getDestroyedTypeInfo())
return SemaRef.Owned(E->Retain()); return SemaRef.Owned(E->Retain());
return getDerived().RebuildCXXPseudoDestructorExpr(move(Base), return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
E->getOperatorLoc(), E->getOperatorLoc(),
E->isArrow(), E->isArrow(),
E->getDestroyedTypeLoc(),
DestroyedType,
Qualifier, Qualifier,
E->getQualifierRange()); E->getQualifierRange(),
ScopeTypeInfo,
E->getColonColonLoc(),
DestroyedTypeInfo);
} }
template<typename Derived> template<typename Derived>
@ -5755,6 +5746,50 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
return move(Result); return move(Result);
} }
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(ExprArg Base,
SourceLocation OperatorLoc,
bool isArrow,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
TypeSourceInfo *DestroyedType) {
CXXScopeSpec SS;
if (Qualifier) {
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
}
Expr *BaseE = (Expr *)Base.get();
QualType BaseType = BaseE->getType();
if (BaseE->isTypeDependent() ||
(!isArrow && !BaseType->getAs<RecordType>()) ||
(isArrow && BaseType->getAs<PointerType>() &&
!BaseType->getAs<PointerType>()->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,
DestroyedType,
/*FIXME?*/true);
}
DeclarationName Name
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(DestroyedType->getType()));
// FIXME: the ScopeType should be tacked onto SS.
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
OperatorLoc, isArrow,
SS, /*FIXME: FirstQualifier*/ 0,
Name,
DestroyedType->getTypeLoc().getSourceRange().getBegin(),
/*TemplateArgs*/ 0);
}
} // end namespace clang } // end namespace clang
#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H #endif // LLVM_CLANG_SEMA_TREETRANSFORM_H