diff options
-rw-r--r-- | include/clang/AST/Expr.h | 9 | ||||
-rw-r--r-- | include/clang/AST/ExprCXX.h | 27 | ||||
-rw-r--r-- | include/clang/AST/StmtNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Basic/SourceManager.h | 1 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 7 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 30 | ||||
-rw-r--r-- | lib/AST/StmtSerialization.cpp | 14 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 50 | ||||
-rw-r--r-- | test/SemaCXX/qualified-id-lookup.cpp | 1 |
15 files changed, 138 insertions, 24 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 62a93b51e8..0490aab200 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -273,9 +273,15 @@ class DeclRefExpr : public Expr { SourceLocation Loc; 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) {} + DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD, + bool VD) : + Expr(SC, t, TD, VD), D(d), Loc(l) {} + public: // FIXME: Eventually, this constructor will go away and all clients // will have to provide the type- and value-dependent flags. @@ -294,7 +300,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass || - T->getStmtClass() == CXXConditionDeclExprClass; + T->getStmtClass() == CXXConditionDeclExprClass || + T->getStmtClass() == QualifiedDeclRefExprClass; } static bool classof(const DeclRefExpr *) { return true; } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 37436575a2..a9ff1546e9 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -747,6 +747,33 @@ public: static UnaryTypeTraitExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C); }; +/// QualifiedDeclRefExpr - A reference to a declared variable, +/// function, enum, etc., that includes a qualification, e.g., +/// "N::foo". +class QualifiedDeclRefExpr : public DeclRefExpr { + /// NestedNameLoc - The location of the beginning of the + /// nested-name-specifier that qualifies this declaration. + SourceLocation NestedNameLoc; + +public: + QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, + bool VD, SourceLocation nnl) + : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), + NestedNameLoc(nnl) { } + + virtual SourceRange getSourceRange() const { + return SourceRange(NestedNameLoc, getLocation()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == QualifiedDeclRefExprClass; + } + static bool classof(const QualifiedDeclRefExpr *) { return true; } + + virtual void EmitImpl(llvm::Serializer& S) const; + static QualifiedDeclRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); +}; + } // end namespace clang #endif diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 7bd378220b..26d1e89637 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -114,6 +114,7 @@ STMT(CXXNewExpr , Expr) STMT(CXXDeleteExpr , Expr) STMT(CXXDependentNameExpr , Expr) STMT(UnaryTypeTraitExpr , Expr) +STMT(QualifiedDeclRefExpr , DeclRefExpr) // Obj-C Expressions. STMT(ObjCStringLiteral , Expr) diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 175c40488c..5185aa1655 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -49,6 +49,7 @@ namespace SrcMgr { /// ContentCache - Once instance of this struct is kept for every file /// loaded or used. This object owns the MemoryBuffer object. class ContentCache { + public: /// Buffer - The actual buffer containing the characters from the input /// file. This is owned by the ContentCache object. const llvm::MemoryBuffer* Buffer; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index eafa717d65..26260132e7 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -395,7 +395,8 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType()) return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx); return LV_Valid; - case DeclRefExprClass: { // C99 6.5.1p2 + case DeclRefExprClass: + case QualifiedDeclRefExprClass: { // C99 6.5.1p2 const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl(); if (DeclCanBeLvalue(RefdDecl, Ctx)) return LV_Valid; @@ -638,7 +639,8 @@ bool Expr::hasGlobalStorage() const { return cast<ImplicitCastExpr>(this)->getSubExpr()->hasGlobalStorage(); case CompoundLiteralExprClass: return cast<CompoundLiteralExpr>(this)->isFileScope(); - case DeclRefExprClass: { + case DeclRefExprClass: + case QualifiedDeclRefExprClass: { const Decl *D = cast<DeclRefExpr>(this)->getDecl(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->hasGlobalStorage(); @@ -813,6 +815,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, return false; } case DeclRefExprClass: + case QualifiedDeclRefExprClass: if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl())) { Result = D->getInitVal(); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 89a185d965..679c897497 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/StmtVisitor.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/PrettyPrinter.h" #include "llvm/Support/Compiler.h" @@ -513,6 +514,35 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { OS << Node->getDecl()->getNameAsString(); } +void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) { + // FIXME: Should we keep enough information in QualifiedDeclRefExpr + // to produce the same qualification that the user wrote? + llvm::SmallVector<DeclContext *, 4> Contexts; + + NamedDecl *D = Node->getDecl(); + + // Build up a stack of contexts. + DeclContext *Ctx = 0; + if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) + Ctx = SD->getDeclContext(); + else if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) + Ctx = Ovl->getDeclContext(); + for (; Ctx; Ctx = Ctx->getParent()) + if (!Ctx->isTransparentContext()) + Contexts.push_back(Ctx); + + while (!Contexts.empty()) { + DeclContext *Ctx = Contexts.back(); + if (isa<TranslationUnitDecl>(Ctx)) + OS << "::"; + else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(Ctx)) + OS << SD->getNameAsString() << "::"; + Contexts.pop_back(); + } + + OS << D->getNameAsString(); +} + void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { if (Node->getBase()) { PrintExpr(Node->getBase()); diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index f7c4cf9b93..02ccde3da2 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/lib/AST/StmtSerialization.cpp @@ -249,6 +249,9 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) { case CXXTryStmtClass: return CXXTryStmt::CreateImpl(D, C); + + case QualifiedDeclRefExprClass: + return QualifiedDeclRefExpr::CreateImpl(D, C); } } @@ -1578,3 +1581,14 @@ CXXTryStmt::CreateImpl(llvm::Deserializer& D, ASTContext& C) { return new CXXTryStmt(TryLoc, Stmts[0], &Stmts[1], size - 1); } + +void QualifiedDeclRefExpr::EmitImpl(llvm::Serializer& S) const { + DeclRefExpr::EmitImpl(S); + S.Emit(NestedNameLoc); +} + +QualifiedDeclRefExpr* +QualifiedDeclRefExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { + assert(false && "Cannot deserialize qualified decl references"); + return 0; +} diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index b5a9cb4809..1487ed6f2c 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -347,6 +347,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) { } case Stmt::DeclRefExprClass: + case Stmt::QualifiedDeclRefExprClass: VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false); break; @@ -446,6 +447,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) { return; case Stmt::DeclRefExprClass: + case Stmt::QualifiedDeclRefExprClass: VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true); return; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 18ccb27301..2742395db8 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -116,7 +116,9 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: return EmitCallExprLValue(cast<CallExpr>(E)); - case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E)); + case Expr::DeclRefExprClass: + case Expr::QualifiedDeclRefExprClass: + return EmitDeclRefLValue(cast<DeclRefExpr>(E)); case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); case Expr::PredefinedExprClass: return EmitPredefinedLValue(cast<PredefinedExpr>(E)); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index a82efca614..71216a5d63 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -542,7 +542,8 @@ public: C, ".compoundliteral", &CGM.getModule()); return C; } - case Expr::DeclRefExprClass: { + case Expr::DeclRefExprClass: + case Expr::QualifiedDeclRefExprClass: { NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) return CGM.GetAddrOfFunction(FD); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e35c06dd2f..ccc6b8c4cb 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -43,6 +43,7 @@ namespace clang { class Expr; class InitListExpr; class CallExpr; + class DeclRefExpr; class VarDecl; class ParmVarDecl; class TypedefDecl; @@ -674,6 +675,9 @@ public: TypeTy *Ty, bool HasTrailingLParen, const CXXScopeSpec &SS); + DeclRefExpr *BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, + bool TypeDependent, bool ValueDependent, + const CXXScopeSpec *SS = 0); ExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, DeclarationName Name, bool HasTrailingLParen, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 14aa996821..5bb78cd765 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -883,7 +883,8 @@ 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::DeclRefExprClass: + case Stmt::QualifiedDeclRefExprClass: { // 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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0396f520a8..dce1e129a5 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1570,7 +1570,8 @@ bool Sema::CheckAddressConstantExpressionLValue(const Expr* Init) { } case Expr::CompoundLiteralExprClass: return cast<CompoundLiteralExpr>(Init)->isFileScope(); - case Expr::DeclRefExprClass: { + case Expr::DeclRefExprClass: + case Expr::QualifiedDeclRefExprClass: { const Decl *D = cast<DeclRefExpr>(Init)->getDecl(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage()) @@ -1829,7 +1830,8 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) { InitializerElementNotConstant(Init); return true; } - case Expr::DeclRefExprClass: { + case Expr::DeclRefExprClass: + case Expr::QualifiedDeclRefExprClass: { const Decl *D = cast<DeclRefExpr>(Init)->getDecl(); if (isa<EnumConstantDecl>(D)) return false; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5e07dfe8d8..8b2aca61ea 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -358,6 +358,19 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS); } +/// BuildDeclRefExpr - Build either a DeclRefExpr or a +/// QualifiedDeclRefExpr based on whether or not SS is a +/// nested-name-specifier. +DeclRefExpr *Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, + bool TypeDependent, bool ValueDependent, + const CXXScopeSpec *SS) { + if (SS && !SS->isEmpty()) + return new QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent, + SS->getRange().getBegin()); + else + return new DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent); +} + /// ActOnDeclarationNameExpr - The parser has read some kind of name /// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine /// performs lookup on that name and returns an expression that refers @@ -536,7 +549,7 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Make the DeclRefExpr or BlockDeclRefExpr for the decl. if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) - return new DeclRefExpr(Ovl, Context.OverloadTy, Loc); + return BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc, false, false, SS); ValueDecl *VD = cast<ValueDecl>(D); @@ -634,8 +647,8 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // (FIXME!). } - return new DeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, - TypeDependent, ValueDependent); + return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, + TypeDependent, ValueDependent, SS); } Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, @@ -1595,17 +1608,15 @@ Sema::ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc, // If we're directly calling a function or a set of overloaded // functions, get the appropriate declaration. - { - DeclRefExpr *DRExpr = NULL; - if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn)) - DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()); - else - DRExpr = dyn_cast<DeclRefExpr>(Fn); - - if (DRExpr) { - FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); - Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl()); - } + DeclRefExpr *DRExpr = NULL; + if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn)) + DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()); + else + DRExpr = dyn_cast<DeclRefExpr>(Fn); + + if (DRExpr) { + FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); + Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl()); } if (Ovl) { @@ -1615,8 +1626,14 @@ Sema::ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc, return true; // Update Fn to refer to the actual function selected. - Expr *NewFn = new DeclRefExpr(FDecl, FDecl->getType(), - Fn->getSourceRange().getBegin()); + Expr *NewFn = 0; + if (QualifiedDeclRefExpr *QDRExpr = dyn_cast<QualifiedDeclRefExpr>(DRExpr)) + NewFn = new QualifiedDeclRefExpr(FDecl, FDecl->getType(), + QDRExpr->getLocation(), false, false, + QDRExpr->getSourceRange().getBegin()); + else + NewFn = new DeclRefExpr(FDecl, FDecl->getType(), + Fn->getSourceRange().getBegin()); Fn->Destroy(Context); Fn = NewFn; } @@ -2928,6 +2945,7 @@ 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: // Fields cannot be declared with a 'register' storage class. diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index 1321d734d9..0ef8e69107 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -59,6 +59,7 @@ void test_f1(int i) { int &v1 = N::f1(); float &v2 = N::f1(i); int v3 = ::i1; + int v4 = N::f1::member; } typedef int f2_type; |