From: Aaron Ballman Date: Wed, 17 Aug 2016 13:10:42 +0000 (+0000) Subject: Add an AST matcher for external formal linkage. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=301bc621b5f774ca2998f9804730ee5d15846c8a;p=clang Add an AST matcher for external formal linkage. Patch by Visoiu Mistrih git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@278926 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index b87cae230b..f97183895c 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -2740,6 +2740,26 @@ memberExpr(isArrow()) +Matcher<NamedDecl>hasExternalFormalLinkage +
Matches a declaration that has external formal linkage.
+
+Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
+void f() {
+  int x;
+  static int y;
+}
+int z;
+
+Example matches f() because it has external formal linkage despite being
+unique to the translation unit as though it has internal likage
+(matcher = functionDecl(hasExternalFormalLinkage()))
+
+namespace {
+void f() {}
+}
+
+ + Matcher<NamedDecl>hasNamestd::string Name
Matches NamedDecl nodes that have the specified name.
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 6f194e2a57..63ec2a4a94 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -5476,6 +5476,30 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher,
   return false;
 }
 
+/// \brief Matches a declaration that has external formal linkage.
+///
+/// Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
+/// \code
+/// void f() {
+///   int x;
+///   static int y;
+/// }
+/// int z;
+/// \endcode
+///
+/// Example matches f() because it has external formal linkage despite being
+/// unique to the translation unit as though it has internal likage
+/// (matcher = functionDecl(hasExternalFormalLinkage()))
+///
+/// \code
+/// namespace {
+/// void f() {}
+/// }
+/// \endcode
+AST_MATCHER(NamedDecl, hasExternalFormalLinkage) {
+  return Node.hasExternalFormalLinkage();
+}
+
 } // end namespace ast_matchers
 } // end namespace clang
 
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 192b4b6d2a..6e594d7a7f 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -226,6 +226,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasEitherOperand);
   REGISTER_MATCHER(hasElementType);
   REGISTER_MATCHER(hasElse);
+  REGISTER_MATCHER(hasExternalFormalLinkage);
   REGISTER_MATCHER(hasFalseExpression);
   REGISTER_MATCHER(hasGlobalStorage);
   REGISTER_MATCHER(hasImplicitDestinationType);
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 108fd435ce..1527eacb6a 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1937,5 +1937,21 @@ TEST(NullPointerConstants, Basic) {
   EXPECT_TRUE(notMatches("int i = 0;", expr(nullPointerConstant())));
 }
 
+TEST(HasExternalFormalLinkage, Basic) {
+  EXPECT_TRUE(matches("int a = 0;", namedDecl(hasExternalFormalLinkage())));
+  EXPECT_TRUE(
+      notMatches("static int a = 0;", namedDecl(hasExternalFormalLinkage())));
+  EXPECT_TRUE(notMatches("static void f(void) { int a = 0; }",
+                         namedDecl(hasExternalFormalLinkage())));
+  EXPECT_TRUE(matches("void f(void) { int a = 0; }",
+                      namedDecl(hasExternalFormalLinkage())));
+
+  // Despite having internal semantic linkage, the anonymous namespace member
+  // has external linkage because the member has a unique name in all
+  // translation units.
+  EXPECT_TRUE(matches("namespace { int a = 0; }",
+                      namedDecl(hasExternalFormalLinkage())));
+}
+
 } // namespace ast_matchers
 } // namespace clang