[cfe-commits] r72481 - in /cfe/trunk: lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/example-dynarray.cpp test/SemaTemplate/instantiate-declref.cpp

Douglas Gregor dgregor at apple.com
Wed May 27 10:07:53 PDT 2009


Author: dgregor
Date: Wed May 27 12:07:49 2009
New Revision: 72481

URL: http://llvm.org/viewvc/llvm-project?rev=72481&view=rev
Log:
Improve name lookup for and template instantiation of declaration
references. There are several smallish fixes here:

  - Make sure we look through template parameter scope when
    determining whether we're parsing a nested class (or nested class
    *template*). This makes sure that we delay parsing the bodies of
    inline member functions until after we're out of the outermost
    class (template) scope.
  - Since the bodies of member functions are always parsed
    "out-of-line", even when they were declared in-line, teach
    unqualified name lookup to look into the (semantic) parents.
  - Use the new InstantiateDeclRef to handle the instantiation of a
    reference to a declaration (in DeclRefExpr), which drastically
    simplifies template instantiation for DeclRefExprs.
  - When we're instantiating a ParmVarDecl, it must be in the current
    instantiation scope, so only look there.

Also, remove the #if 0's and FIXME's from the dynarray example, which
now compiles and executes thanks to Anders and Eli.


Added:
    cfe/trunk/test/SemaTemplate/instantiate-declref.cpp
Modified:
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/SemaTemplate/example-dynarray.cpp

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=72481&r1=72480&r2=72481&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed May 27 12:07:49 2009
@@ -1067,7 +1067,9 @@
   //
   // FIXME: Only function bodies and constructor ctor-initializers are
   // parsed correctly, fix the rest.
-  if (!CurScope->getParent()->isClassScope()) {
+  if (!CurScope->getParent()->isClassScope() && 
+      !(CurScope->getParent()->isTemplateParamScope() &&
+        CurScope->getParent()->getParent()->isClassScope())) {
     // We are not inside a nested class. This class and its nested classes
     // are complete and we can parse the delayed portions of method
     // declarations and the lexed inline method definitions.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed May 27 12:07:49 2009
@@ -687,7 +687,8 @@
         if (R || RedeclarationOnly)
           return std::make_pair(true, R);
       }
-      if (Ctx->getParent() != Ctx->getLexicalParent()) {
+      if (Ctx->getParent() != Ctx->getLexicalParent() 
+          || isa<CXXMethodDecl>(Ctx)) {
         // It is out of line defined C++ method or struct, we continue
         // doing name lookup in parent context. Once we will find namespace
         // or translation-unit we save it for possible checking

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed May 27 12:07:49 2009
@@ -697,9 +697,13 @@
 NamedDecl *
 Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) {
   DeclContext *ParentDC = D->getDeclContext();
+  if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) {
+    // D is a local of some kind. Look into the map of local
+    // declarations to their instantiations.
+    return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
+  }
 
-  if (!ParentDC->isFileContext()) {
-    NamedDecl *ParentDecl = cast<NamedDecl>(ParentDC);
+  if (NamedDecl *ParentDecl = dyn_cast<NamedDecl>(ParentDC)) {
     ParentDecl = InstantiateDeclRef(ParentDecl, TemplateArgs);
     if (!ParentDecl)
       return 0;
@@ -707,12 +711,6 @@
     ParentDC = cast<DeclContext>(ParentDecl);
   }
 
-  if (ParentDC->isFunctionOrMethod()) {
-    // D is a local of some kind. Look into the map of local
-    // variables to their instantiations.
-    return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
-  }
-
   if (ParentDC != D->getDeclContext()) {
     // We performed some kind of instantiation in the parent context,
     // so now we need to look into the instantiated parent context to

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Wed May 27 12:07:49 2009
@@ -109,8 +109,7 @@
 Sema::OwningExprResult
 TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
   // FIXME: Recast this in terms of Sema::InstantiateDeclRef.
-  Decl *D = E->getDecl();
-  ValueDecl *NewD = 0;
+  NamedDecl *D = E->getDecl();
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     assert(NTTP->getDepth() == 0 && "No nested templates yet");
     const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
@@ -131,29 +130,22 @@
                                                  *Arg.getAsIntegral(),
                                                  T, 
                                        E->getSourceRange().getBegin()));
-  } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
-    NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
-  } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
-    if (Var->hasLocalStorage())
-      NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Var);
-    else
-      assert(false && 
-             "FIXME: instantiation of non-local variable declarations");
-  } else if (isa<FunctionDecl>(D)) {
-    // FIXME: Instantiate decl!
-    NewD = cast<ValueDecl>(D);
-  } else if (isa<OverloadedFunctionDecl>(D)) {
-    // FIXME: instantiate decls?
-    return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(cast<NamedDecl>(D),
+  }
+
+  if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
+    // FIXME: instantiate each decl in the overload set
+    return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl,
                                                    SemaRef.Context.OverloadTy,
                                                            E->getLocation(),
                                                            false, false));
-  } else
-    assert(false && "FIXME: unhandled declaration reference kind");
+  }
 
+  ValueDecl *NewD 
+    = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateDeclRef(D, TemplateArgs));
   if (!NewD)
     return SemaRef.ExprError();
 
+  // FIXME: Build QualifiedDeclRefExpr?
   QualType T = NewD->getType();
   return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(NewD,
                                                       T.getNonReferenceType(),

Modified: cfe/trunk/test/SemaTemplate/example-dynarray.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/example-dynarray.cpp?rev=72481&r1=72480&r2=72481&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/example-dynarray.cpp (original)
+++ cfe/trunk/test/SemaTemplate/example-dynarray.cpp Wed May 27 12:07:49 2009
@@ -120,8 +120,6 @@
   assert(di.size() == 4);
   di.push_back(4);
 
-#if 0
-  // FIXME: Copy construction via copy initialization
   dynarray<int> di2 = di;
   assert(di2.size() == 5);
   assert(di.begin() != di2.begin());
@@ -129,7 +127,6 @@
        I != IEnd; ++I)
     assert(*I == I - di2.begin());
 
-  // FIXME: Copy construction via direct initialization
   dynarray<int> di3(di);
   assert(di3.size() == 5);
   assert(di.begin() != di3.begin());
@@ -137,7 +134,6 @@
        I != IEnd; ++I)
     assert(*I == I - di3.begin());
 
-  // FIXME: assignment operator 
   dynarray<int> di4;
   assert(di4.size() == 0);
   di4 = di;
@@ -146,7 +142,6 @@
   for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end(); 
        I != IEnd; ++I)
     assert(*I == I - di4.begin());
-#endif
 
   return 0;
 }

Added: cfe/trunk/test/SemaTemplate/instantiate-declref.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-declref.cpp?rev=72481&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-declref.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-declref.cpp Wed May 27 12:07:49 2009
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only %s
+
+namespace N {
+  struct Outer {
+    struct Inner {
+      template<typename T>
+      struct InnerTemplate {
+        struct VeryInner {
+          typedef T type;
+
+          static enum K1 { K1Val = sizeof(T) } Kind1;
+          // FIXME: Remove the name K2, below
+          static enum K2 { K2Val = sizeof(T)*2 } Kind2;
+
+          void foo() {
+            K1 k1 = K1Val;
+            Kind1 = K1Val;
+            Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
+          }
+        };
+      };
+    };
+  };
+}
+
+typedef int INT;
+template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner;





More information about the cfe-commits mailing list