summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-05-15 02:43:47 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-05-15 02:43:47 +0000
commitae2d06735fec992d61c44cf531984e5ffc7e67d1 (patch)
treee0992751f5c71b4c19bf4ba7138d1672a4bccea5
parent89a69a81af1a840e00a54c7ce303f546f89d0cba (diff)
downloadclang-ae2d06735fec992d61c44cf531984e5ffc7e67d1.tar.gz
clang-ae2d06735fec992d61c44cf531984e5ffc7e67d1.tar.bz2
clang-ae2d06735fec992d61c44cf531984e5ffc7e67d1.tar.xz
PR19748: Make sure we don't lose colon protection after the parenthesized type-id in a cast-expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208843 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Parse/Parser.h6
-rw-r--r--lib/Parse/ParseExpr.cpp17
-rw-r--r--lib/Parse/ParseExprCXX.cpp15
-rw-r--r--test/Parser/cxx-casting.cpp11
4 files changed, 32 insertions, 17 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 79c65c6db4..57adf9d385 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1391,9 +1391,9 @@ private:
ParsedType &CastTy,
SourceLocation &RParenLoc);
- ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
- ParsedType &CastTy,
- BalancedDelimiterTracker &Tracker);
+ ExprResult ParseCXXAmbiguousParenExpression(
+ ParenParseOption &ExprType, ParsedType &CastTy,
+ BalancedDelimiterTracker &Tracker, ColonProtectionRAIIObject &ColonProt);
ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index eea475f869..e69a213247 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -641,15 +641,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
: CastExpr;
ParsedType CastTy;
SourceLocation RParenLoc;
-
- {
- // The inside of the parens don't need to be a colon protected scope, and
- // isn't immediately a message send.
- ColonProtectionRAIIObject X(*this, false);
-
- Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- isTypeCast == IsTypeCast, CastTy, RParenLoc);
- }
+ Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
+ isTypeCast == IsTypeCast, CastTy, RParenLoc);
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
@@ -1928,6 +1921,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
bool isTypeCast, ParsedType &CastTy,
SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
+ ColonProtectionRAIIObject ColonProtection(*this, false);
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen())
return ExprError();
@@ -2003,6 +1997,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
TypeResult Ty = ParseTypeName();
T.consumeClose();
+ ColonProtection.restore();
RParenLoc = T.getCloseLocation();
ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
@@ -2023,7 +2018,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// if stopIfCastExpr is false, we need to determine the context past the
// parens, so we defer to ParseCXXAmbiguousParenExpression for that.
if (isAmbiguousTypeId && !stopIfCastExpr) {
- ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T);
+ ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T,
+ ColonProtection);
RParenLoc = T.getCloseLocation();
return res;
}
@@ -2051,6 +2047,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
} else {
// Match the ')'.
T.consumeClose();
+ ColonProtection.restore();
RParenLoc = T.getCloseLocation();
if (Tok.is(tok::l_brace)) {
ExprType = CompoundLiteral;
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 7d9fa1482d..f1d6c8d642 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -2909,7 +2909,8 @@ ExprResult Parser::ParseExpressionTrait() {
ExprResult
Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParsedType &CastTy,
- BalancedDelimiterTracker &Tracker) {
+ BalancedDelimiterTracker &Tracker,
+ ColonProtectionRAIIObject &ColonProt) {
assert(getLangOpts().CPlusPlus && "Should only be called for C++!");
assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
assert(isTypeIdInParens() && "Not a type-id!");
@@ -2958,6 +2959,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// Try parsing the cast-expression that may follow.
// If it is not a cast-expression, NotCastExpr will be true and no token
// will be consumed.
+ ColonProt.restore();
Result = ParseCastExpression(false/*isUnaryExpression*/,
false/*isAddressofOperand*/,
NotCastExpr,
@@ -2983,17 +2985,22 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
if (ParseAs >= CompoundLiteral) {
// Parse the type declarator.
DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- ParseDeclarator(DeclaratorInfo);
+ {
+ ColonProtectionRAIIObject InnerColonProtection(*this);
+ ParseSpecifierQualifierList(DS);
+ ParseDeclarator(DeclaratorInfo);
+ }
// Match the ')'.
Tracker.consumeClose();
+ ColonProt.restore();
if (ParseAs == CompoundLiteral) {
ExprType = CompoundLiteral;
+ // FIXME: This is entirely wrong.
TypeResult Ty = ParseTypeName();
- return ParseCompoundLiteralExpression(Ty.get(),
+ return ParseCompoundLiteralExpression(Ty.get(),
Tracker.getOpenLocation(),
Tracker.getCloseLocation());
}
diff --git a/test/Parser/cxx-casting.cpp b/test/Parser/cxx-casting.cpp
index 69680e421b..55309a1356 100644
--- a/test/Parser/cxx-casting.cpp
+++ b/test/Parser/cxx-casting.cpp
@@ -90,5 +90,16 @@ void test3() {
// expected-error {{expected unqualified-id}}
}
+// Ensure that a C-style cast doesn't turn off colon protection.
+void PR19748() {
+ struct A {};
+ int A = 0, b;
+ int test1 = true ? (int)A : b;
+
+ struct f {};
+ extern B f(), (*p)();
+ (true ? (B(*)())f : p)();
+}
+
// PR13619. Must be at end of file.
int n = reinterpret_cast // expected-error {{expected '<'}} expected-error {{expected ';'}}