From: Douglas Gregor Date: Wed, 24 Feb 2010 22:38:50 +0000 (+0000) Subject: Split ActOnPseudoDestructorExpr into the part that interprets the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b57fb49b6569db9716877de6857e4de572edfb75;p=clang Split ActOnPseudoDestructorExpr into the part that interprets the parser's data structures and the part that performs semantic analysis and AST building, in preparation for improved template instantiation of pseudo-destructor expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97070 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 57e527e94a..689ad493e8 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2181,6 +2181,15 @@ public: OwningExprResult DiagnoseDtorReference(SourceLocation NameLoc, ExprArg MemExpr); + OwningExprResult BuildPseudoDestructorExpr(ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeType, + SourceLocation CCLoc, + TypeSourceInfo *DestroyedType, + bool HasTrailingLParen); + OwningExprResult ActOnDependentPseudoDestructorExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 53b3ab070f..90d6a0a026 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -2426,6 +2427,102 @@ Sema::OwningExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, /*RPLoc*/ ExpectedLParenLoc); } +Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeTypeInfo, + SourceLocation CCLoc, + TypeSourceInfo *DestructedTypeLoc, + bool HasTrailingLParen) { + assert(DestructedTypeLoc && "No destructed type in pseudo-destructor expr?"); + + // C++ [expr.pseudo]p2: + // The left-hand side of the dot operator shall be of scalar type. The + // left-hand side of the arrow operator shall be of pointer to scalar type. + // This scalar type is the object type. + Expr *BaseE = (Expr *)Base.get(); + QualType ObjectType = BaseE->getType(); + if (OpKind == tok::arrow) { + if (const PointerType *Ptr = ObjectType->getAs()) { + ObjectType = Ptr->getPointeeType(); + } else if (!BaseE->isTypeDependent()) { + // The user wrote "p->" when she probably meant "p."; fix it. + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << true + << CodeModificationHint::CreateReplacement(OpLoc, "."); + if (isSFINAEContext()) + return ExprError(); + + OpKind = tok::period; + } + } + + if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { + Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) + << ObjectType << BaseE->getSourceRange(); + return ExprError(); + } + + // 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 = DestructedTypeLoc->getType(); + SourceLocation DestructedTypeStart + = DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin(); + if (!DestructedType->isDependentType() && !ObjectType->isDependentType() && + !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { + Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) + << ObjectType << DestructedType << BaseE->getSourceRange() + << DestructedTypeLoc->getTypeLoc().getSourceRange(); + + // Recover by + DestructedType = ObjectType; + DestructedTypeLoc = Context.getTrivialTypeSourceInfo(ObjectType, + DestructedTypeStart); + } + + // C++ [expr.pseudo]p2: + // [...] Furthermore, the two type-names in a pseudo-destructor-name of the + // form + // + // ::[opt] nested-name-specifier[opt] type-name :: ~ type-name + // + // shall designate the same scalar type. + if (ScopeTypeInfo) { + QualType ScopeType = ScopeTypeInfo->getType(); + if (!ScopeType->isDependentType() && !ObjectType->isDependentType() && + !Context.hasSameType(ScopeType, ObjectType)) { + + Diag(ScopeTypeInfo->getTypeLoc().getSourceRange().getBegin(), + diag::err_pseudo_dtor_type_mismatch) + << ObjectType << ScopeType << BaseE->getSourceRange() + << ScopeTypeInfo->getTypeLoc().getSourceRange(); + + ScopeType = QualType(); + ScopeTypeInfo = 0; + } + } + + OwningExprResult Result + = Owned(new (Context) CXXPseudoDestructorExpr(Context, + Base.takeAs(), + OpKind == tok::arrow, + OpLoc, + (NestedNameSpecifier *) SS.getScopeRep(), + SS.getRange(), + ScopeTypeInfo, + CCLoc, + DestructedType, + DestructedTypeStart)); + if (HasTrailingLParen) + return move(Result); + + return DiagnoseDtorReference( + DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin(), + move(Result)); +} + Sema::OwningExprResult Sema::ActOnDependentPseudoDestructorExpr(Scope *S, ExprArg Base, @@ -2592,29 +2689,20 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, if (OpKind == tok::arrow) { if (const PointerType *Ptr = ObjectType->getAs()) { ObjectType = Ptr->getPointeeType(); - } else { + } else if (!BaseE->isTypeDependent()) { // 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; } } - - if (!ObjectType->isScalarType()) { - Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) - << ObjectType << BaseE->getSourceRange(); - return ExprError(); - } - - // - // 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. + // Convert the name of the type being destructed (following the ~) into a + // type (with source-location information). QualType DestructedType; TypeSourceInfo *DestructedTypeInfo = 0; if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) { @@ -2630,42 +2718,34 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, // Recover by assuming we had the right type all along. DestructedType = ObjectType; - } else { + } else DestructedType = GetTypeFromParser(T, &DestructedTypeInfo); - - if (!DestructedType->isDependentType() && - !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { - // The types mismatch. Recover by assuming we had the right type - // all along. - Diag(SecondTypeName.StartLocation, diag::err_pseudo_dtor_type_mismatch) - << ObjectType << DestructedType << BaseE->getSourceRange(); - - DestructedType = ObjectType; - DestructedTypeInfo = 0; - } - } } else { - // FIXME: C++0x template aliases would allow a template-id here. For now, - // just diagnose this as an error. + // Resolve the template-id to a type. TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId; - Diag(TemplateId->TemplateNameLoc, diag::err_pseudo_dtor_template) - << TemplateId->Name << ObjectType - << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); - if (isSFINAEContext()) - return ExprError(); - - // Recover by assuming we had the right type all along. - DestructedType = ObjectType; + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + if (T.isInvalid() || !T.get()) { + // Recover by assuming we had the right type all along. + DestructedType = ObjectType; + } else + DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo); } - // C++ [expr.pseudo]p2: - // [...] Furthermore, the two type-names in a pseudo-destructor-name of the - // form - // - // ::[opt] nested-name-specifier[opt] type-name :: ~ type-name - // - // shall designate the same scalar type. - TypeSourceInfo *ScopeTypeLoc; + // If we've performed some kind of recovery, (re-)build the type source + // information. + if (!DestructedTypeInfo) + DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType, + SecondTypeName.StartLocation); + + // Convert the name of the scope type (the type prior to '::') into a type. + TypeSourceInfo *ScopeTypeInfo = 0; QualType ScopeType; if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.Identifier) { @@ -2677,53 +2757,36 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, Diag(FirstTypeName.StartLocation, diag::err_pseudo_dtor_destructor_non_type) << FirstTypeName.Identifier << ObjectType; + if (isSFINAEContext()) - return ExprError(); - } else { - // FIXME: Drops source-location information. - ScopeType = GetTypeFromParser(T, &ScopeTypeLoc); + return ExprError(); - if (!ScopeType->isDependentType() && - !Context.hasSameUnqualifiedType(DestructedType, ScopeType)) { - // The types mismatch. Recover by assuming we don't have a scoping - // type. - Diag(FirstTypeName.StartLocation, diag::err_pseudo_dtor_type_mismatch) - << ObjectType << ScopeType << BaseE->getSourceRange(); - - ScopeType = QualType(); - ScopeTypeLoc = 0; - } - } + // Just drop this type. It's unnecessary anyway. + ScopeType = QualType(); + } else + ScopeType = GetTypeFromParser(T, &ScopeTypeInfo); } else { - // FIXME: C++0x template aliases would allow a template-id here. For now, - // just diagnose this as an error. + // Resolve the template-id to a type. TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId; - Diag(TemplateId->TemplateNameLoc, diag::err_pseudo_dtor_template) - << TemplateId->Name << ObjectType - << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); - if (isSFINAEContext()) - return ExprError(); - - // Recover by assuming we have no scoping type. - DestructedType = ObjectType; + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + if (T.isInvalid() || !T.get()) { + // Recover by dropping this type. + ScopeType = QualType(); + } else + ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo); } } - - OwningExprResult Result - = Owned(new (Context) CXXPseudoDestructorExpr(Context, - Base.takeAs(), - OpKind == tok::arrow, - OpLoc, - (NestedNameSpecifier *) SS.getScopeRep(), - SS.getRange(), - ScopeTypeLoc, - CCLoc, - DestructedType, - SecondTypeName.StartLocation)); - if (HasTrailingLParen) - return move(Result); - - return DiagnoseDtorReference(SecondTypeName.StartLocation, move(Result)); + + return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS, + ScopeTypeInfo, CCLoc, DestructedTypeInfo, + HasTrailingLParen); } CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,