From: John McCall Date: Wed, 23 Mar 2011 23:43:04 +0000 (+0000) Subject: Call out ObjC parameter types as a different kind of declarator context X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c05a94b7accd4035bf5d5897c434c445b22da855;p=clang Call out ObjC parameter types as a different kind of declarator context from a normal type-spec, just for completeness. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128185 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index b51632c6ac..45f1f2af45 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1495,7 +1495,7 @@ private: TypeResult ParseTypeName(SourceRange *Range = 0, Declarator::TheContext Context - = Declarator::TypeNameContext); + = Declarator::TypeNameContext); void ParseBlockId(); void ProhibitAttributes(ParsedAttributesWithRange &attrs) { diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 03573b02a3..0e06330434 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1317,6 +1317,7 @@ public: enum TheContext { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. + ObjCPrototypeContext,// Within a method prototype. KNRTypeListContext, // K&R type definition list for formals. TypeNameContext, // Abstract declarator for types. MemberContext, // Struct/Union field. @@ -1405,6 +1406,10 @@ public: TheContext getContext() const { return Context; } + bool isPrototypeContext() const { + return (Context == PrototypeContext || Context == ObjCPrototypeContext); + } + /// getSourceRange - Get the source range that spans this declarator. const SourceRange &getSourceRange() const { return Range; } @@ -1449,26 +1454,76 @@ public: /// not allowed. This is true for typenames, prototypes, and template /// parameter lists. bool mayOmitIdentifier() const { - return Context == TypeNameContext || Context == PrototypeContext || - Context == TemplateParamContext || Context == CXXCatchContext || - Context == BlockLiteralContext || Context == TemplateTypeArgContext; + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + return false; + + case TypeNameContext: + case PrototypeContext: + case ObjCPrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return true; + } + llvm_unreachable("unknown context kind!"); } /// mayHaveIdentifier - Return true if the identifier is either optional or /// required. This is true for normal declarators and prototypes, but not /// typenames. bool mayHaveIdentifier() const { - return Context != TypeNameContext && Context != BlockLiteralContext && - Context != TemplateTypeArgContext; + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + case PrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + return true; + + case TypeNameContext: + case ObjCPrototypeContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return false; + } + llvm_unreachable("unknown context kind!"); } /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be /// followed by a C++ direct initializer, e.g. "int x(1);". bool mayBeFollowedByCXXDirectInit() const { - return !hasGroupingParens() && - (Context == FileContext || - Context == BlockContext || - Context == ForContext); + if (hasGroupingParens()) return false; + + switch (Context) { + case FileContext: + case BlockContext: + case ForContext: + return true; + + case KNRTypeListContext: + case MemberContext: + case ConditionContext: + case PrototypeContext: + case ObjCPrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case TypeNameContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return false; + } + llvm_unreachable("unknown context kind!"); } /// isPastIdentifier - Return true if we have parsed beyond the point where diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index d4391ee3e9..dab63548a4 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -776,7 +776,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, ParsedType Ty; if (isTypeSpecifierQualifier()) { - TypeResult TypeSpec = ParseTypeName(); + TypeResult TypeSpec = ParseTypeName(0, Declarator::ObjCPrototypeContext); if (!TypeSpec.isInvalid()) Ty = TypeSpec.get(); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 88541c9508..b3cdbb2725 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1550,6 +1550,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::KNRTypeListContext: assert(0 && "K&R type lists aren't allowed in C++"); break; + case Declarator::ObjCPrototypeContext: case Declarator::PrototypeContext: Error = 0; // Function prototype break; @@ -1698,8 +1699,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, ASM = ArrayType::Static; else ASM = ArrayType::Normal; - if (ASM == ArrayType::Star && - D.getContext() != Declarator::PrototypeContext) { + if (ASM == ArrayType::Star && !D.isPrototypeContext()) { // FIXME: This check isn't quite right: it allows star in prototypes // for function definitions, and disallows some edge cases detailed // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html @@ -2168,6 +2168,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::FileContext: case Declarator::KNRTypeListContext: + case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here? case Declarator::TypeNameContext: case Declarator::MemberContext: case Declarator::BlockContext: