зеркало из 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.
|
// If this identifier is followed by a '<', we may have a template-id.
|
||||||
DeclTy *Template;
|
DeclTy *Template;
|
||||||
if (getLang().CPlusPlus && NextToken().is(tok::less) &&
|
if (NextToken().is(tok::less) &&
|
||||||
(Template = Actions.isTemplateName(*Tok.getIdentifierInfo(),
|
(Template = Actions.isTemplateName(*Tok.getIdentifierInfo(),
|
||||||
CurScope))) {
|
CurScope))) {
|
||||||
IdentifierInfo *II = Tok.getIdentifierInfo();
|
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
|
// If this identifier is the name of the current class, it's a
|
||||||
// constructor name.
|
// constructor name.
|
||||||
else if (getLang().CPlusPlus &&
|
else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
|
||||||
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
|
|
||||||
D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(),
|
D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(),
|
||||||
CurScope),
|
CurScope),
|
||||||
Tok.getLocation());
|
Tok.getLocation());
|
||||||
|
@ -1535,9 +1534,21 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||||
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
|
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
goto PastIdentifier;
|
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.
|
// This should be a C++ destructor.
|
||||||
SourceLocation TildeLoc = ConsumeToken();
|
SourceLocation TildeLoc = ConsumeToken();
|
||||||
if (Tok.is(tok::identifier)) {
|
if (Tok.is(tok::identifier)) {
|
||||||
|
@ -1561,22 +1572,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||||
goto PastIdentifier;
|
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
|
// 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 {
|
} else {
|
||||||
InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
|
InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
|
||||||
|
|
||||||
NewFD = CXXConversionDecl::Create(Context,
|
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
||||||
cast<CXXRecordDecl>(DC),
|
|
||||||
D.getIdentifierLoc(), Name, R,
|
D.getIdentifierLoc(), Name, R,
|
||||||
isInline, isExplicit);
|
isInline, isExplicit);
|
||||||
|
|
||||||
|
|
|
@ -1230,21 +1230,6 @@ Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
||||||
|
|
||||||
// Make sure we aren't redeclaring the conversion function.
|
// Make sure we aren't redeclaring the conversion function.
|
||||||
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
|
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:
|
// C++ [class.conv.fct]p1:
|
||||||
// [...] A conversion function is never used to convert a
|
// [...] A conversion function is never used to convert a
|
||||||
|
@ -1272,6 +1257,19 @@ Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
||||||
<< ClassType << ConvType;
|
<< ClassType << ConvType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
ClassDecl->addConversionFunction(Context, Conversion);
|
||||||
|
|
||||||
return (DeclTy *)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;
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче