aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-10-12 18:23:32 +0000
committerDouglas Gregor <dgregor@apple.com>2010-10-12 18:23:32 +0000
commit8cfb7a39caa44797522773cf417ad9c1a6ffbc6f (patch)
tree4757657779dca88a0dc9b0fd768fce36341b4902
parent75c29a012793292ff4578015a9113bf086156d7f (diff)
If we end up instantiating a function parameter whose default argument
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
-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));
+ };
+ };
+}