aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/Parser.h6
-rw-r--r--include/clang/Sema/Sema.h4
-rw-r--r--lib/Parse/ParseExpr.cpp77
-rw-r--r--lib/Parse/ParseExprCXX.cpp19
-rw-r--r--lib/Sema/SemaExpr.cpp20
-rw-r--r--test/ARCMT/checking.m2
-rw-r--r--test/SemaObjC/arc-type-conversion.m26
-rw-r--r--test/SemaObjCXX/arc-type-conversion.mm3
8 files changed, 104 insertions, 53 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 626ad5316d..abd1ff2170 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1135,10 +1135,10 @@ private:
ExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
- ParsedType TypeOfCast);
+ bool isTypeCast);
ExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand = false,
- ParsedType TypeOfCast = ParsedType());
+ bool isTypeCast = false);
/// Returns true if the next token would start a postfix-expression
/// suffix.
@@ -1179,7 +1179,7 @@ private:
};
ExprResult ParseParenExpression(ParenParseOption &ExprType,
bool stopIfCastExpr,
- ParsedType TypeOfCast,
+ bool isTypeCast,
ParsedType &CastTy,
SourceLocation &RParenLoc);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index bcac0342ce..69686b34fa 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2376,8 +2376,8 @@ public:
MultiExprArg ExecConfig, SourceLocation GGGLoc);
ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- ParsedType Ty, SourceLocation RParenLoc,
- Expr *Op);
+ Declarator &D, ParsedType &Ty,
+ SourceLocation RParenLoc, Expr *Op);
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
TypeSourceInfo *Ty,
SourceLocation RParenLoc,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index bd723f0325..5e8bb53b2d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -220,7 +220,7 @@ ExprResult Parser::ParseAssignmentExpression() {
if (Tok.is(tok::kw_throw))
return ParseThrowExpression();
- ExprResult LHS = ParseCastExpression(false, false, ParsedType());
+ ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false);
return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
}
@@ -415,12 +415,12 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
///
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
- ParsedType TypeOfCast) {
+ bool isTypeCast) {
bool NotCastExpr;
ExprResult Res = ParseCastExpression(isUnaryExpression,
isAddressOfOperand,
NotCastExpr,
- TypeOfCast);
+ isTypeCast);
if (NotCastExpr)
Diag(Tok, diag::err_expected_expression);
return move(Res);
@@ -589,7 +589,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
- ParsedType TypeOfCast) {
+ bool isTypeCast) {
ExprResult Res;
tok::TokenKind SavedKind = Tok.getKind();
NotCastExpr = false;
@@ -620,7 +620,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
ColonProtectionRAIIObject X(*this, false);
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- TypeOfCast, CastTy, RParenLoc);
+ isTypeCast, CastTy, RParenLoc);
}
switch (ParenExprType) {
@@ -952,7 +952,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
if (!Tok.is(tok::annot_cxxscope))
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, TypeOfCast);
+ NotCastExpr, isTypeCast);
Token Next = NextToken();
if (Next.is(tok::annot_template_id)) {
@@ -965,7 +965,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
AnnotateTemplateIdTokenAsType();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, TypeOfCast);
+ NotCastExpr, isTypeCast);
}
}
@@ -982,7 +982,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// expression.
AnnotateTemplateIdTokenAsType();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, TypeOfCast);
+ NotCastExpr, isTypeCast);
}
// Fall through to treat the template-id as an id-expression.
@@ -1105,7 +1105,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
ConsumeCodeCompletionToken();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, TypeOfCast);
+ NotCastExpr, isTypeCast);
case tok::l_square:
// These can be followed by postfix-expr pieces.
if (getLang().ObjC1)
@@ -1422,7 +1422,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
EnterExpressionEvaluationContext Unevaluated(Actions,
Sema::Unevaluated);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
- ParsedType(), CastTy, RParenLoc);
+ false, CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
// If ParseParenExpression parsed a '(typename)' sequence only, then this is
@@ -1746,7 +1746,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
/// (__bridge_retained type-name) cast-expression
ExprResult
Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
- ParsedType TypeOfCast, ParsedType &CastTy,
+ bool isTypeCast, ParsedType &CastTy,
SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
@@ -1804,7 +1804,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
TypeResult Ty = ParseTypeName();
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, OpenLoc);
- ExprResult SubExpr = ParseCastExpression(false, false, ParsedType());
+ ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
if (Ty.isInvalid() || SubExpr.isInvalid())
return ExprError();
@@ -1826,20 +1826,23 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
OpenLoc, RParenLoc);
- TypeResult Ty;
-
- {
- InMessageExpressionRAIIObject InMessage(*this, false);
- Ty = ParseTypeName();
- }
+ // Parse the type declarator.
+ DeclSpec DS(AttrFactory);
+ ParseSpecifierQualifierList(DS);
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ ParseDeclarator(DeclaratorInfo);
// If our type is followed by an identifier and either ':' or ']', then
// this is probably an Objective-C message send where the leading '[' is
// missing. Recover as if that were the case.
- if (!Ty.isInvalid() && Tok.is(tok::identifier) && !InMessageExpression &&
- getLang().ObjC1 && !Ty.get().get().isNull() &&
- (NextToken().is(tok::colon) || NextToken().is(tok::r_square)) &&
- Ty.get().get()->isObjCObjectOrInterfaceType()) {
+ if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&
+ !InMessageExpression && getLang().ObjC1 &&
+ (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
+ TypeResult Ty;
+ {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+ Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ }
Result = ParseObjCMessageExpressionBody(SourceLocation(),
SourceLocation(),
Ty.get(), 0);
@@ -1852,21 +1855,31 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (Tok.is(tok::l_brace)) {
ExprType = CompoundLiteral;
+ TypeResult Ty;
+ {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+ Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ }
return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
}
if (ExprType == CastExpr) {
// We parsed '(' type-name ')' and the thing after it wasn't a '{'.
- if (Ty.isInvalid())
+ if (DeclaratorInfo.isInvalidType())
return ExprError();
- CastTy = Ty.get();
-
// Note that this doesn't parse the subsequent cast-expression, it just
// returns the parsed type to the callee.
- if (stopIfCastExpr)
+ if (stopIfCastExpr) {
+ TypeResult Ty;
+ {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+ Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ }
+ CastTy = Ty.get();
return ExprResult();
+ }
// Reject the cast of super idiom in ObjC.
if (Tok.is(tok::identifier) && getLang().ObjC1 &&
@@ -1880,17 +1893,21 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Parse the cast-expression that follows it next.
// TODO: For cast expression with CastTy.
- Result = ParseCastExpression(false, false, CastTy);
- if (!Result.isInvalid())
- Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, CastTy,
+ Result = ParseCastExpression(/*isUnaryExpression=*/false,
+ /*isAddressOfOperand=*/false,
+ /*isTypeCast=*/true);
+ if (!Result.isInvalid()) {
+ Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
+ DeclaratorInfo, CastTy,
RParenLoc, Result.take());
+ }
return move(Result);
}
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
return ExprError();
}
- } else if (TypeOfCast) {
+ } else if (isTypeCast) {
// Parse the expression-list.
InMessageExpressionRAIIObject InMessage(*this, false);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 632499295f..6822681c7a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -2200,7 +2200,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
Result = ParseCastExpression(false/*isUnaryExpression*/,
false/*isAddressofOperand*/,
NotCastExpr,
- ParsedType()/*TypeOfCast*/);
+ // type-id has priority.
+ true/*isTypeCast*/);
}
// If we parsed a cast-expression, it's really a type-id, otherwise it's
@@ -2219,7 +2220,11 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ConsumeAnyToken();
if (ParseAs >= CompoundLiteral) {
- TypeResult Ty = ParseTypeName();
+ // Parse the type declarator.
+ DeclSpec DS(AttrFactory);
+ ParseSpecifierQualifierList(DS);
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ ParseDeclarator(DeclaratorInfo);
// Match the ')'.
if (Tok.is(tok::r_paren))
@@ -2229,21 +2234,21 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
if (ParseAs == CompoundLiteral) {
ExprType = CompoundLiteral;
+ TypeResult Ty = ParseTypeName();
return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
}
// We parsed '(' type-id ')' and the thing after it wasn't a '{'.
assert(ParseAs == CastExpr);
- if (Ty.isInvalid())
+ if (DeclaratorInfo.isInvalidType())
return ExprError();
- CastTy = Ty.get();
-
// Result is what ParseCastExpression returned earlier.
if (!Result.isInvalid())
- Result = Actions.ActOnCastExpr(getCurScope(), LParenLoc, CastTy, RParenLoc,
- Result.take());
+ Result = Actions.ActOnCastExpr(getCurScope(), LParenLoc,
+ DeclaratorInfo, CastTy,
+ RParenLoc, Result.take());
return move(Result);
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index af0a3db688..68b767b474 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4138,15 +4138,23 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
}
ExprResult
-Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty,
+Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ Declarator &D, ParsedType &Ty,
SourceLocation RParenLoc, Expr *castExpr) {
- assert((Ty != 0) && (castExpr != 0) &&
+ assert(!D.isInvalidType() && (castExpr != 0) &&
"ActOnCastExpr(): missing type or expr");
- TypeSourceInfo *castTInfo;
- QualType castType = GetTypeFromParser(Ty, &castTInfo);
- if (!castTInfo)
- castTInfo = Context.getTrivialTypeSourceInfo(castType);
+ TypeSourceInfo *castTInfo = GetTypeForDeclaratorCast(D, castExpr->getType());
+ if (D.isInvalidType())
+ return ExprError();
+
+ if (getLangOptions().CPlusPlus) {
+ // Check that there are no default arguments (C++ only).
+ CheckExtraCXXDefaultArguments(D);
+ }
+
+ QualType castType = castTInfo->getType();
+ Ty = CreateParsedType(castType, castTInfo);
bool isVectorLiteral = false;
diff --git a/test/ARCMT/checking.m b/test/ARCMT/checking.m
index 08277c8a56..ed1592416b 100644
--- a/test/ARCMT/checking.m
+++ b/test/ARCMT/checking.m
@@ -100,7 +100,7 @@ void * cvt(id arg)
(void)(int*)arg; // expected-error {{disallowed}}
(void)(id)arg;
(void)(__autoreleasing id*)arg; // expected-error {{disallowed}}
- (void)(id*)arg; // expected-error {{pointer to non-const type 'id' with no explicit ownership}} expected-error {{disallowed}}
+ (void)(id*)arg; // expected-error {{disallowed}}
(void)(__autoreleasing id**)voidp_val;
(void)(void*)voidp_val;
diff --git a/test/SemaObjC/arc-type-conversion.m b/test/SemaObjC/arc-type-conversion.m
index 1c38597865..bb5686b691 100644
--- a/test/SemaObjC/arc-type-conversion.m
+++ b/test/SemaObjC/arc-type-conversion.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-nonfragile-abi -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-nonfragile-abi -verify -fblocks %s
void * cvt(id arg)
{
@@ -6,7 +6,7 @@ void * cvt(id arg)
(void)(int*)arg; // expected-error {{cast of an Objective-C pointer to 'int *' is disallowed with ARC}}
(void)(id)arg;
(void)(__autoreleasing id*)arg; // expected-error {{cast of an Objective-C pointer to '__autoreleasing id *' is disallowed with ARC}}
- (void)(id*)arg; // expected-error {{pointer to non-const type 'id' with no explicit ownership}} expected-error {{cast of an Objective-C pointer to '__autoreleasing id *' is disallowed with ARC}}
+ (void)(id*)arg; // expected-error {{cast of an Objective-C pointer to '__strong id *' is disallowed with ARC}}
(void)(__autoreleasing id**)voidp_val;
(void)(void*)voidp_val;
@@ -53,3 +53,25 @@ void from_void(void *vp) {
aip = vp; // expected-error{{implicit conversion of a non-Objective-C pointer type 'void *' to '__autoreleasing id *' is disallowed with ARC}}
uip = vp; // expected-error{{implicit conversion of a non-Objective-C pointer type 'void *' to '__unsafe_unretained id *' is disallowed with ARC}}
}
+
+typedef void (^Block)();
+typedef void (^Block_strong)() __strong;
+typedef void (^Block_autoreleasing)() __autoreleasing;
+
+@class NSString;
+
+void ownership_transfer_in_cast(void *vp, Block *pblk) {
+ __strong NSString **sip = (NSString**)(__strong id *)vp;
+ __weak NSString **wip = (NSString**)(__weak id *)vp;
+ __autoreleasing id *aip = (id*)(__autoreleasing id *)vp;
+ __unsafe_unretained id *uip = (id*)(__unsafe_unretained id *)vp;
+
+ __strong id **sipp = (id**)(__strong id **)vp;
+ __weak id **wipp = (id**)(__weak id **)vp;
+ __autoreleasing id **aipp = (id**)(__autoreleasing id **)vp;
+ __unsafe_unretained id **uipp = (id**)(__unsafe_unretained id **)vp;
+
+ Block_strong blk_strong1;
+ Block_strong blk_strong2 = (Block)blk_strong1;
+ Block_autoreleasing *blk_auto = (Block*)pblk;
+}
diff --git a/test/SemaObjCXX/arc-type-conversion.mm b/test/SemaObjCXX/arc-type-conversion.mm
index 7c6beaf1ad..7e2700ec6e 100644
--- a/test/SemaObjCXX/arc-type-conversion.mm
+++ b/test/SemaObjCXX/arc-type-conversion.mm
@@ -7,8 +7,7 @@ void * cvt(id arg) // expected-note{{candidate function not viable: cannot conve
(void)(int*)arg; // expected-error {{cast of an Objective-C pointer to 'int *' is disallowed with ARC}}
(void)(id)arg;
(void)(__autoreleasing id*)arg; // expected-error{{C-style cast from 'id' to '__autoreleasing id *' casts away qualifiers}}
- (void)(id*)arg; // expected-error {{pointer to non-const type 'id' with no explicit ownership}} \
- // expected-error{{C-style cast from 'id' to '__autoreleasing id *' casts away qualifiers}}
+ (void)(id*)arg; // expected-error{{C-style cast from 'id' to '__strong id *' casts away qualifiers}}
(void)(__autoreleasing id**)voidp_val;
(void)(void*)voidp_val;