[cfe-commits] r140944 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseObjc.cpp lib/Sema/SemaType.cpp test/CodeGenObjC/arc.m
John McCall
rjmccall at apple.com
Sat Oct 1 02:56:14 PDT 2011
Author: rjmccall
Date: Sat Oct 1 04:56:14 2011
New Revision: 140944
URL: http://llvm.org/viewvc/llvm-project?rev=140944&view=rev
Log:
Parse attributes written in an ObjC method parameter type as
attributes on the parameter declaration.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/CodeGenObjC/arc.m
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Oct 1 04:56:14 2011
@@ -1138,13 +1138,8 @@
bool isTokIdentifier_in() const;
- /// \brief The context in which we are parsing an Objective-C type name.
- enum ObjCTypeNameContext {
- OTN_ResultType,
- OTN_ParameterType
- };
-
- ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, ObjCTypeNameContext Context);
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, Declarator::TheContext Ctx,
+ ParsedAttributes *ParamAttrs);
void ParseObjCMethodRequirement();
Decl *ParseObjCMethodPrototype(
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
@@ -1508,8 +1503,8 @@
void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none);
- void ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
- ObjCTypeNameContext Context);
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
+ Declarator::TheContext Context);
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
@@ -1684,7 +1679,6 @@
TypeResult ParseTypeName(SourceRange *Range = 0,
Declarator::TheContext Context
= Declarator::TypeNameContext,
- ObjCDeclSpec *objcQuals = 0,
AccessSpecifier AS = AS_none,
Decl **OwnedType = 0);
void ParseBlockId();
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Sat Oct 1 04:56:14 2011
@@ -736,6 +736,7 @@
const IdentifierInfo *getSetterName() const { return SetterName; }
IdentifierInfo *getSetterName() { return SetterName; }
void setSetterName(IdentifierInfo *name) { SetterName = name; }
+
private:
// FIXME: These two are unrelated and mutially exclusive. So perhaps
// we can put them in a union to reflect their mutual exclusiveness
@@ -1368,7 +1369,8 @@
enum TheContext {
FileContext, // File scope declaration.
PrototypeContext, // Within a function prototype.
- ObjCPrototypeContext,// Within a method prototype.
+ ObjCResultContext, // An ObjC method result type.
+ ObjCParameterContext,// An ObjC method parameter type.
KNRTypeListContext, // K&R type definition list for formals.
TypeNameContext, // Abstract declarator for types.
MemberContext, // Struct/Union field.
@@ -1466,7 +1468,9 @@
TheContext getContext() const { return Context; }
bool isPrototypeContext() const {
- return (Context == PrototypeContext || Context == ObjCPrototypeContext);
+ return (Context == PrototypeContext ||
+ Context == ObjCParameterContext ||
+ Context == ObjCResultContext);
}
/// getSourceRange - Get the source range that spans this declarator.
@@ -1526,7 +1530,8 @@
case AliasDeclContext:
case AliasTemplateContext:
case PrototypeContext:
- case ObjCPrototypeContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
case TemplateParamContext:
case CXXNewContext:
case CXXCatchContext:
@@ -1559,7 +1564,8 @@
case CXXNewContext:
case AliasDeclContext:
case AliasTemplateContext:
- case ObjCPrototypeContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
case BlockLiteralContext:
case TemplateTypeArgContext:
return false;
@@ -1582,7 +1588,8 @@
case MemberContext:
case ConditionContext:
case PrototypeContext:
- case ObjCPrototypeContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
case TemplateParamContext:
case CXXCatchContext:
case ObjCCatchContext:
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Oct 1 04:56:14 2011
@@ -33,12 +33,10 @@
/// Called type-id in C++.
TypeResult Parser::ParseTypeName(SourceRange *Range,
Declarator::TheContext Context,
- ObjCDeclSpec *objcQuals,
AccessSpecifier AS,
Decl **OwnedType) {
// Parse the common declaration-specifiers piece.
DeclSpec DS(AttrFactory);
- DS.setObjCQualifiers(objcQuals);
ParseSpecifierQualifierList(DS, AS);
if (OwnedType)
*OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Oct 1 04:56:14 2011
@@ -519,7 +519,7 @@
TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
Declarator::AliasTemplateContext :
- Declarator::AliasDeclContext, 0, AS, OwnedType);
+ Declarator::AliasDeclContext, AS, OwnedType);
} else
// Parse (optional) attributes (most likely GNU strong-using extension).
MaybeParseGNUAttributes(attrs);
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Sat Oct 1 04:56:14 2011
@@ -742,11 +742,14 @@
/// objc-type-qualifiers objc-type-qualifier
///
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
- ObjCTypeNameContext Context) {
+ Declarator::TheContext Context) {
+ assert(Context == Declarator::ObjCParameterContext ||
+ Context == Declarator::ObjCResultContext);
+
while (1) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
- Context == OTN_ParameterType);
+ Context == Declarator::ObjCParameterContext);
return cutOffParsing();
}
@@ -779,12 +782,51 @@
}
}
+/// Take all the decl attributes out of the given list and add
+/// them to the given attribute set.
+static void takeDeclAttributes(ParsedAttributes &attrs,
+ AttributeList *list) {
+ while (list) {
+ AttributeList *cur = list;
+ list = cur->getNext();
+
+ if (!cur->isUsedAsTypeAttr()) {
+ // Clear out the next pointer. We're really completely
+ // destroying the internal invariants of the declarator here,
+ // but it doesn't matter because we're done with it.
+ cur->setNext(0);
+ attrs.add(cur);
+ }
+ }
+}
+
+/// takeDeclAttributes - Take all the decl attributes from the given
+/// declarator and add them to the given list.
+static void takeDeclAttributes(ParsedAttributes &attrs,
+ Declarator &D) {
+ // First, take ownership of all attributes.
+ attrs.getPool().takeAllFrom(D.getAttributePool());
+ attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());
+
+ // Now actually move the attributes over.
+ takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList());
+ takeDeclAttributes(attrs, D.getAttributes());
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
+ takeDeclAttributes(attrs,
+ const_cast<AttributeList*>(D.getTypeObject(i).getAttrs()));
+}
+
/// objc-type-name:
/// '(' objc-type-qualifiers[opt] type-name ')'
/// '(' objc-type-qualifiers[opt] ')'
///
ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
- ObjCTypeNameContext Context) {
+ Declarator::TheContext context,
+ ParsedAttributes *paramAttrs) {
+ assert(context == Declarator::ObjCParameterContext ||
+ context == Declarator::ObjCResultContext);
+ assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext));
+
assert(Tok.is(tok::l_paren) && "expected (");
SourceLocation LParenLoc = ConsumeParen();
@@ -792,15 +834,30 @@
ObjCDeclContextSwitch ObjCDC(*this);
// Parse type qualifiers, in, inout, etc.
- ParseObjCTypeQualifierList(DS, Context);
+ ParseObjCTypeQualifierList(DS, context);
ParsedType Ty;
if (isTypeSpecifierQualifier()) {
- TypeResult TypeSpec =
- ParseTypeName(0, Declarator::ObjCPrototypeContext, &DS);
- if (!TypeSpec.isInvalid())
- Ty = TypeSpec.get();
- } else if (Context == OTN_ResultType && Tok.is(tok::identifier)) {
+ // Parse an abstract declarator.
+ DeclSpec declSpec(AttrFactory);
+ declSpec.setObjCQualifiers(&DS);
+ ParseSpecifierQualifierList(declSpec);
+ Declarator declarator(declSpec, context);
+ ParseDeclarator(declarator);
+
+ // If that's not invalid, extract a type.
+ if (!declarator.isInvalidType()) {
+ TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
+ if (!type.isInvalid())
+ Ty = type.get();
+
+ // If we're parsing a parameter, steal all the decl attributes
+ // and add them to the decl spec.
+ if (context == Declarator::ObjCParameterContext)
+ takeDeclAttributes(*paramAttrs, declarator);
+ }
+ } else if (context == Declarator::ObjCResultContext &&
+ Tok.is(tok::identifier)) {
if (!Ident_instancetype)
Ident_instancetype = PP.getIdentifierInfo("instancetype");
@@ -869,7 +926,7 @@
ParsedType ReturnType;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
- ReturnType = ParseObjCTypeName(DSRet, OTN_ResultType);
+ ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0);
// If attributes exist before the method, parse them.
ParsedAttributes methodAttrs(AttrFactory);
@@ -934,9 +991,12 @@
ArgInfo.Type = ParsedType();
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
- ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, OTN_ParameterType);
+ ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
+ Declarator::ObjCParameterContext,
+ ¶mAttrs);
// If attributes exist before the argument name, parse them.
+ // Regardless, collect all the attributes we've parsed so far.
ArgInfo.ArgAttrs = 0;
if (getLang().ObjC2) {
MaybeParseGNUAttributes(paramAttrs);
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Oct 1 04:56:14 2011
@@ -1752,7 +1752,8 @@
case Declarator::KNRTypeListContext:
llvm_unreachable("K&R type lists aren't allowed in C++");
break;
- case Declarator::ObjCPrototypeContext:
+ case Declarator::ObjCParameterContext:
+ case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
Error = 0; // Function prototype
break;
@@ -1861,7 +1862,8 @@
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
break;
case Declarator::PrototypeContext:
- case Declarator::ObjCPrototypeContext:
+ case Declarator::ObjCParameterContext:
+ case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
@@ -2482,7 +2484,8 @@
case Declarator::FileContext:
case Declarator::KNRTypeListContext:
- case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here?
+ case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
+ case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
case Declarator::TypeNameContext:
case Declarator::CXXNewContext:
case Declarator::AliasDeclContext:
@@ -3065,7 +3068,10 @@
return true;
// Make sure there are no unused decl attributes on the declarator.
- checkUnusedDeclAttributes(D);
+ // We don't want to do this for ObjC parameters because we're going
+ // to apply them to the actual parameter declaration.
+ if (D.getContext() != Declarator::ObjCParameterContext)
+ checkUnusedDeclAttributes(D);
if (getLangOptions().CPlusPlus) {
// Check that there are no default arguments (C++ only).
Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=140944&r1=140943&r2=140944&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Sat Oct 1 04:56:14 2011
@@ -1912,3 +1912,27 @@
// CHECK: define internal void @"\01-[Test65 setNblock:]"(
// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true)
@end
+
+// Verify that we successfully parse and preserve this attribute in
+// this position.
+ at interface Test66
+- (void) consume: (id __attribute__((ns_consumed))) ptr;
+ at end
+void test66(void) {
+ extern Test66 *test66_receiver(void);
+ extern id test66_arg(void);
+ [test66_receiver() consume: test66_arg()];
+}
+// CHECK: define void @test66()
+// CHECK: [[T0:%.*]] = call [[TEST66:%.*]]* @test66_receiver()
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST66]]* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST66]]*
+// CHECK-NEXT: [[T4:%.*]] = call i8* @test66_arg()
+// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]])
+// CHECK-NEXT: [[T6:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T7:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
+// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]])
+// CHECK-NEXT: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T8]])
+// CHECK-NEXT: ret void
More information about the cfe-commits
mailing list