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.
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; }
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
STMT(CXXDeleteExpr , Expr)
STMT(CXXDependentNameExpr , Expr)
STMT(UnaryTypeTraitExpr , Expr)
+STMT(QualifiedDeclRefExpr , DeclRefExpr)
// Obj-C Expressions.
STMT(ObjCStringLiteral , Expr)
/// 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;
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;
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();
return false;
}
case DeclRefExprClass:
+ case QualifiedDeclRefExprClass:
if (const EnumConstantDecl *D =
dyn_cast<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl())) {
Result = D->getInitVal();
//===----------------------------------------------------------------------===//
#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"
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());
case CXXTryStmtClass:
return CXXTryStmt::CreateImpl(D, C);
+
+ case QualifiedDeclRefExprClass:
+ return QualifiedDeclRefExpr::CreateImpl(D, 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;
+}
}
case Stmt::DeclRefExprClass:
+ case Stmt::QualifiedDeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
break;
return;
case Stmt::DeclRefExprClass:
+ case Stmt::QualifiedDeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
return;
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));
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);
class Expr;
class InitListExpr;
class CallExpr;
+ class DeclRefExpr;
class VarDecl;
class ParmVarDecl;
class TypedefDecl;
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,
// 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.
}
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())
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;
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
// 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);
// (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,
// 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) {
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;
}
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.
int &v1 = N::f1();
float &v2 = N::f1(i);
int v3 = ::i1;
+ int v4 = N::f1::member;
}
typedef int f2_type;