]> granicus.if.org Git - clang/commitdiff
If we end up instantiating a function parameter whose default argument
authorDouglas Gregor <dgregor@apple.com>
Tue, 12 Oct 2010 18:23:32 +0000 (18:23 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 12 Oct 2010 18:23:32 +0000 (18:23 +0000)
has not yet been parsed, note that the default argument hasn't been
parsed and keep track of all of the instantiations of that function
parameter. When its default argument does get parsed, imbue the
instantiations with that default argument. Fixes PR8245.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116324 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/CXX/class/class.mem/p1.cpp

index 7d5fda20ba350d9e9c3e865a6d13d753d0a55e93..7e0497836870d494d813a9c89977e6aaa780394c 100644 (file)
@@ -484,6 +484,22 @@ public:
   /// \brief The number of SFINAE diagnostics that have been trapped.
   unsigned NumSFINAEErrors;
 
+  typedef llvm::DenseMap<ParmVarDecl *, llvm::SmallVector<ParmVarDecl *, 1> >
+    UnparsedDefaultArgInstantiationsMap;
+  
+  /// \brief A mapping from parameters with unparsed default arguments to the
+  /// set of instantiations of each parameter.
+  ///
+  /// This mapping is a temporary data structure used when parsing
+  /// nested class templates or nested classes of class templates,
+  /// where we might end up instantiating an inner class before the
+  /// default arguments of its methods have been parsed. 
+  UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations;
+  
+  // Contains the locations of the beginning of unparsed default
+  // argument locations.
+  llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
+
   typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
   typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
 
@@ -497,7 +513,6 @@ public:
   /// of -Wselector.
   llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
 
-
   GlobalMethodPool::iterator ReadMethodPool(Selector Sel);
 
   /// Private Helper predicate to check for 'self'.
@@ -723,11 +738,6 @@ public:
   bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
                                SourceLocation EqualLoc);
 
-
-  // Contains the locations of the beginning of unparsed default
-  // argument locations.
-  llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
-
   void AddInitializerToDecl(Decl *dcl, Expr *init);
   void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
   void ActOnUninitializedDecl(Decl *dcl, bool TypeContainsUndeducedAuto);
index a27785e4f3571d8e8d41e02a5e060bb2b9176e28..ec02f75ecbe5bb93afda91f022e7b0e78c0777d7 100644 (file)
@@ -142,6 +142,18 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
   // Okay: add the default argument to the parameter
   Param->setDefaultArg(Arg);
 
+  // We have already instantiated this parameter; provide each of the 
+  // instantiations with the uninstantiated default argument.
+  UnparsedDefaultArgInstantiationsMap::iterator InstPos
+    = UnparsedDefaultArgInstantiations.find(Param);
+  if (InstPos != UnparsedDefaultArgInstantiations.end()) {
+    for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I)
+      InstPos->second[I]->setUninstantiatedDefaultArg(Arg);
+    
+    // We're done tracking this parameter's instantiations.
+    UnparsedDefaultArgInstantiations.erase(InstPos);
+  }
+  
   return false;
 }
 
index a2c3df653b7a0d1bfc0c4a940a863cacb413b714..98b8ccd8d850d987f92d514bbcb3b5a5f35e36dc 100644 (file)
@@ -1062,6 +1062,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
   if (OldParm->hasUninstantiatedDefaultArg()) {
     Expr *Arg = OldParm->getUninstantiatedDefaultArg();
     NewParm->setUninstantiatedDefaultArg(Arg);
+  } else if (OldParm->hasUnparsedDefaultArg()) {
+    NewParm->setUnparsedDefaultArg();
+    UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
   } else if (Expr *Arg = OldParm->getDefaultArg())
     NewParm->setUninstantiatedDefaultArg(Arg);
 
index 55507d4e961616ec2d5b408fbbfcccfe7d2997fc..a41f1dbb75ec1d51f4a35e1e6943993c155b1641 100644 (file)
@@ -62,3 +62,30 @@ struct S5
   
   
 };
+
+namespace PR8245 {
+  class X {
+  public:
+    template<class C> 
+    class Inner {
+    public:
+      void foo(bool bar = true);
+      int bam;
+    };
+
+    Inner<int> _foo;    
+  };
+
+  void f() {
+    X::Inner<int> c2i;
+    X::Inner<float> c2f;
+    c2i.foo();
+    c2f.foo();
+  }
+
+  class Y {
+    class Inner {
+      void foo(int = sizeof(Y));
+    };
+  };
+}