aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-24 23:39:01 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-24 23:39:01 +0000
commit7dfd0fb08300b60a9657748bda7d8b3ceb07babe (patch)
tree715b857826ec7e69eae325d2d3b0e7b3f6c6267c
parent6b304a0254a13f42390b865ff5ba668a49cc58ae (diff)
When entering the scope of a declarator, make sure that the scope is
complete (or, possibly causing template instantiation). Test this via some explicit specializations of member functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82732 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Parse/Action.h4
-rw-r--r--include/clang/Parse/Parser.h4
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp12
-rw-r--r--test/SemaTemplate/explicit-specialization-member.cpp11
5 files changed, 28 insertions, 5 deletions
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index df85dfe8eb..8fdf779acd 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -300,7 +300,9 @@ public:
/// looked up in the declarator-id's scope, until the declarator is parsed and
/// ActOnCXXExitDeclaratorScope is called.
/// The 'SS' should be a non-empty valid CXXScopeSpec.
- virtual void ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ /// \returns true if an error occurred, false otherwise.
+ virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ return false;
}
/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index b9b17d24d1..e11ca0ce6b 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1123,7 +1123,9 @@ private:
void EnterDeclaratorScope() {
assert(!EnteredScope && "Already entered the scope!");
assert(SS.isSet() && "C++ scope was not set!");
- P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS);
+ if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
+ SS.setScopeRep(0);
+
if (!SS.isInvalid())
EnteredScope = true;
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 18b56c5bfb..0bb72568b1 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2151,7 +2151,7 @@ public:
/// looked up in the declarator-id's scope, until the declarator is parsed and
/// ActOnCXXExitDeclaratorScope is called.
/// The 'SS' should be a non-empty valid CXXScopeSpec.
- virtual void ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+ virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 60661f147e..8f536da777 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -519,10 +519,18 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
/// looked up in the declarator-id's scope, until the declarator is parsed and
/// ActOnCXXExitDeclaratorScope is called.
/// The 'SS' should be a non-empty valid CXXScopeSpec.
-void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- if (DeclContext *DC = computeDeclContext(SS, true))
+ if (DeclContext *DC = computeDeclContext(SS, true)) {
+ // Before we enter a declarator's context, we need to make sure that
+ // it is a complete declaration context.
+ if (!DC->isDependentContext() && RequireCompleteDeclContext(SS))
+ return true;
+
EnterDeclaratorContext(S, DC);
+ }
+
+ return false;
}
/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
diff --git a/test/SemaTemplate/explicit-specialization-member.cpp b/test/SemaTemplate/explicit-specialization-member.cpp
new file mode 100644
index 0000000000..197dae5a15
--- /dev/null
+++ b/test/SemaTemplate/explicit-specialization-member.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T>
+struct X0 {
+ typedef T* type;
+
+ void f0(T);
+ void f1(type);
+};
+
+template<> void X0<char>::f0(char);
+template<> void X0<char>::f1(type);