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.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5e07dfe..8b2aca6 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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.