]> granicus.if.org Git - clang/commitdiff
Don't require nullability on template parameters in typedefs.
authorJordan Rose <jordan_rose@apple.com>
Wed, 2 Nov 2016 20:44:07 +0000 (20:44 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 2 Nov 2016 20:44:07 +0000 (20:44 +0000)
Previously the following code would warn on the use of "T":

  template <typename T>
  struct X {
    typedef T *type;
  };

...because nullability is /allowed/ on template parameters (because
they could be pointers). (Actually putting nullability on this use of
'T' will of course break if the argument is a non-pointer type.)

This fix doesn't handle the case where a template parameter is used
/outside/ of a typedef. That seems trickier, especially in parameter
position.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285856 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaType.cpp
test/SemaObjCXX/Inputs/nullability-consistency-1.h

index e9acd9db73da73c00dcb7896704e65ea88e55582..46cc0b9ac1e910d338ebb959d96e33b8250acb5b 100644 (file)
@@ -3600,7 +3600,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
     // inner pointers.
     complainAboutMissingNullability = CAMN_InnerPointers;
 
-    if (T->canHaveNullability() && !T->getNullability(S.Context)) {
+    auto isDependentNonPointerType = [](QualType T) -> bool {
+      // Note: This is intended to be the same check as Type::canHaveNullability
+      // except with all of the ambiguous cases being treated as 'false' rather
+      // than 'true'.
+      return T->isDependentType() && !T->isAnyPointerType() &&
+        !T->isBlockPointerType() && !T->isMemberPointerType();
+    };
+
+    if (T->canHaveNullability() && !T->getNullability(S.Context) &&
+        !isDependentNonPointerType(T)) {
+      // Note that we allow but don't require nullability on dependent types.
       ++NumPointersRemaining;
     }
 
index 6ab48fe0cd8f34c4cb1364ced3daa6e3a6d96d60..a99f091e0f24852de269248b33a0538373347300 100644 (file)
@@ -13,5 +13,13 @@ class X {
   int X:: *memptr; // expected-warning{{member pointer is missing a nullability type specifier}}
 };
 
+template <typename T>
+struct Typedefs {
+  typedef T *Base; // no-warning
+  typedef Base *type; // expected-warning{{pointer is missing a nullability type specifier}}
+};
+
+Typedefs<int> xx;
+Typedefs<void *> yy;