diff options
author | Douglas Gregor <dgregor@apple.com> | 2015-06-19 18:14:38 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2015-06-19 18:14:38 +0000 |
commit | 813a066f16df52783708fdc2ef708bb76a9ff521 (patch) | |
tree | 0657ccae705e2a09c50dd92d26d645bff370aded /clang/lib/AST/DeclPrinter.cpp | |
parent | b4866e85e5ffa0d352d496958582f0983172dc01 (diff) | |
download | bcm5719-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.cpp | 74 |
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 << ';'; |