[cfe-commits] r61789 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/ExprCXX.h include/clang/AST/StmtNodes.def include/clang/Basic/SourceManager.h lib/AST/Expr.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtSerialization.cpp lib/Analysis/GRExprEngine.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprConstant.cpp lib/Sema/Sema.h lib/Sema/SemaChecking.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp test/SemaCXX/qualified-id-lookup.cpp

Douglas Gregor dgregor at apple.com
Mon Jan 5 21:10:23 PST 2009


Author: dgregor
Date: Mon Jan  5 23:10:23 2009
New Revision: 61789

URL: http://llvm.org/viewvc/llvm-project?rev=61789&view=rev
Log:
Add QualifiedDeclRefExpr, which retains additional source-location
information for declarations that were referenced via a qualified-id,
e.g., N::C::value. We keep track of the location of the start of the
nested-name-specifier. Note that the difference between
QualifiedDeclRefExpr and DeclRefExpr does have an effect on the
semantics of function calls in two ways:
  1) The use of a qualified-id instead of an unqualified-id suppresses
     argument-dependent lookup
  2) If the name refers to a virtual function, the qualified-id
  version will call the function determined statically while the
  unqualified-id version will call the function determined dynamically
  (by looking up the appropriate function in the vtable).

Neither of these features is implemented yet, but we do print out
qualified names for QualifiedDeclRefExprs as part of the AST printing.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtSerialization.cpp
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Jan  5 23:10:23 2009
@@ -273,9 +273,15 @@
   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 @@
   
   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; }
   

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Jan  5 23:10:23 2009
@@ -747,6 +747,33 @@
   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

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Mon Jan  5 23:10:23 2009
@@ -114,6 +114,7 @@
 STMT(CXXDeleteExpr          , Expr)
 STMT(CXXDependentNameExpr   , Expr)
 STMT(UnaryTypeTraitExpr     , Expr)
+STMT(QualifiedDeclRefExpr   , DeclRefExpr)
 
 // Obj-C Expressions.
 STMT(ObjCStringLiteral    , Expr)

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Mon Jan  5 23:10:23 2009
@@ -49,6 +49,7 @@
   /// 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;

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Jan  5 23:10:23 2009
@@ -395,7 +395,8 @@
     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 @@
     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 @@
     return false;
   }
   case DeclRefExprClass:
+  case QualifiedDeclRefExprClass:
     if (const EnumConstantDecl *D = 
           dyn_cast<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl())) {
       Result = D->getInitVal();

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Jan  5 23:10:23 2009
@@ -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 @@
   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());

Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Mon Jan  5 23:10:23 2009
@@ -249,6 +249,9 @@
 
     case CXXTryStmtClass:
       return CXXTryStmt::CreateImpl(D, C);
+
+    case QualifiedDeclRefExprClass:
+      return QualifiedDeclRefExpr::CreateImpl(D, C);
   }
 }
 
@@ -1578,3 +1581,14 @@
 
   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;
+}

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Jan  5 23:10:23 2009
@@ -347,6 +347,7 @@
     }
       
     case Stmt::DeclRefExprClass:
+    case Stmt::QualifiedDeclRefExprClass:
       VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
       break;
       
@@ -446,6 +447,7 @@
       return;
       
     case Stmt::DeclRefExprClass:
+    case Stmt::QualifiedDeclRefExprClass:
       VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
       return;
       

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Jan  5 23:10:23 2009
@@ -116,7 +116,9 @@
   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));

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Jan  5 23:10:23 2009
@@ -542,7 +542,8 @@
                                    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);

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan  5 23:10:23 2009
@@ -43,6 +43,7 @@
   class Expr;
   class InitListExpr;
   class CallExpr;
+  class DeclRefExpr;
   class VarDecl;
   class ParmVarDecl;
   class TypedefDecl;
@@ -674,6 +675,9 @@
                                                     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,

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jan  5 23:10:23 2009
@@ -883,7 +883,8 @@
   // 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.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan  5 23:10:23 2009
@@ -1570,7 +1570,8 @@
   }
   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 @@
     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;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jan  5 23:10:23 2009
@@ -358,6 +358,19 @@
   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 @@
 
   // 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 @@
     //      (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 @@
 
   // 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 @@
       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 @@
 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.

Modified: cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp?rev=61789&r1=61788&r2=61789&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp (original)
+++ cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp Mon Jan  5 23:10:23 2009
@@ -59,6 +59,7 @@
   int &v1 = N::f1();
   float &v2 = N::f1(i);
   int v3 = ::i1;
+  int v4 = N::f1::member;
 }
 
 typedef int f2_type;





More information about the cfe-commits mailing list