[clang] [clang] Fix isInStdNamespace for Decl flagged extern c++ (PR #81776)

Fred Tingaud via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 14 10:50:14 PST 2024


https://github.com/frederic-tingaud-sonarsource created https://github.com/llvm/llvm-project/pull/81776

The MSVC STL implementation declares multiple classes using:

```cpp
namespace std {
  extern "C++" class locale {
    ...
  };
}
```

`isInStdNamespace` uses the first DeclContext to check whether a Decl is inside the `std` namespace. Here, the first DeclContext of the `locale` Decl is a LinkageSpecDecl so the method will return false.
We need to skip this LinkageSpecDecl to find the first DeclContext of type Namespace and actually check whether we're in the `std` namespace.

>From c12b2e26ad7a114aff09b89c75178d4ab7890a20 Mon Sep 17 00:00:00 2001
From: Fred Tingaud <frederic.tingaud at sonarsource.com>
Date: Wed, 14 Feb 2024 19:40:29 +0100
Subject: [PATCH] [clang] Fix isInStdNamespace for Decl flagged extern c++

---
 clang/lib/AST/DeclBase.cpp                               | 3 +++
 clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 5 +++++
 2 files changed, 8 insertions(+)

diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 8163f9bdaf8d97..4cfe9ed3340735 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -402,6 +402,9 @@ bool Decl::isInAnonymousNamespace() const {
 
 bool Decl::isInStdNamespace() const {
   const DeclContext *DC = getDeclContext();
+  while (auto const LD = dyn_cast_or_null<LinkageSpecDecl>(DC)) {
+    DC = LD->getDeclContext();
+  }
   return DC && DC->isStdNamespace();
 }
 
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index edcdae4559d970..b75da7bc1ed069 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -3637,6 +3637,11 @@ TEST_P(ASTMatchersTest, InStdNamespace) {
                       "  class vector {};"
                       "}",
                       cxxRecordDecl(hasName("vector"), isInStdNamespace())));
+
+  EXPECT_TRUE(matches("namespace std {"
+                      "  extern \"C++\" class vector {};"
+                      "}",
+                      cxxRecordDecl(hasName("vector"), isInStdNamespace())));
 }
 
 TEST_P(ASTMatchersTest, InAnonymousNamespace) {



More information about the cfe-commits mailing list