зеркало из https://github.com/microsoft/clang-1.git
When we notice that a member function is defined with "= delete" or "=
default", make a note of which is used when creating the initial declaration. Previously, we would wait until later to handle default/delete as a definition, but this is too late: when adding the declaration, we already treated the declaration as "user-provided" when in fact it was merely "user-declared". Fixes PR10861 and PR10442, along with a bunch of FIXMEs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144011 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
cf6ba2eeae
Коммит
45fa560c72
|
@ -1134,7 +1134,9 @@ private:
|
|||
Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs,
|
||||
ParsingDeclarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
const VirtSpecifiers& VS, ExprResult& Init);
|
||||
const VirtSpecifiers& VS,
|
||||
FunctionDefinitionKind DefinitionKind,
|
||||
ExprResult& Init);
|
||||
void ParseCXXNonStaticMemberInitializer(Decl *VarD);
|
||||
void ParseLexedAttributes(ParsingClass &Class);
|
||||
void ParseLexedAttribute(LateParsedAttribute &LA);
|
||||
|
|
|
@ -1379,6 +1379,15 @@ struct DeclaratorChunk {
|
|||
|
||||
};
|
||||
|
||||
/// \brief Described the kind of function definition (if any) provided for
|
||||
/// a function.
|
||||
enum FunctionDefinitionKind {
|
||||
FDK_Declaration,
|
||||
FDK_Definition,
|
||||
FDK_Defaulted,
|
||||
FDK_Deleted
|
||||
};
|
||||
|
||||
/// Declarator - Information about one declarator, including the parsed type
|
||||
/// information and the identifier. When the declarator is fully formed, this
|
||||
/// is turned into the appropriate Decl object.
|
||||
|
@ -1434,8 +1443,11 @@ private:
|
|||
/// GroupingParens - Set by Parser::ParseParenDeclarator().
|
||||
bool GroupingParens : 1;
|
||||
|
||||
/// FunctionDefinition - Is this Declarator for a function or member defintion
|
||||
bool FunctionDefinition : 1;
|
||||
/// FunctionDefinition - Is this Declarator for a function or member
|
||||
/// definition and, if so, what kind?
|
||||
///
|
||||
/// Actually a FunctionDefinitionKind.
|
||||
unsigned FunctionDefinition : 2;
|
||||
|
||||
// Redeclaration - Is this Declarator is a redeclaration.
|
||||
bool Redeclaration : 1;
|
||||
|
@ -1465,7 +1477,8 @@ public:
|
|||
Declarator(const DeclSpec &ds, TheContext C)
|
||||
: DS(ds), Range(ds.getSourceRange()), Context(C),
|
||||
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
|
||||
GroupingParens(false), FunctionDefinition(false), Redeclaration(false),
|
||||
GroupingParens(false), FunctionDefinition(FDK_Declaration),
|
||||
Redeclaration(false),
|
||||
Attrs(ds.getAttributePool().getFactory()), AsmLabel(0),
|
||||
InlineParamsUsed(false), Extension(false) {
|
||||
}
|
||||
|
@ -1827,8 +1840,17 @@ public:
|
|||
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
|
||||
void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
|
||||
|
||||
void setFunctionDefinition(bool Val) { FunctionDefinition = Val; }
|
||||
bool isFunctionDefinition() const { return FunctionDefinition; }
|
||||
void setFunctionDefinitionKind(FunctionDefinitionKind Val) {
|
||||
FunctionDefinition = Val;
|
||||
}
|
||||
|
||||
bool isFunctionDefinition() const {
|
||||
return getFunctionDefinitionKind() != FDK_Declaration;
|
||||
}
|
||||
|
||||
FunctionDefinitionKind getFunctionDefinitionKind() const {
|
||||
return (FunctionDefinitionKind)FunctionDefinition;
|
||||
}
|
||||
|
||||
void setRedeclaration(bool Val) { Redeclaration = Val; }
|
||||
bool isRedeclaration() const { return Redeclaration; }
|
||||
|
|
|
@ -451,8 +451,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
|||
// -- class X has no virtual functions [...]
|
||||
data().HasTrivialCopyAssignment = false;
|
||||
data().HasTrivialMoveAssignment = false;
|
||||
// FIXME: Destructor?
|
||||
|
||||
|
||||
// C++0x [class]p7:
|
||||
// A standard-layout class is a class that: [...]
|
||||
// -- has no virtual functions
|
||||
|
@ -574,9 +573,10 @@ NotASpecialMember:;
|
|||
// This bit is the C++03 POD bit, not the 0x one.
|
||||
data().PlainOldData = false;
|
||||
|
||||
// C++0x [class.dtor]p5:
|
||||
// A destructor is trivial if it is not user-provided and [...]
|
||||
if (DD->isUserProvided())
|
||||
// C++11 [class.dtor]p5:
|
||||
// A destructor is trivial if it is not user-provided and if
|
||||
// -- the destructor is not virtual.
|
||||
if (DD->isUserProvided() || DD->isVirtual())
|
||||
data().HasTrivialDestructor = false;
|
||||
|
||||
return;
|
||||
|
|
|
@ -24,8 +24,10 @@ using namespace clang;
|
|||
Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
|
||||
AttributeList *AccessAttrs,
|
||||
ParsingDeclarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
const VirtSpecifiers& VS, ExprResult& Init) {
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
const VirtSpecifiers& VS,
|
||||
FunctionDefinitionKind DefinitionKind,
|
||||
ExprResult& Init) {
|
||||
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
|
||||
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) ||
|
||||
Tok.is(tok::equal)) &&
|
||||
|
@ -36,7 +38,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
|
|||
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
|
||||
|
||||
Decl *FnD;
|
||||
D.setFunctionDefinition(true);
|
||||
D.setFunctionDefinitionKind(DefinitionKind);
|
||||
if (D.getDeclSpec().isFriendSpecified())
|
||||
FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,
|
||||
move(TemplateParams));
|
||||
|
|
|
@ -1779,25 +1779,27 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
HasInitializer = true;
|
||||
}
|
||||
|
||||
bool IsDefinition = false;
|
||||
FunctionDefinitionKind DefinitionKind = FDK_Declaration;
|
||||
// function-definition:
|
||||
//
|
||||
// In C++11, a non-function declarator followed by an open brace is a
|
||||
// braced-init-list for an in-class member initialization, not an
|
||||
// erroneous function definition.
|
||||
if (Tok.is(tok::l_brace) && !getLang().CPlusPlus0x) {
|
||||
IsDefinition = true;
|
||||
DefinitionKind = FDK_Definition;
|
||||
} else if (DeclaratorInfo.isFunctionDeclarator()) {
|
||||
if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
|
||||
IsDefinition = true;
|
||||
DefinitionKind = FDK_Definition;
|
||||
} else if (Tok.is(tok::equal)) {
|
||||
const Token &KW = NextToken();
|
||||
if (KW.is(tok::kw_default) || KW.is(tok::kw_delete))
|
||||
IsDefinition = true;
|
||||
if (KW.is(tok::kw_default))
|
||||
DefinitionKind = FDK_Defaulted;
|
||||
else if (KW.is(tok::kw_delete))
|
||||
DefinitionKind = FDK_Deleted;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsDefinition) {
|
||||
if (DefinitionKind) {
|
||||
if (!DeclaratorInfo.isFunctionDeclarator()) {
|
||||
Diag(Tok, diag::err_func_def_no_params);
|
||||
ConsumeBrace();
|
||||
|
@ -1825,7 +1827,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
|
||||
Decl *FunDecl =
|
||||
ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
|
||||
VS, Init);
|
||||
VS, DefinitionKind, Init);
|
||||
|
||||
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
|
||||
LateParsedAttrs[i]->setDecl(FunDecl);
|
||||
|
|
|
@ -876,7 +876,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
|
|||
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
|
||||
Scope *ParentScope = getCurScope()->getParent();
|
||||
|
||||
D.setFunctionDefinition(true);
|
||||
D.setFunctionDefinitionKind(FDK_Definition);
|
||||
Decl *DP = Actions.HandleDeclarator(ParentScope, D,
|
||||
move(TemplateParameterLists));
|
||||
D.complete(DP);
|
||||
|
|
|
@ -3145,7 +3145,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
|
|||
}
|
||||
|
||||
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
|
||||
D.setFunctionDefinition(false);
|
||||
D.setFunctionDefinitionKind(FDK_Declaration);
|
||||
return HandleDeclarator(S, D, MultiTemplateParamsArg(*this));
|
||||
}
|
||||
|
||||
|
@ -4803,7 +4803,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// scope specifier, or is the object of a friend declaration, the
|
||||
// lexical context will be different from the semantic context.
|
||||
NewFD->setLexicalDeclContext(CurContext);
|
||||
|
||||
|
||||
// Match up the template parameter lists with the scope specifier, then
|
||||
// determine whether we have a template or a template specialization.
|
||||
bool Invalid = false;
|
||||
|
@ -4995,10 +4995,26 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
NewFD->setAccess(AS_public);
|
||||
}
|
||||
|
||||
// If a function is defined as defaulted or deleted, mark it as such now.
|
||||
switch (D.getFunctionDefinitionKind()) {
|
||||
case FDK_Declaration:
|
||||
case FDK_Definition:
|
||||
break;
|
||||
|
||||
case FDK_Defaulted:
|
||||
NewFD->setDefaulted();
|
||||
break;
|
||||
|
||||
case FDK_Deleted:
|
||||
NewFD->setDeletedAsWritten();
|
||||
break;
|
||||
}
|
||||
|
||||
if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&
|
||||
D.isFunctionDefinition()) {
|
||||
// A method is implicitly inline if it's defined in its class
|
||||
// definition.
|
||||
// C++ [class.mfct]p2:
|
||||
// A member function may be defined (8.4) in its class definition, in
|
||||
// which case it is an inline member function (7.1.2)
|
||||
NewFD->setImplicitlyInline();
|
||||
}
|
||||
|
||||
|
@ -6885,7 +6901,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
|
|||
assert(D.isFunctionDeclarator() && "Not a function declarator!");
|
||||
Scope *ParentScope = FnBodyScope->getParent();
|
||||
|
||||
D.setFunctionDefinition(true);
|
||||
D.setFunctionDefinitionKind(FDK_Definition);
|
||||
Decl *DP = HandleDeclarator(ParentScope, D,
|
||||
MultiTemplateParamsArg(*this));
|
||||
return ActOnStartOfFunctionDef(FnBodyScope, DP);
|
||||
|
|
|
@ -5219,7 +5219,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
|
|||
|
||||
Scope *ParentScope = FnBodyScope->getParent();
|
||||
|
||||
D.setFunctionDefinition(true);
|
||||
D.setFunctionDefinitionKind(FDK_Definition);
|
||||
Decl *DP = HandleDeclarator(ParentScope, D,
|
||||
move(TemplateParameterLists));
|
||||
if (FunctionTemplateDecl *FunctionTemplate
|
||||
|
|
|
@ -18,6 +18,7 @@ struct UserProvDtor {
|
|||
constexpr UserProvDtor(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}}
|
||||
~UserProvDtor(); // expected-note {{has a user-provided destructor}}
|
||||
};
|
||||
|
||||
struct NonTrivDtor {
|
||||
constexpr NonTrivDtor(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}}
|
||||
virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}}
|
||||
|
|
|
@ -13,3 +13,18 @@ static_assert(!__is_trivial(NonTrivial2), "NonTrivial2 is trivial");
|
|||
static_assert(!__is_trivial(NonTrivial3), "NonTrivial3 is trivial");
|
||||
static_assert(!__is_trivial(NonTrivial4), "NonTrivial4 is trivial");
|
||||
static_assert(!__is_trivial(NonTrivial5), "NonTrivial5 is trivial");
|
||||
|
||||
struct Trivial2 {
|
||||
Trivial2() = default;
|
||||
Trivial2(const Trivial2 &) = default;
|
||||
Trivial2(Trivial2 &&) = default;
|
||||
Trivial2 &operator=(const Trivial2 &) = default;
|
||||
Trivial2 &operator=(Trivial2 &) = default;
|
||||
~Trivial2() = default;
|
||||
};
|
||||
|
||||
class NonTrivial6 { ~NonTrivial6(); };
|
||||
|
||||
NonTrivial6::~NonTrivial6() = default;
|
||||
|
||||
static_assert(!__is_trivial(NonTrivial6), "NonTrivial6 is trivial");
|
||||
|
|
|
@ -64,3 +64,15 @@ struct NonAggr6 {
|
|||
int n;
|
||||
};
|
||||
NonAggr6 na6 = { 42 }; // expected-error {{non-aggregate type 'NonAggr6'}}
|
||||
|
||||
struct DefaultedAggr {
|
||||
int n;
|
||||
|
||||
DefaultedAggr() = default;
|
||||
DefaultedAggr(const DefaultedAggr &) = default;
|
||||
DefaultedAggr(DefaultedAggr &&) = default;
|
||||
DefaultedAggr &operator=(const DefaultedAggr &) = default;
|
||||
DefaultedAggr &operator=(DefaultedAggr &) = default;
|
||||
~DefaultedAggr() = default;
|
||||
};
|
||||
DefaultedAggr da = { 42 } ;
|
||||
|
|
|
@ -48,10 +48,8 @@ class Deleted3a { const int a; }; // expected-note {{here}} \
|
|||
Deleted3a d3a; // expected-error {{deleted constructor}}
|
||||
class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{here}}
|
||||
Deleted3b d3b; // expected-error {{deleted constructor}}
|
||||
// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's
|
||||
// default constructor is user-provided.
|
||||
class Deleted3c { const DefaultedDefCtor2 a; }; // desired-note {{here}}
|
||||
Deleted3c d3c; // desired-error {{deleted constructor}}
|
||||
class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{deleted}}
|
||||
Deleted3c d3c; // expected-error {{deleted constructor}}
|
||||
class NotDeleted3a { const int a = 0; };
|
||||
NotDeleted3a nd3a;
|
||||
class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; };
|
||||
|
@ -159,11 +157,7 @@ static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor
|
|||
|
||||
// Otherwise, the default constructor is non-trivial.
|
||||
class Trivial2 { Trivial2() = delete; };
|
||||
//static_assert(__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial");
|
||||
// FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial.
|
||||
static_assert(!__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial");
|
||||
static_assert(__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial");
|
||||
|
||||
class Trivial3 { Trivial3() = default; };
|
||||
//static_assert(__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial");
|
||||
// FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial.
|
||||
static_assert(!__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial");
|
||||
static_assert(__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial");
|
||||
|
|
|
@ -31,8 +31,7 @@ namespace test1 {
|
|||
|
||||
void test() {
|
||||
A a;
|
||||
// FIXME: this error about variadics is bogus
|
||||
foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} expected-error {{cannot pass object of non-trivial type 'test1::A' through variadic function}}
|
||||
foo(a); // expected-error {{calling a private constructor of class 'test1::A'}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче