45 changes: 15 additions & 30 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1087,35 +1087,18 @@ LambdaCaptureKind LambdaCapture::getCaptureKind() const {

LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
SourceLocation CaptureDefaultLoc, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack)
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary),
IntroducerRange(IntroducerRange), CaptureDefaultLoc(CaptureDefaultLoc),
NumCaptures(Captures.size()), CaptureDefault(CaptureDefault),
NumCaptures(CaptureInits.size()), CaptureDefault(CaptureDefault),
ExplicitParams(ExplicitParams), ExplicitResultType(ExplicitResultType),
ClosingBrace(ClosingBrace) {
assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
CXXRecordDecl *Class = getLambdaClass();
CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();

// FIXME: Propagate "has unexpanded parameter pack" bit.

// Copy captures.
const ASTContext &Context = Class->getASTContext();
Data.NumCaptures = NumCaptures;
Data.NumExplicitCaptures = 0;
Data.Captures =
(LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * NumCaptures);
LambdaCapture *ToCapture = Data.Captures;
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
if (Captures[I].isExplicit())
++Data.NumExplicitCaptures;

*ToCapture++ = Captures[I];
}
assert(NumCaptures == Class->capture_size() && "Wrong number of captures");
assert(CaptureDefault == Class->getLambdaCaptureDefault());

// Copy initialization expressions for the non-static data members.
Stmt **Stored = getStoredStmts();
Expand All @@ -1128,22 +1111,24 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
setDependence(computeDependence(this, ContainsUnexpandedParameterPack));
}

LambdaExpr *LambdaExpr::Create(
const ASTContext &Context, CXXRecordDecl *Class,
SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
LambdaExpr *LambdaExpr::Create(const ASTContext &Context, CXXRecordDecl *Class,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
bool ExplicitParams, bool ExplicitResultType,
ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);

unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
unsigned Size = totalSizeToAlloc<Stmt *>(CaptureInits.size() + 1);
void *Mem = Context.Allocate(Size);
return new (Mem)
LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
Captures, ExplicitParams, ExplicitResultType, CaptureInits,
ClosingBrace, ContainsUnexpandedParameterPack);
ExplicitParams, ExplicitResultType, CaptureInits, ClosingBrace,
ContainsUnexpandedParameterPack);
}

LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ static llvm::json::Object
createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {
llvm::json::Object Ret;

FIELD2("simple", hasSimpleCopyAssignment);
FIELD2("trivial", hasTrivialCopyAssignment);
FIELD2("nonTrivial", hasNonTrivialCopyAssignment);
FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,7 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "CopyAssignment";
}
FLAG(hasSimpleCopyAssignment, simple);
FLAG(hasTrivialCopyAssignment, trivial);
FLAG(hasNonTrivialCopyAssignment, non_trivial);
FLAG(hasCopyAssignmentWithConstParam, has_const_param);
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13789,8 +13789,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, CopyAssignment);

if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) {
ClassDecl->setImplicitCopyAssignmentIsDeleted();
SetDeclDeleted(CopyAssignment, ClassLoc);
}

if (S)
PushOnScopeChains(CopyAssignment, S, false);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CaptureInits.push_back(Init.get());
}

Class->setCaptures(Captures);

// C++11 [expr.prim.lambda]p6:
// The closure type for a lambda-expression with no lambda-capture
// has a public non-virtual non-explicit const conversion function
Expand Down Expand Up @@ -1811,7 +1813,6 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,

LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
CaptureDefault, CaptureDefaultLoc,
Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, EndLoc,
ContainsUnexpandedParameterPack);
Expand Down
1 change: 1 addition & 0 deletions clang/test/AST/ast-dump-decl-context-json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ void S::Method() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down
30 changes: 15 additions & 15 deletions clang/test/AST/ast-dump-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ namespace testCXXRecordDecl {
// CHECK-NEXT: DefaultConstructor exists trivial constexpr
// CHECK-NEXT: CopyConstructor simple trivial has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial
// CHECK-NEXT: CopyAssignment trivial has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial
// CHECK-NEXT: Destructor simple irrelevant trivial

Expand All @@ -94,7 +94,7 @@ namespace testCXXRecordDecl {
// CHECK-NEXT: DefaultConstructor exists non_trivial
// CHECK-NEXT: CopyConstructor simple non_trivial has_const_param
// CHECK-NEXT: MoveConstructor exists simple non_trivial
// CHECK-NEXT: CopyAssignment non_trivial has_const_param
// CHECK-NEXT: CopyAssignment simple non_trivial has_const_param
// CHECK-NEXT: MoveAssignment exists simple non_trivial
// CHECK-NEXT: Destructor simple irrelevant trivial
// CHECK-NEXT: virtual private 'testCXXRecordDecl::A'
Expand Down Expand Up @@ -283,7 +283,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | | |-DefaultConstructor exists non_trivial user_provided
// CHECK-NEXT: | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveConstructor
// CHECK-NEXT: | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveAssignment
// CHECK-NEXT: | | `-Destructor non_trivial user_declared
// CHECK-NEXT: | |-CXXRecordDecl 0x{{.+}} <col:24, col:30> col:30 implicit referenced class TestClassTemplate
Expand All @@ -297,7 +297,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | | |-DefaultConstructor exists non_trivial user_provided
// CHECK-NEXT: | | |-CopyConstructor simple trivial has_const_param implicit_has_const_param
// CHECK-NEXT: | | |-MoveConstructor
// CHECK-NEXT: | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveAssignment
// CHECK-NEXT: | | `-Destructor non_trivial user_declared
// CHECK-NEXT: | |-TemplateArgument type 'testClassTemplateDecl::A'
Expand All @@ -318,7 +318,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::B'
Expand All @@ -330,7 +330,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists non_trivial user_provided
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment
// CHECK-NEXT: | `-Destructor non_trivial user_declared
// CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::C'
Expand All @@ -346,7 +346,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists non_trivial user_provided
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment
// CHECK-NEXT: | `-Destructor non_trivial user_declared
// CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::D'
Expand All @@ -365,7 +365,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} <col:38, col:44> col:44 implicit class TestClassTemplatePartial
Expand All @@ -376,7 +376,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-0'
Expand All @@ -399,7 +399,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <col:24, col:31> col:31 implicit struct TestTemplateDefaultType
Expand Down Expand Up @@ -427,7 +427,7 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <col:41, col:48> col:48 implicit struct TestTemplateTemplateDefaultType
Expand Down Expand Up @@ -466,7 +466,7 @@ namespace testCanonicalTemplate {
// CHECK-NEXT: | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
// CHECK-NEXT: | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: | |-CXXRecordDecl 0x{{.+}} <col:25, col:31> col:31 implicit class TestClassTemplate
Expand All @@ -479,7 +479,7 @@ namespace testCanonicalTemplate {
// CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: |-TemplateArgument type 'testCanonicalTemplate::A'
Expand Down Expand Up @@ -510,7 +510,7 @@ namespace testCanonicalTemplate {
// CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param implicit_has_const_param
// CHECK-NEXT: | |-MoveConstructor exists simple trivial
// CHECK-NEXT: | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: |-TemplateArgument type 'testCanonicalTemplate::A'
Expand All @@ -534,7 +534,7 @@ namespace testCanonicalTemplate {
// CHECK-NEXT: | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
// CHECK-NEXT: | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: | | |-MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: | | `-Destructor simple irrelevant trivial needs_implicit
// CHECK-NEXT: | `-CXXRecordDecl 0x{{.+}} <col:25, col:31> col:31 implicit class TestClassTemplate2
Expand Down
1 change: 1 addition & 0 deletions clang/test/AST/ast-dump-expr-json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3735,6 +3735,7 @@ void TestNonADLCall3() {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down
227 changes: 72 additions & 155 deletions clang/test/AST/ast-dump-record-definition-data-json.cpp

Large diffs are not rendered by default.

26 changes: 23 additions & 3 deletions clang/test/AST/ast-dump-records-json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -597,6 +598,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -693,6 +695,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -820,6 +823,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1019,6 +1023,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1218,6 +1223,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1443,6 +1449,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1863,6 +1870,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1959,6 +1967,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2086,6 +2095,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2285,6 +2295,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2484,6 +2495,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "copyAssign": {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2724,6 +2736,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "copyAssign": {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2964,6 +2977,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "copyAssign": {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -3205,6 +3219,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -3316,6 +3331,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -3424,7 +3440,8 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "copyAssign": {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "nonTrivial": true
// CHECK-NEXT: "nonTrivial": true,
// CHECK-NEXT: "simple": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
// CHECK-NEXT: "hasConstParam": true,
Expand Down Expand Up @@ -3662,7 +3679,8 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "copyAssign": {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "nonTrivial": true
// CHECK-NEXT: "nonTrivial": true,
// CHECK-NEXT: "simple": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
// CHECK-NEXT: "hasConstParam": true,
Expand Down Expand Up @@ -3914,7 +3932,8 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "copyAssign": {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "nonTrivial": true
// CHECK-NEXT: "nonTrivial": true,
// CHECK-NEXT: "simple": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
// CHECK-NEXT: "hasConstParam": true,
Expand Down Expand Up @@ -4153,6 +4172,7 @@ struct Derived6 : virtual public Bases... {
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down
22 changes: 11 additions & 11 deletions clang/test/AST/ast-dump-records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct A {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand Down Expand Up @@ -44,7 +44,7 @@ struct C {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand All @@ -55,7 +55,7 @@ struct C {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
int a;
Expand All @@ -69,7 +69,7 @@ struct C {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
int c;
Expand All @@ -91,7 +91,7 @@ struct C {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
int e, f;
Expand All @@ -113,7 +113,7 @@ struct D {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand All @@ -138,7 +138,7 @@ union E {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand Down Expand Up @@ -170,7 +170,7 @@ union G {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand All @@ -181,7 +181,7 @@ union G {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand All @@ -198,7 +198,7 @@ union G {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand All @@ -221,7 +221,7 @@ union G {
// CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
// CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
// CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
// CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
// CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit

Expand Down
6 changes: 5 additions & 1 deletion clang/test/AST/ast-dump-special-member-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,14 @@ struct DoesNotNeedImplicitCopyAssignment {
DoesNotNeedImplicitCopyAssignment& operator=(const DoesNotNeedImplicitCopyAssignment&) {}
};

struct DeclaresCopyAssignment {
DeclaresCopyAssignment &operator=(const DeclaresCopyAssignment&) &;
};

struct CopyAssignmentNeedsOverloadResolution {
// CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CopyAssignmentNeedsOverloadResolution definition
// CHECK: CopyAssignment {{.*}}needs_overload_resolution{{.*}}
mutable int i;
DeclaresCopyAssignment i;
};

struct CopyAssignmentDoesNotNeedOverloadResolution {
Expand Down
7 changes: 7 additions & 0 deletions clang/test/AST/ast-dump-template-decls-json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1461,6 +1462,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1643,6 +1645,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1747,6 +1750,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -1939,6 +1943,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2093,6 +2098,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down Expand Up @@ -2247,6 +2253,7 @@ void V<Ty>::f() {}
// CHECK-NEXT: "hasConstParam": true,
// CHECK-NEXT: "implicitHasConstParam": true,
// CHECK-NEXT: "needsImplicit": true,
// CHECK-NEXT: "simple": true,
// CHECK-NEXT: "trivial": true
// CHECK-NEXT: },
// CHECK-NEXT: "copyCtor": {
Expand Down
40 changes: 40 additions & 0 deletions clang/test/SemaCXX/type-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2789,3 +2789,43 @@ namespace ErrorType {
};
bool b = __has_unique_object_representations(T);
};

namespace PR46209 {
// Foo has both a trivial assignment operator and a non-trivial one.
struct Foo {
Foo &operator=(const Foo &) & { return *this; }
Foo &operator=(const Foo &) && = default;
};

// Bar's copy assignment calls Foo's non-trivial assignment.
struct Bar {
Foo foo;
};

static_assert(!__is_trivially_assignable(Foo &, const Foo &), "");
static_assert(!__is_trivially_assignable(Bar &, const Bar &), "");

// Foo2 has both a trivial assignment operator and a non-trivial one.
struct Foo2 {
Foo2 &operator=(const Foo2 &) & = default;
Foo2 &operator=(const Foo2 &) && { return *this; }
};

// Bar2's copy assignment calls Foo2's trivial assignment.
struct Bar2 {
Foo2 foo;
};

static_assert(__is_trivially_assignable(Foo2 &, const Foo2 &), "");
static_assert(__is_trivially_assignable(Bar2 &, const Bar2 &), "");
}

namespace ConstClass {
struct A {
A &operator=(const A&) = default;
};
struct B {
const A a;
};
static_assert(!__is_trivially_assignable(B&, const B&), "");
}
2 changes: 1 addition & 1 deletion clang/test/SemaObjCXX/arc-0x.mm
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void test() {

struct S1 {
union {
union { // expected-note 2 {{'S1' is implicitly deleted because variant field '' has a non-trivial}} expected-note 5 {{'S1' is implicitly deleted because field '' has a deleted}}
union { // expected-note 7 {{'S1' is implicitly deleted because field '' has a deleted}}
id f0; // expected-note 3 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
char f1;
};
Expand Down
41 changes: 19 additions & 22 deletions clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1330,33 +1330,30 @@ TEST(Matcher, MatchesPureMethod) {
}

TEST(Matcher, MatchesCopyAssignmentOperator) {
EXPECT_TRUE(matches("class X { X &operator=(X); };",
cxxMethodDecl(isCopyAssignmentOperator())));
EXPECT_TRUE(matches("class X { X &operator=(X &); };",
cxxMethodDecl(isCopyAssignmentOperator())));
EXPECT_TRUE(matches("class X { X &operator=(const X &); };",
cxxMethodDecl(isCopyAssignmentOperator())));
EXPECT_TRUE(matches("class X { X &operator=(volatile X &); };",
cxxMethodDecl(isCopyAssignmentOperator())));
auto CopyAssignment =
cxxMethodDecl(isCopyAssignmentOperator(), unless(isImplicit()));
EXPECT_TRUE(matches("class X { X &operator=(X); };", CopyAssignment));
EXPECT_TRUE(matches("class X { X &operator=(X &); };", CopyAssignment));
EXPECT_TRUE(matches("class X { X &operator=(const X &); };", CopyAssignment));
EXPECT_TRUE(matches("class X { X &operator=(volatile X &); };", //
CopyAssignment));
EXPECT_TRUE(matches("class X { X &operator=(const volatile X &); };",
cxxMethodDecl(isCopyAssignmentOperator())));
EXPECT_TRUE(notMatches("class X { X &operator=(X &&); };",
cxxMethodDecl(isCopyAssignmentOperator())));
CopyAssignment));
EXPECT_TRUE(notMatches("class X { X &operator=(X &&); };", CopyAssignment));
}

TEST(Matcher, MatchesMoveAssignmentOperator) {
EXPECT_TRUE(notMatches("class X { X &operator=(X); };",
cxxMethodDecl(isMoveAssignmentOperator())));
EXPECT_TRUE(matches("class X { X &operator=(X &&); };",
cxxMethodDecl(isMoveAssignmentOperator())));
EXPECT_TRUE(matches("class X { X &operator=(const X &&); };",
cxxMethodDecl(isMoveAssignmentOperator())));
EXPECT_TRUE(matches("class X { X &operator=(volatile X &&); };",
cxxMethodDecl(isMoveAssignmentOperator())));
auto MoveAssignment =
cxxMethodDecl(isMoveAssignmentOperator(), unless(isImplicit()));
EXPECT_TRUE(notMatches("class X { X &operator=(X); };", MoveAssignment));
EXPECT_TRUE(matches("class X { X &operator=(X &&); };", MoveAssignment));
EXPECT_TRUE(matches("class X { X &operator=(const X &&); };", //
MoveAssignment));
EXPECT_TRUE(matches("class X { X &operator=(volatile X &&); };", //
MoveAssignment));
EXPECT_TRUE(matches("class X { X &operator=(const volatile X &&); };",
cxxMethodDecl(isMoveAssignmentOperator())));
EXPECT_TRUE(notMatches("class X { X &operator=(X &); };",
cxxMethodDecl(isMoveAssignmentOperator())));
MoveAssignment));
EXPECT_TRUE(notMatches("class X { X &operator=(X &); };", MoveAssignment));
}

TEST(Matcher, MatchesConstMethod) {
Expand Down