[cfe-commits] r91771 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseCXXInlineMethods.cpp lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/temp/temp.spec/temp.explicit/p3.cpp
John McCall
rjmccall at apple.com
Sat Dec 19 02:49:30 PST 2009
Author: rjmccall
Date: Sat Dec 19 04:49:29 2009
New Revision: 91771
URL: http://llvm.org/viewvc/llvm-project?rev=91771&view=rev
Log:
Refactor to remove more dependencies on PreDeclaratorDC. I seem to have made
the redeclaration problems in the [temp.explicit]p3 testcase worse, but I can
live with that; they'll need to be fixed more holistically anyhow.
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sat Dec 19 04:49:29 2009
@@ -1351,6 +1351,14 @@
virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) {
}
+ /// ActOnStartDelayedMemberDeclarations - We have completed parsing
+ /// a C++ class, and we are about to start parsing any parts of
+ /// member declarations that could not be parsed earlier. Enter
+ /// the appropriate record scope.
+ virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
+ DeclPtrTy Record) {
+ }
+
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
@@ -1381,6 +1389,14 @@
DeclPtrTy Method) {
}
+ /// ActOnFinishDelayedMemberDeclarations - We have finished parsing
+ /// a C++ class, and we are about to start parsing any parts of
+ /// member declarations that could not be parsed earlier. Enter the
+ /// appropriate record scope.
+ virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
+ DeclPtrTy Record) {
+ }
+
/// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
ExprArg AssertExpr,
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Dec 19 04:49:29 2009
@@ -1243,10 +1243,7 @@
CreatedScope = true;
P.EnterScope(0); // Not a decl scope.
- if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
- SS.setScopeRep(0);
-
- if (!SS.isInvalid())
+ if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
EnteredScope = true;
}
Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sat Dec 19 04:49:29 2009
@@ -95,9 +95,12 @@
if (HasTemplateScope)
Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);
+ // The current scope is still active if we're the top-level class.
+ // Otherwise we'll need to push and enter a new scope.
bool HasClassScope = !Class.TopLevelClass;
- ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
- HasClassScope);
+ ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope);
+ if (HasClassScope)
+ Actions.ActOnStartDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
LateParsedMethodDeclaration &LM = Class.MethodDecls.front();
@@ -148,6 +151,9 @@
for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
ParseLexedMethodDeclarations(*Class.NestedClasses[I]);
+
+ if (HasClassScope)
+ Actions.ActOnFinishDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
}
/// ParseLexedMethodDefs - We finished parsing the member specification of a top
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Dec 19 04:49:29 2009
@@ -2193,11 +2193,15 @@
SourceLocation RBrac);
virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template);
+ virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
+ DeclPtrTy Record);
virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
DeclPtrTy Method);
virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param);
virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
DeclPtrTy Method);
+ virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
+ DeclPtrTy Record);
virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
ExprArg AssertExpr,
Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Sat Dec 19 04:49:29 2009
@@ -605,15 +605,18 @@
/// The 'SS' should be a non-empty valid CXXScopeSpec.
bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- 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);
- }
-
+
+ if (SS.isInvalid()) return true;
+
+ DeclContext *DC = computeDeclContext(SS, true);
+ if (!DC) return 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;
}
@@ -626,6 +629,7 @@
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
if (SS.isInvalid())
return;
- if (computeDeclContext(SS, true))
- ExitDeclaratorContext(S);
+ assert(!SS.isInvalid() && computeDeclContext(SS, true) &&
+ "exiting declarator scope we never really entered");
+ ExitDeclaratorContext(S);
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Dec 19 04:49:29 2009
@@ -321,23 +321,47 @@
/// EnterDeclaratorContext - Used when we must lookup names in the context
/// of a declarator's nested name specifier.
+///
void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
- assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
- PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
+ // C++0x [basic.lookup.unqual]p13:
+ // A name used in the definition of a static data member of class
+ // X (after the qualified-id of the static member) is looked up as
+ // if the name was used in a member function of X.
+ // C++0x [basic.lookup.unqual]p14:
+ // If a variable member of a namespace is defined outside of the
+ // scope of its namespace then any name used in the definition of
+ // the variable member (after the declarator-id) is looked up as
+ // if the definition of the variable member occurred in its
+ // namespace.
+ // Both of these imply that we should push a scope whose context
+ // is the semantic context of the declaration. We can't use
+ // PushDeclContext here because that context is not necessarily
+ // lexically contained in the current context. Fortunately,
+ // the containing scope should have the appropriate information.
+
+ assert(!S->getEntity() && "scope already has entity");
+
+#ifndef NDEBUG
+ Scope *Ancestor = S->getParent();
+ while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+ assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
+#endif
+
CurContext = DC;
- assert(CurContext && "No context?");
- S->setEntity(CurContext);
+ S->setEntity(DC);
}
void Sema::ExitDeclaratorContext(Scope *S) {
- S->setEntity(PreDeclaratorDC);
- PreDeclaratorDC = 0;
+ assert(S->getEntity() == CurContext && "Context imbalance!");
- // Reset CurContext to the nearest enclosing context.
- while (!S->getEntity() && S->getParent())
- S = S->getParent();
- CurContext = static_cast<DeclContext*>(S->getEntity());
- assert(CurContext && "No context?");
+ // Switch back to the lexical context. The safety of this is
+ // enforced by an assert in EnterDeclaratorContext.
+ Scope *Ancestor = S->getParent();
+ while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+ CurContext = (DeclContext*) Ancestor->getEntity();
+
+ // We don't need to do anything with the scope, which is going to
+ // disappear.
}
/// \brief Determine whether we allow overloading of the function
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Dec 19 04:49:29 2009
@@ -2266,6 +2266,18 @@
}
}
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+ if (!RecordD) return;
+ AdjustDeclIfTemplate(RecordD);
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD.getAs<Decl>());
+ PushDeclContext(S, Record);
+}
+
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+ if (!RecordD) return;
+ PopDeclContext();
+}
+
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
@@ -2275,18 +2287,6 @@
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
- if (!MethodD)
- return;
-
- AdjustDeclIfTemplate(MethodD);
-
- CXXScopeSpec SS;
- FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
- QualType ClassTy
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- SS.setScopeRep(
- NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
- ActOnCXXEnterDeclaratorScope(S, SS);
}
/// ActOnDelayedCXXMethodParameter - We've already started a delayed
@@ -2323,12 +2323,6 @@
AdjustDeclIfTemplate(MethodD);
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
- CXXScopeSpec SS;
- QualType ClassTy
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- SS.setScopeRep(
- NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
- ActOnCXXExitDeclaratorScope(S, SS);
// Now that we have our default arguments, check the constructor
// again. It could produce additional diagnostics or affect whether
@@ -5544,31 +5538,7 @@
// We should only get called for declarations with scope specifiers, like:
// int foo::bar;
assert(D->isOutOfLine());
-
- // C++0x [basic.lookup.unqual]p13:
- // A name used in the definition of a static data member of class
- // X (after the qualified-id of the static member) is looked up as
- // if the name was used in a member function of X.
- // C++0x [basic.lookup.unqual]p14:
- // If a variable member of a namespace is defined outside of the
- // scope of its namespace then any name used in the definition of
- // the variable member (after the declarator-id) is looked up as
- // if the definition of the variable member occurred in its
- // namespace.
- // Both of these imply that we should push a scope whose context
- // is the semantic context of the declaration. We can't use
- // PushDeclContext here because that context is not necessarily
- // lexically contained in the current context. Fortunately,
- // scopes should work.
-
-#ifndef NDEBUG
- Scope *Ancestor = S->getParent();
- while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
- assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
-#endif
-
- CurContext = D->getDeclContext();
- S->setEntity(CurContext);
+ EnterDeclaratorContext(S, D->getDeclContext());
}
/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
@@ -5579,11 +5549,7 @@
if (D == 0) return;
assert(D->isOutOfLine());
- assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
-
- Scope *Ancestor = S->getParent();
- while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
- CurContext = (DeclContext*) Ancestor->getEntity();
+ ExitDeclaratorContext(S);
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp?rev=91771&r1=91770&r2=91771&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp Sat Dec 19 04:49:29 2009
@@ -8,14 +8,12 @@
// A definition of the class or class template containing a member function
// template shall be in scope at the point of the explicit instantiation of
// the member function template.
-struct X0; // expected-note 2{{forward declaration}}
-template<typename> struct X1; // expected-note 5{{declared here}}
+struct X0; // expected-note 3{{forward declaration}}
+template<typename> struct X1; // expected-note 8{{declared here}}
// FIXME: Repeated diagnostics here!
-template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \
- // expected-error{{does not refer}}
-template void X1<int>::f0<int>(int); // expected-error 2{{implicit instantiation of undefined template}} \
- // expected-error{{does not refer}}
+template void X0::f0<int>(int); // expected-error 3{{incomplete type}} // expected-error{{invalid token after top level declarator}}
+template void X1<int>::f0<int>(int); // expected-error 3{{implicit instantiation of undefined template}} // expected-error{{invalid token after top level declarator}}
// A definition of a class template or class member template shall be in scope
// at the point of the explicit instantiation of the class template or class
@@ -35,10 +33,10 @@
// A definition of a class template shall be in scope at the point of an
// explicit instantiation of a member function or a static data member of the
// class template.
-template void X1<int>::f1(int); // expected-error{{undefined template}} \
+template void X1<int>::f1(int); // expected-error 2{{undefined template}} \
// expected-error{{does not refer}}
-template int X1<int>::member; // expected-error{{undefined template}} \
+template int X1<int>::member; // expected-error 2{{undefined template}} \
// expected-error{{does not refer}}
// A definition of a member class of a class template shall be in scope at the
More information about the cfe-commits
mailing list