diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-09-08 17:18:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-09-08 17:18:35 +0000 |
commit | 5471bc85b69912e3b448de004498a80c0de32296 (patch) | |
tree | 722748ed81ac2868f8f853092a64891c338fbf99 | |
parent | 6aff47db98890aa537edfb579b21d11d5ea3d1cd (diff) |
Allow C++0x enumerations with a fixed underlying type in
Objective-C. The @encode'ing of such an enumeration type is the same
as its underlying type. <rdar://problem/5276348>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139297 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/LanguageExtensions.html | 19 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 19 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 5 | ||||
-rw-r--r-- | test/CodeGenObjC/encode-test-4.m | 7 | ||||
-rw-r--r-- | test/SemaObjC/enum-fixed-type.m | 22 |
6 files changed, 66 insertions, 7 deletions
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html index a7d8019f97..79c42fda2e 100644 --- a/docs/LanguageExtensions.html +++ b/docs/LanguageExtensions.html @@ -81,6 +81,7 @@ <ul> <li><a href="#objc_instancetype">Related result types</a></li> <li><a href="#objc_arc">Automatic reference counting</a></li> + <li><a href="#objc_fixed_enum">Enumerations with a fixed underlying type</a></li> </ul> </li> <li><a href="#overloading-in-c">Function Overloading in C</a></li> @@ -774,6 +775,24 @@ returns <tt>id</tt>.</p> <p>Clang provides support for <a href="AutomaticReferenceCounting.html">automated reference counting</a> in Objective-C, which eliminates the need for manual retain/release/autorelease message sends. There are two feature macros associated with automatic reference counting: <code>__has_feature(objc_arc)</code> indicates the availability of automated reference counting in general, while <code>__has_feature(objc_arc_weak)</code> indicates that automated reference counting also includes support for <code>__weak</code> pointers to Objective-C objects.</p> <!-- ======================================================================= --> +<h2 id="objc_fixed_enum">Enumerations with a fixed underlying type</h2> +<!-- ======================================================================= --> + +<p>Clang provides support for C++0x enumerations with a fixed +underlying type within Objective-C. For example, one can write an +enumeration type as:</p> + +<pre> +typedef enum : unsigned char { Red, Green, Blue } Color; +</pre> + +<p>This specifies that the underlying type, which is used to store the +enumeration value, is <tt>unsigned char</tt>.</p> + +<p>Use <tt>__has_feature(objc_fixed_enum)</tt> to determine whether +support for fixed underlying types is available in Objective-C.</p> + +<!-- ======================================================================= --> <h2 id="overloading-in-c">Function Overloading in C</h2> <!-- ======================================================================= --> diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3a3fba5d61..5fa6704dba 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4204,6 +4204,17 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { } } +static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { + EnumDecl *Enum = ET->getDecl(); + + // The encoding of an non-fixed enum type is always 'i', regardless of size. + if (!Enum->isFixed()) + return 'i'; + + // The encoding of a fixed enum type matches its fixed underlying type. + return ObjCEncodingForPrimitiveKind(C, Enum->getIntegerType()); +} + static void EncodeBitField(const ASTContext *Ctx, std::string& S, QualType T, const FieldDecl *FD) { const Expr *E = FD->getBitWidth(); @@ -4228,8 +4239,8 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, const RecordDecl *RD = FD->getParent(); const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); - if (T->isEnumeralType()) - S += 'i'; + if (const EnumType *ET = T->getAs<EnumType>()) + S += ObjCEncodingForEnumType(Ctx, ET); else S += ObjCEncodingForPrimitiveKind(Ctx, T); } @@ -4415,11 +4426,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - if (T->isEnumeralType()) { + if (const EnumType *ET = T->getAs<EnumType>()) { if (FD && FD->isBitField()) EncodeBitField(this, S, T, FD); else - S += 'i'; + S += ObjCEncodingForEnumType(this, ET); return; } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 2bf172dec1..c7b00ea5c3 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -599,6 +599,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("objc_arc", LangOpts.ObjCAutoRefCount) .Case("objc_arc_weak", LangOpts.ObjCAutoRefCount && LangOpts.ObjCRuntimeHasWeak) + .Case("objc_fixed_enum", LangOpts.ObjC2) .Case("objc_instancetype", LangOpts.ObjC2) .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI) .Case("objc_weak_class", LangOpts.ObjCNonFragileABI) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4928bde002..40674ee7a9 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2555,7 +2555,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft; + bool AllowFixedUnderlyingType + = getLang().CPlusPlus0x || getLang().Microsoft || getLang().ObjC2; CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLang().CPlusPlus) { @@ -2658,7 +2659,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SourceRange Range; BaseType = ParseTypeName(&Range); - if (!getLang().CPlusPlus0x) + if (!getLang().CPlusPlus0x && !getLang().ObjC2) Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type) << Range; } diff --git a/test/CodeGenObjC/encode-test-4.m b/test/CodeGenObjC/encode-test-4.m index 117e173348..2624bc71fc 100644 --- a/test/CodeGenObjC/encode-test-4.m +++ b/test/CodeGenObjC/encode-test-4.m @@ -1,5 +1,10 @@ // RUN: %clang_cc1 -emit-llvm -o - %s -O2 | grep "ret i32 1" +typedef long Integer; +typedef enum : Integer { Red, Green, Blue} Color; +typedef enum { Cyan, Magenta, Yellow, Key } PrintColor; int a() { - return @encode(int) == @encode(int); + return @encode(int) == @encode(int) && + @encode(Color) == @encode(long) && + @encode(PrintColor) == @encode(int); } diff --git a/test/SemaObjC/enum-fixed-type.m b/test/SemaObjC/enum-fixed-type.m new file mode 100644 index 0000000000..0ec8db476c --- /dev/null +++ b/test/SemaObjC/enum-fixed-type.m @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#if !__has_feature(objc_fixed_enum) +# error Enumerations with a fixed underlying type are not supported +#endif + +typedef long Integer; + +typedef enum : Integer { Enumerator1, Enumerator2 } Enumeration; + +int array[sizeof(Enumeration) == sizeof(long)? 1 : -1]; + + +enum Color { Red, Green, Blue }; + +struct X { + enum Color : 4; + enum Color field1: 4; + enum Other : Integer field2; + enum Other : Integer field3 : 4; + enum : Integer { Blah, Blarg } field4 : 4; +}; |