Switch parsing of using declarations over to ParseUnqualifiedId.

llvm-svn: 86027
This commit is contained in:
Douglas Gregor 2009-11-04 16:30:06 +00:00
parent 531045d554
commit 220f4277bd
8 changed files with 87 additions and 65 deletions

View File

@ -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<

View File

@ -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">;

View File

@ -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<typename T, typename Alloc> 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);

View File

@ -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) {

View File

@ -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);
// 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();
}
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 ';'.
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);
}

View File

@ -1893,9 +1893,7 @@ public:
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
OverloadedOperatorKind Op,
UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName);

View File

@ -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);

View File

@ -7,6 +7,6 @@ struct A {
};
struct B : A {
using A::f<double>; // expected-error{{using declaration can not refer to template specialization}}
using A::X<int>; // expected-error{{using declaration can not refer to template specialization}}
};
using A::f<double>; // expected-error{{using declaration can not refer to a template specialization}}
using A::X<int>; // expected-error{{using declaration can not refer to a template specialization}}
};