Make it possible for using decls to point to operators. Fixes PR4441.

llvm-svn: 74362
This commit is contained in:
Anders Carlsson 2009-06-27 00:27:47 +00:00
parent 8e5f6951eb
commit 74d7f0dd65
6 changed files with 50 additions and 17 deletions

View File

@ -967,12 +967,13 @@ public:
/// ActOnUsingDirective - This is called when using-directive is parsed.
virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
AttributeList *AttrList,
bool IsTypeName);
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
OverloadedOperatorKind Op,
AttributeList *AttrList,
bool IsTypeName);
/// ActOnParamDefaultArgument - Parse default argument for function parameter
virtual void ActOnParamDefaultArgument(DeclPtrTy param,

View File

@ -48,6 +48,7 @@ Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
OverloadedOperatorKind Op,
AttributeList *AttrList,
bool IsTypeName) {

View File

@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/OperatorKinds.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
@ -274,8 +275,6 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
ParseOptionalCXXScopeSpecifier(SS);
AttributeList *AttrList = 0;
IdentifierInfo *TargetName = 0;
SourceLocation IdentLoc = SourceLocation();
// Check nested-name specifier.
if (SS.isInvalid()) {
@ -287,17 +286,33 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SkipUntil(tok::semi);
return DeclPtrTy();
}
if (Tok.isNot(tok::identifier)) {
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();
}
} 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 identifier.
TargetName = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken();
// Parse (optional) attributes (most likely GNU strong-using extension).
if (Tok.is(tok::kw___attribute))
AttrList = ParseAttributes();
@ -308,7 +323,8 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
AttrList ? "attributes list" : "namespace name", tok::semi);
return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS,
IdentLoc, TargetName, AttrList, IsTypeName);
IdentLoc, TargetName, Op,
AttrList, IsTypeName);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.

View File

@ -1574,6 +1574,7 @@ public:
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
OverloadedOperatorKind Op,
AttributeList *AttrList,
bool IsTypeName);

View File

@ -1785,18 +1785,24 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
OverloadedOperatorKind Op,
AttributeList *AttrList,
bool IsTypeName) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(TargetName && "Invalid TargetName.");
assert(TargetName || Op && "Invalid TargetName.");
assert(IdentLoc.isValid() && "Invalid TargetName location.");
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
UsingDecl *UsingAlias = 0;
DeclarationName Name;
if (TargetName)
Name = TargetName;
else
Name = Context.DeclarationNames.getCXXOperatorName(Op);
// Lookup target name.
LookupResult R = LookupParsedName(S, &SS, TargetName,
LookupOrdinaryName, false);
LookupResult R = LookupParsedName(S, &SS, Name, LookupOrdinaryName, false);
if (NamedDecl *NS = R) {
if (IsTypeName && !isa<TypeDecl>(NS)) {

View File

@ -0,0 +1,8 @@
// RUN: clang-cc -fsyntax-only -verify %s
namespace A {
struct B { };
void operator+(B,B);
}
using A::operator+;