aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h9
-rw-r--r--include/clang/AST/ExprCXX.h27
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/Basic/SourceManager.h1
-rw-r--r--lib/AST/Expr.cpp7
-rw-r--r--lib/AST/StmtPrinter.cpp30
-rw-r--r--lib/AST/StmtSerialization.cpp14
-rw-r--r--lib/Analysis/GRExprEngine.cpp2
-rw-r--r--lib/CodeGen/CGExpr.cpp4
-rw-r--r--lib/CodeGen/CGExprConstant.cpp3
-rw-r--r--lib/Sema/Sema.h4
-rw-r--r--lib/Sema/SemaChecking.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp6
-rw-r--r--lib/Sema/SemaExpr.cpp50
-rw-r--r--test/SemaCXX/qualified-id-lookup.cpp1
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;