Skip to content

[clang] Make nullability-on-classes more robust to redeclarations #114778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 4, 2024

Conversation

sam-mccall
Copy link
Collaborator

This is relevant after b24650e where
the selected template decl can be anything, even apparently a friend
declaration in some cases.

This is relevant after b24650e where
the selected template decl can be anything, even apparently a friend
declaration in some cases.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 4, 2024
@sam-mccall sam-mccall requested a review from gribozavr November 4, 2024 11:50
@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2024

@llvm/pr-subscribers-clang

Author: Sam McCall (sam-mccall)

Changes

This is relevant after b24650e where
the selected template decl can be anything, even apparently a friend
declaration in some cases.


Full diff: https://github.com/llvm/llvm-project/pull/114778.diff

2 Files Affected:

  • (modified) clang/lib/AST/Type.cpp (+13-5)
  • (added) clang/test/SemaCXX/nullability_redecl.cpp (+27)
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 229721aeae8114..a01d7be0cacc95 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -44,6 +44,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
@@ -4774,7 +4775,10 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
                 ->getTemplateName()
                 .getAsTemplateDecl())
       if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl))
-        return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
+        return llvm::any_of(
+            CTD->redecls(), [](const RedeclarableTemplateDecl *RTD) {
+              return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
+            });
     return ResultIfUnknown;
 
   case Type::Builtin:
@@ -4841,10 +4845,14 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
     // For template specializations, look only at primary template attributes.
     // This is a consistent regardless of whether the instantiation is known.
     if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
-      return CTSD->getSpecializedTemplate()
-          ->getTemplatedDecl()
-          ->hasAttr<TypeNullableAttr>();
-    return RD->hasAttr<TypeNullableAttr>();
+      return llvm::any_of(
+          CTSD->getSpecializedTemplate()->redecls(),
+          [](const RedeclarableTemplateDecl *RTD) {
+            return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
+          });
+    return llvm::any_of(RD->redecls(), [](const TagDecl *RD) {
+      return RD->hasAttr<TypeNullableAttr>();
+    });
   }
 
   // Non-pointer types.
diff --git a/clang/test/SemaCXX/nullability_redecl.cpp b/clang/test/SemaCXX/nullability_redecl.cpp
new file mode 100644
index 00000000000000..99bc521b89c13c
--- /dev/null
+++ b/clang/test/SemaCXX/nullability_redecl.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion -I%S/Inputs
+
+class Foo;
+using Foo1 = Foo _Nonnull; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'Foo'}}
+class _Nullable Foo;
+using Foo2 = Foo _Nonnull;
+class Foo;
+using Foo3 = Foo _Nonnull;
+
+template <class T>
+class Bar;
+using Bar1 = Bar<int> _Nonnull; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'Bar<int>'}}
+template <class T>
+class _Nullable Bar;
+using Bar2 = Bar<int> _Nonnull;
+template <class T>
+class Bar;
+using Bar3 = Bar<int> _Nonnull;
+
+namespace std {
+  template<class T> class unique_ptr;
+  using UP1 = unique_ptr<int> _Nonnull;
+  class X { template<class T> friend class unique_ptr; };
+  using UP2 = unique_ptr<int> _Nonnull;
+  template<class T> class unique_ptr;
+  using UP3 = unique_ptr<int> _Nonnull;
+}

Copy link

github-actions bot commented Nov 4, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@sam-mccall sam-mccall merged commit 17d8ed7 into llvm:main Nov 4, 2024
5 of 7 checks passed
PhilippRados pushed a commit to PhilippRados/llvm-project that referenced this pull request Nov 6, 2024
…vm#114778)

This is relevant after b24650e where
the selected template decl can be anything, even apparently a friend
declaration in some cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants