diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 83 |
2 files changed, 61 insertions, 33 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 182f2f080d..2e0b6a55d5 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1019,6 +1019,17 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, // Parse the tilde. assert(Tok.is(tok::tilde) && "ParseOptionalCXXScopeSpecifier fail"); SourceLocation TildeLoc = ConsumeToken(); + + if (Tok.is(tok::kw_decltype) && !FirstTypeName.isValid() && SS.isEmpty()) { + DeclSpec DS(AttrFactory); + SourceLocation EndLoc = ParseDecltypeSpecifier(DS); + if (DS.getTypeSpecType() == TST_error) + return ExprError(); + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, + OpKind, TildeLoc, DS, + Tok.is(tok::l_paren)); + } + if (!Tok.is(tok::identifier)) { Diag(Tok, diag::err_destructor_tilde_identifier); return ExprError(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index e7e6b892e5..eaa330b183 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" +#include "TypeLocBuilder.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -4313,37 +4314,45 @@ ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, /*RPLoc*/ ExpectedLParenLoc); } -ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - TypeSourceInfo *ScopeTypeInfo, - SourceLocation CCLoc, - SourceLocation TildeLoc, - PseudoDestructorTypeStorage Destructed, - bool HasTrailingLParen) { - TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); - +static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *Base, + tok::TokenKind& OpKind, SourceLocation OpLoc) { // 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. - QualType ObjectType = Base->getType(); if (OpKind == tok::arrow) { if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { ObjectType = Ptr->getPointeeType(); } else if (!Base->isTypeDependent()) { // The user wrote "p->" when she probably meant "p."; fix it. - Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) << ObjectType << true << FixItHint::CreateReplacement(OpLoc, "."); - if (isSFINAEContext()) - return ExprError(); + if (S.isSFINAEContext()) + return true; OpKind = tok::period; } } + return false; +} + +ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeTypeInfo, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage Destructed, + bool HasTrailingLParen) { + TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); + + QualType ObjectType = Base->getType(); + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) << ObjectType << Base->getSourceRange(); @@ -4442,25 +4451,9 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid second type name in pseudo-destructor"); - // 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. QualType ObjectType = Base->getType(); - if (OpKind == tok::arrow) { - if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { - ObjectType = Ptr->getPointeeType(); - } 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 - << FixItHint::CreateReplacement(OpLoc, "."); - if (isSFINAEContext()) - return ExprError(); - - OpKind = tok::period; - } - } + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); // Compute the object type that we should use for name lookup purposes. Only // record types and dependent types matter. @@ -4580,6 +4573,30 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, Destructed, HasTrailingLParen); } +ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation TildeLoc, + const DeclSpec& DS, + bool HasTrailingLParen) { + + QualType ObjectType = Base->getType(); + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + + TypeLocBuilder TLB; + DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); + DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T); + PseudoDestructorTypeStorage Destructed(DestructedTypeInfo); + + return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(), + 0, SourceLocation(), TildeLoc, + Destructed, HasTrailingLParen); +} + ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, CXXMethodDecl *Method, bool HadMultipleCandidates) { |