Fix/Improve SourceRange of explicitly defaulted members

When adding the implicit compound statement (required for Codegen?), the
end location was previously overridden by the start location, probably
based on the assumptions:

* The location of the compound statement should be the member's location
* The compound statement if present is the last element of a FunctionDecl

This patch changes the location of the compound statement to the
member's end location.

Code review: http://reviews.llvm.org/D4175

llvm-svn: 211344
This commit is contained in:
Daniel Jasper 2014-06-20 08:44:22 +00:00
parent cd60ed53f6
commit b3b0b8034c
4 changed files with 56 additions and 18 deletions

View File

@ -8407,7 +8407,9 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
return;
}
SourceLocation Loc = Constructor->getLocation();
SourceLocation Loc = Constructor->getLocEnd().isValid()
? Constructor->getLocEnd()
: Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
Constructor->markUsed(Context);
@ -8869,7 +8871,9 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
return;
}
SourceLocation Loc = Destructor->getLocation();
SourceLocation Loc = Destructor->getLocEnd().isValid()
? Destructor->getLocEnd()
: Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
Destructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
@ -9569,8 +9573,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Our location for everything implicitly-generated.
SourceLocation Loc = CopyAssignOperator->getLocation();
SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid()
? CopyAssignOperator->getLocEnd()
: CopyAssignOperator->getLocation();
// Builds a DeclRefExpr for the "other" object.
RefBuilder OtherRef(Other, OtherRefType);
@ -9974,7 +9980,9 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
"Bad argument type of defaulted move assignment");
// Our location for everything implicitly-generated.
SourceLocation Loc = MoveAssignOperator->getLocation();
SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid()
? MoveAssignOperator->getLocEnd()
: MoveAssignOperator->getLocation();
// Builds a reference to the "other" object.
RefBuilder OtherRef(Other, OtherRefType);
@ -10111,8 +10119,9 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
ExprResult ThisObj =
CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
@ -10288,10 +10297,12 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
<< CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
CopyConstructor->setInvalidDecl();
} else {
SourceLocation Loc = CopyConstructor->getLocEnd().isValid()
? CopyConstructor->getLocEnd()
: CopyConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
CopyConstructor->setBody(ActOnCompoundStmt(
CopyConstructor->getLocation(), CopyConstructor->getLocation(), None,
/*isStmtExpr=*/ false).getAs<Stmt>());
CopyConstructor->setBody(
ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
}
CopyConstructor->markUsed(Context);
@ -10444,10 +10455,12 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
<< CXXMoveConstructor << Context.getTagDeclType(ClassDecl);
MoveConstructor->setInvalidDecl();
} else {
SourceLocation Loc = MoveConstructor->getLocEnd().isValid()
? MoveConstructor->getLocEnd()
: MoveConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
MoveConstructor->setBody(ActOnCompoundStmt(
MoveConstructor->getLocation(), MoveConstructor->getLocation(), None,
/*isStmtExpr=*/ false).getAs<Stmt>());
Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
}
MoveConstructor->markUsed(Context);

View File

@ -2452,12 +2452,12 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>105</integer>
// CHECK-NEXT: <key>col</key><integer>21</integer>
// CHECK-NEXT: <key>col</key><integer>53</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>105</integer>
// CHECK-NEXT: <key>col</key><integer>28</integer>
// CHECK-NEXT: <key>col</key><integer>53</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@ -2469,7 +2469,7 @@ namespace PR17746 {
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>105</integer>
// CHECK-NEXT: <key>col</key><integer>21</integer>
// CHECK-NEXT: <key>col</key><integer>53</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <key>ranges</key>
@ -2477,12 +2477,12 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>105</integer>
// CHECK-NEXT: <key>col</key><integer>21</integer>
// CHECK-NEXT: <key>col</key><integer>53</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>105</integer>
// CHECK-NEXT: <key>col</key><integer>28</integer>
// CHECK-NEXT: <key>col</key><integer>53</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>

View File

@ -133,6 +133,31 @@ class TestCXXDestructorDecl {
// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void (void) noexcept'
// CHECK-NEXT: CompoundStmt
// Test that the range of a defaulted members is computed correctly.
// FIXME: This should include the "= default".
class TestMemberRanges {
public:
TestMemberRanges() = default;
TestMemberRanges(const TestMemberRanges &Other) = default;
TestMemberRanges(TestMemberRanges &&Other) = default;
~TestMemberRanges() = default;
TestMemberRanges &operator=(const TestMemberRanges &Other) = default;
TestMemberRanges &operator=(TestMemberRanges &&Other) = default;
};
void SomeFunction() {
TestMemberRanges A;
TestMemberRanges B(A);
B = A;
A = static_cast<TestMemberRanges &&>(B);
TestMemberRanges C(static_cast<TestMemberRanges &&>(A));
}
// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:20>
// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:49>
// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:44>
// CHECK: CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:21>
// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:60>
// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:55>
class TestCXXConversionDecl {
operator int() { return 0; }
};

View File

@ -13,5 +13,5 @@ void f() {
a1 = a2;
B b1, b2;
b1 = b2;
b1 = b2;
}