Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -2740,6 +2740,26 @@ +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.
 
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -5476,6 +5476,30 @@
   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
 
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -226,6 +226,7 @@
   REGISTER_MATCHER(hasEitherOperand);
   REGISTER_MATCHER(hasElementType);
   REGISTER_MATCHER(hasElse);
+  REGISTER_MATCHER(hasExternalFormalLinkage);
   REGISTER_MATCHER(hasFalseExpression);
   REGISTER_MATCHER(hasGlobalStorage);
   REGISTER_MATCHER(hasImplicitDestinationType);
Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1937,5 +1937,21 @@
   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