[cfe-commits] r61486 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/Parser/cxx-using-directive.cpp www/cxx_status.html
Douglas Gregor
dgregor at apple.com
Mon Dec 29 19:27:24 PST 2008
Author: dgregor
Date: Mon Dec 29 21:27:21 2008
New Revision: 61486
URL: http://llvm.org/viewvc/llvm-project?rev=61486&view=rev
Log:
Parser support for C++ using directives, from Piotr Rak
Added:
cfe/trunk/test/Parser/cxx-using-directive.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/www/cxx_status.html
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Dec 29 21:27:21 2008
@@ -1462,6 +1462,10 @@
DIAG(err_anon_type_definition, ERROR,
"declaration of anonymous %0 must be a definition")
+// Namespaces.
+DIAG(err_expected_namespace_name, ERROR,
+ "expected namespace name")
+
// C++ member initializers.
DIAG(err_mem_init_not_member_or_class, ERROR,
"member initializer %0 does not name a non-static data member or base "
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Dec 29 21:27:21 2008
@@ -731,6 +731,15 @@
return;
}
+ /// ActOnUsingDirective - This is called when using-directive is parsed.
+ virtual DeclTy *ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList);
+
/// ActOnParamDefaultArgument - Parse default argument for function parameter
virtual void ActOnParamDefaultArgument(DeclTy *param,
SourceLocation EqualLoc,
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Dec 29 21:27:21 2008
@@ -931,6 +931,9 @@
DeclTy *ParseNamespace(unsigned Context);
DeclTy *ParseLinkage(unsigned Context);
+ DeclTy *ParseUsingDirectiveOrDeclaration(unsigned Context);
+ DeclTy *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc);
+ DeclTy *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc);
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Dec 29 21:27:21 2008
@@ -216,6 +216,8 @@
/// others [FIXME]
/// [C++] template-declaration
/// [C++] namespace-definition
+/// [C++] using-directive
+/// [C++] using-declaration [TODO]
/// others... [FIXME]
///
Parser::DeclTy *Parser::ParseDeclaration(unsigned Context) {
@@ -225,6 +227,8 @@
return ParseTemplateDeclaration(Context);
case tok::kw_namespace:
return ParseNamespace(Context);
+ case tok::kw_using:
+ return ParseUsingDirectiveOrDeclaration(Context);
default:
return ParseSimpleDeclaration(Context);
}
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Dec 29 21:27:21 2008
@@ -131,6 +131,91 @@
&InnerDecls.front(), InnerDecls.size());
}
+/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
+/// using-directive. Assumes that current token is 'using'.
+Parser::DeclTy *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context)
+{
+ assert(Tok.is(tok::kw_using) && "Not using token");
+
+ // Eat 'using'.
+ SourceLocation UsingLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_namespace)) {
+ // Next token after 'using' is 'namespace' so it must be using-directive
+ return ParseUsingDirective(Context, UsingLoc);
+ } else {
+ // Otherwise, it must be using-declaration.
+ return ParseUsingDeclaration(Context, UsingLoc); //FIXME: It is just stub.
+ }
+}
+
+/// ParseUsingDirective - Parse C++ using-directive, assumes
+/// that current token is 'namespace' and 'using' was already parsed.
+///
+/// using-directive: [C++ 7.3.p4: namespace.udir]
+/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
+/// namespace-name ;
+/// [GNU] using-directive:
+/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
+/// namespace-name attributes[opt] ;
+///
+Parser::DeclTy *Parser::ParseUsingDirective(unsigned Context,
+ SourceLocation UsingLoc) {
+ assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
+
+ // Eat 'namespace'.
+ SourceLocation NamespcLoc = ConsumeToken();
+
+ CXXScopeSpec SS;
+ // Parse (optional) nested-name-specifier.
+ MaybeParseCXXScopeSpecifier(SS);
+
+ AttributeList *AttrList = 0;
+ IdentifierInfo *NamespcName = 0;
+ SourceLocation IdentLoc = SourceLocation();
+
+ // Parse namespace-name.
+ if (!SS.isInvalid() && Tok.is(tok::identifier)) {
+ // Parse identifier.
+ NamespcName = Tok.getIdentifierInfo();
+ IdentLoc = ConsumeToken();
+ // Parse (optional) attributes (most likely GNU strong-using extension)
+ if (Tok.is(tok::kw___attribute)) {
+ AttrList = ParseAttributes();
+ }
+ // Eat ';'.
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ AttrList? "attributes list" : "namespace name")) {
+ SkipUntil(tok::semi);
+ return 0;
+ }
+ } else {
+ Diag(Tok, diag::err_expected_namespace_name);
+ // If there was invalid namespace name, skip to end of decl, and eat ';'.
+ SkipUntil(tok::semi);
+ // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
+ return 0;
+ }
+
+ return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
+ IdentLoc ,NamespcName, AttrList);
+}
+
+/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
+/// 'using' was already seen.
+///
+/// using-declaration: [C++ 7.3.p3: namespace.udecl]
+/// 'using' 'typename'[opt] ::[opt] nested-name-specifier
+/// unqualified-id [TODO]
+/// 'using' :: unqualified-id [TODO]
+///
+Parser::DeclTy *Parser::ParseUsingDeclaration(unsigned Context,
+ SourceLocation UsingLoc) {
+ assert(false && "Not implemented");
+ // FIXME: Implement parsing.
+ return 0;
+}
+
/// ParseClassName - Parse a C++ class-name, which names a class. Note
/// that we only check that the result names a type; semantic analysis
/// will need to verify that the type names a class. The result is
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Dec 29 21:27:21 2008
@@ -43,6 +43,21 @@
/// Out-of-line virtual destructor to provide home for Action class.
Action::~Action() {}
+// Defined out-of-line here because of dependecy on AttributeList
+Action::DeclTy *Action::ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList) {
+
+ // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+ // passed AttributeList, however other actions don't free it, is it
+ // temporary state or bug?
+ delete AttrList;
+ return 0;
+}
DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID);
@@ -358,6 +373,7 @@
ConsumeToken();
}
return 0;
+ case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
case tok::kw_template:
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Dec 29 21:27:21 2008
@@ -491,11 +491,25 @@
void CheckCXXDefaultArguments(FunctionDecl *FD);
void CheckExtraCXXDefaultArguments(Declarator &D);
+ // FIXME: NamespaceNameOnly parameter is added temporarily
+ // we will need a better way to specify lookup criteria for things
+ // like template specializations, explicit template instatatiation etc.
+
/// More parsing and symbol table subroutines...
Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx = 0,
bool enableLazyBuiltinCreation = true,
- bool LookInParent = true);
+ bool LookInParent = true,
+ bool NamespaceNameOnly = false);
+
+ Decl *LookupNamespaceName(DeclarationName Name, Scope *S,
+ const DeclContext *LookupCtx) {
+ return LookupDecl(Name, Decl::IDNS_Tag | Decl::IDNS_Ordinary, S,
+ LookupCtx,
+ /* enableLazyBuiltinCreation */ false,
+ /* LookInParent */ true,
+ /* NamespaceNameOnly */ true);
+ }
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S);
@@ -807,6 +821,14 @@
SourceLocation LBrace);
virtual void ActOnFinishNamespaceDef(DeclTy *Dcl, SourceLocation RBrace);
+ virtual DeclTy *ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList);
+
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
/// e.g: "int x(1);"
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Dec 29 21:27:21 2008
@@ -243,11 +243,15 @@
}
/// LookupDecl - Look up the inner-most declaration in the specified
-/// namespace.
+/// namespace. NamespaceNameOnly - during lookup only namespace names
+/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
+/// 'When looking up a namespace-name in a using-directive or
+/// namespace-alias-definition, only namespace names are considered.'
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx,
bool enableLazyBuiltinCreation,
- bool LookInParent) {
+ bool LookInParent,
+ bool NamespaceNameOnly) {
if (!Name) return 0;
unsigned NS = NSI;
if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
@@ -259,6 +263,7 @@
// labels in C++ is purely lexical, so search in the
// declarations attached to the name.
assert(!LookupCtx && "Can't perform qualified name lookup here");
+ assert(!NamespaceNameOnly && "Can't perform namespace name lookup here");
IdentifierResolver::iterator I
= IdResolver.begin(Name, CurContext, LookInParent);
@@ -268,14 +273,19 @@
// deep shadowing is extremely uncommon.
for (; I != IdResolver.end(); ++I)
if ((*I)->getIdentifierNamespace() & NS)
- return *I;
+ return *I;
} else if (LookupCtx) {
// Perform qualified name lookup into the LookupCtx.
// FIXME: Will need to look into base classes and such.
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
- if ((*I)->getIdentifierNamespace() & NS)
- return MaybeConstructOverloadSet(Context, I, E);
+ if ((*I)->getIdentifierNamespace() & NS) {
+ if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {
+ // Skip non-namespace name.
+ } else {
+ return MaybeConstructOverloadSet(Context, I, E);
+ }
+ }
} else {
// Name lookup for ordinary names and tag names in C++ requires
// looking into scopes that aren't strictly lexical, and
@@ -289,17 +299,21 @@
// FIXME: The isDeclScope check could be expensive. Can we do better?
for (; I != IEnd && S->isDeclScope(*I); ++I) {
if ((*I)->getIdentifierNamespace() & NS) {
- // We found something. Look for anything else in our scope
- // with this same name and in an acceptable identifier
- // namespace, so that we can construct an overload set if we
- // need to.
- IdentifierResolver::iterator LastI = I;
- for (++LastI; LastI != IEnd; ++LastI) {
- if (((*LastI)->getIdentifierNamespace() & NS) == 0 ||
- !S->isDeclScope(*LastI))
- break;
+ if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {
+ // Skip non-namespace name.
+ } else {
+ // We found something. Look for anything else in our scope
+ // with this same name and in an acceptable identifier
+ // namespace, so that we can construct an overload set if we
+ // need to.
+ IdentifierResolver::iterator LastI = I;
+ for (++LastI; LastI != IEnd; ++LastI) {
+ if (((*LastI)->getIdentifierNamespace() & NS) == 0 ||
+ !S->isDeclScope(*LastI))
+ break;
+ }
+ return MaybeConstructOverloadSet(Context, I, LastI);
}
- return MaybeConstructOverloadSet(Context, I, LastI);
}
}
@@ -314,8 +328,10 @@
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = Ctx->lookup(Context, Name); I != E; ++I) {
// FIXME: Cache this result in the IdResolver
- if ((*I)->getIdentifierNamespace() & NS)
- return MaybeConstructOverloadSet(Context, I, E);
+ if ((*I)->getIdentifierNamespace() & NS) {
+ if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {}
+ else return MaybeConstructOverloadSet(Context, I, E);
+ }
}
Ctx = Ctx->getParent();
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Dec 29 21:27:21 2008
@@ -1349,6 +1349,34 @@
PopDeclContext();
}
+Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList) {
+ assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+ assert(NamespcName && "Invalid NamespcName.");
+ assert(IdentLoc.isValid() && "Invalid NamespceName location.");
+
+ // FIXME: This still requires lot more checks, and AST support.
+ // Lookup namespace name.
+ DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());
+ Decl *NS = 0;
+
+ if ((NS = LookupNamespaceName(NamespcName, S, DC))) {
+ assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
+ } else {
+ DiagnosticBuilder Builder = Diag(IdentLoc, diag::err_expected_namespace_name);
+ if (SS.isSet())
+ Builder << SS.getRange();
+ }
+
+ // FIXME: We ignore AttrList for now, and delete it to avoid leak.
+ delete AttrList;
+ return 0;
+}
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
Added: cfe/trunk/test/Parser/cxx-using-directive.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-using-directive.cpp?rev=61486&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx-using-directive.cpp (added)
+++ cfe/trunk/test/Parser/cxx-using-directive.cpp Mon Dec 29 21:27:21 2008
@@ -0,0 +1,32 @@
+// RUN: clang -fsyntax-only -verify %s
+
+class A {};
+
+namespace B {
+ namespace A {}
+ using namespace A ;
+}
+
+namespace C {}
+
+namespace D {
+
+ class C {
+
+ using namespace B ; // expected-error{{expected unqualified-id}}
+ //FIXME: this needs better error message
+ };
+
+ namespace B {}
+
+ using namespace C ;
+ using namespace B::A ; // expected-error{{expected namespace name}}
+ //FIXME: would be nice to note, that A is not member of D::B
+ using namespace ::B::A ;
+ using namespace ::D::C ; // expected-error{{expected namespace name}}
+}
+
+using namespace ! ; // expected-error{{expected namespace name}}
+using namespace A ; // expected-error{{expected namespace name}}
+using namespace ::A B ; // expected-error{{expected ';' after namespace name}}
+
Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=61486&r1=61485&r2=61486&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Mon Dec 29 21:27:21 2008
@@ -963,7 +963,14 @@
<tr><td> 7.3.1.2 [namespace.memdef]</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td> 7.3.2 [namespace.alias]</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td> 7.3.3 [namespace.udecl]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td> 7.3.4 [namespace.udir]</td><td></td><td></td><td></td><td></td><td></td></tr>
+<tr>
+ <td> 7.3.4[namespace.udir]</td>
+ <td class="complete" align="center">✓</td>
+ <td class="broken" align="center"></td>
+ <td class="broken" align="center"></td>
+ <td class="broken" align="center"></td>
+ <td></td>
+</tr>
<tr><td> 7.4 [dcl.asm]</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td> 7.5 [dcl.link]</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>8 [dcl.decl]</td><td></td><td></td><td></td><td></td><td></td></tr>
More information about the cfe-commits
mailing list