]> granicus.if.org Git - clang/commitdiff
Call out ObjC parameter types as a different kind of declarator context
authorJohn McCall <rjmccall@apple.com>
Wed, 23 Mar 2011 23:43:04 +0000 (23:43 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 23 Mar 2011 23:43:04 +0000 (23:43 +0000)
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

include/clang/Parse/Parser.h
include/clang/Sema/DeclSpec.h
lib/Parse/ParseObjc.cpp
lib/Sema/SemaType.cpp

index b51632c6acca111628186596eca00ff7ee72354c..45f1f2af45afede163f765f72003f243fdb49926 100644 (file)
@@ -1495,7 +1495,7 @@ private:
 
   TypeResult ParseTypeName(SourceRange *Range = 0,
                            Declarator::TheContext Context
-                                                 = Declarator::TypeNameContext);
+                             = Declarator::TypeNameContext);
   void ParseBlockId();
 
   void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
index 03573b02a375978a5665603ec3884a5205c6233b..0e06330434960794d6389889886da18945ffff6f 100644 (file)
@@ -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
index d4391ee3e93fad02c1de120de41cbc816d3254ae..dab63548a45694c509cc4ef1a934d448fd8341a9 100644 (file)
@@ -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();
   }
index 88541c9508ecb6f4fa0cb84c0bb629f4dd370906..b3cdbb272539e1a526c509b8335f7197177d7d5c 100644 (file)
@@ -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: