From 12c118a8ff9f61a4d63146fe1a5c0d60987f99bb Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 4 Nov 2009 16:30:06 +0000 Subject: [PATCH] Switch parsing of using declarations over to ParseUnqualifiedId. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86027 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticParseKinds.td | 3 -- include/clang/Basic/DiagnosticSemaKinds.td | 8 ++- include/clang/Parse/Action.h | 35 +++++++++++-- lib/Parse/MinimalAction.cpp | 6 +-- lib/Parse/ParseDeclCXX.cpp | 49 ++++++------------- lib/Sema/Sema.h | 4 +- lib/Sema/SemaDeclCXX.cpp | 39 ++++++++++----- .../namespace.udecl/p5-cxx0x.cpp | 6 +-- 8 files changed, 86 insertions(+), 64 deletions(-) diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index db8d580a2c..e173cffdfd 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -166,9 +166,6 @@ def err_use_of_tag_name_without_tag : Error< "use of tagged type %0 without '%1' tag">; def err_expected_ident_in_using : Error< "expected an identifier in using directive">; -def err_using_decl_can_not_refer_to_template_spec : Error< - "using declaration can not refer to template specialization">; - /// Objective-C parser diagnostics def err_objc_no_attributes_on_category : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 99fddb5810..368496975a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -107,8 +107,14 @@ def err_using_decl_nested_name_specifier_is_not_a_base_class : Error< "using declaration refers into '%0', which is not a base class of %1">; def err_using_decl_can_not_refer_to_class_member : Error< "using declaration can not refer to class member">; - def err_using_decl_can_not_refer_to_namespace : Error< +def err_using_decl_can_not_refer_to_namespace : Error< "using declaration can not refer to namespace">; +def err_using_decl_constructor : Error< + "using declaration can not refer to a constructor">; +def err_using_decl_destructor : Error< + "using declaration can not refer to a destructor">; +def err_using_decl_template_id : Error< + "using declaration can not refer to a template specialization">; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 073365dced..657a14fff0 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1174,14 +1174,41 @@ public: return DeclPtrTy(); } - /// ActOnUsingDirective - This is called when using-directive is parsed. + /// \brief Parsed a C++ using-declaration. + /// + /// This callback will be invoked when the parser has parsed a C++ + /// using-declaration, e.g., + /// + /// \code + /// namespace std { + /// template class vector; + /// } + /// + /// using std::vector; // using-declaration here + /// \endcode + /// + /// \param CurScope the scope in which this using declaration was parsed. + /// + /// \param AS the currently-active access specifier. + /// + /// \param UsingLoc the location of the 'using' keyword. + /// + /// \param SS the nested-name-specifier that precedes the name. + /// + /// \param Name the name to which the using declaration refers. + /// + /// \param AttrList attributes applied to this using declaration, if any. + /// + /// \param IsTypeName whether this using declaration started with the + /// 'typename' keyword. FIXME: This will eventually be split into a + /// separate action. + /// + /// \returns a representation of the using declaration. virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, + UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName); diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 1e7d397fdf..bf05b2bacc 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -42,14 +42,12 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope, return DeclPtrTy(); } -// Defined out-of-line here because of dependecy on AttributeList +// Defined out-of-line here because of dependency on AttributeList Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, + UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName) { diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 91f86864f8..154c292348 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -285,6 +285,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, bool IsTypeName; // Ignore optional 'typename'. + // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { ConsumeToken(); IsTypeName = true; @@ -302,41 +303,21 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, SkipUntil(tok::semi); return DeclPtrTy(); } - if (Tok.is(tok::annot_template_id)) { - // C++0x N2914 [namespace.udecl]p5: - // A using-declaration shall not name a template-id. - Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec); - SkipUntil(tok::semi); - return DeclPtrTy(); - } - - IdentifierInfo *TargetName = 0; - OverloadedOperatorKind Op = OO_None; - SourceLocation IdentLoc; - if (Tok.is(tok::kw_operator)) { - IdentLoc = Tok.getLocation(); - - Op = TryParseOperatorFunctionId(); - if (!Op) { - // If there was an invalid operator, skip to end of decl, and eat ';'. - SkipUntil(tok::semi); - return DeclPtrTy(); - } - // FIXME: what about conversion functions? - } else if (Tok.is(tok::identifier)) { - // Parse identifier. - TargetName = Tok.getIdentifierInfo(); - IdentLoc = ConsumeToken(); - } else { - // FIXME: Use a better diagnostic here. - Diag(Tok, diag::err_expected_ident_in_using); - - // If there was invalid identifier, skip to end of decl, and eat ';'. + // Parse the unqualified-id. We allow parsing of both constructor and + // destructor names and allow the action module to diagnose any semantic + // errors. + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/true, + /*ObjectType=*/0, + Name)) { SkipUntil(tok::semi); return DeclPtrTy(); } - + // Parse (optional) attributes (most likely GNU strong-using extension). if (Tok.is(tok::kw___attribute)) AttrList = ParseAttributes(); @@ -344,10 +325,10 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, // Eat ';'. DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - AttrList ? "attributes list" : "namespace name", tok::semi); + AttrList ? "attributes list" : "using declaration", + tok::semi); - return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, - IdentLoc, TargetName, Op, + return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name, AttrList, IsTypeName); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0f84b46ed4..b0aa7b7473 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1893,9 +1893,7 @@ public: AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, + UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bc255137fc..3314ee26cb 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2700,22 +2700,37 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, + UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName) { - assert((TargetName || Op) && "Invalid TargetName."); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); - DeclarationName Name; - if (TargetName) - Name = TargetName; - else - Name = Context.DeclarationNames.getCXXOperatorName(Op); - - NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc, - Name, AttrList, IsTypeName); + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_ConversionFunctionId: + break; + + case UnqualifiedId::IK_ConstructorName: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor) + << SS.getRange(); + return DeclPtrTy(); + + case UnqualifiedId::IK_DestructorName: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor) + << SS.getRange(); + return DeclPtrTy(); + + case UnqualifiedId::IK_TemplateId: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id) + << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); + return DeclPtrTy(); + } + + DeclarationName TargetName = GetNameFromUnqualifiedId(Name); + NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, + Name.getSourceRange().getBegin(), + TargetName, AttrList, IsTypeName); if (UD) { PushOnScopeChains(UD, S); UD->setAccess(AS); diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp index 63e5c3cd27..31218c4130 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp @@ -7,6 +7,6 @@ struct A { }; struct B : A { - using A::f; // expected-error{{using declaration can not refer to template specialization}} - using A::X; // expected-error{{using declaration can not refer to template specialization}} -}; \ No newline at end of file + using A::f; // expected-error{{using declaration can not refer to a template specialization}} + using A::X; // expected-error{{using declaration can not refer to a template specialization}} +}; -- 2.40.0