From: Douglas Gregor Date: Mon, 31 Aug 2009 23:41:50 +0000 (+0000) Subject: Eliminate CXXAdornedMemberExpr entirely. Instead, optionally allocate X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83f6faf37d9bf58986bedc9bc0ea897a56b4dbad;p=clang Eliminate CXXAdornedMemberExpr entirely. Instead, optionally allocate space within the MemberExpr for the nested-name-specifier and its source range. We'll do the same thing with explicitly-specified template arguments, assuming I don't flip-flop again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80642 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index f5048edc34..1835edc1d0 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -33,7 +33,6 @@ namespace clang { class BlockDecl; class CXXOperatorCallExpr; class CXXMemberCallExpr; - class CXXAdornedMemberExpr; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -1034,6 +1033,16 @@ public: virtual child_iterator child_end(); }; +/// \brief Represents the qualifier that may precede a C++ name, e.g., the +/// "std::" in "std::sort". +struct NameQualifier { + /// \brief The nested name specifier. + NestedNameSpecifier *NNS; + + /// \brief The source range covered by the nested name specifier. + SourceRange Range; +}; + /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr : public Expr { @@ -1049,25 +1058,48 @@ class MemberExpr : public Expr { SourceLocation MemberLoc; /// IsArrow - True if this is "X->F", false if this is "X.F". - bool IsArrow; + bool IsArrow : 1; -protected: - MemberExpr(StmtClass SC, Expr *base, bool isarrow, NamedDecl *memberdecl, - SourceLocation l, QualType ty) - : Expr(SC, ty, - base->isTypeDependent(), base->isValueDependent()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {} + /// \brief True if this member expression used a nested-name-specifier to + /// refer to the member, e.g., "x->Base::f". + bool HasQualifier : 1; + + /// \brief Retrieve the qualifier that preceded the member name, if any. + NameQualifier *getMemberQualifier() { + if (!HasQualifier) + return 0; + + return reinterpret_cast (this + 1); + } + + /// \brief Retrieve the qualifier that preceded the member name, if any. + const NameQualifier *getMemberQualifier() const { + if (!HasQualifier) + return 0; + + return reinterpret_cast (this + 1); + } + MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, + SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, + QualType ty); + public: MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l, QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent(), base->isValueDependent()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {} + Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), + HasQualifier(false) {} /// \brief Build an empty member reference expression. explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { } + static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, + NestedNameSpecifier *qual, SourceRange qualrange, + NamedDecl *memberdecl, + SourceLocation l, QualType ty); + void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast(Base); } @@ -1081,7 +1113,27 @@ public: /// \brief Determines whether this adorned member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const; + bool hasQualifier() const { return HasQualifier; } + + /// \brief If the member name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the member name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { + if (!HasQualifier) + return SourceRange(); + + return getMemberQualifier()->Range; + } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// NULL. + NestedNameSpecifier *getQualifier() const { + if (!HasQualifier) + return 0; + + return getMemberQualifier()->NNS; + } bool isArrow() const { return IsArrow; } void setArrow(bool A) { IsArrow = A; } @@ -1103,11 +1155,9 @@ public: virtual SourceLocation getExprLoc() const { return MemberLoc; } static bool classof(const Stmt *T) { - return T->getStmtClass() == MemberExprClass || - T->getStmtClass() == CXXAdornedMemberExprClass; + return T->getStmtClass() == MemberExprClass; } static bool classof(const MemberExpr *) { return true; } - static bool classof(const CXXAdornedMemberExpr *) { return true; } // Iterators virtual child_iterator child_begin(); diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 626cbd155b..6e9df9128f 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1285,43 +1285,6 @@ public: virtual child_iterator child_end(); }; -/// \brief Represents a C++ member access expression that was written using -/// either a qualified name, e.g., "x->Base::f()" or originally had -/// explicitly-specified template arguments (TODO!). -class CXXAdornedMemberExpr : public MemberExpr { - /// QualifierRange - The source range that covers the - /// nested-name-specifier. - SourceRange QualifierRange; - - /// \brief The nested-name-specifier that qualifies this declaration - /// name. - NestedNameSpecifier *Qualifier; - -public: - CXXAdornedMemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *Qual, - SourceRange QualRange, NamedDecl *memberdecl, - SourceLocation l, QualType ty) - : MemberExpr(CXXAdornedMemberExprClass, base, isarrow, memberdecl, l, ty), - QualifierRange(QualRange), Qualifier(Qual) { } - - /// \brief Retrieve the source range of the nested-name-specifier that - /// qualifies the member name. - SourceRange getQualifierRange() const { return QualifierRange; } - - /// \brief Retrieve the nested-name-specifier that qualifies the - /// member reference expression. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - - /// \brief Determines whether this adorned C++ member expression has a - /// nested-name-specifier associated with it. - bool hasQualifier() const { return getQualifier() != 0; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXAdornedMemberExprClass; - } - static bool classof(const CXXAdornedMemberExpr *) { return true; } -}; - /// \brief Represents a C++ member access expression where the actual member /// referenced could not be resolved, e.g., because the base expression or the /// member name was dependent. diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 35f2815059..af345991f1 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -134,7 +134,6 @@ EXPR(CXXBindTemporaryExpr , Expr) EXPR(CXXExprWithTemporaries , Expr) EXPR(CXXTemporaryObjectExpr , CXXConstructExpr) EXPR(CXXUnresolvedConstructExpr, Expr) -EXPR(CXXAdornedMemberExpr, MemberExpr) EXPR(CXXUnresolvedMemberExpr, Expr) // Obj-C Expressions. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6bc4854628..5b583a5200 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -262,6 +262,36 @@ QualType CallExpr::getCallReturnType() const { return FnType->getResultType(); } +MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, + SourceRange qualrange, NamedDecl *memberdecl, + SourceLocation l, QualType ty) + : Expr(MemberExprClass, ty, + base->isTypeDependent() || (qual && qual->isDependent()), + base->isValueDependent() || (qual && qual->isDependent())), + Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), + HasQualifier(qual != 0) { + // Initialize the qualifier, if any. + if (HasQualifier) { + NameQualifier *NQ = getMemberQualifier(); + NQ->NNS = qual; + NQ->Range = qualrange; + } +} + +MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, + NestedNameSpecifier *qual, + SourceRange qualrange, + NamedDecl *memberdecl, + SourceLocation l, QualType ty) { + std::size_t Size = sizeof(MemberExpr); + if (qual != 0) + Size += sizeof(NameQualifier); + + void *Mem = C.Allocate(Size, llvm::alignof()); + return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l, + ty); +} + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "<<=". const char *BinaryOperator::getOpcodeStr(Opcode Op) { @@ -498,7 +528,6 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, } case MemberExprClass: - case CXXAdornedMemberExprClass: // If the base pointer or element is to a volatile pointer/field, accessing // it is a side effect. if (getType().isVolatileQualified()) @@ -686,8 +715,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; break; } - case MemberExprClass: - case CXXAdornedMemberExprClass: { + case MemberExprClass: { const MemberExpr *m = cast(this); if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4: NamedDecl *Member = m->getMemberDecl(); @@ -958,8 +986,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { } return false; } - case MemberExprClass: - case CXXAdornedMemberExprClass: { + case MemberExprClass: { const MemberExpr *M = cast(this); return M->getBase()->isOBJCGCCandidate(Ctx); } @@ -1917,13 +1944,6 @@ Stmt::child_iterator CallExpr::child_end() { Stmt::child_iterator MemberExpr::child_begin() { return &Base; } Stmt::child_iterator MemberExpr::child_end() { return &Base+1; } -bool MemberExpr::hasQualifier() const { - if (const CXXAdornedMemberExpr *A = dyn_cast(this)) - return A->hasQualifier(); - - return false; -} - // ExtVectorElementExpr Stmt::child_iterator ExtVectorElementExpr::child_begin() { return &Base; } Stmt::child_iterator ExtVectorElementExpr::child_end() { return &Base+1; } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index d09358c08a..4be4a8ac4f 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -739,6 +739,9 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { OS << (Node->isArrow() ? "->" : "."); // FIXME: Suppress printing references to unnamed objects // representing anonymous unions/structs + if (NestedNameSpecifier *Qualifier = Node->getQualifier()) + Qualifier->print(OS, Policy); + OS << Node->getMemberDecl()->getNameAsString(); } void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) { @@ -1126,16 +1129,6 @@ StmtPrinter::VisitCXXUnresolvedConstructExpr( OS << ")"; } -void StmtPrinter::VisitCXXAdornedMemberExpr(CXXAdornedMemberExpr *Node) { - // FIXME: Suppress printing implicit bases (like "this") - PrintExpr(Node->getBase()); - OS << (Node->isArrow() ? "->" : "."); - // FIXME: Suppress printing references to unnamed objects - // representing anonymous unions/structs - Node->getQualifier()->print(OS, Policy); - OS << Node->getMemberDecl()->getNameAsString(); -} - void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) { PrintExpr(Node->getBase()); OS << (Node->isArrow() ? "->" : "."); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 8ce620c625..2545d34818 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -272,6 +272,7 @@ void StmtProfiler::VisitCallExpr(CallExpr *S) { void StmtProfiler::VisitMemberExpr(MemberExpr *S) { VisitExpr(S); VisitDecl(S->getMemberDecl()); + VisitNestedNameSpecifier(S->getQualifier()); ID.AddBoolean(S->isArrow()); } @@ -546,11 +547,6 @@ StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) { VisitType(S->getTypeAsWritten()); } -void StmtProfiler::VisitCXXAdornedMemberExpr(CXXAdornedMemberExpr *S) { - VisitMemberExpr(S); - VisitNestedNameSpecifier(S->getQualifier()); -} - void StmtProfiler::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *S) { VisitExpr(S); ID.AddBoolean(S->isArrow()); diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 4390025f58..d0b6bbf095 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -407,7 +407,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { break; case Stmt::MemberExprClass: - case Stmt::CXXAdornedMemberExprClass: VisitMemberExpr(cast(S), Pred, Dst, false); break; @@ -514,7 +513,6 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, return; case Stmt::MemberExprClass: - case Stmt::CXXAdornedMemberExprClass: VisitMemberExpr(cast(Ex), Pred, Dst, true); return; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 83f54b76eb..48326ee832 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -241,7 +241,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::ExtVectorElementExprClass: return EmitExtVectorElementExpr(cast(E)); case Expr::MemberExprClass: - case Stmt::CXXAdornedMemberExprClass: return EmitMemberExpr(cast(E)); case Expr::CompoundLiteralExprClass: return EmitCompoundLiteralLValue(cast(E)); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index cab807b999..24eb8b1d5e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1456,8 +1456,7 @@ static DeclRefExpr* EvalVal(Expr *E) { } // Accesses to members are potential references to data on the stack. - case Stmt::MemberExprClass: - case Stmt::CXXAdornedMemberExprClass: { + case Stmt::MemberExprClass: { MemberExpr *M = cast(E); // Check for indirect access. We only want direct field accesses. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7f680f5d2f..df94f20af7 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -878,15 +878,14 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { return false; } -/// \brief Build a MemberExpr or CXXAdornedMemberExpr, as appropriate. +/// \brief Build a MemberExpr AST node. static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, const CXXScopeSpec *SS, NamedDecl *Member, SourceLocation Loc, QualType Ty) { if (SS && SS->isSet()) - return new (C) CXXAdornedMemberExpr(Base, isArrow, - (NestedNameSpecifier *)SS->getScopeRep(), - SS->getRange(), - Member, Loc, Ty); + return MemberExpr::Create(C, Base, isArrow, + (NestedNameSpecifier *)SS->getScopeRep(), + SS->getRange(), Member, Loc, Ty); return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty); } @@ -4837,7 +4836,6 @@ static NamedDecl *getPrimaryDecl(Expr *E) { case Stmt::QualifiedDeclRefExprClass: return cast(E)->getDecl(); case Stmt::MemberExprClass: - case Stmt::CXXAdornedMemberExprClass: // If this is an arrow operator, the address is an offset from // the base's value, so the object the base refers to is // irrelevant. diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 8cb57d904f..3879b39e6e 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -835,13 +835,23 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. OwningExprResult RebuildMemberExpr(ExprArg Base, SourceLocation OpLoc, - bool isArrow, SourceLocation MemberLoc, + bool isArrow, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + SourceLocation MemberLoc, NamedDecl *Member) { + CXXScopeSpec SS; + if (Qualifier) { + SS.setRange(QualifierRange); + SS.setScopeRep(Qualifier); + } + return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, isArrow? tok::arrow : tok::period, MemberLoc, Member->getDeclName(), - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0)); + /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0), + &SS); } /// \brief Build a new binary operator expression. @@ -1421,30 +1431,6 @@ public: RParenLoc); } - /// \brief Build a new qualified member access expression. - /// - /// By default, performs semantic analysis to build the new expression. - /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildCXXAdornedMemberExpr(ExprArg Base, - SourceLocation OpLoc, - bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - SourceLocation MemberLoc, - NamedDecl *Member) { - CXXScopeSpec SS; - if (Qualifier) { - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); - } - return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, - isArrow? tok::arrow : tok::period, - MemberLoc, - Member->getDeclName(), - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0), - &SS); - } - /// \brief Build a new member reference expression. /// /// By default, performs semantic analysis to build the new expression. @@ -2973,6 +2959,15 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { if (Base.isInvalid()) return SemaRef.ExprError(); + NestedNameSpecifier *Qualifier = 0; + if (E->hasQualifier()) { + Qualifier + = getDerived().TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (Qualifier == 0); + return SemaRef.ExprError(); + } + NamedDecl *Member = cast_or_null(getDerived().TransformDecl(E->getMemberDecl())); if (!Member) @@ -2980,6 +2975,7 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() && + Qualifier == E->getQualifier() && Member == E->getMemberDecl()) return SemaRef.Owned(E->Retain()); @@ -2989,6 +2985,8 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { return getDerived().RebuildMemberExpr(move(Base), FakeOperatorLoc, E->isArrow(), + Qualifier, + E->getQualifierRange(), E->getMemberLoc(), Member); } @@ -4016,45 +4014,7 @@ TreeTransform::TransformCXXUnresolvedConstructExpr( FakeCommaLocs.data(), E->getRParenLoc()); } - -template -Sema::OwningExprResult -TreeTransform::TransformCXXAdornedMemberExpr( - CXXAdornedMemberExpr *E) { - OwningExprResult Base = getDerived().TransformExpr(E->getBase()); - if (Base.isInvalid()) - return SemaRef.ExprError(); - - NamedDecl *Member - = cast_or_null(getDerived().TransformDecl(E->getMemberDecl())); - if (!Member) - return SemaRef.ExprError(); - NestedNameSpecifier *Qualifier - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (Qualifier == 0 && E->getQualifier() != 0) - return SemaRef.ExprError(); - - if (!getDerived().AlwaysRebuild() && - Base.get() == E->getBase() && - Member == E->getMemberDecl() && - Qualifier == E->getQualifier()) - return SemaRef.Owned(E->Retain()); - - // FIXME: Bogus source location for the operator - SourceLocation FakeOperatorLoc - = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd()); - - return getDerived().RebuildCXXAdornedMemberExpr(move(Base), - FakeOperatorLoc, - E->isArrow(), - Qualifier, - E->getQualifierRange(), - E->getMemberLoc(), - Member); -} - template Sema::OwningExprResult TreeTransform::TransformCXXUnresolvedMemberExpr(