aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/Sema.h22
-rw-r--r--lib/Sema/SemaDeclCXX.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp3
-rw-r--r--test/CXX/class/class.mem/p1.cpp27
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));
+ };
+ };
+}