diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 22 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 3 | ||||
-rw-r--r-- | test/CXX/class/class.mem/p1.cpp | 27 |
4 files changed, 58 insertions, 6 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 7d5fda20ba..7e04978368 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a27785e4f3..ec02f75ecb 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index a2c3df653b..98b8ccd8d8 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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); diff --git a/test/CXX/class/class.mem/p1.cpp b/test/CXX/class/class.mem/p1.cpp index 55507d4e96..a41f1dbb75 100644 --- a/test/CXX/class/class.mem/p1.cpp +++ b/test/CXX/class/class.mem/p1.cpp @@ -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)); + }; + }; +} |