зеркало из https://github.com/microsoft/clang-1.git
Add support for out-of-line definitions of conversion functions and member operators
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61442 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4bcd44d3b3
Коммит
70316a065b
|
@ -1514,7 +1514,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
|
||||
// If this identifier is followed by a '<', we may have a template-id.
|
||||
DeclTy *Template;
|
||||
if (getLang().CPlusPlus && NextToken().is(tok::less) &&
|
||||
if (NextToken().is(tok::less) &&
|
||||
(Template = Actions.isTemplateName(*Tok.getIdentifierInfo(),
|
||||
CurScope))) {
|
||||
IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||
|
@ -1525,8 +1525,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
}
|
||||
// If this identifier is the name of the current class, it's a
|
||||
// constructor name.
|
||||
else if (getLang().CPlusPlus &&
|
||||
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
|
||||
else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
|
||||
D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(),
|
||||
CurScope),
|
||||
Tok.getLocation());
|
||||
|
@ -1535,9 +1534,21 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
|
||||
ConsumeToken();
|
||||
goto PastIdentifier;
|
||||
}
|
||||
} else if (Tok.is(tok::kw_operator)) {
|
||||
SourceLocation OperatorLoc = Tok.getLocation();
|
||||
|
||||
if (Tok.is(tok::tilde)) {
|
||||
// First try the name of an overloaded operator
|
||||
if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
|
||||
D.setOverloadedOperator(Op, OperatorLoc);
|
||||
} else {
|
||||
// This must be a conversion function (C++ [class.conv.fct]).
|
||||
if (TypeTy *ConvType = ParseConversionFunctionId())
|
||||
D.setConversionFunction(ConvType, OperatorLoc);
|
||||
else
|
||||
D.SetIdentifier(0, Tok.getLocation());
|
||||
}
|
||||
goto PastIdentifier;
|
||||
} else if (Tok.is(tok::tilde)) {
|
||||
// This should be a C++ destructor.
|
||||
SourceLocation TildeLoc = ConsumeToken();
|
||||
if (Tok.is(tok::identifier)) {
|
||||
|
@ -1561,22 +1572,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
goto PastIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
if (Tok.is(tok::kw_operator)) {
|
||||
SourceLocation OperatorLoc = Tok.getLocation();
|
||||
|
||||
// First try the name of an overloaded operator
|
||||
if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
|
||||
D.setOverloadedOperator(Op, OperatorLoc);
|
||||
} else {
|
||||
// This must be a conversion function (C++ [class.conv.fct]).
|
||||
if (TypeTy *ConvType = ParseConversionFunctionId())
|
||||
D.setConversionFunction(ConvType, OperatorLoc);
|
||||
else
|
||||
D.SetIdentifier(0, Tok.getLocation());
|
||||
}
|
||||
goto PastIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
// If we reached this point, we are either in C/ObjC or the token didn't
|
||||
|
|
|
@ -1186,8 +1186,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
|
|||
} else {
|
||||
InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
|
||||
|
||||
NewFD = CXXConversionDecl::Create(Context,
|
||||
cast<CXXRecordDecl>(DC),
|
||||
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
||||
D.getIdentifierLoc(), Name, R,
|
||||
isInline, isExplicit);
|
||||
|
||||
|
|
|
@ -1230,21 +1230,6 @@ Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
|||
|
||||
// Make sure we aren't redeclaring the conversion function.
|
||||
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
|
||||
OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions();
|
||||
for (OverloadedFunctionDecl::function_iterator Func
|
||||
= Conversions->function_begin();
|
||||
Func != Conversions->function_end(); ++Func) {
|
||||
CXXConversionDecl *OtherConv = cast<CXXConversionDecl>(*Func);
|
||||
if (ConvType == Context.getCanonicalType(OtherConv->getConversionType())) {
|
||||
Diag(Conversion->getLocation(), diag::err_conv_function_redeclared);
|
||||
Diag(OtherConv->getLocation(),
|
||||
OtherConv->isThisDeclarationADefinition()?
|
||||
diag::note_previous_definition
|
||||
: diag::note_previous_declaration);
|
||||
Conversion->setInvalidDecl();
|
||||
return (DeclTy *)Conversion;
|
||||
}
|
||||
}
|
||||
|
||||
// C++ [class.conv.fct]p1:
|
||||
// [...] A conversion function is never used to convert a
|
||||
|
@ -1272,7 +1257,20 @@ Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
|||
<< ClassType << ConvType;
|
||||
}
|
||||
|
||||
ClassDecl->addConversionFunction(Context, Conversion);
|
||||
if (Conversion->getPreviousDeclaration()) {
|
||||
OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions();
|
||||
for (OverloadedFunctionDecl::function_iterator
|
||||
Conv = Conversions->function_begin(),
|
||||
ConvEnd = Conversions->function_end();
|
||||
Conv != ConvEnd; ++Conv) {
|
||||
if (*Conv == Conversion->getPreviousDeclaration()) {
|
||||
*Conv = Conversion;
|
||||
return (DeclTy *)Conversion;
|
||||
}
|
||||
}
|
||||
assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
|
||||
} else
|
||||
ClassDecl->addConversionFunction(Context, Conversion);
|
||||
|
||||
return (DeclTy *)Conversion;
|
||||
}
|
||||
|
|
|
@ -103,3 +103,23 @@ namespace E {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Operators {
|
||||
Operators operator+(const Operators&) const; // expected-note{{member declaration nearly matches}}
|
||||
operator bool();
|
||||
};
|
||||
|
||||
Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition does not match any declaration in 'Operators'}}
|
||||
Operators ops;
|
||||
return ops;
|
||||
}
|
||||
|
||||
Operators Operators::operator+(const Operators&) const {
|
||||
Operators ops;
|
||||
return ops;
|
||||
}
|
||||
|
||||
Operators::operator bool() {
|
||||
return true;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче