diff options
-rw-r--r-- | clang/include/clang/AST/Expr.h | 231 | ||||
-rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 44 | ||||
-rw-r--r-- | clang/include/clang/AST/StmtNodes.def | 1 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 92 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 14 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReaderStmt.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriterStmt.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 50 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 49 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 84 |
20 files changed, 396 insertions, 231 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 0d09ea325c3..302c508b638 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -322,47 +322,221 @@ public: // Primary Expressions. //===----------------------------------------------------------------------===// +/// \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; +}; + +/// \brief Represents an explicit template argument list in C++, e.g., +/// the "<int>" in "sort<int>". +struct ExplicitTemplateArgumentList { + /// \brief The source location of the left angle bracket ('<'); + SourceLocation LAngleLoc; + + /// \brief The source location of the right angle bracket ('>'); + SourceLocation RAngleLoc; + + /// \brief The number of template arguments in TemplateArgs. + /// The actual template arguments (if any) are stored after the + /// ExplicitTemplateArgumentList structure. + unsigned NumTemplateArgs; + + /// \brief Retrieve the template arguments + TemplateArgument *getTemplateArgs() { + return reinterpret_cast<TemplateArgument *> (this + 1); + } + + /// \brief Retrieve the template arguments + const TemplateArgument *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgument *> (this + 1); + } +}; + /// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, /// enum, etc. class DeclRefExpr : public Expr { - NamedDecl *D; + enum { + // Flag on DecoratedD that specifies when this declaration reference + // expression has a C++ nested-name-specifier. + HasQualifierFlag = 0x01, + // Flag on DecoratedD that specifies when this declaration reference + // expression has an explicit C++ template argument list. + HasExplicitTemplateArgumentListFlag = 0x02 + }; + + // DecoratedD - The declaration that we are referencing, plus two bits to + // indicate whether (1) the declaration's name was explicitly qualified and + // (2) the declaration's name was followed by an explicit template + // argument list. + llvm::PointerIntPair<NamedDecl *, 2> DecoratedD; + + // Loc - The location of the declaration name itself. SourceLocation Loc; + /// \brief Retrieve the qualifier that preceded the declaration name, if any. + NameQualifier *getNameQualifier() { + if (DecoratedD.getInt() & HasQualifierFlag == 0) + return 0; + + return reinterpret_cast<NameQualifier *> (this + 1); + } + + /// \brief Retrieve the qualifier that preceded the member name, if any. + const NameQualifier *getNameQualifier() const { + return const_cast<DeclRefExpr *>(this)->getNameQualifier(); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + if (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag == 0) + return 0; + + if (DecoratedD.getInt() & HasQualifierFlag == 0) + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return reinterpret_cast<ExplicitTemplateArgumentList *>( + getNameQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList(); + } + + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + NamedDecl *D, SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD); + protected: // FIXME: Eventually, this constructor will go away and all subclasses // will have to provide the type- and value-dependent flags. DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) : - Expr(SC, t), D(d), Loc(l) {} + Expr(SC, t), DecoratedD(d, 0), Loc(l) {} DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : - Expr(SC, t, TD, VD), D(d), Loc(l) {} + Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {} public: // FIXME: Eventually, this constructor will go away and all clients // will have to provide the type- and value-dependent flags. DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) : - Expr(DeclRefExprClass, t), D(d), Loc(l) {} + Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {} DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : - Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {} + Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {} /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } - NamedDecl *getDecl() { return D; } - const NamedDecl *getDecl() const { return D; } - void setDecl(NamedDecl *NewD) { D = NewD; } + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + QualType T, bool TD, bool VD); + + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD); + + NamedDecl *getDecl() { return DecoratedD.getPointer(); } + const NamedDecl *getDecl() const { return DecoratedD.getPointer(); } + void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + virtual SourceRange getSourceRange() const; + /// \brief Determine whether this declaration reference was preceded by a + /// C++ nested-name-specifier, e.g., \c N::foo. + bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; } + + /// \brief If the name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { + if (!hasQualifier()) + return SourceRange(); + + return getNameQualifier()->Range; + } + + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name. Otherwise, returns NULL. + NestedNameSpecifier *getQualifier() const { + if (!hasQualifier()) + return 0; + + return getNameQualifier()->NNS; + } + + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgumentList() const { + return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag; + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + if (!hasExplicitTemplateArgumentList()) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgument *getTemplateArgs() const { + if (!hasExplicitTemplateArgumentList()) + return 0; + + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!hasExplicitTemplateArgumentList()) + return 0; + + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + if (!hasExplicitTemplateArgumentList()) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->RAngleLoc; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass || - T->getStmtClass() == CXXConditionDeclExprClass || - T->getStmtClass() == QualifiedDeclRefExprClass; + T->getStmtClass() == CXXConditionDeclExprClass; } static bool classof(const DeclRefExpr *) { return true; } @@ -1062,41 +1236,6 @@ 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; -}; - -/// \brief Represents an explicit template argument list in C++, e.g., -/// the "<int>" in "sort<int>". -struct ExplicitTemplateArgumentList { - /// \brief The source location of the left angle bracket ('<'); - SourceLocation LAngleLoc; - - /// \brief The source location of the right angle bracket ('>'); - SourceLocation RAngleLoc; - - /// \brief The number of template arguments in TemplateArgs. - /// The actual template arguments (if any) are stored after the - /// ExplicitTemplateArgumentList structure. - unsigned NumTemplateArgs; - - /// \brief Retrieve the template arguments - TemplateArgument *getTemplateArgs() { - return reinterpret_cast<TemplateArgument *> (this + 1); - } - - /// \brief Retrieve the template arguments - const TemplateArgument *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgument *> (this + 1); - } -}; - /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr : public Expr { diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 3f66b1f40bf..8fdb98df1b8 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1061,46 +1061,11 @@ public: virtual child_iterator child_end(); }; -/// QualifiedDeclRefExpr - A reference to a declared variable, -/// function, enum, etc., that includes a qualification, e.g., -/// "N::foo". -class QualifiedDeclRefExpr : public DeclRefExpr { - /// QualifierRange - The source range that covers the - /// nested-name-specifier. - SourceRange QualifierRange; - - /// \brief The nested-name-specifier that qualifies this declaration - /// name. - NestedNameSpecifier *NNS; - -public: - QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, - bool VD, SourceRange R, NestedNameSpecifier *NNS) - : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), - QualifierRange(R), NNS(NNS) { } - - /// \brief Retrieve the source range of the nested-name-specifier. - SourceRange getQualifierRange() const { return QualifierRange; } - - /// \brief Retrieve the nested-name-specifier that qualifies this - /// declaration. - NestedNameSpecifier *getQualifier() const { return NNS; } - - virtual SourceRange getSourceRange() const { - return SourceRange(QualifierRange.getBegin(), getLocation()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == QualifiedDeclRefExprClass; - } - static bool classof(const QualifiedDeclRefExpr *) { return true; } -}; - /// \brief A qualified reference to a name whose declaration cannot /// yet be resolved. /// -/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that -/// it expresses a qualified reference to a declaration such as +/// UnresolvedDeclRefExpr is similar to eclRefExpr in that +/// it expresses a reference to a declaration such as /// X<T>::value. The difference, however, is that an /// UnresolvedDeclRefExpr node is used only within C++ templates when /// the qualification (e.g., X<T>::) refers to a dependent type. In @@ -1108,8 +1073,8 @@ public: /// declaration will differ from on instantiation of X<T> to the /// next. Therefore, UnresolvedDeclRefExpr keeps track of the /// qualifier (X<T>::) and the name of the entity being referenced -/// ("value"). Such expressions will instantiate to -/// QualifiedDeclRefExprs. +/// ("value"). Such expressions will instantiate to a DeclRefExpr once the +/// declaration can be found. class UnresolvedDeclRefExpr : public Expr { /// The name of the entity we will be referencing. DeclarationName Name; @@ -1126,6 +1091,7 @@ class UnresolvedDeclRefExpr : public Expr { NestedNameSpecifier *NNS; /// \brief Whether this expr is an address of (&) operand. + /// FIXME: Stash this bit into NNS! bool IsAddressOfOperand; public: diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index 8d7e4b5fc0a..034029a1697 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/include/clang/AST/StmtNodes.def @@ -127,7 +127,6 @@ EXPR(CXXDeleteExpr , Expr) EXPR(CXXPseudoDestructorExpr, Expr) EXPR(UnresolvedFunctionNameExpr , Expr) EXPR(UnaryTypeTraitExpr , Expr) -EXPR(QualifiedDeclRefExpr , DeclRefExpr) EXPR(UnresolvedDeclRefExpr , Expr) EXPR(TemplateIdRefExpr , Expr) EXPR(CXXConstructExpr , Expr) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index a4de3e5b0f7..47df95dc71b 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -30,6 +30,91 @@ using namespace clang; // Primary Expressions. //===----------------------------------------------------------------------===// +DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD) + : Expr(DeclRefExprClass, T, TD, VD), + DecoratedD(D, + (Qualifier? HasQualifierFlag : 0) | + (HasExplicitTemplateArgumentList? + HasExplicitTemplateArgumentListFlag : 0)), + Loc(NameLoc) { + if (Qualifier) { + NameQualifier *NQ = getNameQualifier(); + NQ->NNS = Qualifier; + NQ->Range = QualifierRange; + } + + if (HasExplicitTemplateArgumentList) { + ExplicitTemplateArgumentList *ETemplateArgs + = getExplicitTemplateArgumentList(); + ETemplateArgs->LAngleLoc = LAngleLoc; + ETemplateArgs->RAngleLoc = RAngleLoc; + ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs; + + TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs(); + for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I) + new (TemplateArgs + I) TemplateArgument(ExplicitTemplateArgs[I]); + } +} + +DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + QualType T, bool TD, bool VD) { + return Create(Context, Qualifier, QualifierRange, D, NameLoc, + false, SourceLocation(), 0, 0, SourceLocation(), + T, TD, VD); +} + +DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD) { + std::size_t Size = sizeof(DeclRefExpr); + if (Qualifier != 0) + Size += sizeof(NameQualifier); + + if (HasExplicitTemplateArgumentList) + Size += sizeof(ExplicitTemplateArgumentList) + + sizeof(TemplateArgument) * NumExplicitTemplateArgs; + + void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); + return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc, + HasExplicitTemplateArgumentList, + LAngleLoc, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + RAngleLoc, + T, TD, VD); +} + +SourceRange DeclRefExpr::getSourceRange() const { + // FIXME: Does not handle multi-token names well, e.g., operator[]. + SourceRange R(Loc); + + if (hasQualifier()) + R.setBegin(getQualifierRange().getBegin()); + if (hasExplicitTemplateArgumentList()) + R.setEnd(getRAngleLoc()); + return R; +} + // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT, @@ -855,8 +940,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType()) return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx); return LV_Valid; - case DeclRefExprClass: - case QualifiedDeclRefExprClass: { // C99 6.5.1p2 + case DeclRefExprClass: { // C99 6.5.1p2 const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl(); if (DeclCanBeLvalue(RefdDecl, Ctx)) return LV_Valid; @@ -1133,8 +1217,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx); case CStyleCastExprClass: return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx); - case DeclRefExprClass: - case QualifiedDeclRefExprClass: { + case DeclRefExprClass: { const Decl *D = cast<DeclRefExpr>(this)->getDecl(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage()) @@ -1432,7 +1515,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return ICEDiag(2, E->getLocStart()); } case Expr::DeclRefExprClass: - case Expr::QualifiedDeclRefExprClass: if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) return NoDiag(); if (Ctx.getLangOptions().CPlusPlus && diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 2af19765dfa..4bd7f964be6 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -473,14 +473,14 @@ void StmtPrinter::VisitExpr(Expr *Node) { } void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { + if (NestedNameSpecifier *Qualifier = Node->getQualifier()) + Qualifier->print(OS, Policy); OS << Node->getDecl()->getNameAsString(); -} - -void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) { - NamedDecl *D = Node->getDecl(); - - Node->getQualifier()->print(OS, Policy); - OS << D->getNameAsString(); + if (Node->hasExplicitTemplateArgumentList()) + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), + Node->getNumTemplateArgs(), + Policy); } void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c4d42f6be22..a6327c9ea70 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -206,7 +206,9 @@ void StmtProfiler::VisitExpr(Expr *S) { void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) { VisitExpr(S); + VisitNestedNameSpecifier(S->getQualifier()); VisitDecl(S->getDecl()); + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) { @@ -521,11 +523,6 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) { VisitType(S->getQueriedType()); } -void StmtProfiler::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *S) { - VisitDeclRefExpr(S); - VisitNestedNameSpecifier(S->getQualifier()); -} - void StmtProfiler::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *S) { VisitExpr(S); VisitName(S->getDeclName()); diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index ea0255ded8a..08e02feb082 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -409,7 +409,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { } case Stmt::DeclRefExprClass: - case Stmt::QualifiedDeclRefExprClass: VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false); break; @@ -522,7 +521,6 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, return; case Stmt::DeclRefExprClass: - case Stmt::QualifiedDeclRefExprClass: VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true); return; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index bb487f6e3fd..ca0d4b7c604 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -245,7 +245,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::VAArgExprClass: return EmitVAArgExprLValue(cast<VAArgExpr>(E)); case Expr::DeclRefExprClass: - case Expr::QualifiedDeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E)); case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); case Expr::PredefinedExprClass: @@ -866,9 +865,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { llvm::Value *V = LocalDeclMap[IPD]; assert(V && "BlockVarDecl not entered in LocalDeclMap?"); return LValue::MakeAddr(V, MakeQualifiers(E->getType())); - } else if (const QualifiedDeclRefExpr *QDRExpr = - dyn_cast<QualifiedDeclRefExpr>(E)) { - return EmitPointerToDataMemberLValue(QDRExpr); + } else if (E->getQualifier()) { + // FIXME: the qualifier check does not seem sufficient here + return EmitPointerToDataMemberLValue(E); } assert(0 && "Unimp declref"); //an invalid LValue, but the assert will @@ -1519,8 +1518,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { } -LValue CodeGenFunction::EmitPointerToDataMemberLValue( - const QualifiedDeclRefExpr *E) { +LValue CodeGenFunction::EmitPointerToDataMemberLValue(const DeclRefExpr *E) { const FieldDecl *Field = cast<FieldDecl>(E->getDecl()); const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext()); QualType NNSpecTy = diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index f47b6ab3c8c..5f12d427cf8 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -297,7 +297,7 @@ void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) { assert(MPT->getPointeeType()->isFunctionProtoType() && "Unexpected member pointer type!"); - const QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr()); + const DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr()); const CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl()); const llvm::Type *PtrDiffTy = diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index fc3748c8e3c..f8923efd24a 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -434,7 +434,7 @@ public: E->getType()->getAs<MemberPointerType>()) { QualType T = MPT->getPointeeType(); if (T->isFunctionProtoType()) { - QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr()); + DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr()); return EmitMemberFunctionPointer(cast<CXXMethodDecl>(DRE->getDecl())); } @@ -739,8 +739,7 @@ public: E->getType().getAddressSpace()); return C; } - case Expr::DeclRefExprClass: - case Expr::QualifiedDeclRefExprClass: { + case Expr::DeclRefExprClass: { NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) return CGM.GetAddrOfFunction(FD); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 639e683f036..f290571b7d7 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -819,7 +819,7 @@ public: LValue EmitConditionalOperatorLValue(const ConditionalOperator *E); LValue EmitCastLValue(const CastExpr *E); LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E); - LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E); + LValue EmitPointerToDataMemberLValue(const DeclRefExpr *E); llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); diff --git a/clang/lib/Frontend/PCHReaderStmt.cpp b/clang/lib/Frontend/PCHReaderStmt.cpp index 4b9496e00f8..60f6d196009 100644 --- a/clang/lib/Frontend/PCHReaderStmt.cpp +++ b/clang/lib/Frontend/PCHReaderStmt.cpp @@ -347,6 +347,8 @@ unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { VisitExpr(E); E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); + // FIXME: read qualifier + // FIXME: read explicit template arguments return 0; } diff --git a/clang/lib/Frontend/PCHWriterStmt.cpp b/clang/lib/Frontend/PCHWriterStmt.cpp index 9497f973f6b..afed7fae58f 100644 --- a/clang/lib/Frontend/PCHWriterStmt.cpp +++ b/clang/lib/Frontend/PCHWriterStmt.cpp @@ -314,6 +314,8 @@ void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { VisitExpr(E); Writer.AddDeclRef(E->getDecl(), Record); Writer.AddSourceLocation(E->getLocation(), Record); + // FIXME: write qualifier + // FIXME: write explicit template arguments Code = pch::EXPR_DECL_REF; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 589b0c6bd0e..b7ccedec709 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1420,8 +1420,7 @@ static DeclRefExpr* EvalVal(Expr *E) { // viewed AST node. We then recursively traverse the AST by calling // EvalAddr and EvalVal appropriately. switch (E->getStmtClass()) { - case Stmt::DeclRefExprClass: - case Stmt::QualifiedDeclRefExprClass: { + case Stmt::DeclRefExprClass: { // DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking // at code that refers to a variable's name. We check if it has local // storage within the function, and if so, return the expression. diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 381151325a0..b877b1cadb5 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1171,8 +1171,7 @@ void Sema::CodeCompleteCase(Scope *S) { // At the XXX, our completions are TagDecl::TK_union, // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, // TK_struct, and TK_class. - if (QualifiedDeclRefExpr *QDRE = dyn_cast<QualifiedDeclRefExpr>(DRE)) - Qualifier = QDRE->getQualifier(); + Qualifier = DRE->getQualifier(); } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ae45429952c..accdc7e5c85 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -446,9 +446,7 @@ Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, isAddressOfOperand); } -/// BuildDeclRefExpr - Build either a DeclRefExpr or a -/// QualifiedDeclRefExpr based on whether or not SS is a -/// nested-name-specifier. +/// BuildDeclRefExpr - Build a DeclRefExpr. Sema::OwningExprResult Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, bool TypeDependent, bool ValueDependent, @@ -476,15 +474,11 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, MarkDeclarationReferenced(Loc, D); - Expr *E; - if (SS && !SS->isEmpty()) { - E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, - ValueDependent, SS->getRange(), - static_cast<NestedNameSpecifier *>(SS->getScopeRep())); - } else - E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent); - - return Owned(E); + return Owned(DeclRefExpr::Create(Context, + SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, + SS? SS->getRange() : SourceRange(), + D, Loc, + Ty, TypeDependent, ValueDependent)); } /// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or @@ -2738,16 +2732,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, cast<UnaryOperator>(FnExpr)->getOpcode() == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) { - // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). - ArgumentDependentLookup = false; - Qualifier = QDRExpr->getQualifier(); - QualifierRange = QDRExpr->getQualifierRange(); - Function = dyn_cast<NamedDecl>(QDRExpr->getDecl()); - break; } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { Function = dyn_cast<NamedDecl>(DRExpr->getDecl()); + if ((Qualifier = DRExpr->getQualifier())) { + ArgumentDependentLookup = false; + QualifierRange = DRExpr->getQualifierRange(); + } break; } else if (UnresolvedFunctionNameExpr *DepName = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { @@ -2933,16 +2923,10 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, return ExprError(); // Update Fn to refer to the actual function selected. - Expr *NewFn = 0; - if (Qualifier) - NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), - Fn->getLocStart(), - false, false, - QualifierRange, - Qualifier); - else - NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(), - Fn->getLocStart()); + // FIXME: Use FixOverloadedFunctionReference? + Expr *NewFn = DeclRefExpr::Create(Context, Qualifier, QualifierRange, FDecl, + Fn->getLocStart(), FDecl->getType(), false, + false); Fn->Destroy(Context); Fn = NewFn; } @@ -5083,7 +5067,6 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, static NamedDecl *getPrimaryDecl(Expr *E) { switch (E->getStmtClass()) { case Stmt::DeclRefExprClass: - case Stmt::QualifiedDeclRefExprClass: return cast<DeclRefExpr>(E)->getDecl(); case Stmt::MemberExprClass: // If this is an arrow operator, the address is an offset from @@ -5199,7 +5182,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit // scope qualifier for the class. - if (isa<QualifiedDeclRefExpr>(op)) { + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) { DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (FD->getType()->isReferenceType()) { @@ -5216,7 +5199,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) { // Okay: we can take the address of a function. // As above. - if (isa<QualifiedDeclRefExpr>(op) && MD->isInstance()) + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() && + MD->isInstance()) return Context.getMemberPointerType(op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); } else if (!isa<FunctionDecl>(dcl)) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index ebcf3ad8e2b..9e79b999e7f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5370,18 +5370,19 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (Method->isStatic()) { // Do nothing: static member functions aren't any different // from non-member functions. - } else if (QualifiedDeclRefExpr *DRE - = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr())) { - // We have taken the address of a pointer to member - // function. Perform the computation here so that we get the - // appropriate pointer to member type. - DRE->setDecl(Fn); - DRE->setType(Fn->getType()); - QualType ClassType - = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); - E->setType(Context.getMemberPointerType(Fn->getType(), - ClassType.getTypePtr())); - return E; + } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) { + if (DRE->getQualifier()) { + // We have taken the address of a pointer to member + // function. Perform the computation here so that we get the + // appropriate pointer to member type. + DRE->setDecl(Fn); + DRE->setType(Fn->getType()); + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); + E->setType(Context.getMemberPointerType(Fn->getType(), + ClassType.getTypePtr())); + return E; + } } // FIXME: TemplateIdRefExpr referring to a member function template // specialization! @@ -5401,18 +5402,20 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { MemExpr->setMemberDecl(Fn); E->setType(Fn->getType()); } else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) { - // FIXME: We should capture the template arguments here. - if (NestedNameSpecifier *Qualifier = TID->getQualifier()) - E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(), - TID->getTemplateNameLoc(), - /*FIXME?*/false, /*FIXME?*/false, - TID->getQualifierRange(), - Qualifier); - else - E = new (Context) DeclRefExpr(Fn, Fn->getType(), - TID->getTemplateNameLoc()); + E = DeclRefExpr::Create(Context, + TID->getQualifier(), TID->getQualifierRange(), + Fn, TID->getTemplateNameLoc(), + true, + TID->getLAngleLoc(), + TID->getTemplateArgs(), + TID->getNumTemplateArgs(), + TID->getRAngleLoc(), + Fn->getType(), + /*FIXME?*/false, /*FIXME?*/false); - TID->Destroy(Context); + // FIXME: Don't destroy TID here, since we need its template arguments + // to survive. + // TID->Destroy(Context); } else { assert(false && "Invalid reference to overloaded function"); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0f223208a93..2bb790dda4e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1845,7 +1845,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { // template-parameter shall be one of: [...] // // -- a pointer to member expressed as described in 5.3.1. - QualifiedDeclRefExpr *DRE = 0; + DeclRefExpr *DRE = 0; // Ignore (and complain about) any excess parentheses. while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { @@ -1860,8 +1860,11 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { } if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) - if (UnOp->getOpcode() == UnaryOperator::AddrOf) - DRE = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr()); + if (UnOp->getOpcode() == UnaryOperator::AddrOf) { + DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); + if (DRE && !DRE->getQualifier()) + DRE = 0; + } if (!DRE) return Diag(Arg->getSourceRange().getBegin(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 53d158088c8..1790d27eeb3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -618,10 +618,21 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this? InstD = InstD->getUnderlyingDecl(); - // FIXME: nested-name-specifier for QualifiedDeclRefExpr + CXXScopeSpec SS; + NestedNameSpecifier *Qualifier = 0; + if (E->getQualifier()) { + Qualifier = TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (!Qualifier) + return SemaRef.ExprError(); + + SS.setScopeRep(Qualifier); + SS.setRange(E->getQualifierRange()); + } + return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, /*FIXME:*/false, - /*FIXME:*/0, + &SS, /*FIXME:*/false); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index dec94994a8a..94a0e11ec8e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -781,10 +781,15 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildDeclRefExpr(NamedDecl *ND, SourceLocation Loc) { + OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *ND, SourceLocation Loc) { + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + SS.setRange(QualifierRange); return getSema().BuildDeclarationNameExpr(Loc, ND, /*FIXME:*/false, - /*SS=*/0, + &SS, /*FIXME:*/false); } @@ -1392,26 +1397,6 @@ public: T.getAsOpaquePtr(), RParenLoc); } - /// \brief Build a new qualified declaration reference expression. - /// - /// By default, performs semantic analysis to build the new expression. - /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildQualifiedDeclRefExpr(NestedNameSpecifier *NNS, - SourceRange QualifierRange, - NamedDecl *ND, - SourceLocation Location, - bool IsAddressOfOperand) { - CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(NNS); - return getSema().ActOnDeclarationNameExpr(/*Scope=*/0, - Location, - ND->getDeclName(), - /*Trailing lparen=*/false, - &SS, - IsAddressOfOperand); - } - /// \brief Build a new (previously unresolved) declaration reference /// expression. /// @@ -3276,15 +3261,40 @@ TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { + NestedNameSpecifier *Qualifier = 0; + if (E->getQualifier()) { + Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (!Qualifier) + return SemaRef.ExprError(); + } + NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl())); if (!ND) return SemaRef.ExprError(); - if (!getDerived().AlwaysRebuild() && ND == E->getDecl()) + if (!getDerived().AlwaysRebuild() && + Qualifier == E->getQualifier() && + ND == E->getDecl() && + !E->hasExplicitTemplateArgumentList()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildDeclRefExpr(ND, E->getLocation()); + // FIXME: We're losing the explicit template arguments in this transformation. + + llvm::SmallVector<TemplateArgument, 4> TransArgs; + for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { + TemplateArgument TransArg + = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]); + if (TransArg.isNull()) + return SemaRef.ExprError(); + + TransArgs.push_back(TransArg); + } + + // FIXME: Pass the qualifier/qualifier range along. + return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(), + ND, E->getLocation()); } template<typename Derived> @@ -4301,32 +4311,6 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) { - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!NNS) - return SemaRef.ExprError(); - - NamedDecl *ND - = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl())); - if (!ND) - return SemaRef.ExprError(); - - if (!getDerived().AlwaysRebuild() && - NNS == E->getQualifier() && - ND == E->getDecl()) - return SemaRef.Owned(E->Retain()); - - return getDerived().RebuildQualifiedDeclRefExpr(NNS, - E->getQualifierRange(), - ND, - E->getLocation(), - /*FIXME:*/false); -} - -template<typename Derived> -Sema::OwningExprResult TreeTransform<Derived>::TransformUnresolvedDeclRefExpr( UnresolvedDeclRefExpr *E) { NestedNameSpecifier *NNS |