diff options
author | Douglas Gregor <dgregor@apple.com> | 2015-06-19 17:51:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2015-06-19 17:51:05 +0000 |
commit | 261a89b0f70b3193b5358698eb92d18c4c855b36 (patch) | |
tree | 9c12c7684ec69fc50b2e33f16c10314ffa033017 /clang/lib/Sema/SemaDecl.cpp | |
parent | 4f093bf1ce0c6b4c9cd4472fbaa0b2b0a942a38c (diff) | |
download | bcm5719-llvm-261a89b0f70b3193b5358698eb92d18c4c855b36.tar.gz bcm5719-llvm-261a89b0f70b3193b5358698eb92d18c4c855b36.zip |
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 73bdd984c0b..f4af3f320a8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2465,6 +2465,28 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, if (!foundAny) newDecl->dropAttrs(); } +static void mergeParamDeclTypes(ParmVarDecl *NewParam, + const ParmVarDecl *OldParam, + Sema &S) { + if (auto Oldnullability = OldParam->getType()->getNullability(S.Context)) { + if (auto Newnullability = NewParam->getType()->getNullability(S.Context)) { + if (*Oldnullability != *Newnullability) { + S.Diag(NewParam->getLocation(), diag::warn_mismatched_nullability_attr) + << static_cast<unsigned>(*Newnullability) + << static_cast<unsigned>(*Oldnullability); + S.Diag(OldParam->getLocation(), diag::note_previous_declaration); + } + } + else { + QualType NewT = NewParam->getType(); + NewT = S.Context.getAttributedType( + AttributedType::getNullabilityAttrKind(*Oldnullability), + NewT, NewT); + NewParam->setType(NewT); + } + } +} + namespace { /// Used in MergeFunctionDecl to keep track of function parameters in @@ -3101,9 +3123,12 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, // Merge attributes from the parameters. These can mismatch with K&R // declarations. if (New->getNumParams() == Old->getNumParams()) - for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) - mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), - *this); + for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) { + ParmVarDecl *NewParam = New->getParamDecl(i); + ParmVarDecl *OldParam = Old->getParamDecl(i); + mergeParamDeclAttributes(NewParam, OldParam, *this); + mergeParamDeclTypes(NewParam, OldParam, *this); + } if (getLangOpts().CPlusPlus) return MergeCXXFunctionDecl(New, Old, S); |