r213220 - Fix FriendDecl source location and range for class templates and function declarations that don't start with 'friend' keyword. Add more unittests.
Nikola Smiljanic
popizdeh at gmail.com
Wed Jul 16 18:59:35 PDT 2014
Author: nikola
Date: Wed Jul 16 20:59:34 2014
New Revision: 213220
URL: http://llvm.org/viewvc/llvm-project?rev=213220&view=rev
Log:
Fix FriendDecl source location and range for class templates and function declarations that don't start with 'friend' keyword. Add more unittests.
Modified:
cfe/trunk/include/clang/AST/DeclFriend.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/unittests/AST/SourceLocationTest.cpp
Modified: cfe/trunk/include/clang/AST/DeclFriend.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclFriend.h?rev=213220&r1=213219&r2=213220&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclFriend.h (original)
+++ cfe/trunk/include/clang/AST/DeclFriend.h Wed Jul 16 20:59:34 2014
@@ -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();
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=213220&r1=213219&r2=213220&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jul 16 20:59:34 2014
@@ -5254,6 +5254,7 @@ public:
TemplateParameterList *TemplateParams,
AccessSpecifier AS,
SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc,
unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=213220&r1=213219&r2=213220&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jul 16 20:59:34 2014
@@ -10817,6 +10817,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
SS, Name, NameLoc, Attr,
TemplateParams, AS,
ModulePrivateLoc,
+ /*FriendLoc*/SourceLocation(),
TemplateParameterLists.size()-1,
TemplateParameterLists.data());
return Result.get();
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=213220&r1=213219&r2=213220&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jul 16 20:59:34 2014
@@ -11626,11 +11626,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scop
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.
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=213220&r1=213219&r2=213220&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jul 16 20:59:34 2014
@@ -838,6 +838,7 @@ Sema::CheckClassTemplate(Scope *S, unsig
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, unsig
/* 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(S
Attr,
TemplateParams,
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
+ /*FriendLoc*/SourceLocation(),
TemplateParameterLists.size() - 1,
TemplateParameterLists.data());
}
Modified: cfe/trunk/unittests/AST/SourceLocationTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/SourceLocationTest.cpp?rev=213220&r1=213219&r2=213220&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/SourceLocationTest.cpp (original)
+++ cfe/trunk/unittests/AST/SourceLocationTest.cpp Wed Jul 16 20:59:34 2014
@@ -263,7 +263,7 @@ TEST(UnresolvedUsingValueDecl, SourceRan
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);
@@ -340,6 +378,100 @@ TEST(FriendDecl, FriendDecltypeRange) {
"};\n",
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;
More information about the cfe-commits
mailing list