forked from OSchip/llvm-project
Fix FriendDecl source location and range for class templates and function declarations that don't start with 'friend' keyword. Add more unittests.
llvm-svn: 213220
This commit is contained in:
parent
354e23b029
commit
4fc91538e9
|
@ -135,8 +135,12 @@ public:
|
|||
/// Retrieves the source range for the friend declaration.
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
if (NamedDecl *ND = getFriendDecl()) {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
|
||||
return FD->getSourceRange();
|
||||
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
|
||||
return FTD->getSourceRange();
|
||||
if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
|
||||
return CTD->getSourceRange();
|
||||
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) {
|
||||
if (DD->getOuterLocStart() != DD->getInnerLocStart())
|
||||
return DD->getSourceRange();
|
||||
|
|
|
@ -5254,6 +5254,7 @@ public:
|
|||
TemplateParameterList *TemplateParams,
|
||||
AccessSpecifier AS,
|
||||
SourceLocation ModulePrivateLoc,
|
||||
SourceLocation FriendLoc,
|
||||
unsigned NumOuterTemplateParamLists,
|
||||
TemplateParameterList **OuterTemplateParamLists);
|
||||
|
||||
|
|
|
@ -10817,6 +10817,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
SS, Name, NameLoc, Attr,
|
||||
TemplateParams, AS,
|
||||
ModulePrivateLoc,
|
||||
/*FriendLoc*/SourceLocation(),
|
||||
TemplateParameterLists.size()-1,
|
||||
TemplateParameterLists.data());
|
||||
return Result.get();
|
||||
|
|
|
@ -11626,11 +11626,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
|
|||
if (Invalid)
|
||||
return nullptr;
|
||||
|
||||
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
|
||||
SS, Name, NameLoc, Attr,
|
||||
TemplateParams, AS_public,
|
||||
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name,
|
||||
NameLoc, Attr, TemplateParams, AS_public,
|
||||
/*ModulePrivateLoc=*/SourceLocation(),
|
||||
TempParamLists.size() - 1,
|
||||
FriendLoc, TempParamLists.size() - 1,
|
||||
TempParamLists.data()).get();
|
||||
} else {
|
||||
// The "template<>" header is extraneous.
|
||||
|
|
|
@ -838,6 +838,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
AttributeList *Attr,
|
||||
TemplateParameterList *TemplateParams,
|
||||
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
|
||||
SourceLocation FriendLoc,
|
||||
unsigned NumOuterTemplateParamLists,
|
||||
TemplateParameterList** OuterTemplateParamLists) {
|
||||
assert(TemplateParams && TemplateParams->size() > 0 &&
|
||||
|
@ -1123,10 +1124,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
/* AddToContext = */ false);
|
||||
}
|
||||
|
||||
FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
|
||||
NewClass->getLocation(),
|
||||
NewTemplate,
|
||||
/*FIXME:*/NewClass->getLocation());
|
||||
FriendDecl *Friend = FriendDecl::Create(
|
||||
Context, CurContext, NewClass->getLocation(), NewTemplate, FriendLoc);
|
||||
Friend->setAccess(AS_public);
|
||||
CurContext->addDecl(Friend);
|
||||
}
|
||||
|
@ -6123,6 +6122,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
Attr,
|
||||
TemplateParams,
|
||||
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
|
||||
/*FriendLoc*/SourceLocation(),
|
||||
TemplateParameterLists.size() - 1,
|
||||
TemplateParameterLists.data());
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ TEST(UnresolvedUsingValueDecl, SourceRange) {
|
|||
unresolvedUsingValueDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendFunctionLocation) {
|
||||
TEST(FriendDecl, FriendNonMemberFunctionLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(2, 13);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
|
@ -272,7 +272,7 @@ TEST(FriendDecl, FriendFunctionLocation) {
|
|||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendFunctionRange) {
|
||||
TEST(FriendDecl, FriendNonMemberFunctionRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(2, 1, 2, 15);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
|
@ -281,7 +281,25 @@ TEST(FriendDecl, FriendFunctionRange) {
|
|||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendClassLocation) {
|
||||
TEST(FriendDecl, FriendNonMemberFunctionDefinitionLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(2, 12);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"friend int f() { return 0; }\n"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendNonMemberFunctionDefinitionRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(2, 1, 2, 28);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"friend int f() { return 0; }\n"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendElaboratedTypeLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(2, 8);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
|
@ -290,7 +308,7 @@ TEST(FriendDecl, FriendClassLocation) {
|
|||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendClassRange) {
|
||||
TEST(FriendDecl, FriendElaboratedTypeRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(2, 1, 2, 14);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
|
@ -299,6 +317,26 @@ TEST(FriendDecl, FriendClassRange) {
|
|||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendSimpleTypeLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(3, 8);
|
||||
EXPECT_TRUE(Verifier.match("class B;\n"
|
||||
"struct A {\n"
|
||||
"friend B;\n"
|
||||
"};\n",
|
||||
friendDecl(), Lang_CXX11));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendSimpleTypeRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(3, 1, 3, 8);
|
||||
EXPECT_TRUE(Verifier.match("class B;\n"
|
||||
"struct A {\n"
|
||||
"friend B;\n"
|
||||
"};\n",
|
||||
friendDecl(), Lang_CXX11));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendTemplateParameterLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(3, 8);
|
||||
|
@ -341,6 +379,100 @@ TEST(FriendDecl, FriendDecltypeRange) {
|
|||
friendDecl(), Lang_CXX11));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendConstructorDestructorLocation) {
|
||||
const std::string Code = "struct B {\n"
|
||||
"B();\n"
|
||||
"~B();\n"
|
||||
"};\n"
|
||||
"struct A {\n"
|
||||
"friend B::B(), B::~B();\n"
|
||||
"};\n";
|
||||
LocationVerifier<FriendDecl> ConstructorVerifier;
|
||||
ConstructorVerifier.expectLocation(6, 11);
|
||||
EXPECT_TRUE(ConstructorVerifier.match(
|
||||
Code, friendDecl(has(constructorDecl(ofClass(hasName("B")))))));
|
||||
LocationVerifier<FriendDecl> DestructorVerifier;
|
||||
DestructorVerifier.expectLocation(6, 19);
|
||||
EXPECT_TRUE(DestructorVerifier.match(
|
||||
Code, friendDecl(has(destructorDecl(ofClass(hasName("B")))))));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendConstructorDestructorRange) {
|
||||
const std::string Code = "struct B {\n"
|
||||
"B();\n"
|
||||
"~B();\n"
|
||||
"};\n"
|
||||
"struct A {\n"
|
||||
"friend B::B(), B::~B();\n"
|
||||
"};\n";
|
||||
RangeVerifier<FriendDecl> ConstructorVerifier;
|
||||
ConstructorVerifier.expectRange(6, 1, 6, 13);
|
||||
EXPECT_TRUE(ConstructorVerifier.match(
|
||||
Code, friendDecl(has(constructorDecl(ofClass(hasName("B")))))));
|
||||
RangeVerifier<FriendDecl> DestructorVerifier;
|
||||
DestructorVerifier.expectRange(6, 1, 6, 22);
|
||||
EXPECT_TRUE(DestructorVerifier.match(
|
||||
Code, friendDecl(has(destructorDecl(ofClass(hasName("B")))))));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendTemplateFunctionLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(3, 13);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"template <typename T>\n"
|
||||
"friend void f();\n"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendTemplateFunctionRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(2, 1, 3, 15);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"template <typename T>\n"
|
||||
"friend void f();\n"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendTemplateClassLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(3, 14);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"template <typename T>\n"
|
||||
"friend class B;\n"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendTemplateClassRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(2, 1, 3, 14);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"template <typename T>\n"
|
||||
"friend class B;\n"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendInlineFunctionLocation) {
|
||||
LocationVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectLocation(2, 19);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"int inline friend f() { return 0; }"
|
||||
"};\n",
|
||||
friendDecl()));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, FriendInlineFunctionRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(2, 1, 2, 35);
|
||||
EXPECT_TRUE(Verifier.match("struct A {\n"
|
||||
"int inline friend f() { return 0; }"
|
||||
"};\n",
|
||||
friendDecl(), Lang_CXX11));
|
||||
}
|
||||
|
||||
TEST(FriendDecl, InstantiationSourceRange) {
|
||||
RangeVerifier<FriendDecl> Verifier;
|
||||
Verifier.expectRange(4, 3, 4, 35);
|
||||
|
|
Loading…
Reference in New Issue