summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/DeclPrinter.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2015-06-19 18:14:38 +0000
committerDouglas Gregor <dgregor@apple.com>2015-06-19 18:14:38 +0000
commit813a066f16df52783708fdc2ef708bb76a9ff521 (patch)
tree0657ccae705e2a09c50dd92d26d645bff370aded /clang/lib/AST/DeclPrinter.cpp
parentb4866e85e5ffa0d352d496958582f0983172dc01 (diff)
downloadbcm5719-llvm-813a066f16df52783708fdc2ef708bb76a9ff521.tar.gz
bcm5719-llvm-813a066f16df52783708fdc2ef708bb76a9ff521.zip
Extend type nullability qualifiers for Objective-C.
Introduce context-sensitive, non-underscored nullability specifiers (nonnull, nullable, null_unspecified) for Objective-C method return types, method parameter types, and properties. Introduce Objective-C-specific semantics, including computation of the nullability of the result of a message send, merging of nullability information from the @interface of a class into its @implementation, etc . This is the Objective-C part of rdar://problem/18868820. llvm-svn: 240154
Diffstat (limited to 'clang/lib/AST/DeclPrinter.cpp')
-rw-r--r--clang/lib/AST/DeclPrinter.cpp74
1 files changed, 66 insertions, 8 deletions
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index d8cd40ec9c6..609cc08545a 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -37,6 +37,13 @@ namespace {
void Print(AccessSpecifier AS);
+ /// Print an Objective-C method type in parentheses.
+ ///
+ /// \param Quals The Objective-C declaration qualifiers.
+ /// \param T The type to print.
+ void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
+ QualType T);
+
public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false)
@@ -930,24 +937,64 @@ void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Objective-C declarations
//----------------------------------------------------------------------------
+/// Strip off the top-level nullability annotation, if it's there.
+static Optional<NullabilityKind> stripOuterNullability(QualType &T) {
+ if (auto attributed = dyn_cast<AttributedType>(T.getTypePtr())) {
+ if (auto nullability = attributed->getImmediateNullability()) {
+ T = attributed->getModifiedType();
+ return nullability;
+ }
+ }
+
+ return None;
+ }
+
+void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
+ Decl::ObjCDeclQualifier Quals,
+ QualType T) {
+ Out << '(';
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
+ Out << "in ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
+ Out << "inout ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
+ Out << "out ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
+ Out << "bycopy ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
+ Out << "byref ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
+ Out << "oneway ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
+ if (auto nullability = stripOuterNullability(T)) {
+ Out << getNullabilitySpelling(*nullability).substr(2) << ' ';
+ }
+ }
+
+ Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
+ Out << ')';
+}
+
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstanceMethod())
Out << "- ";
else
Out << "+ ";
- if (!OMD->getReturnType().isNull())
- Out << '(' << OMD->getASTContext()
- .getUnqualifiedObjCPointerType(OMD->getReturnType())
- .getAsString(Policy) << ")";
+ if (!OMD->getReturnType().isNull()) {
+ PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),
+ OMD->getReturnType());
+ }
std::string name = OMD->getSelector().getAsString();
std::string::size_type pos, lastPos = 0;
for (const auto *PI : OMD->params()) {
// FIXME: selector is missing here!
pos = name.find_first_of(':', lastPos);
- Out << " " << name.substr(lastPos, pos - lastPos);
- Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()).
- getAsString(Policy) << ')' << *PI;
+ Out << " " << name.substr(lastPos, pos - lastPos) << ':';
+ PrintObjCMethodType(OMD->getASTContext(),
+ PI->getObjCDeclQualifier(),
+ PI->getType());
+ Out << *PI;
lastPos = pos + 1;
}
@@ -1103,6 +1150,8 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
Out << "@optional\n";
+ QualType T = PDecl->getType();
+
Out << "@property";
if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
bool first = true;
@@ -1161,10 +1210,19 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
first = false;
}
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_nullability) {
+ if (auto nullability = stripOuterNullability(T)) {
+ Out << (first ? ' ' : ',')
+ << getNullabilitySpelling(*nullability).substr(2);
+ first = false;
+ }
+ }
+
(void) first; // Silence dead store warning due to idiomatic code.
Out << " )";
}
- Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()).
+ Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
getAsString(Policy) << ' ' << *PDecl;
if (Policy.PolishForDeclaration)
Out << ';';
OpenPOWER on IntegriCloud